Player.Update() now uses Bresenham's line algorithm.
This works, but is still a bit hacky. Cleanups to follow soon. GitOrigin-RevId: 597a857a200584fee2c06237d7d7dd10403bdfeb
This commit is contained in:
parent
4410ff137a
commit
946497160b
113
Shared/Player.cs
113
Shared/Player.cs
@ -1,5 +1,6 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SemiColinGames {
|
||||
@ -17,10 +18,12 @@ namespace SemiColinGames {
|
||||
private const int gravity = 2400;
|
||||
|
||||
private const int spriteSize = 48;
|
||||
// TODO: rename to spriteHalfWidth / spriteHalfHeight.
|
||||
private const int spriteWidth = 7;
|
||||
private const int spriteHeight = 13;
|
||||
private readonly Texture2D texture;
|
||||
|
||||
private Point position = new Point(64, 16 * 14);
|
||||
private Point position = new Point(64, 16 * 10);
|
||||
private int jumps = 0;
|
||||
private Facing facing = Facing.Right;
|
||||
private Pose pose = Pose.Jumping;
|
||||
@ -43,65 +46,89 @@ namespace SemiColinGames {
|
||||
}
|
||||
|
||||
private Aabb Box(Point position, int yOffset) {
|
||||
return new Aabb(new Vector2(position.X, position.Y - 7 + 13 + yOffset),
|
||||
new Vector2(spriteWidth, 13));
|
||||
return new Aabb(new Vector2(position.X, position.Y - 7 + spriteHeight + yOffset),
|
||||
new Vector2(spriteWidth, spriteHeight));
|
||||
}
|
||||
|
||||
public void Update(float modelTime, History<Input> input, Rectangle[] collisionTargets) {
|
||||
Point oldPosition = position;
|
||||
Vector2 movement = HandleInput(modelTime, input);
|
||||
position = new Point((int) (oldPosition.X + movement.X), (int) (oldPosition.Y + movement.Y));
|
||||
|
||||
Rectangle oldBbox = Bbox(oldPosition);
|
||||
Rectangle playerBbox = Bbox(position);
|
||||
bool standingOnGround = false;
|
||||
|
||||
// TODO: we shouldn't hardcode the tile sizes here.
|
||||
Vector2 halfBoxSize = new Vector2(World.TileSize / 2, World.TileSize / 2);
|
||||
foreach (var rect in collisionTargets) {
|
||||
Aabb rectBox = new Aabb(
|
||||
// Broad test: remove all collision targets nowhere near the player.
|
||||
List<Rectangle> candidates = new List<Rectangle>();
|
||||
// TODO: This is strictly larger than it needs to be. We could expand only in the actual
|
||||
// direction of movement.
|
||||
Aabb largeBox = new Aabb(
|
||||
new Vector2(position.X, position.Y - 7 + spriteHeight), // current player position
|
||||
new Vector2(spriteWidth + Math.Abs(movement.X), spriteHeight + Math.Abs(movement.Y)));
|
||||
for (int i = 0; i < collisionTargets.Length; i++) {
|
||||
Rectangle rect = collisionTargets[i];
|
||||
Aabb box = new Aabb(
|
||||
new Vector2(rect.X + World.TileSize / 2, rect.Y + World.TileSize / 2), halfBoxSize);
|
||||
Aabb playerBox = Box(position);
|
||||
playerBbox = Bbox(position);
|
||||
|
||||
// first we check for left-right collisions...
|
||||
if (playerBox.Intersect(rectBox) != null) {
|
||||
if (oldBbox.Right <= rect.Left && playerBbox.Right > rect.Left) {
|
||||
position.X = rect.Left - spriteWidth;
|
||||
}
|
||||
if (oldBbox.Left >= rect.Right && playerBbox.Left < rect.Right) {
|
||||
position.X = rect.Right + spriteWidth;
|
||||
}
|
||||
playerBox = Box(position);
|
||||
if (box.Intersect(largeBox) != null) {
|
||||
Debug.AddRect(box, Color.Green);
|
||||
candidates.Add(rect);
|
||||
}
|
||||
// after fixing that, we check for hitting our head or hitting the ground.
|
||||
if (playerBox.Intersect(rectBox) != null) {
|
||||
if (oldPosition.Y > position.Y) {
|
||||
int diff = playerBbox.Top - rect.Bottom;
|
||||
position.Y -= diff;
|
||||
// TODO: set ySpeed = 0 here so that bonking our head actually reduces hangtime?
|
||||
} else {
|
||||
standingOnGround = true;
|
||||
int diff = playerBbox.Bottom - rect.Top;
|
||||
position.Y -= diff;
|
||||
}
|
||||
|
||||
Point[] movePoints = Line.Rasterize(0, 0, (int) movement.X, (int) movement.Y);
|
||||
for (int i = 1; i < movePoints.Length; i++) {
|
||||
int dx = movePoints[i].X - movePoints[i - 1].X;
|
||||
int dy = movePoints[i].Y - movePoints[i - 1].Y;
|
||||
if (dy != 0) {
|
||||
Point newPosition = new Point(position.X, position.Y + dy);
|
||||
Aabb player = Box(newPosition);
|
||||
bool reject = false;
|
||||
foreach (var rect in candidates) {
|
||||
Aabb box = new Aabb(
|
||||
new Vector2(rect.X + World.TileSize / 2, rect.Y + World.TileSize / 2), halfBoxSize);
|
||||
if (box.Intersect(player) != null) {
|
||||
reject = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
playerBox = Box(position, 1);
|
||||
if (playerBox.Intersect(rectBox) != null) {
|
||||
standingOnGround = true;
|
||||
Debug.AddRect(rect, Color.Cyan);
|
||||
} else {
|
||||
Debug.AddRect(rect, Color.Green);
|
||||
if (!reject) {
|
||||
position = newPosition;
|
||||
}
|
||||
}
|
||||
if (dx != 0) {
|
||||
Point newPosition = new Point(position.X + dx, position.Y);
|
||||
Aabb player = Box(newPosition);
|
||||
bool reject = false;
|
||||
foreach (var rect in candidates) {
|
||||
Aabb box = new Aabb(
|
||||
new Vector2(rect.X + World.TileSize / 2, rect.Y + World.TileSize / 2), halfBoxSize);
|
||||
if (box.Intersect(player) != null) {
|
||||
reject = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!reject) {
|
||||
position = newPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool standingOnGround = false;
|
||||
Aabb groundIntersect = Box(position, 1);
|
||||
foreach (var rect in candidates) {
|
||||
Aabb box = new Aabb(
|
||||
new Vector2(rect.X + World.TileSize / 2, rect.Y + World.TileSize / 2), halfBoxSize);
|
||||
if (groundIntersect.Intersect(box) != null) {
|
||||
standingOnGround = true;
|
||||
Debug.AddRect(rect, Color.Cyan);
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
if (standingOnGround) {
|
||||
jumps = 1;
|
||||
ySpeed = 0;
|
||||
Debug.AddRect(playerBbox, Color.Red);
|
||||
ySpeed = -0.0001f;
|
||||
// Debug.AddRect(playerBbox, Color.Red);
|
||||
} else {
|
||||
jumps = 0;
|
||||
Debug.AddRect(playerBbox, Color.Orange);
|
||||
// Debug.AddRect(playerBbox, Color.Orange);
|
||||
}
|
||||
|
||||
if (movement.X > 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user