115 lines
3.5 KiB
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);
|
|
}
|