Im trying to learn monogame by making a simple platformer, and currently at the point where i need to handle collisions. I’m currently using TiledCs to draw the map from tsk then assigning the tiles on a specific layer to a TileCollider class. To handle the bounds of the tiles and player im using Monogame.extended using RectangleF.
Currently when i run the game the player will fall and land on the ground but then snap below the tile.
if the player lands on the gem it will constantly bounce.
Here is what the issue looks like
This is with the colliders being drawn
Here is the actual code. Any tips or ways to fix this would greatly be appreciated. if you need more info please let me know so i can provide it.
Giving the tiles a Collider:
foreach (var property in tile.properties)
{
if (property.name == "HasCollision" && property.value == "true")
{
var tileBounds = new RectangleF(x, y, _tileWidth, _tileHeight);
var tileCollisionActor = new TileColliderWrapper(tile, (RectangleF)tileBounds, ECollisionType.Solid);
Globals.CollidersInLevel.Add(tileCollisionActor);
}
}
The Collider Interface:
public interface ICollider
{
public ECollisionType CollisionType { get; }
RectangleF Bounds { get; }
}
The Tile Collider class
public class TileColliderWrapper : ICollider
{
private TiledTile _tile;
public RectangleF Bounds { get; }
public ECollisionType CollisionType { get; }
public TileColliderWrapper(TiledTile tile, RectangleF bounds, ECollisionType collisionType)
{
Bounds = bounds;
_tile = tile;
CollisionType = collisionType;
}
}
Then in the player i do a check for each tile in the player bounds. The bounds of the player is held in the Sprite from monogame.extended.
This is the entire player code besides the draw function (not sure if thats needed for help)
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
//_velocity.Y += GRAVITY * (float)gameTime.ElapsedGameTime.TotalSeconds;
HandleInputs(gameTime);
}
private void HandleInputs(GameTime gameTime)
{
var keyboardState = Keyboard.GetState();
var deltaSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;
if (keyboardState.IsKeyDown(Keys.A)) Velocity.X = -MoveSpeed;
else if (keyboardState.IsKeyDown(Keys.D)) Velocity.X = MoveSpeed;
else Velocity.X = 0;
Velocity.Y += GRAVITY * deltaSeconds;
if (keyboardState.IsKeyDown(Keys.Space) && _onGround)
{
Velocity.Y = -JUMP;
}
UpdatePosition(gameTime, deltaSeconds);
}
private void UpdatePosition(GameTime gameTime, float deltaSeconds)
{
_onGround = false;
var newPos = this.Transform.Position + (Velocity * deltaSeconds);
foreach (var collider in GetNearestColliders())
{
var colliderRect = (RectangleF)collider.Bounds;
//Check for collision horizontally
if (Math.Abs(newPos.X - this.Transform.Position.X) > 5f)
{
if (GetBounds().Intersects(colliderRect))
{
if (newPos.X > this.Transform.Position.X) newPos.X = colliderRect.Left - GetBounds().Width + OFFSET;
else newPos.X = colliderRect.Right - OFFSET;
continue;
}
}
//Check for collision vertically
if (GetBounds().Intersects(colliderRect))
{
if (Velocity.Y > 0)
{
newPos.Y = colliderRect.Top - GetBounds().Height;
_onGround = true;
Velocity.Y = 0;
}
else
{
newPos.Y = colliderRect.Bottom;
Velocity.Y = 0;
}
}
}
this.Transform.Position = newPos;
Sprite.Update(deltaSeconds);
}
public List<ICollider> GetNearestColliders()
{
return Globals.CollidersInLevel.Where(colliders => GetBounds().Intersects(colliders.Bounds)).ToList();
}
}