lofivor/src/main.zig

115 lines
3.5 KiB
Zig

const std = @import("std");
const rl = @import("raylib");
const Fixed = @import("fixed.zig").Fixed;
const trig = @import("trig.zig");
const terrain_mod = @import("terrain.zig");
const game = @import("game.zig");
const Terrain = terrain_mod.Terrain;
const GameState = game.GameState;
const Input = game.Input;
const SCREEN_WIDTH = terrain_mod.SCREEN_WIDTH;
const SCREEN_HEIGHT = terrain_mod.SCREEN_HEIGHT;
// colors (vector/oscilloscope aesthetic)
const BG_COLOR = rl.Color{ .r = 10, .g = 10, .b = 18, .a = 255 };
const CYAN = rl.Color{ .r = 0, .g = 255, .b = 255, .a = 255 };
const MAGENTA = rl.Color{ .r = 255, .g = 0, .b = 255, .a = 255 };
const GREEN = rl.Color{ .r = 0, .g = 255, .b = 0, .a = 255 };
const YELLOW = rl.Color{ .r = 255, .g = 255, .b = 0, .a = 255 };
pub fn main() !void {
rl.initWindow(@intCast(SCREEN_WIDTH), @intCast(SCREEN_HEIGHT), "lockstep artillery");
defer rl.closeWindow();
rl.setTargetFPS(60);
// initialize game
const terrain = terrain_mod.generateFixed();
var state = game.initGame(&terrain);
while (!rl.windowShouldClose()) {
// gather input for current player
const input = gatherInput();
// simulate (both players' inputs, but only current player acts)
var inputs: [2]Input = .{ Input.NONE, Input.NONE };
inputs[state.current_turn] = input;
game.simulate(&state, inputs);
// render
rl.beginDrawing();
defer rl.endDrawing();
rl.clearBackground(BG_COLOR);
drawDebugInfo(&state);
}
}
fn gatherInput() Input {
var input = Input.NONE;
// angle: up/down arrows
if (rl.isKeyDown(.up)) input.angle_delta = 1;
if (rl.isKeyDown(.down)) input.angle_delta = -1;
// power: left/right arrows
if (rl.isKeyDown(.right)) input.power_delta = 1;
if (rl.isKeyDown(.left)) input.power_delta = -1;
// fire: space
if (rl.isKeyPressed(.space)) input.fire = true;
return input;
}
fn drawDebugInfo(state: *const GameState) void {
var buf: [256]u8 = undefined;
var y: i32 = 10;
const line_height: i32 = 20;
// tick and turn
const turn_text = std.fmt.bufPrintZ(&buf, "tick: {d} turn: player {d}", .{ state.tick, state.current_turn }) catch "?";
rl.drawText(turn_text, 10, y, 16, rl.Color.white);
y += line_height;
// player 0 info
const p0 = &state.players[0];
const p0_text = std.fmt.bufPrintZ(&buf, "P0: angle={d:.2} power={d:.0} health={d}", .{
p0.cannon_angle.toFloat(),
p0.power.toFloat(),
p0.health,
}) catch "?";
rl.drawText(p0_text, 10, y, 16, CYAN);
y += line_height;
// player 1 info
const p1 = &state.players[1];
const p1_text = std.fmt.bufPrintZ(&buf, "P1: angle={d:.2} power={d:.0} health={d}", .{
p1.cannon_angle.toFloat(),
p1.power.toFloat(),
p1.health,
}) catch "?";
rl.drawText(p1_text, 10, y, 16, MAGENTA);
y += line_height;
// projectile info
if (state.projectile) |proj| {
const proj_text = std.fmt.bufPrintZ(&buf, "projectile: x={d:.1} y={d:.1} vx={d:.2} vy={d:.2}", .{
proj.x.toFloat(),
proj.y.toFloat(),
proj.vx.toFloat(),
proj.vy.toFloat(),
}) catch "?";
rl.drawText(proj_text, 10, y, 16, YELLOW);
} else {
rl.drawText("projectile: none (press SPACE to fire)", 10, y, 16, YELLOW);
}
y += line_height;
// controls
y += line_height;
rl.drawText("controls: UP/DOWN=angle LEFT/RIGHT=power SPACE=fire", 10, y, 14, rl.Color.gray);
}