I am trying to create vertical moving tiles with the Microsoft Platformer Starter Kit. My platforms can move in one direction; however, they fail to switch direction.
If my platform starts at the top, it scrolls down. Once the platform reaches the bottom, however, it fails to move up. I have an issue with
if (Level.GetCollision(tileX + (int)direction, tileY) ==
in the code below this sentence. It always returns Impassable. Here is my modified code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;
namespace Platformer
{
//http://robotfootgames.com/xna-tutorials/78-xna-platformer-starter-kit-movable-platforms
public class MovableTile
{
private Texture2D texture;
private Vector2 origin;
public Level Level
{
get { return level; }
}
Level level;
public Vector2 Position
{
get { return position; }
}
Vector2 position;
public Vector2 Velocity
{
get { return velocity; }
}
Vector2 velocity;
/// <summary>
/// Gets whether or not the player's feet are on the MovableTile.
/// </summary>
public bool PlayerIsOn { get; set; }
public Rectangle BoundingRectangle
{
get
{
int left = (int)Math.Round(Position.X - ScaleManager.GetNewNumber(origin.X)) + localBounds.X;
int top = (int)Math.Round(Position.Y - ScaleManager.GetNewNumber(origin.Y)) + localBounds.Y;
return new Rectangle(left, top, localBounds.Width,
localBounds.Height);
}
}
public FaceDirection Direction
{
get { return direction; }
set { direction = value; }
}
FaceDirection direction;
public TileCollision Collision
{
get { return collision; }
set { collision = value; }
}
public float WaitTime {
get {return waitTime;}
set {WaitTime = value;}
}
private TileCollision collision;
private Rectangle localBounds;
private float waitTime;
private const float MaxWaitTime = 2.0f;
private float MoveSpeed = ScaleManager.GetNewNumber(120.0f);
public MovableTile(Level level, Vector2 position, TileCollision collision, FaceDirection faceDirection)
{
this.level = level;
this.position = position;
this.collision = collision;
this.direction = faceDirection;
LoadContent();
}
public void LoadContent()
{
texture = collision == TileCollision.Platform ? Level.Content.Load<Texture2D>("Tiles/Platform") : Level.Content.Load<Texture2D>("Tiles/BlockB0");
origin = new Vector2(texture.Width / 2.0f, texture.Height / 2.0f);
localBounds = new Rectangle(0, 0, (int)ScaleManager.GetNewNumber(texture.Width), (int)ScaleManager.GetNewNumber(texture.Height));
}
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)GetVerticalDirection());
Debug.WriteLine((int)direction);
}
}
else
{
// If we are about to run into a wall that is not a MovableTile move in other direction.
if (Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Impassable || Level.GetCollision(tileX + (int)direction, tileY) == TileCollision.Platform)
{
Debug.WriteLine("Collision: " + Level.GetCollision(tileX + (int)direction, tileY));
velocity = new Vector2(0.0f, 0.0f);
waitTime = MaxWaitTime;
}
else
{
// Move in the current direction.
int newDirection = GetVerticalDirection();
if(direction == FaceDirection.Left || direction == FaceDirection.Right)
{
velocity = new Vector2((int)direction * MoveSpeed * elapsed, 0.0f);
}
else
{
velocity = new Vector2(0.0f, (int)newDirection * MoveSpeed * elapsed);
}
//I need to make velocity.x an even number. otherwise, the tile and player move at different speeds.
//this causes the player to fall off or glide on the tile, depending on the device
position = position + new Vector2(Convert.ToInt32(velocity.X), Convert.ToInt32(velocity.Y));
}
}
if (level.movableTiles.Count > 0)
{
// If we are 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);
}
}
}
}
}
public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, Position, null, Color.White, 0.0f, origin, ScaleManager.GetNewNumber(1f), SpriteEffects.None, 0.0f);
}
public int GetVerticalDirection()
{
int newDirection = 0;
//get direction
if(direction == FaceDirection.Up)
{
newDirection = 1;
}
else if(direction == FaceDirection.Down)
{
newDirection = -1;
}
else
{
newDirection = (int)direction;
}
return newDirection;
}
}
}
