Player now takes damage from spikes.
GitOrigin-RevId: e9096316218f2590aac74ce1055a0829f71bdff8
This commit is contained in:
parent
a431ad094b
commit
f4581ecaf8
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user