//Executes one turtle step private void MoveTurtle(int length, RenderTarget2D target) { Vector2 newPos = now.currentPosition + (length * GeometryHelper.AngleToVector(GeometryHelper.DegToRad(now.angle))); GraphicsHelper.DrawSquareFromVector(spriteBatch, lineTexture, now.currentPosition, newPos, currentColor, length); now.currentPosition = newPos; }
//Check for collisions on one axis (X or Y) at a time and resolve them private int TerrainCollisionsXY(bool doCollisionX, Tile nextTile = null) { int result = 0; Tile tile = map.GetTileForX((int)position.X); if (nextTile != null) { tile = nextTile; } if (tile == null) { return(result); } Vector2 entityTilePos = map.GlobalToTileCoordinates(position, tile.Index); Rectangle bounds = new Rectangle((int)entityTilePos.X, (int)entityTilePos.Y, Width, Height); //todo: add a condition when player is on tile edge - check next/prev tiles edge line int wblocks = tile.Coords.Width / Block.Width; int hblocks = tile.Coords.Height / Block.Height; //Math.Min(sth, block count in that dimension-1) limits the indexes for searching adjacent blocks. If entity gets out of bounds, it'll be considered as being on the last tile in that dimension int leftBlockX = Math.Min((int)Math.Floor(entityTilePos.X / Block.Width), wblocks - 1); //get the X coordinate for neighbouring blocks on the left int rightBlockX = Math.Min(leftBlockX + (int)Math.Ceiling((double)Width / Block.Width), wblocks - 1); if (leftBlockX < 0) { leftBlockX = 0; } //Just to make sure we really don't collide, in case the entity is smaller than one block, extend the checking range if (rightBlockX <= leftBlockX) { rightBlockX = leftBlockX + 1; } if (rightBlockX >= wblocks) { rightBlockX = wblocks - 1; } int topBlockY = Math.Max(Math.Min((int)Math.Floor(entityTilePos.Y / Block.Height), hblocks - 1), 0); //Math.Max so that we don't check for blocks above the top edge (there are none) int bottomBlockY = Math.Min(topBlockY + (int)Math.Ceiling((double)Height / Block.Height) + 1, hblocks - 1); //Just to make sure we really don't collide, in case the entity is smaller than one block, again... if (bottomBlockY == topBlockY) { ++bottomBlockY; } if (bottomBlockY >= hblocks) { bottomBlockY = hblocks - 1; } //We don't believe we're grounded until we are proved wrong, prevents doublejumping isOnGround = false; //Loops through all blocks in selected range and checks for possible collisions. If found, moves the entity out of them for (int y = topBlockY; y <= bottomBlockY; ++y) { for (int x = leftBlockX; x <= rightBlockX; ++x) { if (tile.Blocks[x, y] != null) { Rectangle otherElement = new Rectangle(x * Block.Width, y * Block.Height, Block.Width, Block.Height); Vector2 depth = GeometryHelper.GetIntersectionDepth(bounds, otherElement); if (depth != Vector2.Zero) { //In the first call, we check for X-axis collisions if (doCollisionX) { position = new Vector2(Position.X + depth.X, Position.Y); bounds = BoundingRectangle; result = (int)depth.X; } //In the second call, we do the Y-axis else { //We hit a box underneath us, we're grounded if ((bounds.Top < otherElement.Top) && (bounds.Bottom > otherElement.Top)) { isOnGround = true; position = new Vector2(Position.X, Position.Y + depth.Y); bounds = BoundingRectangle; } //We hit a box above us, we're jumping else if ((bounds.Bottom > otherElement.Bottom + 1) && (bounds.Top < otherElement.Bottom)) { position = new Vector2(Position.X, Position.Y + depth.Y); jumpTime = MaxJumpTime; //we reached the apex of our jump bounds = BoundingRectangle; } } } } } } if (position.X < 0) { position.X = 0; } else if (position.X + Width > map.Width) { position.X = map.Width - Width; } if (rightBlockX == wblocks - 1 && CurrentTile < map.TileCount && nextTile == null) { var next = map.GetTileByIndex(CurrentTile + 1); if (next != null) { result = TerrainCollisionsXY(doCollisionX, next); } } else if (leftBlockX == 0 && CurrentTile > 0 && nextTile == null && IsPlayer) { var next = map.GetTileByIndex(CurrentTile - 1); if (next != null) { result = TerrainCollisionsXY(doCollisionX, next); } } oldBottom = bounds.Bottom; return(result); }
//Checks how much of the quest is currently completed public void CheckCompletion() { int percent = 0; if (Type == QuestType.KillTargets) { int deadCount = 0; //it doesn't matter how they die. If they're dead we got 'em. Name = BaseName; foreach (Entity e in Targets) { if (!e.Alive) { ++deadCount; } Name += e.Name + (!e.Alive ? "*" : "") + ", "; //A star marks a completed part of the quest } Name = Name.Remove(Name.Length - 2); percent = (int)((float)deadCount / Targets.Count * 100); } else if (Type == QuestType.FetchIitems) { //hackish way of detecting whether items are placed where they need to be int finishedItems = 0; Name = BaseName; foreach (Item i in RequiredItems) { //check whether the item is where it's supposed to be var dest = DestinationBlocks[0].Coords; var pos = i.Position; bool ok = false; if (i.IsPlaced && pos.X >= dest.Left && pos.Y >= dest.Top && pos.X + i.Width <= dest.Right && pos.Y + i.Height <= dest.Bottom) { ++finishedItems; ok = true; } Name += i.Properties.Name + (ok ? "*" : "") + ", "; } Name = Name.Remove(Name.Length - 2); Name = (Name + " to a green area in tile " + map.GetTileForX(DestinationBlocks[0].Coords.X).Index.ToString()); percent = (int)((float)finishedItems / RequiredItems.Count * 100); } else if (Type == QuestType.ReachBlock) { Name = BaseName; //for each point, check whether we've reached it foreach (Zone zone in DestinationBlocks) { bool ok = false; var block = zone.Coords; var newPlayerRect = map.TileToGlobalCoordinates(map.Player.BoundingRectangle, map.GetTileByIndex(map.Player.CurrentTile)); if (GeometryHelper.GetIntersectionDepth(block, newPlayerRect) != Vector2.Zero) { if (!reachedBlocks.Contains(block)) //We only need to reach it once for it to count towards reachedPoints { reachedBlocks.Add(block); zone.Deactivate(); } } if (reachedBlocks.Contains(zone.Coords)) { ok = true; } Name += map.GetTileForX(zone.Coords.X).Index + (ok ? "*" : "") + ", "; } Name = Name.Remove(Name.Length - 2); percent = (int)((float)reachedBlocks.Count / DestinationBlocks.Count * 100); } //Set the display value if (percent == 100) { Progress = "Done"; Completed = true; } else { Progress = percent.ToString() + "%"; } }