diff options
author | Julien Dessaux | 2022-08-14 14:33:29 +0200 |
---|---|---|
committer | Julien Dessaux | 2022-08-14 14:33:29 +0200 |
commit | b951f4de71d47d17a22265b1ea336e67fedeba7a (patch) | |
tree | e224c99bf1311ee7ac6efcecbfbb366b581c844b /src | |
parent | Added lib spoon submodule (diff) | |
download | grenade-brothers-b951f4de71d47d17a22265b1ea336e67fedeba7a.tar.gz grenade-brothers-b951f4de71d47d17a22265b1ea336e67fedeba7a.tar.bz2 grenade-brothers-b951f4de71d47d17a22265b1ea336e67fedeba7a.zip |
Wrote initial game objects
Diffstat (limited to '')
-rw-r--r-- | src/brothers.zig | 46 | ||||
-rw-r--r-- | src/game.zig | 22 | ||||
-rw-r--r-- | src/main.zig | 80 | ||||
-rw-r--r-- | src/playfield.zig | 38 |
4 files changed, 186 insertions, 0 deletions
diff --git a/src/brothers.zig b/src/brothers.zig new file mode 100644 index 0000000..b221ddc --- /dev/null +++ b/src/brothers.zig @@ -0,0 +1,46 @@ +const std = @import("std"); +const spoon = @import("spoon"); + +pub const Side = enum(u1) { + left, + right, +}; + +const startingX = [2]f64{ 15, 60 }; +const colors = [2]spoon.Attribute.Colour{ .blue, .red }; + +pub const Brother = struct { + side: Side, + x: f64, + y: f64, + dx: f64, + dy: f64, + pub fn reset(self: *Brother, side: ?Side) void { + if (side) |s| { + self.side = s; + } + self.x = startingX[@enumToInt(self.side)]; + self.y = 17; + self.dx = 0; + self.dy = 0; + } + pub fn draw(self: Brother, rc: *spoon.Term.RenderContext) !void { + try rc.setAttribute(.{ .fg = colors[@enumToInt(self.side)] }); + var iter = std.mem.split(u8, brother, "\n"); + var y = @floatToInt(usize, std.math.round(self.y)); + var x = @floatToInt(usize, std.math.round(self.x)); + while (iter.next()) |line| : (y += 1) { + try rc.moveCursorTo(y, x); + _ = try rc.buffer.writer().write(line); + } + } +}; + +const brother = + \\█ █ + \\█ █ █ + \\█████ + \\█████ + \\█ █ + \\█ █ +; diff --git a/src/game.zig b/src/game.zig new file mode 100644 index 0000000..fc64001 --- /dev/null +++ b/src/game.zig @@ -0,0 +1,22 @@ +const std = @import("std"); +const spoon = @import("spoon"); + +const brothers = @import("brothers.zig"); +const playfield = @import("playfield.zig"); + +pub const Game = struct { + brothers: [2]brothers.Brother = undefined, + character: ?brothers.Side = undefined, + pub fn draw(self: Game, rc: *spoon.Term.RenderContext) !void { + try playfield.draw(rc); + try self.brothers[0].draw(rc); + try self.brothers[1].draw(rc); + } + pub fn reset(self: *Game) void { + self.resetRound(); + } + pub fn resetRound(self: *Game) void { + self.brothers[0].reset(brothers.Side.left); + self.brothers[1].reset(brothers.Side.right); + } +}; diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..cec8688 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,80 @@ +const std = @import("std"); +const spoon = @import("spoon"); + +const game = @import("game.zig"); + +var term: spoon.Term = undefined; +var done: bool = false; + +//----- Game State ----------------------------------------------------------- +var gs: game.Game = undefined; + +//----- Main ----------------------------------------------------------------- +pub fn main() !void { + try term.init(); + defer term.deinit(); + + std.os.sigaction(std.os.SIG.WINCH, &std.os.Sigaction{ + .handler = .{ .handler = handleSigWinch }, + .mask = std.os.empty_sigset, + .flags = 0, + }, null); + + var fds: [1]std.os.pollfd = undefined; + fds[0] = .{ + .fd = term.tty.handle, + .events = std.os.POLL.IN, + .revents = undefined, + }; + + try term.uncook(.{}); + defer term.cook() catch {}; + + try term.fetchSize(); + try term.setWindowTitle("Grenade Brothers", .{}); + + gs.reset(); + try renderAll(); + + var buf: [16]u8 = undefined; + while (!done) { + _ = try std.os.poll(&fds, 100); + + const read = try term.readInput(&buf); + var it = spoon.inputParser(buf[0..read]); + while (it.next()) |in| { + if (in.eqlDescription("escape") or in.eqlDescription("q")) { + done = true; + break; + } + } + } +} + +fn renderAll() !void { + var rc = try term.getRenderContext(); + defer rc.done() catch {}; + + try rc.clear(); + + if (term.width < 80 or term.width < 24) { + try rc.setAttribute(.{ .fg = .red, .bold = true }); + try rc.writeAllWrapping("Terminal too small!"); + return; + } + + try gs.draw(&rc); +} + +fn handleSigWinch(_: c_int) callconv(.C) void { + term.fetchSize() catch {}; + renderAll() catch {}; +} + +/// Custom panic handler, so that we can try to cook the terminal on a crash, +/// as otherwise all messages will be mangled. +pub fn panic(msg: []const u8, trace: ?*std.builtin.StackTrace) noreturn { + @setCold(true); + term.cook() catch {}; + std.builtin.default_panic(msg, trace); +} diff --git a/src/playfield.zig b/src/playfield.zig new file mode 100644 index 0000000..3878323 --- /dev/null +++ b/src/playfield.zig @@ -0,0 +1,38 @@ +const std = @import("std"); +const spoon = @import("spoon"); + +pub fn draw(rc: *spoon.Term.RenderContext) !void { + var iter = std.mem.split(u8, field, "\n"); + var y: usize = 0; + while (iter.next()) |line| : (y += 1) { + try rc.moveCursorTo(y, 0); + _ = try rc.buffer.writer().write(line); + } +} + +const field = + \\████████████████████████████████████████████████████████████████████████████████ + \\█ ██ █ + \\████████████████████████████████████████████████████████████████████████████████ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\█ ██ █ + \\████████████████████████████████████████████████████████████████████████████████ +; |