public static void MoveDestructableObject(ref Vector2 velocity, ref Vector2 position, int width, int height, ref bool active, float elapsedTime) { #region MOVE HORIZONTALLY //move horizontally position.X += velocity.X * elapsedTime; int topRow = (int)MathHelper.Clamp(position.Y / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); int btmRow = (int)MathHelper.Clamp((position.Y + height - 1) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); int leftCol = (int)MathHelper.Clamp(position.X / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); int rightCol = (int)MathHelper.Clamp((position.X + width - 1) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); //check right-hand side if (velocity.X > 0) { for (int row = topRow; row <= btmRow; row++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[row, rightCol].isSolid()) { position.X = rightCol * Tile.tileSize - width; active = false; return; } } } //check left-hand side else if (velocity.X < 0) { for (int row = topRow; row <= btmRow; row++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[row, leftCol].isSolid()) { position.X = (leftCol + 1) * Tile.tileSize; active = false; return; } } } #endregion #region MOVE VERTICALLY //move vertically velocity.Y += (gravityAcceleration - velocity.Y * airFrictionCoeff) * elapsedTime; position.Y += velocity.Y * elapsedTime; topRow = (int)MathHelper.Clamp(position.Y / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); btmRow = (int)MathHelper.Clamp((position.Y + height - 1) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); leftCol = (int)MathHelper.Clamp(position.X / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); rightCol = (int)MathHelper.Clamp((position.X + width - 1) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); //check bottom if (velocity.Y > 0) { for (int col = leftCol; col <= rightCol; col++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[btmRow, col].isSolid()) { position.Y = btmRow * Tile.tileSize - height; active = false; return; } } } //check top else if (velocity.Y < 0) { for (int col = leftCol; col <= rightCol; col++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[topRow, col].isSolid()) { position.Y = (topRow + 1) * Tile.tileSize; active = false; return; } } } #endregion #region COLLISION WITH MOVING PLATFORMS //coliisions with moving platforms for (int i = 0; i < PlatformsManager.platformsRoomManagers[(int)RoomsManager.CurrentRoom].movingPlatforms.Length; i++) { MovingPlatform p = PlatformsManager.platformsRoomManagers[(int)RoomsManager.CurrentRoom].movingPlatforms[i]; if (!p.Transparent && position.X + width > p.Position.X && position.X < p.Position.X + p.width && position.Y + height - p.Position.Y >= 0 && position.Y + height - p.Position.Y <= velocity.Y * elapsedTime - p.Shift.Y) { position.Y = p.Position.Y - height; active = false; return; } } #endregion }
//move player based on his current velocity and check for collisions with solid tiles static void Move(float elapsedTime) { Vector2 totalSpeed = new Vector2(); #region CHECK IF IS STILL ON THE WALL //CHECK IF IS STILL ON THE WALL int topRow = (int)MathHelper.Clamp(position.Y / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); int btmRow = (int)MathHelper.Clamp((position.Y + height - 0.001f) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); int leftCol = (int)MathHelper.Clamp((position.X - 1) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); int rightCol = (int)MathHelper.Clamp((position.X + 1 + width - 0.001f) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); if (isOnTheWall) { isOnTheWall = false; if (isFacingRight) { for (int row = topRow; row <= btmRow; row++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[row, rightCol].isSolid()) { isOnTheWall = true; } } } else { for (int row = topRow; row <= btmRow; row++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[row, leftCol].isSolid()) { isOnTheWall = true; } } } } #endregion #region CALCULATE VELOCITIES //CALCULATE X VELOCITIES //total speed is a ocnbination of jumpSpeed and movement speed if (isWallJumping) { if (Math.Abs(jumpSpeed.X) > maxHorizontalMovementSpeed) { totalSpeed.X = jumpSpeed.X; } else { if (Math.Sign(jumpSpeed.X) == -Math.Sign(horizontalMovementSpeed)) { if (Math.Abs(jumpSpeed.X) >= maxHorizontalMovementSpeed / 2f) { totalSpeed.X = jumpSpeed.X; } else { isWallJumping = false; jumpSpeed.X = 0; totalSpeed.X = horizontalMovementSpeed; } } else { totalSpeed.X = jumpSpeed.X + horizontalMovementSpeed; totalSpeed.X = MathHelper.Clamp(totalSpeed.X, -maxHorizontalMovementSpeed, maxHorizontalMovementSpeed); } } jumpSpeed.X -= 2f * jumpSpeed.X * Gravity.airFrictionCoeff * elapsedTime;//2 is a magic number } else if (!isTouchingTheGround) { if (Math.Sign(jumpSpeed.X) == -Math.Sign(horizontalMovementSpeed)) { totalSpeed.X = horizontalMovementSpeed; } else if (Math.Abs(jumpSpeed.X) > maxHorizontalMovementSpeed) { totalSpeed.X = jumpSpeed.X; jumpSpeed.X -= 2 * jumpSpeed.X * Gravity.airFrictionCoeff * elapsedTime;//2 is a magic number } else { totalSpeed.X = jumpSpeed.X + horizontalMovementSpeed; totalSpeed.X = MathHelper.Clamp(totalSpeed.X, -maxHorizontalMovementSpeed, maxHorizontalMovementSpeed); jumpSpeed.X -= 6 * jumpSpeed.X * Gravity.airFrictionCoeff * elapsedTime;//6 is a magic number } } else { totalSpeed.X = horizontalMovementSpeed; } horizontalMovementSpeed = 0; if (totalSpeed.X > 0) { isFacingRight = true; } else if (totalSpeed.X < 0) { isFacingRight = false; } //CALCULATE Y VELOCITIES if (!isOnMovingPlatform) { if (isOnTheWall) { if (Gravity.gravityAcceleration - jumpSpeed.Y * Gravity.wallFrictionCoeff > 0) { jumpSpeed.Y += (Gravity.gravityAcceleration - jumpSpeed.Y * Gravity.wallFrictionCoeff) * elapsedTime; } } else { if (Gravity.gravityAcceleration - jumpSpeed.Y * Gravity.airFrictionCoeff > 0) { jumpSpeed.Y += (Gravity.gravityAcceleration - jumpSpeed.Y * Gravity.airFrictionCoeff) * elapsedTime; } } if (jumpSpeed.Y > Gravity.gravityAcceleration * elapsedTime * 15) { isTouchingTheGround = false; isOnMovingPlatform = false; if (currentAnimation != AnimationTypes.die && currentAnimation != AnimationTypes.attack && !isOnTheWall) { currentAnimation = AnimationTypes.fall; } } totalSpeed.Y = jumpSpeed.Y; } else { totalSpeed += PlatformsManager.platformsRoomManagers[(int)RoomsManager.CurrentRoom].movingPlatforms[PlatformsManager.platformIndex].Shift / elapsedTime; } #endregion position.X += totalSpeed.X * elapsedTime; #region CHECK COLLISION WITH SOLID TILES //check collisions with solid tiles topRow = (int)MathHelper.Clamp(position.Y / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); btmRow = (int)MathHelper.Clamp((position.Y + height - 0.001f) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); leftCol = (int)MathHelper.Clamp((position.X - 1) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); rightCol = (int)MathHelper.Clamp((position.X + 1 + width - 0.001f) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); //check right-hand side if (totalSpeed.X >= 0) { for (int row = topRow; row <= btmRow; row++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[row, rightCol].isSolid()) { position.X = rightCol * Tile.tileSize - width; if (!isTouchingTheGround) { isWallJumping = false; if (jumpSpeed.Y > 0 && !isOnTheWall) { jumpSpeed.Y = 0; } if (jumpSpeed.Y > initialJumpSpeed.Y * 0.2f) { isOnTheWall = true; } jumpSpeed.X = 0; } break; } } } //check left-hand side if (totalSpeed.X <= 0) { for (int row = topRow; row <= btmRow; row++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[row, leftCol].isSolid()) { position.X = (leftCol + 1) * Tile.tileSize; if (!isTouchingTheGround) { isWallJumping = false; if (jumpSpeed.Y > 0 && !isOnTheWall) { jumpSpeed.Y = 0; } if (jumpSpeed.Y > initialJumpSpeed.Y * 0.2f) { isOnTheWall = true; } jumpSpeed.X = 0; } break; } } } #endregion position.Y += totalSpeed.Y * elapsedTime; #region CHECK COLLISIONS WITH TILES topRow = (int)MathHelper.Clamp(position.Y / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); btmRow = (int)MathHelper.Clamp((position.Y + height - 0.001f) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomHeightTiles - 1); leftCol = (int)MathHelper.Clamp(position.X / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); rightCol = (int)MathHelper.Clamp((position.X + width - 0.001f) / Tile.tileSize, 0, MapsManager.maps[(int)RoomsManager.CurrentRoom].roomWidthTiles - 1); //check bottom if (totalSpeed.Y > 0) { int span = ((int)(totalSpeed.Y * elapsedTime + Tile.tileSize) / Tile.tileSize); for (int i = span - 1; i >= 0; i--) { for (int col = leftCol; col <= rightCol; col++) { if (btmRow - i < 0) { break; } if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[btmRow - i, col].isSolid()) { position.Y = (btmRow - i) * Tile.tileSize - height; jumpSpeed.Y = 0; jumpSpeed.X = 0; isTouchingTheGround = true; isOnMovingPlatform = false; canDoubleJump = true; isOnTheWall = false; isWallJumping = false; i = 0; break; } } } } //check top else if (totalSpeed.Y < 0) { for (int col = leftCol; col <= rightCol; col++) { if (MapsManager.maps[(int)RoomsManager.CurrentRoom].array[topRow, col].isSolid()) { position.Y = (topRow + 1) * Tile.tileSize; jumpSpeed.Y = 0; isOnMovingPlatform = false; break; } } } #endregion #region CHECK COLLISION WITH MOVING PLATFORM //check collisions with moving platforms if (!isOnMovingPlatform) { for (int i = 0; i < PlatformsManager.platformsRoomManagers[(int)RoomsManager.CurrentRoom].movingPlatforms.Length; i++) { MovingPlatform p = PlatformsManager.platformsRoomManagers[(int)RoomsManager.CurrentRoom].movingPlatforms[i]; if (!p.Transparent && position.X + width > p.Position.X && position.X < p.Position.X + p.width && position.Y + height - p.Position.Y >= 0 && position.Y + height - p.Position.Y <= totalSpeed.Y * elapsedTime - p.Shift.Y) { isOnMovingPlatform = true; position.Y = p.Position.Y - height; jumpSpeed.Y = 0; jumpSpeed.X = 0; PlatformsManager.platformIndex = i; isTouchingTheGround = true; canDoubleJump = true; isOnTheWall = false; isWallJumping = false; return; } } } else { MovingPlatform p = PlatformsManager.platformsRoomManagers[(int)RoomsManager.CurrentRoom].movingPlatforms[PlatformsManager.platformIndex]; if (position.X - p.Position.X <= -width || position.X - p.Position.X >= p.width || p.Transparent) { isOnMovingPlatform = false; } } #endregion }