improved roadbuilding
This commit is contained in:
		@@ -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 = .{
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ pub const InputMode = enum {
 | 
			
		||||
    normal,
 | 
			
		||||
    delete,
 | 
			
		||||
    node,
 | 
			
		||||
    build,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub const RoadState = enum {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user