colors wow

This commit is contained in:
Dario48 2026-04-20 00:41:51 +02:00
commit ef2679d872
2 changed files with 200 additions and 179 deletions

View file

@ -1,6 +1,16 @@
const std = @import("std"); const std = @import("std");
const sand = @import("sand"); const s = @import("sand");
// const colorType = packed struct {
// r: u8,
// g: u8,
// b: u8,
// };
//
// const sand = s.init(colorType, .{ .r = 0, .g = 0, .b = 0 });
const sand = s.init(u9, 0);
const pow = std.math.pow; const pow = std.math.pow;
@ -48,6 +58,8 @@ pub fn main(init: std.process.Init) !void {
var placeChace: u8 = 250; var placeChace: u8 = 250;
var slider: u9 = 1;
raylib.setTargetFPS(50); raylib.setTargetFPS(50);
var timeForUpdate: u64 = 0; var timeForUpdate: u64 = 0;
@ -84,10 +96,11 @@ pub fn main(init: std.process.Init) !void {
const drawTimer = std.Io.Clock.now(.awake, init.io); const drawTimer = std.Io.Clock.now(.awake, init.io);
for (grid.arr, 0..) |line, y| { for (grid.arr, 0..) |line, y| {
for (line, 0..) |cell, x| { for (line, 0..) |cell, x| {
texture[x + screenWidth * y] = if (cell.alive) //texture[x + screenWidth * y] = if (!(cell == sand.dead))
raylib.Color.init(@truncate((255 * y) / screenHeight), @truncate((255 * x) / screenWidth), 0, 255) // raylib.Color.init(@truncate((255 * y) / screenHeight), @truncate((255 * x) / screenWidth), 0, 255)
else //else
.black; // .black;
texture[x + screenWidth * y] = if (cell == 0) .black else raylib.Color.fromHSV(cell - 1, 1, 1);
} }
} }
@ -115,19 +128,20 @@ pub fn main(init: std.process.Init) !void {
if (circleAsyncArray) |_| {} else circleAsyncArray = try init.gpa.alloc(std.Io.Future(void), xend - xstart); if (circleAsyncArray) |_| {} else circleAsyncArray = try init.gpa.alloc(std.Io.Future(void), xend - xstart);
for (xstart..xend, 0..) |x, i| { for (xstart..xend, 0..) |x, i| {
circleAsyncArray.?[i] = init.io.async((struct { circleAsyncArray.?[i] = init.io.async((struct {
pub fn l(IP: raylib.Vector2, IS: f32, fx: usize, rand: *std.Random.DefaultPrng, gr: sand.Grid, pc: u8) void { pub fn l(IP: raylib.Vector2, IS: f32, fx: usize, rand: *std.Random.DefaultPrng, gr: sand.Grid, pc: u8, slid: u9) void {
const ystart: usize = @intCast(@max(0, @as(i32, @trunc(IP.y - IS)))); const ystart: usize = @intCast(@max(0, @as(i32, @trunc(IP.y - IS))));
const yend: usize = @intCast(@max(0, @as(i32, @trunc(IP.y + IS)))); const yend: usize = @intCast(@max(0, @as(i32, @trunc(IP.y + IS))));
for (ystart..yend) |y| { for (ystart..yend) |y| {
const dx = @as(f32, @floatFromInt(fx)) - IP.x; const dx = @as(f32, @floatFromInt(fx)) - IP.x;
const dy = @as(f32, @floatFromInt(y)) - IP.y; const dy = @as(f32, @floatFromInt(y)) - IP.y;
if (fx >= screenWidth or y >= screenHeight) {} else if (pow(f32, dx, 2) + pow(f32, dy, 2) <= pow(f32, IS, 2) and rand.random().int(u8) > pc) if (fx >= screenWidth or y >= screenHeight) {} else if (pow(f32, dx, 2) + pow(f32, dy, 2) <= pow(f32, IS, 2) and rand.random().int(u8) > pc)
gr.arr[y][fx].alive = true; gr.arr[y][fx] = slid;
} }
} }
}).l, .{ IndicatorPosition, IndicatorSize, x, &random, grid, placeChace }); }).l, .{ IndicatorPosition, IndicatorSize, x, &random, grid, placeChace, slider });
} }
} }
slider = (slider % 361) + 1;
} }
if (circleAsyncArray) |arr| { if (circleAsyncArray) |arr| {
for (arr) |*a| { for (arr) |*a| {

View file

@ -2,7 +2,6 @@
const std = @import("std"); const std = @import("std");
const Io = std.Io; const Io = std.Io;
pub const state = enum(u1) { Alive, Dead };
pub const leaning = enum(u1) { pub const leaning = enum(u1) {
Left = 0, Left = 0,
Right = 1, Right = 1,
@ -10,211 +9,219 @@ pub const leaning = enum(u1) {
return @enumFromInt(@intFromBool(self == .Left)); return @enumFromInt(@intFromBool(self == .Left));
} }
}; };
pub const cell = struct { //pub const cell = struct {
alive: bool, // alive: state,
}; //};
pub const position = packed struct { pub const position = packed struct {
x: u16, x: u16,
y: u16, y: u16,
}; };
pub const Grid = struct { pub fn init(comptime cell: type, d: cell) type {
arr: [][]cell, return struct {
max: position, pub const dead = d;
leaning: leaning, pub const Grid = struct {
pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void { arr: [][]cell,
for (self.arr) |line| { max: position,
for (line) |grain| { leaning: leaning,
try writer.writeAll(if (grain.alive) "" else ""); pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
for (self.arr) |line| {
for (line) |grain| {
try writer.writeAll(if (!(grain == dead)) "" else "");
}
try writer.writeByte('\n');
}
} }
try writer.writeByte('\n');
}
}
pub fn init(x: u16, y: u16, allocator: std.mem.Allocator) std.mem.Allocator.Error!Grid { pub fn init(x: u16, y: u16, allocator: std.mem.Allocator) std.mem.Allocator.Error!Grid {
const arr: [][]cell = try allocator.alloc([]cell, y); const arr: [][]cell = try allocator.alloc([]cell, y);
for (arr) |*line| { for (arr) |*line| {
line.* = try allocator.alloc(cell, x); line.* = try allocator.alloc(cell, x);
for (line.*) |*c| { for (line.*) |*c| {
c.* = .{ .alive = false }; c.* = dead;
}
}
return .{
.max = position{
.x = x - 1,
.y = y - 1,
},
.arr = arr,
.leaning = .Left,
};
}
pub fn deinit(self: Grid, allocator: std.mem.Allocator) void {
for (self.arr) |line| {
allocator.free(line);
}
allocator.free(self.arr);
} }
}
return .{ pub fn updateAll(self: *Grid, allocator: std.mem.Allocator) std.mem.Allocator.Error!void {
.max = position{ var newGrid: Grid = try .init(self.max.x + 1, self.max.y + 1, allocator);
.x = x - 1,
.y = y - 1, newGrid.leaning = self.leaning.opposite();
},
.arr = arr, for (0..self.arr.len) |y| {
.leaning = .Left, for (0..self.arr[y].len) |x| {
update(.{ .y = @truncate(y), .x = @truncate(x) }, self.*, newGrid);
}
}
switch (self.leaning) {
.Left => for (0..self.arr.len) |y| {
self.updateLineLeftBiased(newGrid, y);
},
.Right => for (0..self.arr.len) |y| {
self.updateLineRightBiased(newGrid, y);
},
}
self.deinit(allocator);
self.* = newGrid;
}
pub fn updateLineRightBiased(s: Grid, ng: Grid, fy: usize) void {
for (0..s.arr[fy].len) |x| {
update(.{ .y = @truncate(fy), .x = @truncate(x) }, s, ng);
}
}
pub fn updateLineLeftBiased(s: Grid, ng: Grid, fy: usize) void {
for (0..s.arr[fy].len) |x| {
update(.{ .y = @truncate(fy), .x = @truncate((s.arr[fy].len - x) - 1) }, s, ng);
}
}
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();
switch (self.leaning) {
.Left => for (0..self.arr.len) |y| {
async[y] = try io.concurrent(Grid.updateLineLeftBiased, .{ self.*, newGrid, y });
},
.Right => for (0..self.arr.len) |y| {
async[y] = try io.concurrent(Grid.updateLineRightBiased, .{ self.*, newGrid, y });
},
}
for (async) |*a| {
a.await(io);
}
self.deinit(allocator);
self.* = newGrid;
}
pub const copyError = error{wrongDimensions};
pub fn copy(self: Grid, dest: *Grid) void {
std.debug.assert(self.arr.len == dest.arr.len and self.arr[0].len == dest.arr[0].len);
for (dest.arr, self.arr) |des, s| {
@memcpy(des, s);
}
}
pub fn eql(self: Grid, dest: Grid) bool {
if (!(self.max == dest.max)) return false;
for (self.arr, dest.arr) |ls, ld| {
for (ls, ld) |cs, cd| {
if (cs != cd) return false;
}
}
return true;
}
}; };
}
pub fn deinit(self: Grid, allocator: std.mem.Allocator) void {
for (self.arr) |line| {
allocator.free(line);
}
allocator.free(self.arr);
}
pub fn updateAll(self: *Grid, allocator: std.mem.Allocator) std.mem.Allocator.Error!void { pub fn update(self: position, grid: Grid, newGrid: Grid) void {
var newGrid: Grid = try .init(self.max.x + 1, self.max.y + 1, allocator); alive: switch (false) {
newGrid.leaning = self.leaning.opposite();
for (0..self.arr.len) |y| {
for (0..self.arr[y].len) |x| {
update(.{ .y = @truncate(y), .x = @truncate(x) }, self.*, newGrid);
}
}
switch (self.leaning) {
.Left => for (0..self.arr.len) |y| {
self.updateLineLeftBiased(newGrid, y);
},
.Right => for (0..self.arr.len) |y| {
self.updateLineRightBiased(newGrid, y);
},
}
self.deinit(allocator);
self.* = newGrid;
}
pub fn updateLineRightBiased(s: Grid, ng: Grid, fy: usize) void {
for (0..s.arr[fy].len) |x| {
update(.{ .y = @truncate(fy), .x = @truncate(x) }, s, ng);
}
}
pub fn updateLineLeftBiased(s: Grid, ng: Grid, fy: usize) void {
for (0..s.arr[fy].len) |x| {
update(.{ .y = @truncate(fy), .x = @truncate((s.arr[fy].len - x) - 1) }, s, ng);
}
}
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();
switch (self.leaning) {
.Left => for (0..self.arr.len) |y| {
async[y] = try io.concurrent(Grid.updateLineLeftBiased, .{ self.*, newGrid, y });
},
.Right => for (0..self.arr.len) |y| {
async[y] = try io.concurrent(Grid.updateLineRightBiased, .{ self.*, newGrid, y });
},
}
for (async) |*a| {
a.await(io);
}
self.deinit(allocator);
self.* = newGrid;
}
pub const copyError = error{wrongDimensions};
pub fn copy(self: Grid, dest: *Grid) void {
std.debug.assert(self.arr.len == dest.arr.len and self.arr[0].len == dest.arr[0].len);
for (dest.arr, self.arr) |d, s| {
@memcpy(d, s);
}
}
pub fn eql(self: Grid, dest: Grid) bool {
if (!(self.max == dest.max)) return false;
for (self.arr, dest.arr) |ls, ld| {
for (ls, ld) |cs, cd| {
if (cs.alive != cd.alive) return false;
}
}
return true;
}
};
pub fn update(self: position, grid: Grid, newGrid: Grid) void {
alive: switch (false) {
false => {
std.debug.assert(grid.max == newGrid.max);
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) {
false => { false => {
if (@cmpxchgStrong(bool, &newnextline[self.x].alive, false, true, .seq_cst, .monotonic)) |_| { std.debug.assert(grid.max == newGrid.max);
continue :down true; if (grid.arr[self.y][self.x] == dead) return;
} else { if (self.y == grid.max.y) continue :alive true;
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst); const alive = grid.arr[self.y][self.x];
return; const nextline = grid.arr[self.y + 1];
} const newnextline = newGrid.arr[self.y + 1];
},
true => { down: switch (nextline[self.x] == dead) {
if (self.x == grid.max.x) { true => {
if (!nextline[self.x - 1].alive) { if (@cmpxchgStrong(cell, &newnextline[self.x], dead, alive, .seq_cst, .monotonic)) |_| {
if (@cmpxchgStrong(bool, &newnextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else { continue :down false;
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst); } else {
@atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .seq_cst);
return; return;
} }
} },
} else if (self.x == 0) { false => {
if (!nextline[self.x + 1].alive) { if (self.x == grid.max.x) {
if (@cmpxchgStrong(bool, &newnextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else { if (nextline[self.x - 1] == dead) {
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst); if (@cmpxchgStrong(cell, &newnextline[self.x - 1], dead, alive, .seq_cst, .monotonic)) |_| {} else {
return; @atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .seq_cst);
} return;
} }
} else { }
switch (grid.leaning) { } else if (self.x == 0) {
.Right => { if (nextline[self.x + 1] == dead) {
right: switch (nextline[self.x + 1].alive) { if (@cmpxchgStrong(cell, &newnextline[self.x + 1], dead, alive, .seq_cst, .monotonic)) |_| {} else {
false => { @atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .seq_cst);
if (@cmpxchgStrong(bool, &newnextline[self.x + 1].alive, false, true, .seq_cst, .monotonic)) |_| { return;
continue :right true; }
} else { }
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst); } else {
return; switch (grid.leaning) {
.Right => {
right: switch (nextline[self.x + 1] == dead) {
true => {
if (@cmpxchgStrong(cell, &newnextline[self.x + 1], dead, alive, .seq_cst, .monotonic)) |_| {
continue :right false;
} else {
@atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .seq_cst);
return;
}
},
false => {
if (nextline[self.x - 1] == dead) {
if (@cmpxchgStrong(cell, &newnextline[self.x - 1], dead, alive, .seq_cst, .monotonic)) |_| {} else {
@atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .seq_cst);
return;
}
}
},
} }
}, },
true => { .Left => {
if (!nextline[self.x - 1].alive) { left: switch (nextline[self.x - 1] == dead) {
if (@cmpxchgStrong(bool, &newnextline[self.x - 1].alive, false, true, .seq_cst, .monotonic)) |_| {} else { true => {
@atomicStore(bool, &newGrid.arr[self.y][self.x].alive, false, .seq_cst); if (@cmpxchgStrong(cell, &newnextline[self.x - 1], dead, alive, .seq_cst, .monotonic)) |_| {
return; continue :left false;
} } else {
@atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .seq_cst);
return;
}
},
false => {
if (nextline[self.x + 1] == dead) {
if (@cmpxchgStrong(cell, &newnextline[self.x + 1], dead, alive, .seq_cst, .monotonic)) |_| {} else {
@atomicStore(cell, &newGrid.arr[self.y][self.x], dead, .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;
}, },
true => @atomicStore(cell, &newGrid.arr[self.y][self.x], grid.arr[self.y][self.x], .seq_cst),
} }
continue :alive true; }
}, };
true => @atomicStore(bool, &newGrid.arr[self.y][self.x].alive, true, .seq_cst),
}
} }
pub const default = init(u1, 0);