use package core
+Gravity :: 0.3f
+
+
+
Color :: struct {
Empty :: Color.{ 22, 22, 22 };
Sand :: Color.{ 226, 214, 173 };
Water :: Color.{ 100, 100, 255 };
- Wall :: Color.{ 60, 60, 30 };
+ Wood :: Color.{ 60, 60, 30 };
r, g, b: u8;
}
Empty;
Sand;
Water;
- Wall;
+ Wood;
}
- types :: Type.[ .Sand, .Water, .Wall ];
+ types :: Type.[ .Sand, .Water, .Wood ];
type: Type = .Empty;
life: f32 = 0;
switch t {
case .Sand do return .Sand;
case .Water do return .Water;
- case .Wall do return .Wall;
+ case .Wood do return .Wood;
case #default do return .Empty;
}
}
switch particle_type {
case .Sand do update_sand(board, x, y);
case .Water do update_water(board, x, y);
- case .Wall --- // Walls do not need updating
+ case .Wood --- // Woods do not need updating
case .Empty ---
}
}
// This should get inlined by Onyx, when inlining is a thing.
get_index :: (use board: ^ParticleBoard, x: i32, y: i32) -> i32 {
- if x < 0 || y < 0 || x >= width || y >= height do return -1;
+ if x < 0 || y < 0 || x >= ~~width || y >= ~~height do return -1;
return y * width + x;
}
for index: indicies {
if index < 0 do continue;
- if particles[index].type == .Empty {
- return index;
- }
+ if particles[index].type == .Empty do return index;
}
return -1;
update_sand :: (use board: ^ParticleBoard, x: i32, y: i32) {
index := get_index(board, x, y);
- b_index := get_index(board, x, y + 1);
- bl_index := get_index(board, x - 1, y + 1);
- br_index := get_index(board, x + 1, y + 1);
+ particles[index].velocity.y += Gravity;
- move_to_index := first_empty(board, b_index, bl_index, br_index);
+ if particles[get_index(board, x, y + 1)].type != .Empty {
+ particles[index].velocity.y = 0;
+ }
- if move_to_index != -1 {
- particle_set(board, move_to_index, particles[index]);
- particle_set(board, index, .{ .Empty });
- return;
+ vy := cast(i32) particles[index].velocity.y;
+ for yy: y + 1 .. y + vy + 2 {
+ b_index := get_index(board, x, yy);
+ bl_index := get_index(board, x - 1, yy);
+ br_index := get_index(board, x + 1, yy);
+
+ move_to_index := first_empty(board, b_index, bl_index, br_index);
+
+ if move_to_index != -1 {
+ particle_set(board, move_to_index, particles[index]);
+ particle_set(board, index, .{ .Empty });
+ return;
+ }
}
+ b_index := get_index(board, x, y + 1);
if can_sink(board, b_index) {
particle_switch(board, index, b_index);
}
update_water :: (use board: ^ParticleBoard, x: i32, y: i32) {
index := get_index(board, x, y);
- b_index := get_index(board, x, y + 1);
- l_index := get_index(board, x - 1, y);
- r_index := get_index(board, x + 1, y);
- bl_index := get_index(board, x - 1, y + 1);
- br_index := get_index(board, x + 1, y + 1);
+ particles[index].velocity.y += Gravity;
+
+ if particles[get_index(board, x, y + 1)].type != .Empty {
+ particles[index].velocity.y = 0;
+ }
+
+ vy := cast(i32) particles[index].velocity.y;
+ b_index := get_index(board, x, y + vy + 1);
+ bl_index := get_index(board, x - 1, y + vy + 1);
+ br_index := get_index(board, x + 1, y + vy + 1);
- move_to_index := first_empty(board, b_index, br_index, bl_index, r_index, l_index);
+ move_to_index := first_empty(board, b_index, br_index, bl_index);
if move_to_index != -1 {
particle_set(board, move_to_index, particles[index]);
particle_set(board, index, .{ .Empty });
+ return;
+ }
+
+ l_index := get_index(board, x - 1, y);
+ r_index := get_index(board, x + 1, y);
+ if random.int() % 4 >= 2 {
+ if l_index >= 0 && particles[l_index].type == .Empty {
+ particle_set(board, l_index, particles[index]);
+ particle_set(board, index, .{ .Empty });
+ }
+ } else {
+ if r_index >= 0 && particles[r_index].type == .Empty {
+ particle_set(board, r_index, particles[index]);
+ particle_set(board, index, .{ .Empty });
+ }
}
}