|
|
@ -1,4 +1,5 @@ |
|
|
|
using Microsoft.Xna.Framework; |
|
|
|
using Microsoft.Xna.Framework; |
|
|
|
using Microsoft.Xna.Framework.Graphics; |
|
|
|
using Microsoft.Xna.Framework.Input; |
|
|
|
using System; |
|
|
@ -29,19 +30,23 @@ namespace Jumpy { |
|
|
|
this.texture = texture; |
|
|
|
} |
|
|
|
|
|
|
|
private Rectangle Bbox(Point position) { |
|
|
|
return new Rectangle(position.X - spriteWidth, position.Y - 7, spriteWidth * 2, 26); |
|
|
|
} |
|
|
|
|
|
|
|
public void Update( |
|
|
|
GameTime time, History<GamePadState> gamePad, List<Rectangle> collisionTargets) { |
|
|
|
Point oldPosition = position; |
|
|
|
AirState oldAirState = airState; |
|
|
|
UpdateFromGamePad(time, gamePad); |
|
|
|
|
|
|
|
Rectangle oldBbox = new Rectangle(oldPosition.X - spriteWidth, oldPosition.Y - 7, spriteWidth * 2, 26); |
|
|
|
Rectangle playerBbox = new Rectangle(position.X - spriteWidth, position.Y - 7, spriteWidth * 2, 26); |
|
|
|
Rectangle oldBbox = Bbox(oldPosition); |
|
|
|
Rectangle playerBbox = Bbox(position); |
|
|
|
bool standingOnGround = false; |
|
|
|
// TODO: implement https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
|
|
|
|
// e.g. http://members.chello.at/~easyfilter/bresenham.html
|
|
|
|
foreach (var rect in collisionTargets) { |
|
|
|
playerBbox = new Rectangle(position.X - spriteWidth, position.Y - 7, spriteWidth * 2, 26); |
|
|
|
playerBbox = Bbox(position); |
|
|
|
|
|
|
|
// first we check for left-right collisions...
|
|
|
|
if (playerBbox.Intersects(rect)) { |
|
|
@ -51,14 +56,13 @@ namespace Jumpy { |
|
|
|
if (oldBbox.Left >= rect.Right && playerBbox.Left < rect.Right) { |
|
|
|
position.X = rect.Right + spriteWidth; |
|
|
|
} |
|
|
|
playerBbox = new Rectangle(position.X - spriteWidth, position.Y - 7, spriteWidth * 2, 26); |
|
|
|
playerBbox = Bbox(position); |
|
|
|
} |
|
|
|
// after fixing that, we check for hitting our head or hitting the ground.
|
|
|
|
if (playerBbox.Intersects(rect)) { |
|
|
|
if (oldPosition.Y > position.Y) { |
|
|
|
int diff = playerBbox.Top - rect.Bottom; |
|
|
|
position.Y -= diff; |
|
|
|
// ySpeed *= 0.9;
|
|
|
|
} else { |
|
|
|
airState = AirState.Ground; |
|
|
|
int diff = playerBbox.Bottom - rect.Top; |
|
|
@ -91,9 +95,10 @@ namespace Jumpy { |
|
|
|
Debug.AddRect(playerBbox, Color.Yellow); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: refactor input to have a virtual "which directions & buttons were being pressed"
|
|
|
|
// instead of complicated if-statements in this function.
|
|
|
|
// TODO: refactor to use a state-machine.
|
|
|
|
void UpdateFromGamePad(GameTime time, History<GamePadState> gamePad) { |
|
|
|
if (gamePad[0].IsButtonDown(Buttons.A) && gamePad[1].IsButtonUp(Buttons.A) && |
|
|
|
airState == AirState.Ground) { |
|
|
@ -147,44 +152,44 @@ namespace Jumpy { |
|
|
|
position.X = Math.Min(Math.Max(position.X, 0 + spriteWidth), Camera.Width - spriteWidth); |
|
|
|
} |
|
|
|
|
|
|
|
private Point spritePosition(Pose pose, GameTime time) { |
|
|
|
private int spritePosition(Pose pose, GameTime time) { |
|
|
|
int frameNum = (time.TotalGameTime.Milliseconds / 125) % 4; |
|
|
|
if (frameNum == 3) { |
|
|
|
frameNum = 1; |
|
|
|
} |
|
|
|
|
|
|
|
switch (pose) { |
|
|
|
case Pose.Walking: |
|
|
|
return new Point(spriteSize * frameNum + spriteSize * 6, 0); |
|
|
|
case Pose.Crouching: |
|
|
|
return new Point(spriteSize * 7, spriteSize * 2); |
|
|
|
return 6 + frameNum; |
|
|
|
case Pose.Stretching: |
|
|
|
return new Point(spriteSize * frameNum, spriteSize * 2); |
|
|
|
return 18 + frameNum; |
|
|
|
case Pose.Jumping: |
|
|
|
if (jumpTime > 0.25) { |
|
|
|
return new Point(spriteSize * 6, spriteSize); |
|
|
|
return 15; |
|
|
|
} else if (jumpTime > 0) { |
|
|
|
return new Point(spriteSize * 7, spriteSize); |
|
|
|
return 16; |
|
|
|
} else { |
|
|
|
return new Point(spriteSize * 8, spriteSize); |
|
|
|
return 17; |
|
|
|
} |
|
|
|
case Pose.SwordSwing: |
|
|
|
if (swordSwingTime > 0.2) { |
|
|
|
return new Point(spriteSize * 3, spriteSize * 0); |
|
|
|
return 30; |
|
|
|
} else if (swordSwingTime > 0.1) { |
|
|
|
return new Point(spriteSize * 4, spriteSize * 0); |
|
|
|
return 31; |
|
|
|
} else { |
|
|
|
return new Point(spriteSize * 5, spriteSize * 0); |
|
|
|
return 32; |
|
|
|
} |
|
|
|
case Pose.Crouching: |
|
|
|
return 25; |
|
|
|
case Pose.Standing: |
|
|
|
default: |
|
|
|
return new Point(spriteSize * 7, 0); |
|
|
|
return 7; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void Draw(GameTime time, SpriteBatch spriteBatch) { |
|
|
|
Point source = spritePosition(pose, time); |
|
|
|
Rectangle textureSource = new Rectangle(source.X, source.Y, spriteSize, spriteSize); |
|
|
|
// TODO: don't create so many "new" things that could be cached / precomputed.
|
|
|
|
int index = spritePosition(pose, time); |
|
|
|
Rectangle textureSource = new Rectangle(index * spriteSize, 0, spriteSize, spriteSize); |
|
|
|
Vector2 spriteCenter = new Vector2(spriteSize / 2, spriteSize / 2); |
|
|
|
SpriteEffects effect = facing == Facing.Right ? |
|
|
|
SpriteEffects.FlipHorizontally : SpriteEffects.None; |
|
|
|