/// <summary> /// Sets up data for the region to work with, including the physics environment and the chunk data management. /// </summary> public void BuildRegion() { // TODO: generator registry if (TheWorld.Generator == "sphere") { Generator = new SphereGeneratorCore(); } else { Generator = new SimpleGeneratorCore(); } ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount; i++) { pl.AddThread(); } CollisionDetectionSettings.AllowedPenetration = 0.01f; // TODO: This is a global setting - handle it elsewhere, or make it non-global? PhysicsWorld = new Space(pl); PhysicsWorld.TimeStepSettings.MaximumTimeStepsPerFrame = 10; PhysicsWorld.ForceUpdater.Gravity = (GravityNormal * GravityStrength).ToBVector(); PhysicsWorld.DuringForcesUpdateables.Add(new LiquidVolume(this)); PhysicsWorld.TimeStepSettings.TimeStepDuration = 1f / TheServer.CVars.g_fps.ValueF; Collision = new CollisionUtil(PhysicsWorld); // TODO: Perhaps these should be on the server level, not region? EntityConstructors.Add(EntityType.ITEM, new ItemEntityConstructor()); EntityConstructors.Add(EntityType.BLOCK_ITEM, new BlockItemEntityConstructor()); EntityConstructors.Add(EntityType.GLOWSTICK, new GlowstickEntityConstructor()); EntityConstructors.Add(EntityType.MODEL, new ModelEntityConstructor()); EntityConstructors.Add(EntityType.SMOKE_GRENADE, new SmokeGrenadeEntityConstructor()); EntityConstructors.Add(EntityType.MUSIC_BLOCK, new MusicBlockEntityConstructor()); EntityConstructors.Add(EntityType.HOVER_MESSAGE, new HoverMessageEntityConstructor()); ChunkManager = new ChunkDataManager(); ChunkManager.Init(this); }
public void BuildWorld() { MainThread = Thread.CurrentThread; MainThreadID = MainThread.ManagedThreadId; ParallelLooper pl = new ParallelLooper(); for (int i = 0; i < Environment.ProcessorCount; i++) { pl.AddThread(); } CollisionDetectionSettings.AllowedPenetration = 0.01f; PhysicsWorld = new Space(pl); PhysicsWorld.TimeStepSettings.MaximumTimeStepsPerFrame = 10; PhysicsWorld.ForceUpdater.Gravity = new Vector3(0, 0, -9.8f * 3f / 2f); PhysicsWorld.DuringForcesUpdateables.Add(new LiquidVolume(this)); PhysicsWorld.TimeStepSettings.TimeStepDuration = 1f / TheServer.CVars.g_fps.ValueF; Collision = new CollisionUtil(PhysicsWorld); EntityConstructors.Add(EntityType.ITEM, new ItemEntityConstructor()); EntityConstructors.Add(EntityType.BLOCK_ITEM, new BlockItemEntityConstructor()); EntityConstructors.Add(EntityType.GLOWSTICK, new GlowstickEntityConstructor()); EntityConstructors.Add(EntityType.MODEL, new ModelEntityConstructor()); EntityConstructors.Add(EntityType.SMOKE_GRENADE, new SmokeGrenadeEntityConstructor()); EntityConstructors.Add(EntityType.MUSIC_BLOCK, new MusicBlockEntityConstructor()); ChunkManager = new ChunkDataManager(); ChunkManager.Init(this); //LoadRegion(new Location(-MaxViewRadiusInChunks * 30), new Location(MaxViewRadiusInChunks * 30), true); //TheServer.Schedule.RunAllSyncTasks(0.016); // TODO: Separate per-region scheduler // Also don't freeze the entire server/region just because we're waiting on chunks >.> //SysConsole.Output(OutputType.INIT, "Finished building chunks! Now have " + LoadedChunks.Count + " chunks!"); }
public Vector3 GetRandomFreePosition() { var myPos = movable_.GetPosition(); var direction = CollisionUtil.GetRandomFreeDirection(myPos) * (Random.value * 0.8f + 0.1f); return(myPos + direction); }
private static void FillTriangle(float VoxelSizeX, float VoxelSizeY, int ISX, int ISY, int MX, int MY, float ScaleX, float ScaleY, Vector2 P1, Vector2 P2, Vector2 P3, LockBitMap ShadeMap, LockBitMap TextureLookup) { int MaxX = (int)Math.Max(P1.X, Math.Max(P2.X, P3.X)); int MaxY = (int)Math.Max(P1.Y, Math.Max(P2.Y, P3.Y)); int MinX = (int)Math.Min(P1.X, Math.Min(P2.X, P3.X)); int MinY = (int)Math.Min(P1.Y, Math.Min(P2.Y, P3.Y)); Vector2 Pos = new Vector2(); for (int i = MinX; i <= MaxX; i++) { for (int j = MinY; j <= MaxY; j++) { Pos.X = i; Pos.Y = j; int TX = (int)((i % VoxelSizeX) / VoxelSizeX * ISX); int TY = (int)((j % VoxelSizeY) / VoxelSizeY * ISY); if (CollisionUtil.InsideTriangle(Pos, P1, P2, P3)) { ShadeMap.SetPixel(i, j, TextureLookup.GetPixel(TX + MX * ISX, TY + ISY * MY)); } } } }
private void RaycastFilledCellsHelper(Ray ray, Grid3D <T> brick, List <T> blackList, PriorityQueue <Vector3i, float> out_found, int x, int y, int z, int width, int height, int depth) { float distance; if (!CollisionUtil.IntersectsBounds(ray, x, y, z, x + width, y + height, z + depth, out distance)) { return; } if (width == 1 && height == 1 && depth == 1) // Work for all empty lists { if (!blackList.Contains(brick.GetValue(x, y, z))) { out_found.Enqueue(new Vector3i(x, y, z), BrickConstants.LARGE_FLOAT - distance); } } else { int newWidth = (width + 1) / 2; int newHeight = (height + 1) / 2; int newDepth = (depth + 1) / 2; RaycastFilledCellsHelper(ray, brick, blackList, out_found, x, y, z, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x + newWidth, y, z, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x, y + newHeight, z, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x, y, z + newDepth, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x + newWidth, y + newHeight, z, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x + newWidth, y, z + newDepth, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x, y + newHeight, z + newDepth, newWidth, newHeight, newDepth); RaycastFilledCellsHelper(ray, brick, blackList, out_found, x + newWidth, y + newHeight, z + newDepth, newWidth, newHeight, newDepth); } }
public void Execute() { foreach (var entity in _moveRequest.GetEntities()) { var deltaTime = GameConfig.DeltaTime; var mover = entity.move; var dir = entity.dir.value; var pos = entity.pos.value; var moveSpd = mover.moveSpd; //can move 判定 var dirVec = DirUtil.GetDirVec(dir).ToLVector2(); var moveDist = (moveSpd * deltaTime); var fTargetHead = pos + (TankUtil.TANK_HALF_LEN + moveDist) * dirVec; var fPreviewHead = pos + (TankUtil.TANK_HALF_LEN + TankUtil.FORWARD_HEAD_DIST) * dirVec; LFloat maxMoveDist = moveSpd * deltaTime; var headPos = pos + (TankUtil.TANK_HALF_LEN) * dirVec; var dist = CollisionUtil.GetMaxMoveDist(dir, headPos, fTargetHead); var dist2 = CollisionUtil.GetMaxMoveDist(dir, headPos, fPreviewHead); maxMoveDist = LMath.Max(LFloat.zero, LMath.Min(maxMoveDist, dist, dist2)); var diffPos = maxMoveDist * dirVec; pos = pos + diffPos; entity.pos.value = pos; } }
/// <summary> /// Returns whether there is anything solid within a box in 3D space. /// </summary> /// <param name="min">The lowest location</param> /// <param name="max">The highest location</param> /// <param name="world">The world everything is in</param> /// <returns>Whether there is anything solid within the block</returns> public static bool Box(World world, Location min, Location max) { foreach (KeyValuePair <Location, Chunk> chunk in world.LoadedChunks) { Location cpos = new Location(chunk.Value.X * 30, chunk.Value.Y * 30, chunk.Value.Z * 30); if (CollisionUtil.BoxContains(cpos, cpos + new Location(30), min, max)) { // TODO: Less stupid code. for (int z = 0; z < 30; z++) { if (CollisionUtil.BoxContains(cpos + new Location(0, 0, z), cpos + new Location(30, 30, z + 1), min, max)) { for (int x = 0; x < 30; x++) { if (CollisionUtil.BoxContains(cpos + new Location(x, 0, z), cpos + new Location(x + 1, 30, z + 1), min, max)) { for (int y = 0; y < 30; y++) { if (((Material)chunk.Value.Blocks[x, y, z].Type).OccupiesWholeBlock()) { if (CollisionUtil.BoxContains(cpos + new Location(x, y, z), cpos + new Location(x + 1, y + 1, z + 1), min, max)) { return(true); } } } } } } } } } return(false); }
public void GenerateBounds() { Bounds = Geometry.GetBoundsAB(); List<Vector3> VertexList = new List<Vector3>(); for (int i = 0; i < Geometry.CollisionBuffer.Length; i++) { //VertexList.Add(Geometry.CollisionBuffer[i].Position); } Vector3 Direction = new Vector3(0,1,0); int SizeX = (int)((Bounds[1].X - Bounds[0].X) / Precision); int SizeY = (int)((Bounds[1].Y - Bounds[0].Y) / Precision); int SizeZ = (int)((Bounds[1].Z - Bounds[0].Z) / Precision); Particles = new bool[ SizeX, SizeY, SizeZ]; for (int i = 0; i < SizeX; i++) { for (int j = 0; j < SizeY; j++) { for (int k = 0; k < SizeZ; k++) { Vector3 Position = new Vector3(i,j,k) * Precision + Bounds[0]; int Count = CollisionUtil.GetCollisionCount(VertexList, Position, Direction); Particles[i, j, k] = Count % 2 == 1; } } } }
public void Execute() { foreach (var entity in _moveRequest.GetEntities()) { var mover = entity.move; var pos = entity.pos.value; if (mover.isChangedDir) { var idir = (int)(entity.dir.value); var isUD = idir % 2 == 0; if (isUD) { pos.x = CollisionUtil.RoundIfNear(pos.x, TankUtil.SNAP_DIST); } else { pos.y = CollisionUtil.RoundIfNear(pos.y, TankUtil.SNAP_DIST); } } entity.pos.value = pos; mover.isChangedDir = false; entity.RemoveMoveRequest(); } }
private void OnTriggerEnter2D(Collider2D collision) { if (CanCollide && CollisionUtil.IsPlayerBullet(collision)) { HandleExplosion(); } }
IEnumerator AI() { float baseSpeed = movable_.GetSpeed(); while (true) { var pos = movable_.GetPosition(); var direction = CollisionUtil.GetRandomFreeDirection(pos) * (Random.value * 0.8f + 0.1f); movable_.MoveTo(pos + direction); float endTime = Time.time + 3 + Random.value * 2; while (true) { if (me_.IsDead) { yield break; } float time = Time.time; CheckFire(time); if (movable_.MoveTargetReached() || time > endTime) { break; } yield return(null); } yield return(null); } }
/// <summary> /// Returns whether is any solid entity that is not a player in the bounding box area. /// </summary> /// <param name="min">The minimum coordinates of the bounding box.</param> /// <param name="max">The maximum coordinates of the bounding box.</param> /// <returns>Whether there is any solid entity detected.</returns> public bool HassSolidEntity(Location min, Location max) { BoundingBox bb = new BoundingBox(min.ToBVector(), max.ToBVector()); List <BroadPhaseEntry> entries = new List <BroadPhaseEntry>(); PhysicsWorld.BroadPhase.QueryAccelerator.GetEntries(bb, entries); if (entries.Count == 0) { return(false); } Location center = (max + min) * 0.5; Location rel = max - min; BoxShape box = new BoxShape((double)rel.X, (double)rel.Y, (double)rel.Z); RigidTransform start = new RigidTransform(center.ToBVector(), BEPUutilities.Quaternion.Identity); Vector3 sweep = new Vector3(0, 0, 0.01f); foreach (BroadPhaseEntry entry in entries) { if (entry is EntityCollidable && CollisionUtil.ShouldCollide(entry) && entry.CollisionRules.Group != CollisionUtil.Player && // NOTE: Convex cast here to ensure the object is truly 'solid' in the box area, rather than just having an overlapping bounding-box edge. entry.ConvexCast(box, ref start, ref sweep, out RayHit rh)) { return(true); } } return(false); }
protected override void OnPlayerBulletTriggerEnter2D(Collider2D collision) { if (CollisionUtil.IsEnemyBullet(collision)) { var enemyBullet = collision.GetComponent <EnemyBullet>(); if (IsExploding && ShouldEraseBullet) { enemyBullet.DeactivateSelf(); } else { ManagedEnemyBullets.Add(enemyBullet); } } else if (CollisionUtil.IsPlayerBullet(collision)) { var playerBullet = collision.GetComponent <PlayerBullet>(); ManagedPlayerBullets.Add(playerBullet); } else if (CollisionUtil.IsPickup(collision)) { var pickup = collision.GetComponent <Pickup>(); ManagedPickups.Add(pickup); } // Enemy is handled in OnCollideWithEnemy() }
public void Update() { if (prePosition != transform.position) { if (this.owner.syncHeight) { var groundHeight = transform.position.y; if (CollisionUtil.TryGetGroundHeight(transform.position, out groundHeight)) { transform.position = transform.position.SetY(groundHeight); } } prePosition = transform.position; } if (this.state == State.Move) { var direction = Vector3.Normalize(this.corners[this.cornerIndex] - this.transform.position); this.transform.forward = direction; this.transform.position += direction * this.owner.speed; if (Vector3.Distance(this.corners[this.cornerIndex], this.transform.position) <= Mathf.Pow(this.owner.speed * Time.deltaTime, 2)) { this.cornerIndex++; } if (this.cornerIndex >= this.corners.Length) { this.state = State.Idle; this.cornerIndex = 0; } } }
public GameSprite( Texture2D texture, Rectangle rectangle, Rectangle rectangleOffset = default(Rectangle), Vector2 location = default(Vector2), Vector2 origin = default(Vector2), Vector2?scale = null, SpriteEffects spriteEffects = SpriteEffects.None, float rotation = 0.0f, float depth = 0.0f, bool initCollisionData = true ) : base() { this.TextureData = texture; this.TextureRect = rectangle; this.OffsetRect = rectangleOffset; this.Location = location; this.Origin = origin; this.Scale = scale.HasValue ? scale.Value : Vector2.One; this.SpriteEffects = spriteEffects; this.Rotation = rotation; this.Depth = depth; if (initCollisionData) { this.OpaqueData = CollisionUtil.GetOpaqueData(this); } else { this.OpaqueData = null; } }
// detect collision public bool Touches(GameSprite other) { return (this.OpaqueData != null && other.OpaqueData != null && CollisionUtil.DetectCollision(this, other)); }
public void Execute() { foreach (var entity in _AIGroup.GetEntities()) { var aiInfo = entity.aI; aiInfo.timer += GameConfig.DeltaTime; if (aiInfo.timer < aiInfo.updateInterval) { continue; } aiInfo.timer = LFloat.zero; Vector2Int dir = Vector2Int.zero; var curPos = entity.pos.value; var headPos = TankUtil.GetHeadPos(entity.pos.value, entity.dir.value); var isReachTheEnd = CollisionUtil.HasColliderWithBorder(entity.dir.value, headPos); if (isReachTheEnd) { List <int> allWalkableDir = new List <int>(); for (int i = 0; i < (int)(EDir.EnumCount); i++) { var vec = DirUtil.GetDirLVec((EDir)i) * TankUtil.TANK_HALF_LEN; var pos = curPos + vec; if (!CollisionUtil.HasCollider(pos)) { allWalkableDir.Add(i); } } var count = allWalkableDir.Count; if (count > 0) { entity.dir.value = (EDir)(allWalkableDir[_randomService.Range(0, count)]); entity.move.isChangedDir = true; } } var iPos = entity.pos.value.Floor(); if ((entity.pos.value - (iPos.ToLVector2() + TankUtil.UNIT_SIZE)).sqrMagnitude < TankUtil.sqrtTargetDist) { if (_randomService.value > new LFloat(true, 200)) { return; } //random change dir if it can var borderDir = DirUtil.GetDirVec((EDir)((int)(entity.dir.value + 1) % (int)EDir.EnumCount)); var iBorder1 = iPos + borderDir; var iBorder2 = iPos - borderDir; if (!CollisionUtil.HasCollider(iBorder1)) { entity.dir.value = DirUtil.GetEDirFromVec(borderDir); } else if (!CollisionUtil.HasCollider(iBorder2)) { entity.dir.value = DirUtil.GetEDirFromVec(Vector2Int.zero - borderDir); } } } }
protected override void OnPlayerBulletTriggerEnter2D(Collider2D collision) { if (DamageActive && CollisionUtil.IsEnemyBullet(collision)) { var enemyBullet = collision.GetComponent <EnemyBullet>(); GameManager.Instance.ReflectBullet(enemyBullet); } }
protected sealed override void OnTriggerExit2D(Collider2D collision) { if (CollisionUtil.IsEnemy(collision)) { var enemy = collision.GetComponent <Enemy>(); enemy.VoidResume(); } }
public bool IgnorePlayers(BroadPhaseEntry entry) { if (entry.CollisionRules.Group == CollisionUtil.Player) { return(false); } return(CollisionUtil.ShouldCollide(entry)); }
private void OnTriggerEnter2D(Collider2D collision) { if (CollisionUtil.IsPickup(collision)) { Pickup pickup = collision.GetComponent <Pickup>(); pickup.PickUp(); } }
public bool IgnoreThis(BroadPhaseEntry entry) // TODO: PhysicsEntity? { if (entry is EntityCollidable && ((EntityCollidable)entry).Entity.Tag == this) { return(false); } return(CollisionUtil.ShouldCollide(entry)); }
protected override void OnPlayerBulletTriggerEnter2D(Collider2D collision) { if (ReboundActive && CollisionUtil.IsScreenEdge(collision, out ScreenSide screenSide) && screenSide == ScreenSide.Top) { ReboundPowerup.ReboundOffScreenEdge(this); } }
protected override void OnPlayerBulletTriggerEnter2D(Collider2D collision) { if (CollisionUtil.IsEnemyBullet(collision)) { var enemyBullet = collision.GetComponent <EnemyBullet>(); GameManager.Instance.ReflectBulletFromPestControl(enemyBullet, this); DeactivateSelf(); } }
public static bool CheckCollision(GameEntity a, Vector2Int pos) { var cola = a.collider; var posa = a.pos.value; return(CollisionUtil.CheckCollision( posa, cola.radius, cola.size, pos.ToLVector2() + LVector2.half, LVector2.half.magnitude, LVector2.half)); }
protected virtual void OnTriggerExit2D(Collider2D collision) { if (CollisionUtil.IsDestructor(collision)) { if (ShouldDeactivateOnDestructor) { DeactivateSelf(); } } }
protected void OnTriggerEnter2D(Collider2D collision) { if (CollisionUtil.IsPlayer(collision)) { if (HitsPlayer && Player.Instance.CollidesWithBullet(this) && DeactivateOnHit) { DeactivateSelf(); } } }
protected override void OnPlayerBulletTriggerEnter2D(Collider2D collision) { if (IsMaxLevel) { if (CollisionUtil.IsEnemyBullet(collision)) { var bullet = collision.GetComponent <EnemyBullet>(); bullet.DeactivateSelf(); } } }
IEnumerator AI() { float baseSpeed = myMovement_.GetSpeed(); while (true) { while (true) { if (me_.IsDead) { yield break; } bool hasRecentlySeenPlayer = mySenses_.GetPlayerLatestKnownPositionAge() < 2.0f; if (!hasRecentlySeenPlayer) { break; } var target = mySenses_.GetPlayerLatestKnownPosition(PlayerPositionType.Feet); myMovement_.MoveTo(target, baseSpeed * 2); yield return(null); } var pos = myMovement_.GetPosition(); var direction = CollisionUtil.GetRandomFreeDirection(pos) * (Random.value * 0.8f + 0.1f); myMovement_.MoveTo(pos + direction, baseSpeed); float endTime = Time.time + 4 + Random.value; while (true) { if (myMovement_.MoveTargetReached()) { break; } if (Time.time > endTime) { break; } bool hasRecentlySeenPlayer = mySenses_.GetPlayerLatestKnownPositionAge() < 2.0f; if (hasRecentlySeenPlayer) { break; } yield return(null); } yield return(null); } }
public static bool CheckCollision(GameEntity a, GameEntity b) { var cola = a.collider; var colb = b.collider; var posa = a.pos.value; var posb = b.pos.value; return(CollisionUtil.CheckCollision( posa, cola.radius, cola.size, posb, colb.radius, colb.size)); }