summaryrefslogtreecommitdiff
path: root/src/root.zig
diff options
context:
space:
mode:
authorAlec Goncharow <alec@goncharow.dev>2024-01-19 22:39:43 -0500
committerAlec Goncharow <alec@goncharow.dev>2024-01-19 22:39:43 -0500
commitdb229ae38f04e8a6b9759c1e5208af75b81344aa (patch)
tree1cdd2eda0b2c71d0c5f5f16e25a362cdd9d41904 /src/root.zig
initial stuff
got some hexes, got some mouse picking
Diffstat (limited to 'src/root.zig')
-rw-r--r--src/root.zig159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/root.zig b/src/root.zig
new file mode 100644
index 0000000..286c0c2
--- /dev/null
+++ b/src/root.zig
@@ -0,0 +1,159 @@
+const std = @import("std");
+const rl = @cImport(@cInclude("raylib.h"));
+const context = @import("context.zig");
+
+const grid_size: usize = 21;
+const grid_central_row = grid_size / 2 + 1;
+
+pub const MyRect = struct {
+ rect: rl.Rectangle,
+ color: rl.Color,
+};
+
+const hex_radius: f32 = 100.0;
+const hex_rotation = 30.0;
+
+pub const HexCoord = struct {
+ q: i32,
+ r: i32,
+ pub inline fn fracS(q: f32, r: f32) f32 {
+ return -q - r;
+ }
+
+ pub inline fn index(self: HexCoord) usize {
+ return self.r / grid_size + self.q % grid_size;
+ }
+
+ pub inline fn qrToWorld(q: i32, r: i32) rl.Vector2 {
+ return .{
+ .x = hex_radius * (@sqrt(3.0) * @as(f32, @floatFromInt(q)) + @sqrt(3.0) / 2.0 * @as(f32, @floatFromInt(r))),
+ .y = hex_radius * (3.0 / 2.0 * @as(f32, @floatFromInt(r))),
+ };
+ }
+ pub inline fn worldToQr(point: rl.Vector2) HexCoord {
+ const q = (@sqrt(3.0) / 3.0 * point.x - 1.0 / 3.0 * point.y) / hex_radius;
+ const r = (2.0 / 3.0 * point.y) / hex_radius;
+
+ return axialRound(.{ .x = q, .y = r });
+ }
+ pub inline fn axialRound(frac: rl.Vector2) HexCoord {
+ return cubeRound(rl.Vector3{ .x = frac.x, .y = frac.y, .z = fracS(frac.x, frac.y) });
+ }
+
+ pub inline fn cubeRound(frac: rl.Vector3) HexCoord {
+ var q = @round(frac.x);
+ var r = @round(frac.y);
+ var s = @round(frac.z);
+
+ const q_diff = @abs(q - frac.x);
+ const r_diff = @abs(r - frac.y);
+ const s_diff = @abs(s - frac.z);
+
+ if (q_diff > r_diff and q_diff > s_diff) {
+ q = -r - s;
+ } else if (r_diff > s_diff) {
+ r = -q - s;
+ } else {
+ s = -q - r;
+ }
+
+ return .{
+ .q = @as(i32, @intFromFloat(q)),
+ .r = @as(i32, @intFromFloat(r)),
+ };
+ }
+};
+
+pub const Hex = struct {
+ // todo perhaps worth having a sentiental value somewhere to state if a hex is alive or perhaps make the list optinals?
+ color: rl.Color,
+};
+
+pub fn setup() !void {
+ const target = HexCoord.qrToWorld(grid_central_row, grid_central_row);
+ context.camera = rl.Camera2D{ .target = target, .offset = rl.Vector2{ .x = 0, .y = 0 }, .rotation = 0, .zoom = 1 };
+ context.hex_grid = try context.Grid.init(context.gpa, grid_size);
+
+ // TODO think what it means to populate a hex grid
+ for (0..grid_size) |_| {
+ for (0..grid_size) |_| {
+ try context.hex_grid.initPush(Hex{
+ // TODO real colors
+ .color = rl.DARKGREEN,
+ });
+ }
+ }
+}
+
+pub fn update() !void {
+ //----------------------------------------------------------------------------------
+
+ const mouse_pos = rl.GetMousePosition();
+ const mouse_world_pos = rl.GetScreenToWorld2D(mouse_pos, context.camera);
+
+ context.hovered_coords = HexCoord.worldToQr(mouse_world_pos);
+
+ const zoom_scale = context.camera.zoom;
+ if (rl.IsKeyDown(rl.KEY_D)) {
+ context.camera.target.x += 2 / zoom_scale;
+ }
+ if (rl.IsKeyDown(rl.KEY_A)) {
+ context.camera.target.x -= 2 / zoom_scale;
+ }
+ if (rl.IsKeyDown(rl.KEY_W)) {
+ context.camera.target.y -= 2 / zoom_scale;
+ }
+ if (rl.IsKeyDown(rl.KEY_S)) {
+ context.camera.target.y += 2 / zoom_scale;
+ }
+
+ if (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_MIDDLE)) {
+ const delta = rl.GetMouseDelta();
+ context.camera.target.x -= delta.x / zoom_scale;
+ context.camera.target.y -= delta.y / zoom_scale;
+ }
+
+ const wm = rl.GetMouseWheelMove();
+ if (wm != 0.0) {
+ context.camera.zoom += wm * 0.05;
+
+ context.camera.target = mouse_world_pos;
+ context.camera.offset = mouse_pos;
+
+ if (context.camera.zoom > 3.0) context.camera.zoom = 3.0;
+ if (context.camera.zoom < 0.1) context.camera.zoom = 0.1;
+ }
+}
+pub fn draw() !void {
+ rl.BeginDrawing();
+
+ rl.ClearBackground(rl.SKYBLUE);
+
+ rl.BeginMode2D(context.camera);
+ const slice = context.hex_grid.buffer.slice();
+ const colors = slice.items(.color);
+ for (0..grid_size) |r| {
+ var start: usize = 0;
+ var end: usize = 0;
+ if (r < grid_central_row) {
+ start = grid_central_row - r;
+ end = grid_size;
+ } else {
+ start = 0;
+ end = grid_size - (r - grid_central_row);
+ }
+ for (start..end) |q| {
+ const idx = r * grid_size + q;
+ const center = HexCoord.qrToWorld(@intCast(q), @intCast(r));
+ rl.DrawPoly(center, 6, hex_radius, hex_rotation, colors[idx]);
+ rl.DrawPolyLines(center, 6, hex_radius, hex_rotation, rl.BLACK);
+ }
+ }
+
+ const center = HexCoord.qrToWorld(@intCast(context.hovered_coords.q), @intCast(context.hovered_coords.r));
+ rl.DrawPolyLines(center, 6, hex_radius, hex_rotation, rl.WHITE);
+
+ rl.EndMode2D();
+
+ rl.EndDrawing();
+}