Show current day and month
Also check win state
This commit is contained in:
+153
-45
@@ -2,6 +2,9 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const epoch = std.time.epoch;
|
||||
const MonthAndDay = epoch.MonthAndDay;
|
||||
|
||||
pub const platform = @import("platform.zig");
|
||||
|
||||
const V2 = @import("V2.zig");
|
||||
@@ -26,17 +29,27 @@ const Camera = struct {
|
||||
offset: V2,
|
||||
};
|
||||
|
||||
const MonthOrDayTag = enum {
|
||||
month,
|
||||
day_index,
|
||||
};
|
||||
|
||||
const MonthOrDay = union(MonthOrDayTag) {
|
||||
month: epoch.Month,
|
||||
day_index: u5,
|
||||
};
|
||||
|
||||
const BoardTile = struct {
|
||||
blocked: bool,
|
||||
taken: bool,
|
||||
hovering: bool,
|
||||
type: MonthOrDay,
|
||||
label: []const u8,
|
||||
|
||||
fn init(label: []const u8, blocked: bool) BoardTile {
|
||||
fn init(label: []const u8, month_or_day: MonthOrDay) BoardTile {
|
||||
const result: BoardTile = .{
|
||||
.blocked = blocked,
|
||||
.taken = false,
|
||||
.hovering = false,
|
||||
.type = month_or_day,
|
||||
.label = label,
|
||||
};
|
||||
|
||||
@@ -49,7 +62,7 @@ const Board = struct {
|
||||
width: u32,
|
||||
height: u32,
|
||||
tile_size: V2,
|
||||
tiles: [7][7]BoardTile,
|
||||
tiles: [7][7]?BoardTile,
|
||||
|
||||
fn getTilePos(self: Board, i: usize, j: usize) V2 {
|
||||
const tile_pos = V2{
|
||||
@@ -137,7 +150,9 @@ const State = struct {
|
||||
camera: Camera,
|
||||
font_image: Image,
|
||||
font: Font,
|
||||
has_won: bool,
|
||||
draw_bounding_rects: bool,
|
||||
month_and_day: MonthAndDay,
|
||||
grabbed_brick_index: ?usize,
|
||||
bricks: [8]Brick,
|
||||
board: Board,
|
||||
@@ -427,11 +442,10 @@ fn drawImage(buffer: platform.OffscreenBuffer, image: Image, pos: V2, scale: f32
|
||||
}
|
||||
}
|
||||
|
||||
fn drawString(buffer: platform.OffscreenBuffer, font: Font, pos: V2, str: []const u8) void {
|
||||
fn drawString(buffer: platform.OffscreenBuffer, font: Font, pos: V2, scale: f32, str: []const u8) void {
|
||||
const image = font.image;
|
||||
var current_pos = pos;
|
||||
const font_size = 32;
|
||||
const scale = 0.5;
|
||||
const font_width_scaled = scale * font_size;
|
||||
for (str) |c| {
|
||||
const char_image_pos = font.findCharImagePos(c);
|
||||
@@ -500,6 +514,16 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
.y = @floatFromInt(@divTrunc(buffer.height, 2)),
|
||||
};
|
||||
if (!memory.initialized) {
|
||||
state.has_won = false;
|
||||
|
||||
const timestamp = std.time.timestamp();
|
||||
const epoch_seconds = epoch.EpochSeconds{ .secs = @intCast(timestamp) };
|
||||
const epoch_day = epoch_seconds.getEpochDay();
|
||||
const year_and_day = epoch_day.calculateYearDay();
|
||||
const day: MonthAndDay = year_and_day.calculateMonthDay();
|
||||
|
||||
state.month_and_day = day;
|
||||
|
||||
state.camera.offset = mid;
|
||||
|
||||
state.grabbed_brick_index = null;
|
||||
@@ -642,15 +666,26 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
.{ "29", "30", "31", null, null, null, null },
|
||||
};
|
||||
|
||||
var tiles: [7][7]BoardTile = undefined;
|
||||
const tile_types = [7][7]?MonthOrDay{
|
||||
.{ .{ .month = epoch.Month.jan }, .{ .month = epoch.Month.feb }, .{ .month = epoch.Month.mar }, .{ .month = epoch.Month.apr }, .{ .month = epoch.Month.may }, .{ .month = epoch.Month.jun }, null },
|
||||
.{ .{ .month = epoch.Month.jul }, .{ .month = epoch.Month.aug }, .{ .month = epoch.Month.sep }, .{ .month = epoch.Month.oct }, .{ .month = epoch.Month.nov }, .{ .month = epoch.Month.dec }, null },
|
||||
.{ .{ .day_index = 0 }, .{ .day_index = 1 }, .{ .day_index = 2 }, .{ .day_index = 3 }, .{ .day_index = 4 }, .{ .day_index = 5 }, .{ .day_index = 6 } },
|
||||
.{ .{ .day_index = 7 }, .{ .day_index = 8 }, .{ .day_index = 9 }, .{ .day_index = 10 }, .{ .day_index = 11 }, .{ .day_index = 12 }, .{ .day_index = 13 } },
|
||||
.{ .{ .day_index = 14 }, .{ .day_index = 15 }, .{ .day_index = 16 }, .{ .day_index = 17 }, .{ .day_index = 18 }, .{ .day_index = 19 }, .{ .day_index = 20 } },
|
||||
.{ .{ .day_index = 21 }, .{ .day_index = 22 }, .{ .day_index = 23 }, .{ .day_index = 24 }, .{ .day_index = 25 }, .{ .day_index = 26 }, .{ .day_index = 27 } },
|
||||
.{ .{ .day_index = 28 }, .{ .day_index = 29 }, .{ .day_index = 30 }, null, null, null, null },
|
||||
};
|
||||
|
||||
var tiles: [7][7]?BoardTile = undefined;
|
||||
|
||||
for (tile_names, 0..) |row, i| {
|
||||
for (row, 0..) |opt, j| {
|
||||
tiles[i][j] = null;
|
||||
|
||||
if (opt) |tile| {
|
||||
tiles[i][j] = BoardTile.init(tile, false);
|
||||
} else {
|
||||
tiles[i][j] = BoardTile.init("", true);
|
||||
}
|
||||
const tile_type = tile_types[i][j];
|
||||
tiles[i][j] = BoardTile.init(tile, tile_type.?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,7 +706,9 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
memory.initialized = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Update
|
||||
//
|
||||
const mouse_pos = V2{ .x = @floatCast(input.mouse_x), .y = @floatCast(input.mouse_y) };
|
||||
|
||||
const mouse_world_pos = mouse_pos.sub(state.camera.pos);
|
||||
@@ -685,8 +722,11 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
}
|
||||
|
||||
for (&state.board.tiles) |*board_row| {
|
||||
for (board_row) |*board_tile| {
|
||||
board_tile.hovering = false;
|
||||
for (board_row) |*opt| {
|
||||
if (opt.*) |*board_tile| {
|
||||
board_tile.hovering = false;
|
||||
board_tile.taken = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,17 +757,19 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
}
|
||||
|
||||
for (&state.board.tiles, 0..) |*board_row, k| {
|
||||
for (board_row, 0..) |*board_tile, l| {
|
||||
const board_tile_pos = state.board.getTilePos(k, l);
|
||||
for (board_row, 0..) |*opt, l| {
|
||||
if (opt.*) |*board_tile| {
|
||||
const board_tile_pos = state.board.getTilePos(k, l);
|
||||
|
||||
const in_tile = pointInsideRect(tile_mid, board_tile_pos, state.board.tile_size);
|
||||
if (in_tile and !board_tile.blocked and !board_tile.taken) {
|
||||
tile_board_index.* = BoardIndex.init(k, l);
|
||||
// board_tile.taken = true;
|
||||
}
|
||||
const in_tile = pointInsideRect(tile_mid, board_tile_pos, state.board.tile_size);
|
||||
if (in_tile and !board_tile.taken) {
|
||||
tile_board_index.* = BoardIndex.init(k, l);
|
||||
board_tile.taken = true;
|
||||
}
|
||||
|
||||
if (!board_tile.hovering) {
|
||||
board_tile.hovering = in_tile;
|
||||
if (!board_tile.hovering) {
|
||||
board_tile.hovering = in_tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -775,6 +817,29 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
}
|
||||
}
|
||||
|
||||
// Check if player has won
|
||||
var has_won = true;
|
||||
for (state.board.tiles) |board_row| {
|
||||
for (board_row) |opt| {
|
||||
if (opt) |board_tile| {
|
||||
const is_day_or_month = blk: {
|
||||
switch (board_tile.type) {
|
||||
.month => |m| {
|
||||
break :blk state.month_and_day.month == m;
|
||||
},
|
||||
.day_index => |d| {
|
||||
break :blk state.month_and_day.day_index == d;
|
||||
},
|
||||
}
|
||||
};
|
||||
const valid = (board_tile.taken and !is_day_or_month) or (!board_tile.taken and is_day_or_month);
|
||||
has_won = has_won and valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.has_won = has_won;
|
||||
|
||||
if (input.mouse_left_down and state.grabbed_brick_index == null) {
|
||||
const diff = mouse_pos.sub(state.mouse_pos);
|
||||
state.camera.pos = state.camera.pos.add(diff);
|
||||
@@ -782,7 +847,9 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
|
||||
state.mouse_pos = mouse_pos;
|
||||
|
||||
//
|
||||
// Render
|
||||
//
|
||||
fillRect(buffer, 0, 0, buffer.width, buffer.height, 0xFFFFFFFF);
|
||||
|
||||
// Draw board
|
||||
@@ -790,32 +857,52 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
const board = state.board;
|
||||
|
||||
for (board.tiles, 0..) |row, i| {
|
||||
for (row, 0..) |tile, j| {
|
||||
const tile_pos = board.getTilePos(i, j);
|
||||
const width: i32 = @intFromFloat(board.tile_size.x);
|
||||
const height: i32 = @intFromFloat(board.tile_size.y);
|
||||
for (row, 0..) |opt, j| {
|
||||
if (opt) |tile| {
|
||||
const tile_pos = board.getTilePos(i, j);
|
||||
const width: i32 = @intFromFloat(board.tile_size.x);
|
||||
const height: i32 = @intFromFloat(board.tile_size.y);
|
||||
|
||||
const str_width = @divFloor(TILE_SIZE * tile.label.len, 4);
|
||||
const str_height = @divFloor(32, 4);
|
||||
const str_size = V2.initUSize(str_width, str_height);
|
||||
const string_pos = tile_pos.add(board.tile_size.mul(0.5)).sub(str_size.mul(0.5));
|
||||
const str_width = @divFloor(TILE_SIZE * tile.label.len, 4);
|
||||
const str_height = @divFloor(32, 4);
|
||||
const str_size = V2.initUSize(str_width, str_height);
|
||||
const string_pos = tile_pos.add(board.tile_size.mul(0.5)).sub(str_size.mul(0.5));
|
||||
|
||||
var color: u32 = 0xFF000000;
|
||||
if (tile.blocked) {
|
||||
color = 0xFFFFFFFF;
|
||||
} else if (tile.hovering) {
|
||||
color = 0xFF00FF00;
|
||||
var color: u32 = 0xFF000000;
|
||||
|
||||
if (tile.hovering) {
|
||||
color = 0xFF00FF00;
|
||||
}
|
||||
|
||||
const camera_pos = tile_pos.add(state.camera.pos);
|
||||
const pos_x: i32 = @intFromFloat(camera_pos.x);
|
||||
const pos_y: i32 = @intFromFloat(camera_pos.y);
|
||||
|
||||
fillRect(buffer, pos_x, pos_y, width, height, color);
|
||||
|
||||
var outline_color: u32 = 0xFFFFFFFF;
|
||||
var outline_width: i32 = 2;
|
||||
const is_day_color = 0xFFDA983C;
|
||||
switch (tile.type) {
|
||||
.month => |m| {
|
||||
if (state.month_and_day.month == m) {
|
||||
outline_color = is_day_color;
|
||||
outline_width = 4;
|
||||
}
|
||||
},
|
||||
.day_index => |d| {
|
||||
if (state.month_and_day.day_index == d) {
|
||||
outline_color = is_day_color;
|
||||
outline_width = 4;
|
||||
}
|
||||
},
|
||||
}
|
||||
drawRect(buffer, camera_pos, board.tile_size, outline_color, outline_width);
|
||||
|
||||
const string_camera_pos = string_pos.add(state.camera.pos);
|
||||
const scale = 0.5;
|
||||
drawString(buffer, state.font, string_camera_pos, scale, tile.label);
|
||||
}
|
||||
|
||||
const camera_pos = tile_pos.add(state.camera.pos);
|
||||
const pos_x: i32 = @intFromFloat(camera_pos.x);
|
||||
const pos_y: i32 = @intFromFloat(camera_pos.y);
|
||||
|
||||
fillRect(buffer, pos_x, pos_y, width, height, color);
|
||||
drawRect(buffer, camera_pos, board.tile_size, 0xFFFFFFFF, 2);
|
||||
|
||||
const string_camera_pos = string_pos.add(state.camera.pos);
|
||||
drawString(buffer, state.font, string_camera_pos, tile.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -873,6 +960,27 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// UI
|
||||
//
|
||||
if (state.has_won) {
|
||||
const scale = 1.0;
|
||||
const text = "YOU WON";
|
||||
const str_len = @as(i32, @intCast(text.len)) * state.font.glyph_width;
|
||||
const half = @divFloor(buffer.width, 2);
|
||||
const width = half - @divFloor(str_len, 2);
|
||||
|
||||
drawString(buffer, state.font, V2.initI32(width, 32), scale, text);
|
||||
}
|
||||
|
||||
{
|
||||
const scale = 0.5;
|
||||
const height = buffer.height - state.font.glyph_height;
|
||||
|
||||
drawString(buffer, state.font, V2.initI32(8, height - state.font.glyph_height), scale, "Flip: w");
|
||||
|
||||
drawString(buffer, state.font, V2.initI32(8, height - 8), scale, "Rotate: e");
|
||||
}
|
||||
|
||||
state.frame_count += 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user