Player now takes damage from spikes.

GitOrigin-RevId: e9096316218f2590aac74ce1055a0829f71bdff8
This commit is contained in:
Colin McMillen 2020-02-27 19:13:34 -05:00
parent a431ad094b
commit f4581ecaf8
5 changed files with 53 additions and 13 deletions

View File

@ -83,10 +83,15 @@ namespace SemiColinGames {
public readonly struct AABB {
public readonly Vector2 Position; // centroid
public readonly Vector2 HalfSize;
public readonly Terrain Terrain;
public AABB(Vector2 position, Vector2 halfSize) {
public AABB(Vector2 position, Vector2 halfSize) : this(position, halfSize, Terrain.Empty) {
}
public AABB(Vector2 position, Vector2 halfSize, Terrain terrain) {
Position = position;
HalfSize = halfSize;
Terrain = terrain;
}
public float Top {

View File

@ -34,12 +34,13 @@ namespace SemiColinGames {
private const int swordSwingMax = 6;
private float ySpeed = 0;
private double jumpTime = 0;
private float invincibilityTime = 0;
public Player() {
Health = MaxHealth;
}
public int MaxHealth { get; private set; } = 5;
public int MaxHealth { get; private set; } = 3;
public int Health { get; private set; }
@ -56,6 +57,8 @@ namespace SemiColinGames {
return BoxOffset(position, 0);
}
invincibilityTime -= modelTime;
Vector2 movement = HandleInput(modelTime, input);
// Broad test: remove all collision targets nowhere near the player.
@ -71,11 +74,12 @@ namespace SemiColinGames {
new Vector2(halfSize.X + Math.Abs(movement.X) + 1, halfSize.Y + Math.Abs(movement.Y) + 1));
foreach (var box in collisionTargets) {
if (box.Intersect(largeBox) != null) {
Debug.AddRect(box, Color.Green);
// Debug.AddRect(box, Color.Green);
candidates.Add(box);
}
}
bool harmedByCollision = false;
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;
@ -86,8 +90,12 @@ namespace SemiColinGames {
bool reject = false;
foreach (var box in candidates) {
if (box.Intersect(player) != null) {
Debug.AddRect(box, Color.Cyan);
reject = true;
break;
if (box.Terrain.IsHarmful) {
Debug.AddRect(box, Color.Red);
harmedByCollision = true;
}
}
}
if (!reject) {
@ -100,8 +108,12 @@ namespace SemiColinGames {
bool reject = false;
foreach (var box in candidates) {
if (box.Intersect(player) != null) {
Debug.AddRect(box, Color.Cyan);
reject = true;
break;
if (box.Terrain.IsHarmful) {
Debug.AddRect(box, Color.Red);
harmedByCollision = true;
}
}
}
if (!reject) {
@ -114,8 +126,12 @@ namespace SemiColinGames {
AABB groundIntersect = BoxOffset(position, 1);
foreach (var box in candidates) {
if (groundIntersect.Intersect(box) != null) {
Debug.AddRect(box, Color.Cyan);
standingOnGround = true;
break;
if (box.Terrain.IsHarmful) {
Debug.AddRect(box, Color.Red);
harmedByCollision = true;
}
}
}
@ -133,6 +149,11 @@ namespace SemiColinGames {
Debug.AddRect(Box(position), Color.Orange);
}
if (harmedByCollision && invincibilityTime <= 0) {
Health -= 1;
invincibilityTime = 0.6f;
}
if (movement.X > 0) {
Facing = 1;
} else if (movement.X < 0) {
@ -242,7 +263,11 @@ namespace SemiColinGames {
Vector2 spriteCenter = new Vector2(spriteWidth / 2, spriteHeight / 2 + spriteCenterYOffset);
SpriteEffects effect = Facing == 1 ?
SpriteEffects.FlipHorizontally : SpriteEffects.None;
spriteBatch.Draw(Textures.Player.Get, position.ToVector2(), textureSource, Color.White, 0f,
Color color = Color.White;
if (invincibilityTime > 0 && invincibilityTime % 0.2f > 0.1f) {
color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
}
spriteBatch.Draw(Textures.Player.Get, position.ToVector2(), textureSource, color, 0f,
spriteCenter, Vector2.One, effect, 0f);
}
}

View File

@ -24,7 +24,7 @@ namespace SemiColinGames {
// attempt to draw the scene. This is a workaround for the fact that otherwise the first few
// frames can be really slow to draw.
int framesToSuppress;
int levelIdx = 0;
int levelIdx = -1;
Scene scene;
Player player;
@ -73,10 +73,10 @@ namespace SemiColinGames {
framesToSuppress = 2;
camera = new Camera();
player = new Player();
levelIdx++;
world = new World(Levels.ALL_LEVELS[levelIdx % Levels.ALL_LEVELS.Length]);
scene?.Dispose();
scene = new Scene(GraphicsDevice, camera);
levelIdx++;
GC.Collect();
GC.WaitForPendingFinalizers();
@ -122,6 +122,10 @@ namespace SemiColinGames {
player.Update(modelTime, input, world.CollisionTargets);
linesOfSight.Update(player, world.CollisionTargets);
camera.Update(player.Position, world.Width);
if (player.Health <= 0) {
world = new World(Levels.ALL_LEVELS[levelIdx % Levels.ALL_LEVELS.Length]);
player = new Player();
}
}
base.Update(gameTime);

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace SemiColinGames {
class TextureRef {
public class TextureRef {
private static readonly List<TextureRef> allTextures = new List<TextureRef>();
public static void LoadAll(ContentManager content) {
@ -28,7 +28,7 @@ namespace SemiColinGames {
}
}
static class Textures {
public static class Textures {
public static SpriteFont DebugFont;
public static SpriteFont BannerFont;

View File

@ -6,7 +6,7 @@ using System.Linq;
namespace SemiColinGames {
class Terrain {
public class Terrain {
public static Terrain FromSymbol(char symbol) {
if (mapping.ContainsKey(symbol)) {
@ -18,6 +18,7 @@ namespace SemiColinGames {
private readonly static Dictionary<char, Terrain> mapping = new Dictionary<char, Terrain>();
public static Terrain Empty = new Terrain('\0', false, Textures.Grassland, 0, 0);
public static Terrain Grass = new Terrain('=', true, Textures.Grassland, 3, 0);
public static Terrain GrassL = new Terrain('<', true, Textures.Grassland, 2, 0);
public static Terrain GrassR = new Terrain('>', true, Textures.Grassland, 4, 0);
@ -49,6 +50,7 @@ namespace SemiColinGames {
public static Terrain Mushroom = new Terrain('t', false, Textures.Grassland, 17, 2);
public bool IsObstacle { get; private set; }
public bool IsHarmful { get; private set; } = false;
public TextureRef Texture { get; private set; }
public Rectangle TextureSource { get; private set; }
@ -58,6 +60,10 @@ namespace SemiColinGames {
}
mapping[symbol] = this;
IsObstacle = isObstacle;
// TODO: don't hard-code just the one spike.
if (symbol == '^') {
IsHarmful = true;
}
Texture = texture;
int size = World.TileSize;
TextureSource = new Rectangle(x * size, y * size, size, size);
@ -138,7 +144,7 @@ namespace SemiColinGames {
for (int i = 0; i < tiles.Length; i++) {
Vector2 center = new Vector2(
tiles[i].Position.Left + halfSize.X, tiles[i].Position.Top + halfSize.Y);
CollisionTargets[i + 1] = new AABB(center, halfSize);
CollisionTargets[i + 1] = new AABB(center, halfSize, tiles[i].Terrain);
}
// Add a final synthetic collisionTarget on the right side of the world.