make arcade picker
This commit is contained in:
parent
1d9cb6a1f9
commit
c701506d13
1 changed files with 92 additions and 5 deletions
|
|
@ -1,8 +1,95 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const gpa = std.heap.page_allocator;
|
||||||
|
|
||||||
const Conway = @import("conway.zig");
|
const Conway = @import("conway.zig");
|
||||||
|
|
||||||
const games = enum{ conway };
|
const games = enum(u16) {
|
||||||
|
@"Conways Game of Life",
|
||||||
|
};
|
||||||
|
|
||||||
|
fn ui(width: u32, height: u32, writer: *std.Io.Writer) !void {
|
||||||
|
var fd = [_]std.posix.pollfd{.{
|
||||||
|
.fd = std.posix.STDIN_FILENO,
|
||||||
|
.events = std.posix.POLL.IN,
|
||||||
|
.revents = 0
|
||||||
|
}};
|
||||||
|
|
||||||
|
// here we're disabling character echoing and newline requirements on input
|
||||||
|
const oldios = try std.posix.tcgetattr(std.posix.STDIN_FILENO);
|
||||||
|
defer std.posix.tcsetattr(std.posix.STDIN_FILENO, std.posix.TCSA.NOW, oldios) catch {
|
||||||
|
// oh well we've left the terminal in a shitty state, not much we can
|
||||||
|
// do to fix this.
|
||||||
|
};
|
||||||
|
var newios = oldios;
|
||||||
|
|
||||||
|
newios.lflag.ECHO = false;
|
||||||
|
newios.lflag.ICANON = false;
|
||||||
|
try std.posix.tcsetattr(std.posix.STDIN_FILENO, std.posix.TCSA.NOW, newios);
|
||||||
|
|
||||||
|
_ = try writer.write("\x1B[?25l"); // hide cursor
|
||||||
|
var running = true;
|
||||||
|
var cursor_y: i64 = 0;
|
||||||
|
while (running) {
|
||||||
|
try writer.print("\x1B[1;1H\x1B[2J", .{}); // clear
|
||||||
|
|
||||||
|
try writer.print("\x1B[{};{}H", .{(height - 5) / 2, 0}); // y, x
|
||||||
|
try writer.alignBuffer(" @@@@@@ @@@@@@@ @@@@@@@ @@@@@@ @@@@@@@ @@@@@@@@", width, .center, ' ');
|
||||||
|
try writer.alignBuffer("@@! @@@ @@! @@@ !@@ @@! @@@ @@! @@@ @@! ", width, .center, ' ');
|
||||||
|
try writer.alignBuffer("@!@!@!@! @!@!!@! !@! @!@!@!@! @!@ !@! @!!!:! ", width, .center, ' ');
|
||||||
|
try writer.alignBuffer("!!: !!! !!: :!! :!! !!: !!! !!: !!! !!: ", width, .center, ' ');
|
||||||
|
try writer.alignBuffer(" : : : : : : :: :: : : : : :: : : : :: :::", width, .center, ' ');
|
||||||
|
|
||||||
|
cursor_y = @intCast(std.math.clamp(cursor_y, 0, @typeInfo(games).@"enum".fields.len - 1));
|
||||||
|
inline for (@typeInfo(games).@"enum".fields, 0..) |f, i| {
|
||||||
|
try writer.print("\x1B[{};{}H", .{ // y, x
|
||||||
|
((height + i) / 2) + 3,
|
||||||
|
(width - f.name.len) / 2,
|
||||||
|
});
|
||||||
|
try writer.print("{s}{s}\x1B[0m\n", .{
|
||||||
|
if (i == cursor_y) "\x1B[47;30;1m" else "\x1B[40;37m",
|
||||||
|
f.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try writer.flush();
|
||||||
|
|
||||||
|
_ = try std.posix.poll(@constCast(&fd), -1);
|
||||||
|
var buf: [50]u8 = undefined;
|
||||||
|
_ = try std.fs.File.stdin().read(@constCast(&buf));
|
||||||
|
for (buf) |c| switch (c) {
|
||||||
|
'q' => {
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
|
||||||
|
'j' => cursor_y += 1,
|
||||||
|
'k' => cursor_y -= 1,
|
||||||
|
'g' => cursor_y = 1,
|
||||||
|
'G' => cursor_y = @intFromEnum(games.@"Conways Game of Life"),
|
||||||
|
' ' => {
|
||||||
|
// reset the terminal state for the game
|
||||||
|
try std.posix.tcsetattr(std.posix.STDIN_FILENO, std.posix.TCSA.NOW, oldios);
|
||||||
|
_ = try writer.write("\x1B[?25h"); // show cursor
|
||||||
|
defer std.posix.tcsetattr(std.posix.STDIN_FILENO, std.posix.TCSA.NOW, newios) catch {
|
||||||
|
// not much we can do
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (cursor_y) {
|
||||||
|
@intFromEnum(games.@"Conways Game of Life") => try Conway.play(width, height, writer),
|
||||||
|
else => @panic("Game does not exist."),
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = try writer.write("\x1B[?25l"); // hide cursor
|
||||||
|
try writer.flush();
|
||||||
|
},
|
||||||
|
else => break,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Andrew kelly said to not defer writes cause we need to ensure that we
|
||||||
|
// flush properly. He's right.
|
||||||
|
_ = try writer.write("\x1B[?25h"); // show cursor
|
||||||
|
try writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
pub export fn arcade_subcmd(_: *anyopaque, argc: c_int, argv: [*c]u8) callconv(.c) void {
|
pub export fn arcade_subcmd(_: *anyopaque, argc: c_int, argv: [*c]u8) callconv(.c) void {
|
||||||
_ = argc;
|
_ = argc;
|
||||||
|
|
@ -18,8 +105,8 @@ pub export fn arcade_subcmd(_: *anyopaque, argc: c_int, argv: [*c]u8) callconv(.
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
// const title = @embedFile("arcade.txt");
|
const buf: []u8 = gpa.alloc(u8, terminfo.col * terminfo.row) catch @panic("oom");
|
||||||
var buf: [4096]u8 = undefined;
|
const writer = std.fs.File.stdout().writer(buf);
|
||||||
const writer = std.fs.File.stdout().writer(&buf);
|
|
||||||
Conway.play(terminfo.col, terminfo.row, @constCast(&writer.interface)) catch unreachable;
|
ui(terminfo.col, terminfo.row, @constCast(&writer.interface)) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue