summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig191
1 files changed, 141 insertions, 50 deletions
diff --git a/src/main.zig b/src/main.zig
index 105b673..00bf723 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2,18 +2,21 @@ const std = @import("std");
const rl = @import("raylib");
const assert = std.debug.assert;
-const cell_size = 16;
-const world_width = 16 * cell_size;
-const world_height = 9 * cell_size;
+const cell_size = 32;
+const cells_width = 16.0;
+const cells_height = 9.0;
+const world_width = cells_width * cell_size;
+const world_height = cells_height * cell_size;
+const bg_color = rl.Color.init(0x20, 0x2e, 0x37, 0xFF);
-var screen_width: i32 = 1280;
-var screen_height: i32 = 720;
+var screenWidth: i32 = 1280;
+var screenHeight: i32 = 720;
pub fn main() anyerror!void {
// Initialization
//--------------------------------------------------------------------------------------
- rl.initWindow(screen_width, screen_height, "Hackathon");
+ rl.initWindow(screenWidth, screenHeight, "Hackathon");
defer rl.closeWindow(); // Close window and OpenGL context
// rl.setWindowState(.{ .window_resizable = true });
@@ -22,6 +25,7 @@ pub fn main() anyerror!void {
//--------------------------------------------------------------------------------------
var game = Game.init();
+ defer game.deinit();
// Main game loop
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
@@ -37,38 +41,101 @@ pub fn main() anyerror!void {
}
}
-const Cell = struct {
- color: rl.Color = rl.Color.red,
+const Cpu = struct {};
+
+const Cell = union(enum) {
+ none,
+ socket,
+ cpu: Cpu,
+ ai,
+ lane,
+ color: rl.Color,
+
+ fn isLaneConnected(self: Cell) bool {
+ return switch (self) {
+ .lane => true,
+ .ai => true,
+ else => false,
+ };
+ }
};
const Wave = struct {
arena: std.heap.ArenaAllocator,
- map: [world_height][world_width]Cell = [_][world_width]Cell{[_]Cell{Cell{}} ** world_width} ** world_height,
+ map: [cells_height][cells_width]Cell = [_][cells_width]Cell{[_]Cell{.none} ** cells_width} ** cells_height,
+
+ fn init() Wave {
+ var wave = Wave{
+ .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator),
+ };
+
+ for (1..cells_height - 1) |y| {
+ for (1..cells_width - 1) |x| {
+ const isEven = (y + x) % 2 == 0;
+ if (isEven) {
+ wave.map[y][x] = .{ .color = rl.Color.blue };
+ } else {
+ wave.map[y][x] = .socket;
+ }
+ }
+ }
+
+ for (1..cells_width - 1) |x| {
+ wave.map[cells_height - 2][x] = .lane;
+ }
+
+ return wave;
+ }
+
+ fn get(self: *Wave, x: usize, y: usize) Cell {
+ if (x >= cells_width or y >= cells_height) {
+ return .none;
+ }
+ return self.map[y][x];
+ }
};
const Game = struct {
- camera: rl.Camera2D,
+ global_arena: std.heap.ArenaAllocator,
frame_arena: std.heap.ArenaAllocator,
+
+ texture_map: std.AutoHashMap(Cell, rl.Texture2D),
+
+ camera: rl.Camera2D,
wave: Wave,
fn init() Game {
+ var global_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+ const ga = global_arena.allocator();
+ var texture_map = std.AutoHashMap(Cell, rl.Texture2D).init(ga);
+
+ const lane = rl.loadTexture("assets/socket.png") catch unreachable;
+ const socket = rl.loadTexture("assets/lane.png") catch unreachable;
+ texture_map.put(.socket, lane) catch unreachable;
+ texture_map.put(.lane, socket) catch unreachable;
+
return .{
.camera = .{
.target = .{ .x = 128, .y = 128 },
.offset = .{
- .x = @as(f32, @floatFromInt(screen_width)) / 2,
- .y = @as(f32, @floatFromInt(screen_height)) / 2,
+ .x = @as(f32, @floatFromInt(screenWidth)) / 2,
+ .y = @as(f32, @floatFromInt(screenHeight)) / 2,
},
.rotation = 0,
- .zoom = @as(f32, @floatFromInt(screen_height)) / world_height,
+ .zoom = @as(f32, @floatFromInt(screenHeight)) / world_height,
},
+ .global_arena = global_arena,
.frame_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator),
- .wave = .{
- .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator),
- },
+ .wave = .init(),
+ .texture_map = texture_map,
};
}
+ fn deinit(self: *Game) void {
+ self.global_arena.deinit();
+ self.frame_arena.deinit();
+ }
+
fn frameStart(self: *Game) void {
const reset_successful = self.frame_arena.reset(.retain_capacity);
assert(reset_successful);
@@ -88,7 +155,7 @@ const Game = struct {
rl.beginDrawing();
defer rl.endDrawing();
- rl.clearBackground(rl.Color.sky_blue);
+ rl.clearBackground(bg_color);
{
rl.beginMode2D(camera);
@@ -96,25 +163,7 @@ const Game = struct {
for (0..map.len) |y| {
for (0..map[0].len) |x| {
- const cell = map[y][x];
- const isEven = (y + x) % 2 == 0;
- if (isEven) {
- rl.drawRectangle(
- @intCast(x * cell_size),
- @intCast(y * cell_size),
- cell_size,
- cell_size,
- rl.Color.green,
- );
- } else {
- rl.drawRectangle(
- @intCast(x * cell_size),
- @intCast(y * cell_size),
- cell_size,
- cell_size,
- cell.color,
- );
- }
+ drawCell(self, x, y);
}
}
}
@@ -122,19 +171,19 @@ const Game = struct {
rl.drawRectangle(
10,
10,
- @divTrunc(screen_width, 5),
- @divTrunc(screen_height, 5),
+ @divTrunc(screenWidth, 5),
+ @divTrunc(screenHeight, 5),
rl.fade(rl.Color.white, 0.6),
);
rl.drawRectangleLines(
10,
10,
- @divTrunc(screen_width, 5),
- @divTrunc(screen_height, 5),
+ @divTrunc(screenWidth, 5),
+ @divTrunc(screenHeight, 5),
rl.Color.black,
);
- const font_size = @divTrunc(screen_width, 80);
+ const font_size = @divTrunc(screenWidth, 80);
const debug_info = std.fmt.allocPrintZ(
a,
@@ -142,29 +191,71 @@ const Game = struct {
\\Screen: {}x{}
\\World: {}x{} ({})
,
- .{ rl.getFPS(), screen_width, screen_height, world_width, world_height, cell_size },
+ .{ rl.getFPS(), screenWidth, screenHeight, world_width, world_height, cell_size },
) catch return;
rl.drawText(debug_info, 20, 20, font_size, .black);
}
fn updateCamera(self: *Game) void {
- screen_width = rl.getScreenWidth();
- screen_height = rl.getScreenHeight();
+ screenWidth = rl.getScreenWidth();
+ screenHeight = rl.getScreenHeight();
self.camera.offset = .{
- .x = @as(f32, @floatFromInt(screen_width)) / 2,
- .y = @as(f32, @floatFromInt(screen_height)) / 2,
+ .x = @as(f32, @floatFromInt(screenWidth)) / 2,
+ .y = @as(f32, @floatFromInt(screenHeight)) / 2,
};
self.camera.target = .{
- .x = world_width / 2,
- .y = world_height / 2,
+ .x = world_width / 2.0,
+ .y = world_height / 2.0,
};
// Take the average between the ratios
// This avoids "cheating" by changing the ratio to an extreme value
// in order to see more terrain in a certain axis
- const width_ratio = @as(f32, @floatFromInt(screen_width)) / world_width;
- const height_ratio = @as(f32, @floatFromInt(screen_height)) / world_height;
+ const width_ratio = @as(f32, @floatFromInt(screenWidth)) / world_width;
+ const height_ratio = @as(f32, @floatFromInt(screenHeight)) / world_height;
self.camera.zoom = (width_ratio + height_ratio) / 2;
}
+
+ fn drawCell(self: *Game, x: usize, y: usize) void {
+ switch (self.wave.map[y][x]) {
+ .none => return,
+ .socket => {
+ const texture = self.texture_map.get(.socket).?;
+ rl.drawTexture(texture, @intCast(x * cell_size), @intCast(y * cell_size), rl.Color.white);
+ },
+ .lane => {
+ const texture = self.texture_map.get(.lane).?;
+
+ const lane_left = self.wave.get(x - 1, y).isLaneConnected();
+ const lane_right = self.wave.get(x + 1, y).isLaneConnected();
+ const lane_top = self.wave.get(x, y - 1).isLaneConnected();
+ const lane_bottom = self.wave.get(x, y + 1).isLaneConnected();
+
+ var offset: f32 = undefined;
+ if (lane_top and lane_left) {
+ offset = 3;
+ }
+ // TODO(kyren): do the rest
+
+ rl.drawTextureRec(
+ texture,
+ .{ .x = 0, .y = offset * cell_size, .width = cell_size, .height = cell_size },
+ .{ .x = @floatFromInt(x * cell_size), .y = @floatFromInt(y * cell_size) },
+ rl.Color.white,
+ );
+ },
+ .cpu => {},
+ .ai => {},
+ .color => |color| {
+ rl.drawRectangle(
+ @intCast(x * cell_size),
+ @intCast(y * cell_size),
+ cell_size,
+ cell_size,
+ color,
+ );
+ },
+ }
+ }
};