diff --git a/src/root.zig b/src/root.zig index 78ca9a9..716cb1f 100644 --- a/src/root.zig +++ b/src/root.zig @@ -13,6 +13,27 @@ const V2 = struct { const max = V2{ .x = std.math.floatMax(f32), .y = std.math.floatMax(f32) }; const zero = V2{ .x = 0.0, .y = 0.0 }; + fn init(x: f32, y: f32) V2 { + return .{ + .x = x, + .y = y, + }; + } + + fn init_int(x: i32, y: i32) V2 { + return .{ + .x = @floatFromInt(x), + .y = @floatFromInt(y), + }; + } + + fn init_usize(x: usize, y: usize) V2 { + return .{ + .x = @floatFromInt(x), + .y = @floatFromInt(y), + }; + } + fn add(self: V2, other: V2) V2 { return .{ .x = self.x + other.x, @@ -26,6 +47,27 @@ const V2 = struct { .y = self.y - other.y, }; } + + fn mul(self: V2, s: f32) V2 { + return .{ + .x = self.x * s, + .y = self.y * s, + }; + } + + fn inner(self: V2, other: V2) f32 { + const result = self.x * other.x + self.y * other.y; + return result; + } + + fn hadamard(self: V2, other: V2) V2 { + var result = V2.zero; + + result.x = self.x * other.x; + result.y = self.y * other.y; + + return result; + } }; const BBox = struct { @@ -39,6 +81,31 @@ const Camera = struct { offset: V2, }; +const BoardTile = struct { + blocked: bool, + taken: bool, + hovering: bool, + label: []const u8, + + fn init(label: []const u8, blocked: bool) BoardTile { + const result: BoardTile = .{ + .blocked = blocked, + .taken = false, + .hovering = false, + .label = label, + }; + + return result; + } +}; + +const Board = struct { + pos: V2, + width: u32, + height: u32, + tiles: [7][7]BoardTile, +}; + const Brick = struct { rotating: bool, pos: V2, @@ -87,8 +154,10 @@ const State = struct { frame_count: i32, mouse_pos: V2, camera: Camera, + draw_bounding_rects: bool, grabbed_brick_index: ?usize, bricks: [8]Brick, + board: Board, }; const tile_size = V2{ @@ -96,6 +165,13 @@ const tile_size = V2{ .y = TILE_SIZE, }; +fn getTilePos(i: usize, j: usize) V2 { + return V2{ + .x = @floatFromInt(j * TILE_SIZE), + .y = @floatFromInt(i * TILE_SIZE), + }; +} + fn pointInsideRect(p: V2, rect_start: V2, rect_size: V2) bool { var result: bool = false; @@ -109,16 +185,31 @@ fn pointInsideRect(p: V2, rect_start: V2, rect_size: V2) bool { return result; } +fn tilesIntersects(r1: V2, r2: V2) bool { + var result = false; + + const r2a: V2 = V2.init(r2.x, r2.y); + const r2b: V2 = V2.init(r2.x, r2.y + tile_size.y); + const r2c: V2 = V2.init(r2.x + tile_size.x, r2.y); + const r2d: V2 = V2.init(r2.x + tile_size.x, r2.y + tile_size.y); + + const a = pointInsideRect(r2a, r1, tile_size); + const b = pointInsideRect(r2b, r1, tile_size); + const c = pointInsideRect(r2c, r1, tile_size); + const d = pointInsideRect(r2d, r1, tile_size); + + result = a or b or c or d; + + return result; +} + fn findBrickBoundingBox(brick: *const Brick) BBox { var result = BBox{ .min = V2.max, .max = V2.zero, .center = V2.zero }; for (brick.tiles, 0..) |row, i| { for (row, 0..) |tile, j| { if (tile > 0) { - const tile_start = V2{ - .x = @floatFromInt(j * TILE_SIZE), - .y = @floatFromInt(i * TILE_SIZE), - }; + const tile_start = getTilePos(i, j); const tile_end = tile_start.add(tile_size); const start = brick.pos.add(tile_start); @@ -345,6 +436,35 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu }, }; + const tile_names = [7][7]?[]const u8{ + .{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", null }, + .{ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", null }, + .{ "1", "2", "3", "4", "5", "6", "7" }, + .{ "8", "9", "10", "11", "12", "13", "14" }, + .{ "15", "16", "17", "18", "19", "20", "21" }, + .{ "22", "23", "24", "25", "26", "27", "28" }, + .{ "29", "30", "31", null, null, null, null }, + }; + + var tiles: [7][7]BoardTile = undefined; + + for (tile_names, 0..) |row, i| { + for (row, 0..) |opt, j| { + if (opt) |tile| { + tiles[i][j] = BoardTile.init(tile, false); + } else { + tiles[i][j] = BoardTile.init("", true); + } + } + } + + state.board = .{ + .pos = mid, + .width = 7, + .height = 7, + .tiles = tiles, + }; + memory.initialized = true; } @@ -353,10 +473,20 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu const mouse_world_pos = mouse_pos.sub(state.camera.pos); + if (keyPressed(&input.key.f1)) { + state.draw_bounding_rects = !state.draw_bounding_rects; + } + if (!input.mouse_left_down) { state.grabbed_brick_index = null; } + for (&state.board.tiles) |*board_row| { + for (board_row) |*board_tile| { + board_tile.hovering = false; + } + } + for (&state.bricks, 0..) |*brick, brick_index| { if (brick.rotating) { brick.rotating_time += input.delta_time; @@ -369,20 +499,25 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu for (brick.tiles, 0..) |row, i| { for (row, 0..) |tile, j| { if (tile > 0) { - const tile_pos = V2{ - .x = @floatFromInt(j * TILE_SIZE), - .y = @floatFromInt(i * TILE_SIZE), - }; - const pos = tile_pos.add(brick.pos); + const pos = getTilePos(i, j).add(brick.pos); - const camera_pos = pos.add(state.camera.pos); if (input.mouse_left_down) { - if (pointInsideRect(state.mouse_pos, camera_pos, tile_size)) { + if (pointInsideRect(mouse_world_pos, pos, tile_size)) { if (state.grabbed_brick_index == null) { state.grabbed_brick_index = brick_index; } } } + + for (&state.board.tiles, 0..) |*board_row, k| { + for (board_row, 0..) |*board_tile, l| { + const board_tile_pos = getTilePos(k, l).add(state.board.pos); + + if (!board_tile.hovering) { + board_tile.hovering = tilesIntersects(board_tile_pos, pos); + } + } + } } } } @@ -424,22 +559,36 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu // Render fillRect(buffer, 0, 0, buffer.width, buffer.height, 0xFFFFFFFF); - const board_pos = mid; - for (0..7) |i| { - for (0..7) |j| { - if (i == 0 and j == 6) continue; - if (i == 1 and j == 6) continue; - if (i == 6 and j == 3) continue; - if (i == 6 and j == 4) continue; - if (i == 6 and j == 5) continue; - if (i == 6 and j == 6) continue; + { + const board = state.board; + // const board_size = V2.init_int( + // @intCast(board.width * TILE_SIZE), + // @intCast(board.height * TILE_SIZE), + // ); + // const half = board_size.mul(0.5); - const tile_pos = V2{ - .x = @floatFromInt(j * TILE_SIZE), - .y = @floatFromInt(i * TILE_SIZE), - }; - const camera_pos = board_pos.add(tile_pos).add(state.camera.pos); - fillSquare(buffer, @intFromFloat(camera_pos.x), @intFromFloat(camera_pos.y), 30, 0xFF000000); + const board_camera_pos = board.pos.add(state.camera.pos); + + for (board.tiles, 0..) |row, i| { + for (row, 0..) |tile, j| { + const tile_pos = V2{ + .x = @floatFromInt(j * TILE_SIZE), + .y = @floatFromInt(i * TILE_SIZE), + }; + const camera_pos = board_camera_pos.add(tile_pos); + const pos_x: i32 = @intFromFloat(camera_pos.x); + const pos_y: i32 = @intFromFloat(camera_pos.y); + + var color: u32 = 0xFF000000; + if (tile.blocked) { + color = 0xFFFFFFFF; + } else if (tile.hovering) { + color = 0xFF00FF00; + } + + fillSquare(buffer, pos_x, pos_y, TILE_SIZE, color); + drawRect(buffer, camera_pos, tile_size, 0xFFFFFFFF, 2); + } } } @@ -449,11 +598,8 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu for (brick.tiles, 0..) |row, i| { for (row, 0..) |tile, j| { if (tile > 0) { - const pos = V2{ - .x = @floatFromInt(j * TILE_SIZE), - .y = @floatFromInt(i * TILE_SIZE), - }; - const camera_pos = brick.pos.add(pos).add(state.camera.pos); + const pos = getTilePos(i, j).add(brick.pos); + const camera_pos = pos.add(state.camera.pos); fillSquare( buffer, @intFromFloat(camera_pos.x), @@ -466,25 +612,27 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu } if (comptime builtin.mode == std.builtin.OptimizeMode.Debug) { - { - const camera_pos = brick.pos.add(state.camera.pos); - drawRect(buffer, camera_pos, .{ .x = 4 * TILE_SIZE, .y = 4 * TILE_SIZE }, 0xFFFF0000, 1); - } + if (state.draw_bounding_rects) { + { + const camera_pos = brick.pos.add(state.camera.pos); + drawRect(buffer, camera_pos, .{ .x = 4 * TILE_SIZE, .y = 4 * TILE_SIZE }, 0xFFFF0000, 1); + } - { - const bbox_size = bounding_box.max.sub(bounding_box.min); - const camera_pos = bounding_box.min.add(state.camera.pos); + { + const bbox_size = bounding_box.max.sub(bounding_box.min); + const camera_pos = bounding_box.min.add(state.camera.pos); - drawRect(buffer, camera_pos, bbox_size, 0xFFFF0000, 1); - } + drawRect(buffer, camera_pos, bbox_size, 0xFFFF0000, 1); + } - { - const size = 8; - const half = @divTrunc(size, 2); - const camera_pos = bounding_box.center.add(state.camera.pos); - const x: i32 = @intFromFloat(camera_pos.x); - const y: i32 = @intFromFloat(camera_pos.y); - fillSquare(buffer, x - half, y - half, 8, 0xFFFF0000); + { + const size = 8; + const half = @divTrunc(size, 2); + const camera_pos = bounding_box.center.add(state.camera.pos); + const x: i32 = @intFromFloat(camera_pos.x); + const y: i32 = @intFromFloat(camera_pos.y); + fillSquare(buffer, x - half, y - half, 8, 0xFFFF0000); + } } } }