112 lines
4.1 KiB
Zig
112 lines
4.1 KiB
Zig
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);
|
|
}
|
|
}
|