From 2e8ebaa737a9bdcf146a606e3bf237f551c93c9c Mon Sep 17 00:00:00 2001 From: Marto Date: Wed, 23 Jul 2025 21:38:55 +0200 Subject: [PATCH] improved roadbuilding --- build.zig.zon | 4 +-- src/area/spawn-area.zig | 57 ++++++------------------------- src/car/car.zig | 2 +- src/main.zig | 9 ++--- src/road/road-manager.zig | 72 ++++++++++++++++++--------------------- src/structures.zig | 1 + 6 files changed, 51 insertions(+), 94 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index bc9065e..77bd21f 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -37,8 +37,8 @@ // internet connectivity. .dependencies = .{ .raylib_zig = .{ - .url = "git+https://github.com/Not-Nik/raylib-zig?ref=devel#5013830647196ba938a3a25a36b8245606e9a9cd", - .hash = "raylib_zig-5.6.0-dev-KE8REM0tBQAHVn9Xjqlgu9l1qgfTmP8aJa1kLhD584bV", + .url = "git+https://github.com/Not-Nik/raylib-zig?ref=devel#e8167c2e560402510220fdf419afbc7c2fc51e5d", + .hash = "raylib_zig-5.6.0-dev-KE8REIouBQDbt-DSHmhUc9YFjJ_pFUS5tvRDPnBzsMdU", }, }, .paths = .{ diff --git a/src/area/spawn-area.zig b/src/area/spawn-area.zig index 77002b6..3af1158 100644 --- a/src/area/spawn-area.zig +++ b/src/area/spawn-area.zig @@ -7,15 +7,19 @@ const car = @import("../car/car.zig"); pub const SpawnArea = struct { area: structures.AreaLocation, location: rl.Vector2, + calculated: rl.Vector2, // x/y + width/height * scale width: i32, height: i32, + red_line_th: f32, pub fn init(area_loc: structures.AreaLocation) SpawnArea { var new_spawn = SpawnArea{ .area = area_loc, .location = undefined, + .calculated = undefined, .width = 100, .height = 50, + .red_line_th = 5.0, }; // need to do this outside the "constructor", as the function needs reference to self @@ -31,6 +35,9 @@ pub const SpawnArea = struct { .bottom_left => rl.Vector2{ .x = 0, .y = globals.getScreenHeightF32() - @as(f32, @floatFromInt(self.height)) * globals.getScale() }, .bottom_right => rl.Vector2{ .x = globals.getScreenWidthF32() - @as(f32, @floatFromInt(self.width)) * globals.getScale(), .y = globals.getScreenHeightF32() - @as(f32, @floatFromInt(self.height)) * globals.getScale() }, }; + + self.calculated.x = self.location.x + intToFloat(self.width) * globals.getScale(); + self.calculated.y = self.location.y + intToFloat(self.height) * globals.getScale(); } pub fn getNodeLocation(self: *const SpawnArea) rl.Vector2 { @@ -49,53 +56,9 @@ pub const SpawnArea = struct { }; rl.drawRectangleRec(rect, .dark_gray); - // red line for hover - if (self.checkHover()) { - var start_pos: rl.Vector2 = undefined; - var end_pos: rl.Vector2 = undefined; - - // this should be precalculated shouldn't need do calculate this each time just for the sake of drawing it - switch (self.area) { - .top_left => { - start_pos = rl.Vector2 { - .x = self.location.x + intToFloat(self.width) * globals.getScale(), - .y = self.location.y, - }; - - end_pos = rl.Vector2 { - .x = start_pos.x, - .y = self.location.y + intToFloat(self.height) * globals.getScale(), - }; - }, - .top_right => { - start_pos = self.location; - end_pos = rl.Vector2 { - .x = start_pos.x, - .y = self.location.y + intToFloat(self.height) * globals.getScale(), - }; - }, - .bottom_left => { - start_pos = rl.Vector2 { - .x = self.location.x + intToFloat(self.width) * globals.getScale(), - .y = self.location.y, - }; - - end_pos = rl.Vector2 { - .x = start_pos.x, - .y = self.location.y + intToFloat(self.height) * globals.getScale(), - }; - }, - .bottom_right => { - start_pos = self.location; - end_pos = rl.Vector2 { - .x = start_pos.x, - .y = self.location.y + intToFloat(self.height) * globals.getScale(), - }; - } - } - - rl.drawLineEx(start_pos, end_pos, 5, .red); - } + // TODO implement a functionality which will prevent user from drawing near corner + // when the corner is touched road will not follow through it will be forbiden + // and the corner rectangle will start shining } fn checkHover(self: *const SpawnArea) bool { diff --git a/src/car/car.zig b/src/car/car.zig index 746f369..dd7c068 100644 --- a/src/car/car.zig +++ b/src/car/car.zig @@ -16,7 +16,7 @@ pub const Car = struct { .parent_location = parent_location, .cell = cells, .slot = slots, - + // destination (will be described as an area the car will try to reach) .location = undefined, .color = .dark_blue, .fuel = 100.0, diff --git a/src/main.zig b/src/main.zig index b279107..d8afe95 100644 --- a/src/main.zig +++ b/src/main.zig @@ -19,16 +19,14 @@ pub fn main() !void { rl.setExitKey(.null); rl.maximizeWindow(); - rl.setTargetFPS(60); + rl.setTargetFPS(144); var area_manager = try areas.Areas.init(allocator, 4); defer area_manager.deinit(); - var road_manager = roadman_str.RoadManager.init(allocator); + var road_manager = try roadman_str.RoadManager.init(allocator, area_manager); defer road_manager.deinit(); - try road_manager.addAreaNodes(area_manager); - while (!rl.windowShouldClose()) { rl.beginDrawing(); defer rl.endDrawing(); @@ -40,8 +38,7 @@ pub fn main() !void { globals.setWindowSize(new_width, new_height); area_manager.recalculate(); try road_manager.updateAreaNodes(area_manager); - // todo this will bring some trouble because what if other nodes/roads, when resized, will be placed upon existing spawn area - + // this will bring some trouble because what if other nodes/roads, when resized, will be placed upon existing spawn area } rl.clearBackground(.light_gray); diff --git a/src/road/road-manager.zig b/src/road/road-manager.zig index 81b04cc..eee1351 100644 --- a/src/road/road-manager.zig +++ b/src/road/road-manager.zig @@ -16,9 +16,14 @@ pub const RoadManager = struct { mode: str.InputMode, selected_road: ?usize, min_distance: f32, + area_num: usize, + temp_nodes: bool, - pub fn init(allocator: std.mem.Allocator) RoadManager { - return RoadManager{ + pub fn init(allocator: std.mem.Allocator, areas: area_str.Areas) !RoadManager { + const nodes = try areas.getNodes(); + defer allocator.free(nodes); + + var road_man = RoadManager{ .buffer = road_data.road_thickness * globals.getScale() / 2.0, .allocator = allocator, .roads = std.ArrayList(road_str.Road).init(allocator), @@ -26,7 +31,12 @@ pub const RoadManager = struct { .mode = str.InputMode.normal, .selected_road = null, .min_distance = globals.getScreenWidthF32() / 25.0, + .area_num = nodes.len, + .temp_nodes = false, }; + + try road_man.nodes.appendSlice(nodes); + return road_man; } pub fn deinit(self: *RoadManager) void { @@ -40,13 +50,16 @@ pub const RoadManager = struct { // if last road exists and is not fully built if (last_id != null and self.roads.items[last_id.?].end_point == null) { + // TODO RETURN IF MOUSE IS IN AREA!!! (we can only draw roads from there) + // only confirm if distance is minimal or greater if (rl.Vector2.distance(self.roads.items[last_id.?].start_point, pos) < self.min_distance) return; - // if too close to existing nodes, return - if (!self.canCreateNode(pos)) return; + // only if close enough to node AND TODO THEN FORCE THE FUCKER TO SNAP ON IT self.roads.items[last_id.?].confirmRoad(pos); try self.nodes.append(node_str.Node.init(pos)); + } else if (self.canCreateNode(pos)) { + return; } try self.roads.append(road_str.Road.init(pos)); @@ -66,9 +79,7 @@ pub const RoadManager = struct { fn clearRoads(self: *RoadManager) void { self.roads.clearAndFree(); - // todo this will delete spawn nodes which MUST NOT be deleted - // fix at earliest convinience - self.nodes.clearAndFree(); + self.nodes.shrinkAndFree(self.area_num); } fn trackRoad(self: *RoadManager, pos: rl.Vector2) void { @@ -124,13 +135,19 @@ pub const RoadManager = struct { fn handleKeyboardInput(self: *RoadManager) void { // keyboard inputs - if (rl.isKeyReleased(.c)) { + if (rl.isKeyReleased(.b)) { + self.toggleMode(str.InputMode.build); + } else if (rl.isKeyReleased(.c)) { self.clearRoads(); } else if (rl.isKeyReleased(.d)) { - self.toggleDeleteMode(); + self.toggleMode(str.InputMode.delete); } else if (rl.isKeyReleased(.n)) { - self.toggleNodeMode(); + self.toggleMode(str.InputMode.node); + } else if (rl.isKeyReleased(.escape)) { + self.toggleMode(str.InputMode.normal); } + + self.temp_nodes = rl.isKeyDown(.left_control); } fn handleMouseInput(self: *RoadManager) !void { @@ -144,7 +161,7 @@ pub const RoadManager = struct { fn handleLeftClick(self: *RoadManager) !void { switch (self.mode) { - .normal => try self.addRoad(rl.getMousePosition()), + .normal => {}, .delete => { if (self.selected_road == null) return; @@ -152,27 +169,15 @@ pub const RoadManager = struct { self.selected_road = null; }, .node => {}, + .build => try self.addRoad(rl.getMousePosition()), } } - fn toggleDeleteMode(self: *RoadManager) void { + fn toggleMode(self: *RoadManager, mode: str.InputMode) void { self.togglePrepare(); - self.mode = switch (self.mode) { - .normal => str.InputMode.delete, - .delete => str.InputMode.normal, - .node => str.InputMode.delete, - }; - } - - fn toggleNodeMode(self: *RoadManager) void { - self.togglePrepare(); - - self.mode = switch (self.mode) { - .normal => str.InputMode.node, - .delete => str.InputMode.node, - .node => str.InputMode.normal, - }; + if (self.mode != mode) + self.mode = mode; } fn togglePrepare(self: *RoadManager) void { @@ -207,19 +212,17 @@ pub const RoadManager = struct { } } - if (self.mode != str.InputMode.node) return; + if (self.mode != str.InputMode.node and !self.temp_nodes) return; for (self.nodes.items) |node| { node.draw(true); } } pub fn drawMode(self: *const RoadManager) !void { - const prefix = "Mode: "; const text = @tagName(self.mode); // this turns an enum into string like "normal" - const full_text = try std.fmt.allocPrintZ(self.allocator, "{s}{s}", .{ prefix, text }); + const full_text = try std.fmt.allocPrintZ(self.allocator, "Mode: {s}", .{text}); defer self.allocator.free(full_text); - // draw funct rl.drawText(full_text, @divTrunc(globals.getScreenWidth(), 3), 50, 100, .dark_blue); } @@ -239,13 +242,6 @@ pub const RoadManager = struct { self.selected_road = null; } - pub fn addAreaNodes(self: *RoadManager, areas: area_str.Areas) !void { - const nodes = try areas.getNodes(); - defer self.allocator.free(nodes); - - try self.nodes.appendSlice(nodes); - } - pub fn updateAreaNodes(self: *RoadManager, areas: area_str.Areas) !void { const nodes = try areas.getNodes(); defer self.allocator.free(nodes); diff --git a/src/structures.zig b/src/structures.zig index bc2bb62..72d2c23 100644 --- a/src/structures.zig +++ b/src/structures.zig @@ -11,6 +11,7 @@ pub const InputMode = enum { normal, delete, node, + build, }; pub const RoadState = enum {