diff --git a/src/assets/levels/level1.txt b/src/assets/levels/level1.txt index 7d09e4e..841322e 100644 --- a/src/assets/levels/level1.txt +++ b/src/assets/levels/level1.txt @@ -14,8 +14,8 @@ x x x x x xxxxxxxxxx x -x SSSS x -x SSSSS x +x x +x S S S x x P S S S S x xxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff --git a/src/context.zig b/src/context.zig index 36eae93..f6fdbdd 100644 --- a/src/context.zig +++ b/src/context.zig @@ -9,6 +9,8 @@ const Renderer = @import("renderer.zig").Renderer; pub const Context = struct { const DefaultDisplayWidth = 960; const DefaultDisplayHeight = 540; + // const DefaultDisplayWidth = 480; + // const DefaultDisplayHeight = 270; allocator: std.mem.Allocator, palette: Palette = undefined, diff --git a/src/engine/point_f.zig b/src/engine/point_f.zig index baf23a9..e606395 100644 --- a/src/engine/point_f.zig +++ b/src/engine/point_f.zig @@ -6,7 +6,7 @@ pub const PointF = struct { x: f32, y: f32, - pub const Zero = Point{ .x = 0, .y = 0 }; + pub const Zero = PointF{ .x = 0, .y = 0 }; pub fn init(x: f32, y: f32) PointF { return PointF{ .x = x, .y = y }; diff --git a/src/game/game.zig b/src/game/game.zig index f16aba7..9eb6e08 100644 --- a/src/game/game.zig +++ b/src/game/game.zig @@ -23,7 +23,7 @@ pub const Game = struct { playerIdleAnimation: Animation, playerWalkingAnimation: Animation, playerDirection: Direction, - isPlayerWalking: bool, + playerVelocity: engine.PointF, starAnimation: Animation, @@ -40,7 +40,7 @@ pub const Game = struct { .playerIdleAnimation = Animation.initPartialLoop(renderer.sprites.get("character_lion_48").?, 0.25, 0, 4), .playerWalkingAnimation = Animation.initPartialLoop(renderer.sprites.get("character_lion_48").?, 0.125, 4, 8), .playerDirection = Direction.Right, - .isPlayerWalking = false, + .playerVelocity = engine.PointF.Zero, .starAnimation = Animation.init(renderer.sprites.get("item_star_32").?, 0.15), .renderer = renderer, .randomTile = TileMap(usize).init(allocator), @@ -79,14 +79,49 @@ pub const Game = struct { renderer.textures.get("opaque").?.drawTintedScaled(allegro.mapRgba(127, 127, 127, 127), topLeftScreen.x, topLeftScreen.y, tileSizeScreen, tileSizeScreen); } - pub fn moveCharacter(self: *Game, distance: f32) void { - self.playerPosition.x += distance; - self.isPlayerWalking = true; - self.playerDirection = if (distance > 0) Direction.Right else Direction.Left; + pub fn movePlayer(self: *Game, dt: f32) void { + const to = self.playerPosition.add(self.playerVelocity.multiply(dt)); + self.playerPosition = to; + if (self.playerVelocity.y > 0 and self.playerIsOnTile()) { + self.playerPosition.y = std.math.floor(self.playerPosition.y); + self.playerVelocity.y = 0; + } else if (self.playerVelocity.y < 0 and self.playerIsUnderTile()) { + self.playerPosition.y = std.math.ceil(self.playerPosition.y); + self.playerVelocity.y = -self.playerVelocity.y; + } + if (self.playerVelocity.x != 0) { + const playerTileTop = @floatToInt(i64, std.math.floor(self.playerPosition.y)); + const playerTileBottom = @floatToInt(i64, std.math.floor(self.playerPosition.y + 0.99)); + if (self.playerVelocity.x < 0) { + const playerTileLeft = @floatToInt(i64, std.math.ceil(self.playerPosition.x)) - 1; + if (self.level.tiles.get(playerTileLeft, playerTileTop) != null or self.level.tiles.get(playerTileLeft, playerTileBottom) != null) { + self.playerPosition.x = std.math.ceil(self.playerPosition.x); + self.playerVelocity.x = 0; + } + } + // const playerTileRight = @floatToInt(i64, std.math.floor(self.playerPosition.x)) + 1; + } + self.playerDirection = if (self.playerVelocity.x == 0) self.playerDirection else if (self.playerVelocity.x > 0) Direction.Right else Direction.Left; self.boundsInTiles = Game.calculateBoundsInTiles(self.playerPosition); } + pub fn playerIsOnTile(self: Game) bool { + const playerTileHeight = @floatToInt(i64, std.math.floor(self.playerPosition.y)) + 1; + const playerTileLeft = @floatToInt(i64, std.math.floor(self.playerPosition.x + 0.5)); + const playerTileRight = @floatToInt(i64, std.math.ceil(self.playerPosition.x - 0.5)); + + return self.level.tiles.get(playerTileLeft, playerTileHeight) != null or self.level.tiles.get(playerTileRight, playerTileHeight) != null; + } + + pub fn playerIsUnderTile(self: Game) bool { + const playerTileHeight = @floatToInt(i64, std.math.ceil(self.playerPosition.y)) - 1; + const playerTileLeft = @floatToInt(i64, std.math.floor(self.playerPosition.x + 0.5)); + const playerTileRight = @floatToInt(i64, std.math.ceil(self.playerPosition.x - 0.5)); + + return self.level.tiles.get(playerTileLeft, playerTileHeight) != null or self.level.tiles.get(playerTileRight, playerTileHeight) != null; + } + pub fn randomTileOffset(self: *Game, x: i64, y: i64, maxOffset: usize) usize { if (self.randomTile.get(x, y)) |offset| { return offset; @@ -134,7 +169,8 @@ pub const Game = struct { } pub fn tick(self: *Game, t: f32, dt: f32) void { + _ = t; + _ = self; _ = dt; - self.playerAnimation.tick(t); } }; diff --git a/src/game_scene.zig b/src/game_scene.zig index f28e309..6e76a1e 100644 --- a/src/game_scene.zig +++ b/src/game_scene.zig @@ -26,21 +26,40 @@ pub const GameScene = struct { } pub fn tick(self: *GameScene, ctx: *Context, t: f32, dt: f32) void { - const speed: f32 = 6; // tiles/s + const horizontalWalkAcceleration: f32 = 13; + const gravity: f32 = 71; + const jumpVelocity: f32 = -26; + const maxFallVelocity: f32 = 23; + const maxHorizontalWalkVelocity: f32 = 7; // tiles/s if (ctx.keys.isKeyPressed(allegro.c.ALLEGRO_KEY_LEFT)) { - self.game.moveCharacter(-speed * dt); - self.game.playerWalkingAnimation.tick(t); + self.game.playerVelocity.x = std.math.max(-maxHorizontalWalkVelocity, self.game.playerVelocity.x - horizontalWalkAcceleration); } else if (ctx.keys.isKeyPressed(allegro.c.ALLEGRO_KEY_RIGHT)) { - self.game.moveCharacter(speed * dt); - self.game.playerWalkingAnimation.tick(t); + self.game.playerVelocity.x = std.math.min(maxHorizontalWalkVelocity, self.game.playerVelocity.x + horizontalWalkAcceleration); } else { - if (self.game.isPlayerWalking) { - self.game.playerWalkingAnimation.reset(); + if (std.math.fabs(self.game.playerVelocity.x) > 0.2) { + self.game.playerVelocity.x = self.game.playerVelocity.x - std.math.sign(self.game.playerVelocity.x) * horizontalWalkAcceleration * dt; + } else { + self.game.playerVelocity.x = 0; } - self.game.isPlayerWalking = false; - self.game.playerIdleAnimation.tick(t); } + + if (self.game.playerVelocity.y == 0 and ctx.keys.isKeyPressed(allegro.c.ALLEGRO_KEY_SPACE)) { + self.game.playerVelocity.y = jumpVelocity; + } else if (!self.game.playerIsOnTile()) { + self.game.playerVelocity.y = std.math.min(maxFallVelocity, self.game.playerVelocity.y + gravity * dt); + } + + // self.game.playerVelocity.y = std.math.min(maxFallVelocity, self.game.playerVelocity.y + self.game.playerAcceleration.y * dt); + if (self.game.playerVelocity.x != 0 and self.game.playerVelocity.y == 0) { + self.game.playerWalkingAnimation.tick(t); + self.game.playerIdleAnimation.reset(); + } else if (self.game.playerVelocity.x == 0) { + self.game.playerIdleAnimation.tick(t); + self.game.playerWalkingAnimation.reset(); + } + self.game.movePlayer(dt); + self.game.starAnimation.tick(t); } @@ -113,14 +132,14 @@ pub const GameScene = struct { } const playerDirectionFrameOffset: usize = if (self.game.playerDirection == game.Game.Direction.Left) 0 else 8; - if (self.game.isPlayerWalking) { + if (self.game.playerVelocity.x != 0 and self.game.playerVelocity.y == 0) { self.game.drawSpriteFrameP("character_lion_48", self.game.playerWalkingAnimation.current + playerDirectionFrameOffset, self.game.playerPosition.add(engine.PointF.init(-0.25, -0.25))); } else { self.game.drawSpriteFrameP("character_lion_48", self.game.playerIdleAnimation.current + playerDirectionFrameOffset, self.game.playerPosition.add(engine.PointF.init(-0.25, -0.25))); } if (ctx.showDebug) { - ctx.renderer.printTextV("debug", ctx.palette.background.text, 0.01, 0.1, Renderer.TextAlignment.Left, "Character: ({d}, {d})", .{ self.game.playerPosition.x, self.game.playerPosition.y }); + ctx.renderer.printTextV("debug", ctx.palette.background.text, 0.01, 0.1, Renderer.TextAlignment.Left, "Character: ({d:.2}, {d:.2})", .{ self.game.playerPosition.x, self.game.playerPosition.y }); ctx.renderer.printTextV("debug", ctx.palette.background.text, 0.01, 0.15, Renderer.TextAlignment.Left, "Tiles: ({d}, {d}) -> ({d}, {d})", .{ tileBounds.min.x, tileBounds.min.y, tileBounds.max.x, tileBounds.max.y }); // self.game.debugHighlightTile(self.game.playerPosition); }