const std = @import("std"); const rl = @import("raylib"); const g = @import("game.zig"); test { _ = g; } pub fn main() !void { const allocator = std.heap.page_allocator; const scaleFactor = 30; var game = try g.Game.create(allocator); defer game.deinit(); const screenWidth = (game.playFieldSize[0] + 1) * scaleFactor; const screenHeight = (game.playFieldSize[1] + 1) * scaleFactor; rl.initWindow(screenWidth, screenHeight, "Snake"); defer rl.closeWindow(); rl.setTargetFPS(60); const tickInterval: f32 = 0.5; const fastTickInterval: f32 = tickInterval / 3.0; var timer: f32 = 0; var isFast = false; while (!rl.windowShouldClose()) { const deltaTime = rl.getFrameTime(); timer += deltaTime; if (game.state == g.State.running) { if (rl.isKeyPressed(.up)) game.setDirection(g.Direction.up); if (rl.isKeyPressed(.down)) game.setDirection(g.Direction.down); if (rl.isKeyPressed(.right)) game.setDirection(g.Direction.right); if (rl.isKeyPressed(.left)) game.setDirection(g.Direction.left); if (rl.isKeyDown(.s)) { if (!isFast) { isFast = true; timer = 0; } } else { isFast = false; } const interval = if (isFast) fastTickInterval else tickInterval; if (timer >= interval) { timer -= interval; try game.tick(); } } else { if (rl.isKeyPressed(.r)) { game.deinit(); game = try g.Game.create(allocator); timer = 0; isFast = false; } } render(game, scaleFactor, screenWidth, screenHeight); } } fn render(game: g.Game, scaleFactor: comptime_int, screenWidth: i32, screenHeight: i32) void { rl.beginDrawing(); defer rl.endDrawing(); rl.clearBackground(.white); const fieldWidth = game.playFieldSize[0] * scaleFactor + scaleFactor; const fieldHeight = game.playFieldSize[1] * scaleFactor + scaleFactor; // Border rl.drawRectangle(0, 0, fieldWidth, scaleFactor, .black); // top rl.drawRectangle(0, 0, scaleFactor, fieldHeight, .black); // left rl.drawRectangle(0, game.playFieldSize[1] * scaleFactor, fieldWidth, scaleFactor, .black); // bottom rl.drawRectangle(game.playFieldSize[0] * scaleFactor, 0, scaleFactor, fieldHeight, .black); // right // Food rl.drawRectangle(game.food[0] * scaleFactor, game.food[1] * scaleFactor, scaleFactor, scaleFactor, .red); // Snake for (game.body.items, 0..) |part, i| { const color: rl.Color = if (i == 0) .green else .dark_green; rl.drawRectangle(part[0] * scaleFactor, part[1] * scaleFactor, scaleFactor, scaleFactor, color); } // Score in top border var scoreBuf: [32]u8 = undefined; const scoreText = std.fmt.bufPrintZ(&scoreBuf, "Score: {d}", .{game.score()}) catch unreachable; rl.drawText(scoreText, scaleFactor + 5, 6, 18, .white); // Game over / win overlays const bigFontSize = 50; const smallFontSize = 22; const restartText = "Press R to restart"; const restartTextWidth = rl.measureText(restartText, smallFontSize); const cx = @divTrunc(screenWidth, 2); const cy = @divTrunc(screenHeight, 2); if (game.state == g.State.lost) { const text = "Game Over!"; const tw = rl.measureText(text, bigFontSize); rl.drawText(text, cx - @divTrunc(tw, 2), cy - @divTrunc(bigFontSize, 2), bigFontSize, .dark_gray); rl.drawText(restartText, cx - @divTrunc(restartTextWidth, 2), cy + @divTrunc(bigFontSize, 2) + 8, smallFontSize, .dark_gray); } if (game.state == g.State.won) { const text = "You Win!"; const tw = rl.measureText(text, bigFontSize); rl.drawText(text, cx - @divTrunc(tw, 2), cy - @divTrunc(bigFontSize, 2), bigFontSize, .dark_gray); rl.drawText(restartText, cx - @divTrunc(restartTextWidth, 2), cy + @divTrunc(bigFontSize, 2) + 8, smallFontSize, .dark_gray); } }