Compare commits
No commits in common. "6c8dd16a972893526673325b00d0a53a0789a7d8" and "07e57c561261dbe5278b2baff9463c89e67275af" have entirely different histories.
6c8dd16a97
...
07e57c5612
6 changed files with 95 additions and 261 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,3 @@
|
||||||
.zig-cache/
|
.zig-cache/
|
||||||
zig-out/
|
zig-out/
|
||||||
zig-pkg/
|
|
||||||
result
|
result
|
||||||
|
|
|
||||||
38
build.zig
38
build.zig
|
|
@ -4,16 +4,6 @@ pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const raylib_dep = b.dependency("raylib_zig", .{
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.linux_display_backend = .Wayland,
|
|
||||||
});
|
|
||||||
|
|
||||||
const raylib = raylib_dep.module("raylib");
|
|
||||||
const raygui = raylib_dep.module("raygui");
|
|
||||||
const raylib_artifact = raylib_dep.artifact("raylib"); // raylib C library
|
|
||||||
|
|
||||||
const mod = b.addModule("sand", .{
|
const mod = b.addModule("sand", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
|
|
@ -27,30 +17,36 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
.{ .name = "sand", .module = mod },
|
.{ .name = "sand", .module = mod },
|
||||||
.{ .name = "raylib", .module = raylib },
|
|
||||||
.{ .name = "raygui", .module = raygui },
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
.use_lld = false,
|
|
||||||
});
|
});
|
||||||
exe.root_module.linkLibrary(raylib_artifact);
|
|
||||||
|
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
const mod_tests = b.addTest(.{
|
const mod_tests = b.addTest(.{
|
||||||
.root_module = mod,
|
.root_module = mod,
|
||||||
});
|
});
|
||||||
|
|
||||||
const run_mod_tests = b.addRunArtifact(mod_tests);
|
const run_mod_tests = b.addRunArtifact(mod_tests);
|
||||||
|
|
||||||
const test_step = b.step("test", "Run tests");
|
const exe_tests = b.addTest(.{
|
||||||
test_step.dependOn(&run_mod_tests.step);
|
|
||||||
|
|
||||||
const exe_check = b.addExecutable(.{
|
|
||||||
.name = "sand",
|
|
||||||
.root_module = exe.root_module,
|
.root_module = exe.root_module,
|
||||||
});
|
});
|
||||||
|
|
||||||
const check = b.step("check", "Check if foo compiles");
|
const run_exe_tests = b.addRunArtifact(exe_tests);
|
||||||
check.dependOn(&exe_check.step);
|
|
||||||
|
const test_step = b.step("test", "Run tests");
|
||||||
|
test_step.dependOn(&run_mod_tests.step);
|
||||||
|
test_step.dependOn(&run_exe_tests.step);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,9 @@
|
||||||
.{
|
.{
|
||||||
.name = .sand,
|
.name = .sand,
|
||||||
.version = "2.0.0",
|
.version = "1.0.0",
|
||||||
.fingerprint = 0xa07a92116fcc91c3, // Changing this has security and trust implications.
|
.fingerprint = 0xa07a92116fcc91c3, // Changing this has security and trust implications.
|
||||||
.minimum_zig_version = "0.16.0",
|
.minimum_zig_version = "0.16.0",
|
||||||
.dependencies = .{
|
.dependencies = .{},
|
||||||
.raylib_zig = .{
|
|
||||||
.url = "git+https://github.com/raylib-zig/raylib-zig?ref=devel#4b6a05cd102d51f00523dd5c5e18e628df359d20",
|
|
||||||
.hash = "raylib_zig-5.6.0-dev-KE8REKNmBQDek2Sz27ULioxYpY9IYR0K0CeIC-iJRLCI",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
|
|
|
||||||
64
flake.nix
64
flake.nix
|
|
@ -14,45 +14,31 @@
|
||||||
let
|
let
|
||||||
forAllSystems =
|
forAllSystems =
|
||||||
f:
|
f:
|
||||||
builtins.foldl' nixpkgs.lib.recursiveUpdate { } (
|
builtins.mapAttrs (system: pkgs: f pkgs zig.packages.${system}.zig_0_16_0) nixpkgs.legacyPackages;
|
||||||
builtins.map (system: f system nixpkgs.legacyPackages.${system} zig.packages.${system}.zig_0_16_0) (
|
|
||||||
builtins.attrNames nixpkgs.legacyPackages
|
|
||||||
)
|
|
||||||
);
|
|
||||||
in
|
in
|
||||||
forAllSystems (
|
{
|
||||||
system: pkgs: zig:
|
devShells = forAllSystems (
|
||||||
let
|
pkgs: zig: {
|
||||||
nativeBuildInputs = with pkgs; [
|
default = pkgs.mkShellNoCC {
|
||||||
wayland-scanner
|
packages = [
|
||||||
pkg-config
|
pkgs.bash
|
||||||
];
|
zig
|
||||||
buildInputs = with pkgs; [
|
zig.zls
|
||||||
libGL
|
];
|
||||||
wayland
|
};
|
||||||
libxkbcommon
|
}
|
||||||
];
|
);
|
||||||
in
|
|
||||||
{
|
|
||||||
devShells.${system}.default = pkgs.mkShellNoCC {
|
|
||||||
packages = [
|
|
||||||
pkgs.bash
|
|
||||||
zig
|
|
||||||
zig.zls
|
|
||||||
];
|
|
||||||
inherit buildInputs;
|
|
||||||
inherit nativeBuildInputs;
|
|
||||||
};
|
|
||||||
|
|
||||||
packages.${system}.default = zig.makePackage {
|
packages = forAllSystems (
|
||||||
pname = "sand";
|
pkgs: zig: {
|
||||||
version = "2.0.0";
|
default = zig.makePackage {
|
||||||
src = ./.;
|
pname = "sand";
|
||||||
zigReleaseMode = "fast";
|
version = "1.0.0";
|
||||||
depsHash = "sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo=";
|
src = ./.;
|
||||||
inherit buildInputs;
|
zigReleaseMode = "fast";
|
||||||
inherit nativeBuildInputs;
|
depsHash = "sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo=";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
104
src/main.zig
104
src/main.zig
|
|
@ -2,98 +2,28 @@ const std = @import("std");
|
||||||
|
|
||||||
const sand = @import("sand");
|
const sand = @import("sand");
|
||||||
|
|
||||||
const raylib = @import("raylib");
|
|
||||||
const raygui = @import("raygui");
|
|
||||||
|
|
||||||
pub fn main(init: std.process.Init) !void {
|
pub fn main(init: std.process.Init) !void {
|
||||||
const screenWidth = 600;
|
var grid: sand.Grid = try .init(4, 4, init.gpa);
|
||||||
const screenHeight = 600;
|
var gridCopy: sand.Grid = try .init(4, 4, init.gpa);
|
||||||
|
|
||||||
var async: [screenHeight]std.Io.Future(void) = undefined;
|
|
||||||
|
|
||||||
var grid: sand.Grid = try .init(screenWidth, screenHeight, init.gpa);
|
|
||||||
defer grid.deinit(init.gpa);
|
defer grid.deinit(init.gpa);
|
||||||
// defer gridCopy.deinit(init.gpa);
|
defer gridCopy.deinit(init.gpa);
|
||||||
//
|
|
||||||
// grid.arr[2][0].alive = true;
|
|
||||||
// grid.arr[2][1].alive = true;
|
|
||||||
// grid.arr[2][2].alive = true;
|
|
||||||
// grid.arr[2][3].alive = true;
|
|
||||||
//
|
|
||||||
// grid.arr[0][1].alive = true;
|
|
||||||
// grid.arr[1][1].alive = true;
|
|
||||||
// grid.arr[1][2].alive = true;
|
|
||||||
//
|
|
||||||
// std.debug.print("{f}\n", .{grid});
|
|
||||||
// try grid.copy(&gridCopy);
|
|
||||||
// grid.updateAll();
|
|
||||||
//
|
|
||||||
// while (!grid.eql(gridCopy)) {
|
|
||||||
// std.debug.print("{f}\n", .{grid});
|
|
||||||
// try grid.copy(&gridCopy);
|
|
||||||
// grid.updateAll();
|
|
||||||
// }
|
|
||||||
|
|
||||||
raylib.initWindow(screenWidth, screenHeight, "sand");
|
grid.arr[2][0].alive = true;
|
||||||
defer raylib.closeWindow();
|
grid.arr[2][1].alive = true;
|
||||||
|
grid.arr[2][2].alive = true;
|
||||||
|
grid.arr[2][3].alive = true;
|
||||||
|
|
||||||
raylib.setTargetFPS(144 * 3);
|
grid.arr[0][1].alive = true;
|
||||||
|
grid.arr[1][1].alive = true;
|
||||||
|
grid.arr[1][2].alive = true;
|
||||||
|
|
||||||
var timeForUpdate: u64 = 0;
|
std.debug.print("{f}\n", .{grid});
|
||||||
var timeForDraw: u64 = 0;
|
try grid.copy(&gridCopy);
|
||||||
|
grid.updateAll();
|
||||||
|
|
||||||
// init grid
|
while (!grid.eql(gridCopy)) {
|
||||||
var random = std.Random.DefaultPrng.init(@bitCast(std.Io.Timestamp.now(init.io, .real).toMicroseconds()));
|
std.debug.print("{f}\n", .{grid});
|
||||||
for (0..300) |y| {
|
try grid.copy(&gridCopy);
|
||||||
for (y..(600 - y)) |x| {
|
grid.updateAll();
|
||||||
grid.arr[y][x] = .{ .alive = random.random().int(u8) > 179 };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const texture: []raylib.Color = try init.gpa.alloc(raylib.Color, screenHeight * screenWidth);
|
|
||||||
defer init.gpa.free(texture);
|
|
||||||
|
|
||||||
const screenImage: raylib.Image = .{
|
|
||||||
.data = @ptrCast(texture.ptr),
|
|
||||||
.width = screenWidth,
|
|
||||||
.height = screenHeight,
|
|
||||||
.mipmaps = 1,
|
|
||||||
.format = .uncompressed_r8g8b8a8,
|
|
||||||
};
|
|
||||||
const screenTexture = try raylib.loadTextureFromImage(screenImage);
|
|
||||||
|
|
||||||
var fps: struct {
|
|
||||||
total: f64,
|
|
||||||
count: f64,
|
|
||||||
} = .{
|
|
||||||
.total = 0,
|
|
||||||
.count = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
while (!raylib.windowShouldClose()) {
|
|
||||||
const updateTimer = std.Io.Clock.now(.awake, init.io);
|
|
||||||
try grid.updateAllConcurrent(init.gpa, init.io, &async);
|
|
||||||
timeForUpdate += @intCast(updateTimer.durationTo(.now(init.io, .awake)).toMicroseconds());
|
|
||||||
|
|
||||||
raylib.beginDrawing();
|
|
||||||
defer raylib.endDrawing();
|
|
||||||
|
|
||||||
const drawTimer = std.Io.Clock.now(.awake, init.io);
|
|
||||||
for (grid.arr, 0..) |line, y| {
|
|
||||||
for (line, 0..) |cell, x| {
|
|
||||||
texture[x + screenWidth * y] = if (cell.alive) .white else .black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
raylib.updateTexture(screenTexture, @ptrCast(texture));
|
|
||||||
raylib.drawTexture(screenTexture, 0, 0, .white);
|
|
||||||
|
|
||||||
timeForDraw += @intCast(drawTimer.durationTo(.now(init.io, .awake)).toMicroseconds());
|
|
||||||
|
|
||||||
fps.count += 1;
|
|
||||||
fps.total += @floatFromInt(raylib.getFPS());
|
|
||||||
std.log.info("fps: {}", .{raylib.getFPS()});
|
|
||||||
}
|
|
||||||
|
|
||||||
std.log.debug("time for draw: {}, time for update: {}", .{ timeForDraw, timeForUpdate });
|
|
||||||
std.log.debug("median fps: {}", .{fps.total / fps.count});
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
140
src/root.zig
140
src/root.zig
|
|
@ -57,46 +57,18 @@ pub const Grid = struct {
|
||||||
allocator.free(self.arr);
|
allocator.free(self.arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateAll(self: *Grid, allocator: std.mem.Allocator) std.mem.Allocator.Error!void {
|
pub fn updateAll(self: *Grid) void {
|
||||||
var newGrid: Grid = try .init(self.max.x + 1, self.max.y + 1, allocator);
|
|
||||||
|
|
||||||
newGrid.leaning = self.leaning.opposite();
|
|
||||||
|
|
||||||
for (0..self.arr.len) |y| {
|
for (0..self.arr.len) |y| {
|
||||||
for (0..self.arr[y].len) |x| {
|
for (0..self.arr[y].len) |x| {
|
||||||
update(.{ .y = @truncate(y), .x = @truncate(x) }, self.*, newGrid);
|
update(.{ .y = @truncate(y), .x = @truncate(x) }, self.*);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.leaning = self.leaning.opposite();
|
||||||
self.deinit(allocator);
|
|
||||||
self.* = newGrid;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn updateAllConcurrent(self: *Grid, allocator: std.mem.Allocator, io: std.Io, async: []std.Io.Future(void)) (std.mem.Allocator.Error || std.Io.ConcurrentError)!void {
|
|
||||||
var newGrid: Grid = try .init(self.max.x + 1, self.max.y + 1, allocator);
|
|
||||||
|
|
||||||
newGrid.leaning = self.leaning.opposite();
|
|
||||||
|
|
||||||
for (0..self.arr.len) |y| {
|
|
||||||
async[y] = try io.concurrent((struct {
|
|
||||||
pub fn updateLine(s: Grid, ng: Grid, fy: usize) void {
|
|
||||||
for (0..s.arr[fy].len) |x| {
|
|
||||||
update(.{ .y = @truncate(fy), .x = @truncate(x) }, s, ng);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).updateLine, .{ self.*, newGrid, y });
|
|
||||||
}
|
|
||||||
for (async) |*a| {
|
|
||||||
a.await(io);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.deinit(allocator);
|
|
||||||
self.* = newGrid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const copyError = error{wrongDimensions};
|
pub const copyError = error{wrongDimensions};
|
||||||
pub fn copy(self: Grid, dest: *Grid) void {
|
pub fn copy(self: Grid, dest: *Grid) copyError!void {
|
||||||
std.debug.assert(self.arr.len == dest.arr.len and self.arr[0].len == dest.arr[0].len);
|
if (self.arr.len != dest.arr.len or self.arr[0].len != dest.arr[0].len) return copyError.wrongDimensions;
|
||||||
for (dest.arr, self.arr) |d, s| {
|
for (dest.arr, self.arr) |d, s| {
|
||||||
@memcpy(d, s);
|
@memcpy(d, s);
|
||||||
}
|
}
|
||||||
|
|
@ -115,87 +87,43 @@ pub const Grid = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn update(self: position, grid: Grid, newGrid: Grid) void {
|
pub fn update(self: position, grid: Grid) void {
|
||||||
alive: switch (false) {
|
if (self.y == grid.max.y) return;
|
||||||
false => {
|
if (!grid.arr[self.y][self.x].alive) return;
|
||||||
std.debug.assert(grid.max == newGrid.max);
|
const nextline = grid.arr[self.y + 1];
|
||||||
if (!grid.arr[self.y][self.x].alive) return;
|
|
||||||
if (self.y == grid.max.y) continue :alive true;
|
|
||||||
const nextline = grid.arr[self.y + 1];
|
|
||||||
const newnextline = newGrid.arr[self.y + 1];
|
|
||||||
|
|
||||||
down: switch (nextline[self.x].alive) {
|
if (@cmpxchgStrong(bool, &nextline[self.x].alive, false, true, .seq_cst, .monotonic)) |_| {
|
||||||
false => {
|
if (self.x == grid.max.x) {
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x].alive, false, true, .seq_cst, .monotonic)) |_| {
|
if (@cmpxchgStrong(bool, &nextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
||||||
continue :down true;
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
|
}
|
||||||
|
} else if (self.x == 0) {
|
||||||
|
if (@cmpxchgStrong(bool, &nextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
||||||
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (grid.leaning) {
|
||||||
|
.Right => {
|
||||||
|
if (@cmpxchgStrong(bool, &nextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {
|
||||||
|
if (@cmpxchgStrong(bool, &nextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
||||||
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true => {
|
.Left => {
|
||||||
if (self.x == grid.max.x) {
|
if (@cmpxchgStrong(bool, &nextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {
|
||||||
if (!nextline[self.x - 1].alive) {
|
if (@cmpxchgStrong(bool, &nextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (self.x == 0) {
|
|
||||||
if (!nextline[self.x + 1].alive) {
|
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (grid.leaning) {
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
.Right => {
|
|
||||||
right: switch (nextline[self.x + 1].alive) {
|
|
||||||
false => {
|
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {
|
|
||||||
continue :right true;
|
|
||||||
} else {
|
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
true => {
|
|
||||||
if (!nextline[self.x - 1].alive) {
|
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.Left => {
|
|
||||||
left: switch (nextline[self.x - 1].alive) {
|
|
||||||
false => {
|
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {
|
|
||||||
continue :left true;
|
|
||||||
} else {
|
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
true => {
|
|
||||||
if (!nextline[self.x + 1].alive) {
|
|
||||||
if (@cmpxchgStrong(bool, &newnextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else {
|
|
||||||
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
continue :alive true;
|
}
|
||||||
},
|
} else {
|
||||||
true => @atomicStore(bool, &newGrid.arr[self.y][self.x].alive, true, .seq_cst),
|
@atomicStore(bool, &grid.arr[self.y][self.x].alive, false, .seq_cst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue