Skip to content

Commit 811b4ee

Browse files
committed
tweak memory settings, play with iOS audio fixes
1 parent 12abd08 commit 811b4ee

File tree

7 files changed

+57
-23
lines changed

7 files changed

+57
-23
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ This code is interesting, and worth a read for the following reasons :
6868
- It uses the excellent http.zig library https://github.com/karlseguin/http.zig to do all the web stuff. I have had exactly zero issues using this lib.
6969
- Single file binary, which includes the game, a web server, all assets such as HTML, images and audio. 1 file - no litter on your filesystem
7070
- Generated docker image = 770Kb (compressed) All it has is the compiled executable (2.5MB), which includes only a single binary, nothing else.
71-
- Run stats - uses about 60MB RAM and really low CPU %
71+
- Run stats - in ReleaseFast mode running a 2 player game, uses less than 2MB RAM to run, and hardly any CPU. Its pretty resource efficient.
7272
- Its about as simple as doing the same thing in Go, there is really nothing too nasty required in the code.
7373
- The router, and all the HTML contents is part of the Game object ... the implications of this are that it is possible to create 'web components' using this
7474
zig/htmx approach that are all self contained, and can be imported into other projects, without having to know about connecting up routes, or pulling in content. Interesting.

build.zig.zon

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
.dependencies = .{
66
.http = .{
77
.url = "https://github.com/zigster64/http.zig/archive/refs/heads/master.tar.gz",
8-
.hash = "1220a436e7e2e498447d79057194e84c9f7158a8c796dbe721dbe14bb1de5f25c92f",
8+
.hash = "1220acf589a63430b28bdb796f5b923b8ad031fdd30291ec3f151b0982e1909be3e5",
99
},
1010
},
1111
}

src/game.zig

+17-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const all_players: u8 = 100;
1010

1111
const Self = @This();
1212

13-
const MAX_PLAYERS = 8;
13+
pub const MAX_PLAYERS = 8;
1414

