/// <summary> /// Paces back and forth along a platform, waiting at either end. /// </summary> public void Update(GameTime gameTime) { float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; // Calculate tile position based on the side we are walking towards. float posX = Position.X + localBounds.Width / 2 * (int)direction; int tileX = (int)Math.Floor(posX / Tile.Width) - (int)direction; int tileY = (int)Math.Floor(Position.Y / Tile.Height); if (waitTime > 0) { // Wait for some amount of time. waitTime = Math.Max(0.0f, waitTime - (float)gameTime.ElapsedGameTime.TotalSeconds); if (waitTime <= 0.0f) { // Then turn around. direction = (FaceDirection)(-(int)direction); } } else { // If we are about to run into a wall or off a cliff, start waiting. if (Level.GetCollision(tileX + (int)direction, tileY - 1) == TileCollision.Impassable || Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Passable) { waitTime = MaxWaitTime; } else { // Move in the current direction. Vector2 velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f); position = position + velocity; } } }
/// <summary> /// Paces back and forth along a platform, waiting at either end. /// </summary> public void Update(GameTime gameTime) { //Change orientation and position to player position if (possessed) { System.Diagnostics.Debug.WriteLine(this.direction); if (player.pubMove == 1) { this.direction = FaceDirection.Right; } else if (player.pubMove == -1) { this.direction = FaceDirection.Left; } else { this.direction = FaceDirection.Idle; } this.position = player.Position; } else { float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; // Calculate tile position based on the side we are walking towards. float posX = Position.X + localBounds.Width / 2 * (int)direction; int tileX = (int)Math.Floor(posX / Tile.Width) - (int)direction; int tileY = (int)Math.Floor(Position.Y / Tile.Height); if (waitTime > 0) { // Wait for some amount of time. waitTime = Math.Max(0.0f, waitTime - (float)gameTime.ElapsedGameTime.TotalSeconds); if (waitTime <= 0.0f) { // Then turn around. direction = (FaceDirection)(-(int)direction); } } else { // If we are about to run into a wall or off a cliff, start waiting. if (Level.GetCollision(tileX + (int)direction, tileY - 1) == TileCollision.Impassable || Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Passable) { waitTime = MaxWaitTime; } else { // Move in the current direction. Vector2 velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f); position = position + velocity; } } } }
public void Update(GameTime gameTime) { float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; // Calculate tile position based on the side we are moving towards. float posX = Position.X + localBounds.Width / 2 * (int)direction; int tileX = (int)Math.Floor(posX / Tile.Width) - (int)direction; int tileY = (int)Math.Floor(Position.Y / Tile.Height); if (waitTime > 0) { // Wait for some amount of time. waitTime = Math.Max(0.0f, waitTime - (float)gameTime.ElapsedGameTime.TotalSeconds); if (waitTime <= 0.0f) { // Then turn around. direction = (FaceDirection)(-(int)direction); } } else { //If we're about to run into a wall that isn't a MovableTile move in other direction. if (Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Impassable || Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Platform) { velocity = new Vector2(0.0f, 0.0f); waitTime = MaxWaitTime; } else { // Move in the current direction. velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f); position = position + velocity; } } if (level.movableTiles.Count > 0) { //If we're about to run into a MovableTile move in other direction. foreach (var movableTile in level.movableTiles) { if (BoundingRectangle != movableTile.BoundingRectangle) { if (BoundingRectangle.Intersects(movableTile.BoundingRectangle)) { direction = (FaceDirection)(-(int)direction); velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f); } } } } }
/// <summary> /// Detects and resolves all collisions between the player and his neighboring /// tiles. When a collision is detected, the player is pushed away along one /// axis to prevent overlapping. There is some special logic for the Y axis to /// handle platforms which behave differently depending on direction of movement. /// </summary> private void HandleCollisions() { // Get the player's bounding rectangle and find neighboring tiles. Rectangle bounds = BoundingRectangle; int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width); int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1; int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height); int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1; // Reset flag to search for ground collision. isOnGround = false; // For each potentially colliding tile, for (int y = topTile; y <= bottomTile; ++y) { for (int x = leftTile; x <= rightTile; ++x) { // If this tile is collidable, TileCollision collision = Level.GetCollision(x, y); if (collision != TileCollision.Passable) { // Determine collision depth (with direction) and magnitude. Rectangle tileBounds = Level.GetBounds(x, y); Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds); if (depth != Vector2.Zero) { float absDepthX = Math.Abs(depth.X); float absDepthY = Math.Abs(depth.Y); // Resolve the collision along the shallow axis. if (absDepthY < absDepthX || collision == TileCollision.Platform) { // If we crossed the top of a tile, we are on the ground. if (previousBottom <= tileBounds.Top) { isOnGround = true; } // Ignore platforms, unless we are on the ground. if (collision == TileCollision.Impassable || IsOnGround) { // Resolve the collision along the Y axis. Position = new Vector2(Position.X, Position.Y + depth.Y); // Perform further collisions with the new bounds. bounds = BoundingRectangle; } } else if (collision == TileCollision.Impassable) // Ignore platforms. { // Resolve the collision along the X axis. Position = new Vector2(Position.X + depth.X, Position.Y); // Perform further collisions with the new bounds. bounds = BoundingRectangle; } } } } } // Save the new bounds bottom. previousBottom = bounds.Bottom; }
/// <summary> /// Detects and resolves all collisions between the player and his neighboring /// tiles. When a collision is detected, the player is pushed away along one /// axis to prevent overlapping. There is some special logic for the Y axis to /// handle platforms which behave differently depending on direction of movement. /// </summary> private void HandleCollisions() { // Get the player's bounding rectangle and find neighboring tiles. Rectangle bounds = BoundingRectangle; int[] ltArray = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }; int[] rtArray = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; int[] ttArray = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; int[] btArray = { 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; int leftTile = 0; int rightTile = 0; int topTile = 0; int bottomTile = 0; //Vector2 drawPosn = GetDrawPosn(); Vector2 collPosn = GetCollPosn(); //if (drawPosn.X < 0) //{ // leftTile = drawPosn.X < -4 ? -1 : 0; //} //else //{ int idxX = (int)collPosn.X; int quoX = (int)(idxX / Tile.Size.X); int remX = (int)(idxX % Tile.Size.X); if (remX < 0) { remX = 0; } int idxLeftTile = ltArray[remX]; int idxRightTile = rtArray[remX]; leftTile = idxLeftTile + quoX; rightTile = idxRightTile + quoX; //} //if (drawPosn.Y < 0) //{ // topTile = drawPosn.Y < -12 ? -1 : 0; //} //else //{ int idxY = (int)collPosn.Y; int quoY = (int)(idxY / Tile.Size.Y); int remY = (int)(idxY % Tile.Size.Y); // this won't crash at least but will go off the sides if (remY < 0) { remY = 0; } int idxTopTile = ttArray[remY]; int idxBottomTile = btArray[remY]; topTile = idxTopTile + quoY; bottomTile = idxBottomTile + quoY; //} int leftTile2 = (int)Math.Floor((float)bounds.Left / Tile.Width); int rightTile2 = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1; int topTile2 = (int)Math.Floor((float)bounds.Top / Tile.Height); int bottomTile2 = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1; if (leftTile != leftTile2 || rightTile != rightTile2 || topTile != topTile2 || bottomTile != bottomTile2) { //String msg = String.Format("(X,Y)=({0},{1}), L:{2} R:{3} T:{4} B:{5}", (int)position.X, (int)position.Y, leftTile, rightTile, topTile, bottomTile); //String msg = String.Format("BoundL:{0} BoundT:{1} BoundW:{2} BoundH:{3}", bounds.Left, bounds.Top, bounds.Width, bounds.Height); //Logger.Info(msg); } if (shouldLog) { //String msg = String.Format("(X,Y)=({0},{1}), L:{2} R:{3} T:{4} B:{5}", (int) position.X, (int) position.Y, leftTile, rightTile, topTile, bottomTile); //String msg = String.Format("BoundL:{0} BoundT:{1} BoundW:{2} BoundH:{3}", bounds.Left, bounds.Top, bounds.Width, bounds.Height); //Logger.Info(msg); } // Reset flag to search for ground collision. isOnGround = false; // For each potentially colliding tile, for (int y = topTile; y <= bottomTile; ++y) { for (int x = leftTile; x <= rightTile; ++x) { // If this tile is collidable, TileCollision collision = Level.GetCollision(x, y); if (collision != TileCollision.Passable) { // Determine collision depth (with direction) and magnitude. Rectangle tileBounds = Level.GetBounds(x, y); Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds); if (depth != Vector2.Zero) { float absDepthX = Math.Abs(depth.X); float absDepthY = Math.Abs(depth.Y); // Resolve the collision along the shallow axis. if (absDepthY < absDepthX || collision == TileCollision.Platform) { // If we crossed the top of a tile, we are on the ground. if (previousBottom <= tileBounds.Top) { isOnGround = true; } // Ignore platforms, unless we are on the ground. if (collision == TileCollision.Impassable || IsOnGround) { // Resolve the collision along the Y axis. Position = new Vector2(Position.X, Position.Y + depth.Y); // Perform further collisions with the new bounds. bounds = BoundingRectangle; } } else if (collision == TileCollision.Impassable) // Ignore platforms. { // Resolve the collision along the X axis. Position = new Vector2(Position.X + depth.X, Position.Y); // Perform further collisions with the new bounds. bounds = BoundingRectangle; } } } } } // Save the new bounds bottom. previousBottom = bounds.Bottom; }
//private float DoJump(float velocityY, GameTime gameTime) //{ // // If the player wants to jump // if (isJumping) // { // // Begin or continue a jump // if ((!wasJumping && IsOnGround) || jumpTime > 0.0f) // { // //if (jumpTime == 0.0f) // // jumpSound.Play(); // jumpTime += (float)gameTime.ElapsedGameTime.TotalSeconds; // //sprite.PlayAnimation(jumpAnimation); // } // // If we are in the ascent of the jump // if (0.0f < jumpTime && jumpTime <= MaxJumpTime) // { // // Fully override the vertical velocity with a power curve that gives players more control over the top of the jump // velocityY = JumpLaunchVelocity * (1.0f - (float)Math.Pow(jumpTime / MaxJumpTime, JumpControlPower)); // } // else // { // // Reached the apex of the jump // jumpTime = 0.0f; // } // } // else // { // // Continues not jumping or cancels a jump in progress // jumpTime = 0.0f; // } // // wasJumping = isJumping; // return velocityY; //} #endregion private void HandleCollisions() { // Get the player's bounding rectangle and find neighboring tiles. //Rectangle bounds = BoundingRectangle; int boundsLeft = (int)Position.X - halfBoundsWidth; int boundsTop = (int)Position.Y - localBoundsHeight; //int boundsRight = boundsLeft + localBoundsWidth; //int boundsBottom = boundsTop + localBoundsHeight; //int left = (int)Position.X - halfBoundsWidth; //=8 //int top = (int)Position.Y - localBoundsHeight; //=12 //Rectangle bounds2 = new Rectangle(left, top, localBoundsWidth, localBoundsHeight); //int boundsLeft = bounds2.Left; //int boundsRight= bounds2.Right; //int boundsTop = bounds2.Top; //int boundsBottom = bounds2.Bottom; int leftTile = 0; int rightTile = 0; int topTile = 0; int bottomTile = 0; //Vector2 drawPosn = GetDrawPosn(); Vector2 collPosn = GetCollPosn(); int idxX = (int)collPosn.X; int quoX = (int)(idxX / Tile.Size.X); int remX = (int)(idxX % Tile.Size.X); if (remX < 0) { remX = 0; } int idxLeftTile = ltArray[remX]; int idxRightTile = rtArray[remX]; leftTile = idxLeftTile + quoX; rightTile = idxRightTile + quoX; int idxY = (int)collPosn.Y; int quoY = (int)(idxY / Tile.Size.Y); int remY = (int)(idxY % Tile.Size.Y); // this won't crash at least but will go off the sides if (remY < 0) { remY = 0; } int idxTopTile = ttArray[remY]; int idxBottomTile = btArray[remY]; topTile = idxTopTile + quoY; bottomTile = idxBottomTile + quoY; // Reset flag to search for ground collision. isOnGround = false; // For each potentially colliding tile, for (int y = topTile; y <= bottomTile; ++y) { for (int x = leftTile; x <= rightTile; ++x) { // If this tile is collidable, TileCollision collision = Level.GetCollision(x, y); if (collision != TileCollision.Passable) { // Determine collision depth (with direction) and magnitude. int tileBoundsLeft = x * Tile.Width; int tileBoundsTop = y * Tile.Height; Process(boundsLeft, boundsTop, tileBoundsLeft, tileBoundsTop); if (depthX != 0 || depthY != 0) { float absDepthX = Math.Abs(depthX); float absDepthY = Math.Abs(depthY); // Resolve the collision along the shallow axis. if (absDepthY < absDepthX || collision == TileCollision.Platform) { // If we crossed the top of a tile, we are on the ground. if (previousBottom <= tileBoundsTop) { isOnGround = true; } // Ignore platforms, unless we are on the ground. if (collision == TileCollision.Impassable || IsOnGround) { // Resolve the collision along the Y axis. Position = new Vector2(Position.X, Position.Y + depthY); // Perform further collisions with the new bounds. //bounds = BoundingRectangle; boundsLeft = (int)Position.X - halfBoundsWidth; boundsTop = (int)Position.Y - localBoundsHeight; } } else if (collision == TileCollision.Impassable) // Ignore platforms. { // Resolve the collision along the X axis. Position = new Vector2(Position.X + depthX, Position.Y); // Perform further collisions with the new bounds. //bounds = BoundingRectangle; boundsLeft = (int)Position.X - halfBoundsWidth; boundsTop = (int)Position.Y - localBoundsHeight; } } } } } // Save the new bounds bottom. boundsLeft = (int)Position.X - halfBoundsWidth; boundsTop = (int)Position.Y - localBoundsHeight; int boundsBottom = boundsTop + localBoundsHeight; previousBottom = boundsBottom; //previousBottom = bounds.Bottom; }
//private float DoJump(float velocityY, GameTime gameTime) //{ // // If the player wants to jump // if (isJumping) // { // // Begin or continue a jump // if ((!wasJumping && IsOnGround) || jumpTime > 0.0f) // { // //if (jumpTime == 0.0f) // // jumpSound.Play(); // jumpTime += (float)gameTime.ElapsedGameTime.TotalSeconds; // //sprite.PlayAnimation(jumpAnimation); // } // // If we are in the ascent of the jump // if (0.0f < jumpTime && jumpTime <= MaxJumpTime) // { // // Fully override the vertical velocity with a power curve that gives players more control over the top of the jump // velocityY = JumpLaunchVelocity * (1.0f - (float)Math.Pow(jumpTime / MaxJumpTime, JumpControlPower)); // } // else // { // // Reached the apex of the jump // jumpTime = 0.0f; // } // } // else // { // // Continues not jumping or cancels a jump in progress // jumpTime = 0.0f; // } // // wasJumping = isJumping; // return velocityY; //} #endregion private void HandleCollisions() { // Get the player's bounding rectangle and find neighboring tiles. //Rectangle bounds = BoundingRectangle; int boundsLeft = (int)Position.X - halfBoundsWidth; int boundsTop = (int)Position.Y - localBoundsHeight; //int boundsRight = boundsLeft + localBoundsWidth; //int boundsBottom = boundsTop + localBoundsHeight; //int left = (int)Position.X - halfBoundsWidth; //=8 //int top = (int)Position.Y - localBoundsHeight; //=12 //Rectangle bounds2 = new Rectangle(left, top, localBoundsWidth, localBoundsHeight); //int boundsLeft = bounds2.Left; //int boundsRight= bounds2.Right; //int boundsTop = bounds2.Top; //int boundsBottom = bounds2.Bottom; int leftTile = 0; int rightTile = 0; int topTile = 0; int bottomTile = 0; //Vector2 drawPosn = GetDrawPosn(); Vector2 collPosn = GetCollPosn(); int idxX = (int)collPosn.X; int quoX = (int)(idxX / Tile.Size.X); int remX = (int)(idxX % Tile.Size.X); if (remX < 0) { remX = 0; } int idxLeftTile = ltArray[remX]; int idxRightTile = rtArray[remX]; leftTile = idxLeftTile + quoX; rightTile = idxRightTile + quoX; int idxY = (int)collPosn.Y; int quoY = (int)(idxY / Tile.Size.Y); int remY = (int)(idxY % Tile.Size.Y); // this won't crash at least but will go off the sides if (remY < 0) { remY = 0; } int idxTopTile = ttArray[remY]; int idxBottomTile = btArray[remY]; topTile = idxTopTile + quoY; bottomTile = idxBottomTile + quoY; // Reset flag to search for ground collision. isOnGround = false; // CHECK Y pos if (shouldLog) { const int ePosX = 40; float diff = Math.Abs(position.X - ePosX); //float diff = position.X - ePosX; string msg = String.Format("PX:{0} EX:{1} Diff:{2}", position.X, ePosX, diff); Logger.Info(msg); } // CHECK Y pos /* * if (shouldLog) * { * const int enemyTop = 2; * const int enemyBot = 3; * string msg = String.Format("PT:{0} PB:{1} ET:{2} EBR:{3} ", topTile, bottomTile, enemyTop, enemyBot); * //if (topTile == enemyTop) * //{ * // msg += "CHECK1 "; * //} * //if (topTile + 1 == enemyTop) * //{ * // msg += "CHECK2 "; * //} * //if (bottomTile + 0 == enemyTop) * //{ * // msg += "CHECK3 "; * //} * if (bottomTile == enemyBot) * { * msg += "CHECK4 "; * } * //if (bottomTile + 0 == enemyBot - 1) * if (bottomTile == enemyTop) * { * msg += "CHECK5 "; * } * Logger.Info(msg); * } */ // For each potentially colliding tile, for (int y = topTile; y <= bottomTile; ++y) { for (int x = leftTile; x <= rightTile; ++x) { // If this tile is collidable, TileCollision collision = Level.GetCollision(x, y); if (collision != TileCollision.Passable) { // Determine collision depth (with direction) and magnitude. int tileBoundsLeft = x * Tile.Width; int tileBoundsTop = y * Tile.Height; Process(boundsLeft, boundsTop, tileBoundsLeft, tileBoundsTop); if (depthX != 0 || depthY != 0) { float absDepthX = Math.Abs(depthX); float absDepthY = Math.Abs(depthY); // Resolve the collision along the shallow axis. if (absDepthY < absDepthX || collision == TileCollision.Platform) { // If we crossed the top of a tile, we are on the ground. if (previousBottom <= tileBoundsTop) { isOnGround = true; } // Ignore platforms, unless we are on the ground. if (collision == TileCollision.Impassable || IsOnGround) { // Resolve the collision along the Y axis. Position = new Vector2(Position.X, Position.Y + depthY); // Perform further collisions with the new bounds. //bounds = BoundingRectangle; boundsLeft = (int)Position.X - halfBoundsWidth; boundsTop = (int)Position.Y - localBoundsHeight; } } else if (collision == TileCollision.Impassable) // Ignore platforms. { // Resolve the collision along the X axis. Position = new Vector2(Position.X + depthX, Position.Y); // Perform further collisions with the new bounds. //bounds = BoundingRectangle; boundsLeft = (int)Position.X - halfBoundsWidth; boundsTop = (int)Position.Y - localBoundsHeight; } } } } } // Save the new bounds bottom. boundsLeft = (int)Position.X - halfBoundsWidth; boundsTop = (int)Position.Y - localBoundsHeight; int boundsBottom = boundsTop + localBoundsHeight; previousBottom = boundsBottom; //previousBottom = bounds.Bottom; }