diff --git a/src/areas.zig b/src/area/areas.zig similarity index 93% rename from src/areas.zig rename to src/area/areas.zig index 5c7264b..77a9951 100644 --- a/src/areas.zig +++ b/src/area/areas.zig @@ -1,7 +1,7 @@ const std = @import("std"); const rl = @import("raylib"); const spawn_area = @import("spawn-area.zig"); -const structures = @import("structures.zig"); +const structures = @import("../structures.zig"); pub const Areas = struct { allocator: std.mem.Allocator, @@ -51,6 +51,12 @@ pub const Areas = struct { } } + pub fn recalculate(self: *Areas) void { + for (self.areas) |*area| { + area.setLocation(); + } + } + fn getEnumValuesMinusUsed(allocator: std.mem.Allocator, used_values: std.ArrayList(structures.AreaLocation), values: []const structures.AreaLocation) ![]structures.AreaLocation { var valuesToRandomise = try allocator.alloc(structures.AreaLocation, values.len - used_values.items.len); diff --git a/src/spawn-area.zig b/src/area/spawn-area.zig similarity index 88% rename from src/spawn-area.zig rename to src/area/spawn-area.zig index e0fd1d8..36c250d 100644 --- a/src/spawn-area.zig +++ b/src/area/spawn-area.zig @@ -1,11 +1,12 @@ +const std = @import("std"); const rl = @import("raylib"); -const structures = @import("structures.zig"); -const globals = @import("globals.zig"); +const structures = @import("../structures.zig"); +const globals = @import("../globals.zig"); +const car = @import("../car/car.zig"); pub const SpawnArea = struct { area: structures.AreaLocation, location: rl.Vector2, - // cars width: i32, height: i32, @@ -24,7 +25,7 @@ pub const SpawnArea = struct { } // todo if window size changes this needs to be recalculated - fn setLocation(self: *SpawnArea) void { + pub fn setLocation(self: *SpawnArea) void { self.location = switch (self.area) { .top_left => rl.Vector2{ .x = 0, .y = 0 }, .top_right => rl.Vector2{ .x = globals.getScreenWidthF32() - @as(f32, @floatFromInt(self.width)) * globals.getScale(), .y = 0 }, diff --git a/src/car.zig b/src/car.zig deleted file mode 100644 index b28d98a..0000000 --- a/src/car.zig +++ /dev/null @@ -1,8 +0,0 @@ -const rl = @import("raylib"); - -const Car = struct { - location: rl.Vector2, - color: rl.Color, - fuel: u7, - speed: u8, -}; diff --git a/src/car/car.zig b/src/car/car.zig new file mode 100644 index 0000000..746f369 --- /dev/null +++ b/src/car/car.zig @@ -0,0 +1,26 @@ +const rl = @import("raylib"); + +pub const Car = struct { + parent_location: rl.Vector2, + cell: [2]i32, + slot: [2]i32, + + location: rl.Vector2, + // todo destination + color: rl.Color, + fuel: f32, + speed: u8, + + pub fn init(parent_location: rl.Vector2, cells: [2]i32, slots: [2]i32) Car { + return Car{ + .parent_location = parent_location, + .cell = cells, + .slot = slots, + + .location = undefined, + .color = .dark_blue, + .fuel = 100.0, + .speed = 0, + }; + } +}; diff --git a/src/globals.zig b/src/globals.zig index a4b3520..db75abc 100644 --- a/src/globals.zig +++ b/src/globals.zig @@ -2,7 +2,7 @@ const rl = @import("raylib"); var screen_width: i32 = 1920; var screen_height: i32 = 1080; -const scale: f32 = 5.0; +const scale: f32 = 6.0; pub fn getScale() f32 { return scale; diff --git a/src/main.zig b/src/main.zig index 07241fb..49bfb45 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,7 +1,8 @@ const std = @import("std"); const rl = @import("raylib"); const globals = @import("globals.zig"); -const areas = @import("areas.zig"); +const areas = @import("area/areas.zig"); +const roadman_str = @import("road/road-manager.zig"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; @@ -19,8 +20,11 @@ pub fn main() !void { rl.maximizeWindow(); rl.setTargetFPS(60); - var spAreas = try areas.Areas.init(allocator, 3); - defer spAreas.deinit(); + var area_manager = try areas.Areas.init(allocator, 3); + defer area_manager.deinit(); + + var road_manager = roadman_str.RoadManager.init(allocator); + defer road_manager.deinit(); while (!rl.windowShouldClose()) { rl.beginDrawing(); @@ -29,14 +33,15 @@ pub fn main() !void { const new_width = rl.getScreenWidth(); const new_height = rl.getScreenHeight(); - // todo fix spawn area locations when resizing if (globals.checkWindowSizeChanged(new_width, new_height)) { globals.setWindowSize(new_width, new_height); + area_manager.recalculate(); } rl.clearBackground(.light_gray); - // draw areas - spAreas.draw(); + area_manager.draw(); + try road_manager.inputHandler(); + road_manager.draw(); } } diff --git a/src/road-data.zig b/src/road-data.zig new file mode 100644 index 0000000..4e97cc7 --- /dev/null +++ b/src/road-data.zig @@ -0,0 +1 @@ +pub const road_thickness: f32 = 10.0; diff --git a/src/road/road-manager.zig b/src/road/road-manager.zig new file mode 100644 index 0000000..21bef6e --- /dev/null +++ b/src/road/road-manager.zig @@ -0,0 +1,113 @@ +const std = @import("std"); +const rl = @import("raylib"); +const road_str = @import("road.zig"); +const road_data = @import("../road-data.zig"); +const globals = @import("../globals.zig"); + +pub const RoadManager = struct { + buffer: f32, + allocator: std.mem.Allocator, + roads: std.ArrayList(road_str.Road), + delete_mode: bool, + selected_road: ?usize, + + pub fn init(allocator: std.mem.Allocator) RoadManager { + return RoadManager{ + .buffer = road_data.road_thickness * globals.getScale() / 2.0, + .allocator = allocator, + .roads = std.ArrayList(road_str.Road).init(allocator), + .delete_mode = false, + .selected_road = null, + }; + } + + pub fn deinit(self: *RoadManager) void { + self.roads.deinit(); + } + + fn addRoad(self: *RoadManager, pos: rl.Vector2) !void { + // IF we have already one road that is incomplete + const last_id = self.getLastIndex(); + + // if last road exists and is not fully built + if (last_id != null and self.roads.items[last_id.?].end_point == null) { + self.roads.items[last_id.?].confirmRoad(pos); + } + + try self.roads.append(road_str.Road.init(pos)); + } + + fn removeLastRoad(self: *RoadManager) void { + _ = self.roads.pop(); + } + + fn clearRoads(self: *RoadManager) void { + self.roads.clearAndFree(); + } + + fn trackRoad(self: *RoadManager, pos: rl.Vector2) void { + if (!self.delete_mode) return; + + self.setDefaultColour(); + self.selected_road = null; + + for (self.roads.items) |*road| { + // we skip because that road is not complete + if (road.end_point == null) continue; + + if (cursorOnRoad(road.start_point, pos, road.end_point)) { + road.*.setColor(true); + // todo pointer or index + break; + } + } + } + + fn cursorOnRoad(start: rl.Vector2, cursor: rl.Vector2, end: rl.Vector2) bool {} + + pub fn inputHandler(self: *RoadManager) !void { + const pos = rl.getMousePosition(); + trackRoad(pos); + + // mouse inputs + if (rl.isMouseButtonReleased(.left)) { + if (self.delete_mode) { + if (self.selected_road == null) return; + // todo might be a problem in the future swapping modes must clear any unfinished roads! + self.roads.swapRemove(self.selected_road.?); + } else { + try self.addRoad(pos); + } + } else if (rl.isMouseButtonReleased(.right)) { + self.removeLastRoad(); + } + + // keyboard inputs + if (rl.isKeyReleased(.c)) { + self.clearRoads(); + } else if (rl.isKeyReleased(.d)) { + self.delete_mode = !self.delete_mode; + if (!self.delete_mode) { + self.setDefaultColour(); + self.selected_road = null; + } + } + } + + pub fn draw(self: *const RoadManager) void { + for (self.roads.items) |road| { + road.draw(); + } + } + + fn getLastIndex(self: *const RoadManager) ?usize { + if (self.roads.items.len == 0) return null; + return self.roads.items.len - 1; + } + + fn setDefaultColour(self: *RoadManager) void { + for (self.roads.items) |*road| { + road.setColor(false); + } + } +}; diff --git a/src/road/road.zig b/src/road/road.zig new file mode 100644 index 0000000..6e63fa1 --- /dev/null +++ b/src/road/road.zig @@ -0,0 +1,30 @@ +const rl = @import("raylib"); +const globals = @import("../globals.zig"); +const road_data = @import("../road-data.zig"); + +pub const Road = struct { + color: rl.Color, + start_point: rl.Vector2, + end_point: ?rl.Vector2, + + pub fn init(pos: rl.Vector2) Road { + return Road{ + .color = .black, + .start_point = pos, + .end_point = null, + }; + } + + pub fn confirmRoad(self: *Road, pos: rl.Vector2) void { + self.end_point = pos; + } + + pub fn setColor(self: *Road, is_selected: bool) void { + self.color = if (is_selected) .green else .black; + } + + pub fn draw(self: *const Road) void { + const pos = rl.getMousePosition(); + rl.drawLineEx(self.start_point, self.end_point orelse pos, road_data.road_thickness * globals.getScale(), self.color); + } +};