1515
const State = enum {
1616
init,
@@ -288,9 +288,9 @@ fn lostAudio(self: *Self, req: *httpz.Request, res: *httpz.Response) !void {
288288
fn calcAudio(self: *Self, player: u8) []const u8 {
289289
if (player == self.current_player) {
290290
return switch (self.player_mode) {
291-
.normal => "<script>yourTurnAudio.play()</script>",
292-
.flipper => "<script>zeroWingAudio.play()</script>",
293-
.nuke => "<script>nukeAudio.play()</script>",
291+
.normal => "<script>yourTurnAudio.volume = 0.8; yourTurnAudio.play()</script>",
292+
.flipper => "<script>zeroWingAudio.volume = 0.7; zeroWingAudio.play()</script>",
293+
.nuke => "<script>nukeAudio.volume = 1; nukeAudio.play()</script>",
294294
};
295295
}
296296
return "";
@@ -393,7 +393,10 @@ fn showBoard(self: *Self, player: u8, res: *httpz.Response) !void {
393393

394394
for (0..self.grid_y) |y| {
395395
for (0..self.grid_x) |x| {
396-
const value = try self.board.get(x, y);
396+
const value = self.board.get(x, y) catch |err| blk: {
397+
std.log.info("get {} {} gives error {}", .{ x, y, err });
398+
break :blk 0;
399+
};
397400

398401
// used square that we cant normally click on
399402
if (value != 0) {
@@ -426,7 +429,7 @@ fn showBoard(self: *Self, player: u8, res: *httpz.Response) !void {
426429
continue;
427430
}
428431

429-
// empty square that we cant click on,because its another player's turn
432+
// empty square that we cant click on,because its not your turn
430433
try w.print(@embedFile("html/board/square.x.html"), .{
431434
.class = "grid-square",
432435
.player = value,
@@ -644,9 +647,14 @@ fn setup(self: *Self, req: *httpz.Request, res: *httpz.Response) !void {
644647
/// events GET handler is an SSE stream that emits events whenever the state changes
645648
/// or a clock event expires. Uses the Game.event_condition to synch with the outer threads
646649
fn events(self: *Self, req: *httpz.Request, res: *httpz.Response) !void {
647-
std.log.info("(event-source) GET /events {}", .{self.state});
650+
const start_time = std.time.timestamp();
651+
std.log.info("(event-source) GET /events {} started at {}", .{self.state, start_time});
648652
_ = req;
649653

654+
errdefer {
655+
std.log.info("(event-source) started at {} now exiting", .{start_time});
656+
}
657+
650658
var stream = try res.startEventStream();
651659

652660
// on initial connect, send the clock details, and send the last event processed
@@ -682,8 +690,8 @@ fn events(self: *Self, req: *httpz.Request, res: *httpz.Response) !void {
682690
defer self.game_mutex.unlock();
683691
std.log.debug("condition fired - last event is {}", .{self.last_event});
684692
if (self.last_event == .login) {
685-
// this is a bit nasty - on a login event, need to wait a short time to let the
686-
// login handler flush itself so the client can get it's new player ID
693+
// this is a bit nasty - on a login event, need to wait a short time to let the
694+
// login handler flush itself so the client can get it's new player ID
687695
// before we signal the frontend that a new login event has happened
688696
std.time.sleep(std.time.ns_per_ms * 200);
689697
}

src/html/header/winner-lost.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<span class="red">You Lost !</span>
2-
<script>lostAudio.play()</script>
2+
<script>lostAudio.volume = 1; lostAudio.play()</script>

src/html/index.html

+16-5
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010
<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script>
1111
<script src="https://unpkg.com/htmx.org/dist/ext/json-enc.js"></script>
1212

13-
<meta name="app-version" version="20230728.4">
14-
<meta fix="use player uuids for security">
15-
<meta fix="maybe fixes the login race condition">
16-
<meta fix="added link to user manual / wiki">
17-
<meta fix="readme updates">
13+
<meta name="app-version" version="20230803.1">
14+
<meta fix="tweak memory settings">
15+
<meta fix="iOS audio fixes">
1816

1917
<link rel="stylesheet" href="styles.css">
2018
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -63,6 +61,19 @@
6361
const victoryAudio = new Audio("audio/victory.mp3")
6462
const lostAudio = new Audio("audio/lost.mp3")
6563

64+
function sing(audio, volume) {
65+
audio.volume = volume;
66+
audio.play();
67+
}
68+
69+
function initAllAudio() {
70+
sing(yourTurnAudio, 1);
71+
sing(zeroWingAudio, 0);
72+
sing(nukeAudio, 0);
73+
sing(victoryAudio, 0);
74+
sing(lostAudio, 0);
75+
}
76+
6677
// Just some minimal vanilla-JS to add a couple of helper functions
6778
function getPlayer() {
6879
return document.getElementById("player").innerText;

src/html/setup/setup_game.x.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<form hx-post="/setup" hx-ext="json-enc">
22
<div>
3-
<input type="range" id="x" name="x" value="{[x]}" min="2" max="15"
3+
<input type="range" id="x" name="x" value="{[x]}" min="2" max="12"
44
oninput="document.getElementById('x-value').textContent = this.value">
55
<span id="x-value">{[x]}</span>
66
<label for="x">Columns</label>
@@ -36,7 +36,7 @@
3636
<label for="nuke">% Chance to set us up the Bomb ?</label>
3737
</div>
3838
<div>
39-
<input class="blue-button" type="button" value="Enable Audio" onclick="yourTurnAudio.play()">
39+
<input class="blue-button" type="button" value="Enable Audio" onclick="initAllAudio()">
4040
</div>
4141
<button class="green-button">Start</button>
4242
</form>

src/main.zig

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@ const std = @import("std");
22
const httpz = @import("httpz");
33
const Game = @import("game.zig");
44

5+
const default_port = 3000;
6+
7+
// always log .info, even in release modes
8+
pub const std_options = struct {
9+
pub const log_level = .info;
10+
};
11+
512
pub fn usage() void {
613
std.debug.print("USAGE: zig-zag-zoe [-p PORTNUMBER]\n", .{});
714
std.debug.print(" or use the PORT env var to set the port, for like Docker or whatever\n", .{});
815
}
916

1017
pub fn main() !void {
11-
var port: u16 = 3000;
18+
var port: u16 = default_port;
1219

1320
var env_port = std.os.getenv("PORT");
1421
if (env_port != null and env_port.?.len > 0) {
1522
port = try std.fmt.parseInt(u16, env_port.?, 10);
16-
std.debug.print("Port set to {} via ENV\n", .{port});
23+
std.log.debug("Port set to {} via ENV\n", .{port});
1724
}
1825

1926
var args = std.process.args();
@@ -37,8 +44,8 @@ pub fn main() !void {
3744
}
3845
}
3946

40-
std.debug.print("Starting Zig-Zag-Zoe server with new game.\n", .{});
41-
std.debug.print("Go to http://localhost:{} to run the game\n", .{port});
47+
std.log.info("Starting Zig-Zag-Zoe server with new game", .{});
48+
std.log.info("Go to http://localhost:{} to run the game", .{port});
4249
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
4350
const allocator = gpa.allocator();
4451

@@ -55,6 +62,14 @@ pub fn main() !void {
5562
var server = try httpz.ServerCtx(*Game, *Game).init(allocator, .{
5663
.address = "0.0.0.0",
5764
.port = port,
65+
.pool_size = Game.MAX_PLAYERS,
66+
.request = .{
67+
.max_body_size = 256,
68+
},
69+
.response = .{
70+
.body_buffer_size = 100_000, // big enough for the biggest audio file
71+
.header_buffer_size = 256,
72+
},
5873
}, &game);
5974
server.notFound(notFound);
6075
server.errorHandler(errorHandler);

0 commit comments

Comments
 (0)