improved roadbuilding
This commit is contained in:
parent
147202d053
commit
2e8ebaa737
@ -37,8 +37,8 @@
|
|||||||
// internet connectivity.
|
// internet connectivity.
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.raylib_zig = .{
|
.raylib_zig = .{
|
||||||
.url = "git+https://github.com/Not-Nik/raylib-zig?ref=devel#5013830647196ba938a3a25a36b8245606e9a9cd",
|
.url = "git+https://github.com/Not-Nik/raylib-zig?ref=devel#e8167c2e560402510220fdf419afbc7c2fc51e5d",
|
||||||
.hash = "raylib_zig-5.6.0-dev-KE8REM0tBQAHVn9Xjqlgu9l1qgfTmP8aJa1kLhD584bV",
|
.hash = "raylib_zig-5.6.0-dev-KE8REIouBQDbt-DSHmhUc9YFjJ_pFUS5tvRDPnBzsMdU",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
@ -7,15 +7,19 @@ const car = @import("../car/car.zig");
|
|||||||
pub const SpawnArea = struct {
|
pub const SpawnArea = struct {
|
||||||
area: structures.AreaLocation,
|
area: structures.AreaLocation,
|
||||||
location: rl.Vector2,
|
location: rl.Vector2,
|
||||||
|
calculated: rl.Vector2, // x/y + width/height * scale
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
|
red_line_th: f32,
|
||||||
|
|
||||||
pub fn init(area_loc: structures.AreaLocation) SpawnArea {
|
pub fn init(area_loc: structures.AreaLocation) SpawnArea {
|
||||||
var new_spawn = SpawnArea{
|
var new_spawn = SpawnArea{
|
||||||
.area = area_loc,
|
.area = area_loc,
|
||||||
.location = undefined,
|
.location = undefined,
|
||||||
|
.calculated = undefined,
|
||||||
.width = 100,
|
.width = 100,
|
||||||
.height = 50,
|
.height = 50,
|
||||||
|
.red_line_th = 5.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// need to do this outside the "constructor", as the function needs reference to self
|
// 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_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() },
|
.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 {
|
pub fn getNodeLocation(self: *const SpawnArea) rl.Vector2 {
|
||||||
@ -49,53 +56,9 @@ pub const SpawnArea = struct {
|
|||||||
};
|
};
|
||||||
rl.drawRectangleRec(rect, .dark_gray);
|
rl.drawRectangleRec(rect, .dark_gray);
|
||||||
|
|
||||||
// red line for hover
|
// TODO implement a functionality which will prevent user from drawing near corner
|
||||||
if (self.checkHover()) {
|
// when the corner is touched road will not follow through it will be forbiden
|
||||||
var start_pos: rl.Vector2 = undefined;
|
// and the corner rectangle will start shining
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkHover(self: *const SpawnArea) bool {
|
fn checkHover(self: *const SpawnArea) bool {
|
||||||
|
@ -16,7 +16,7 @@ pub const Car = struct {
|
|||||||
.parent_location = parent_location,
|
.parent_location = parent_location,
|
||||||
.cell = cells,
|
.cell = cells,
|
||||||
.slot = slots,
|
.slot = slots,
|
||||||
|
// destination (will be described as an area the car will try to reach)
|
||||||
.location = undefined,
|
.location = undefined,
|
||||||
.color = .dark_blue,
|
.color = .dark_blue,
|
||||||
.fuel = 100.0,
|
.fuel = 100.0,
|
||||||
|
@ -19,16 +19,14 @@ pub fn main() !void {
|
|||||||
|
|
||||||
rl.setExitKey(.null);
|
rl.setExitKey(.null);
|
||||||
rl.maximizeWindow();
|
rl.maximizeWindow();
|
||||||
rl.setTargetFPS(60);
|
rl.setTargetFPS(144);
|
||||||
|
|
||||||
var area_manager = try areas.Areas.init(allocator, 4);
|
var area_manager = try areas.Areas.init(allocator, 4);
|
||||||
defer area_manager.deinit();
|
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();
|
defer road_manager.deinit();
|
||||||
|
|
||||||
try road_manager.addAreaNodes(area_manager);
|
|
||||||
|
|
||||||
while (!rl.windowShouldClose()) {
|
while (!rl.windowShouldClose()) {
|
||||||
rl.beginDrawing();
|
rl.beginDrawing();
|
||||||
defer rl.endDrawing();
|
defer rl.endDrawing();
|
||||||
@ -40,8 +38,7 @@ pub fn main() !void {
|
|||||||
globals.setWindowSize(new_width, new_height);
|
globals.setWindowSize(new_width, new_height);
|
||||||
area_manager.recalculate();
|
area_manager.recalculate();
|
||||||
try road_manager.updateAreaNodes(area_manager);
|
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);
|
rl.clearBackground(.light_gray);
|
||||||
|
@ -16,9 +16,14 @@ pub const RoadManager = struct {
|
|||||||
mode: str.InputMode,
|
mode: str.InputMode,
|
||||||
selected_road: ?usize,
|
selected_road: ?usize,
|
||||||
min_distance: f32,
|
min_distance: f32,
|
||||||
|
area_num: usize,
|
||||||
|
temp_nodes: bool,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) RoadManager {
|
pub fn init(allocator: std.mem.Allocator, areas: area_str.Areas) !RoadManager {
|
||||||
return RoadManager{
|
const nodes = try areas.getNodes();
|
||||||
|
defer allocator.free(nodes);
|
||||||
|
|
||||||
|
var road_man = RoadManager{
|
||||||
.buffer = road_data.road_thickness * globals.getScale() / 2.0,
|
.buffer = road_data.road_thickness * globals.getScale() / 2.0,
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.roads = std.ArrayList(road_str.Road).init(allocator),
|
.roads = std.ArrayList(road_str.Road).init(allocator),
|
||||||
@ -26,7 +31,12 @@ pub const RoadManager = struct {
|
|||||||
.mode = str.InputMode.normal,
|
.mode = str.InputMode.normal,
|
||||||
.selected_road = null,
|
.selected_road = null,
|
||||||
.min_distance = globals.getScreenWidthF32() / 25.0,
|
.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 {
|
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 road exists and is not fully built
|
||||||
if (last_id != null and self.roads.items[last_id.?].end_point == null) {
|
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
|
// 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 (rl.Vector2.distance(self.roads.items[last_id.?].start_point, pos) < self.min_distance) return;
|
||||||
// if too close to existing nodes, return
|
// only if close enough to node AND TODO THEN FORCE THE FUCKER TO SNAP ON IT
|
||||||
if (!self.canCreateNode(pos)) return;
|
|
||||||
|
|
||||||
self.roads.items[last_id.?].confirmRoad(pos);
|
self.roads.items[last_id.?].confirmRoad(pos);
|
||||||
try self.nodes.append(node_str.Node.init(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));
|
try self.roads.append(road_str.Road.init(pos));
|
||||||
@ -66,9 +79,7 @@ pub const RoadManager = struct {
|
|||||||
|
|
||||||
fn clearRoads(self: *RoadManager) void {
|
fn clearRoads(self: *RoadManager) void {
|
||||||
self.roads.clearAndFree();
|
self.roads.clearAndFree();
|
||||||
// todo this will delete spawn nodes which MUST NOT be deleted
|
self.nodes.shrinkAndFree(self.area_num);
|
||||||
// fix at earliest convinience
|
|
||||||
self.nodes.clearAndFree();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trackRoad(self: *RoadManager, pos: rl.Vector2) void {
|
fn trackRoad(self: *RoadManager, pos: rl.Vector2) void {
|
||||||
@ -124,13 +135,19 @@ pub const RoadManager = struct {
|
|||||||
|
|
||||||
fn handleKeyboardInput(self: *RoadManager) void {
|
fn handleKeyboardInput(self: *RoadManager) void {
|
||||||
// keyboard inputs
|
// keyboard inputs
|
||||||
if (rl.isKeyReleased(.c)) {
|
if (rl.isKeyReleased(.b)) {
|
||||||
|
self.toggleMode(str.InputMode.build);
|
||||||
|
} else if (rl.isKeyReleased(.c)) {
|
||||||
self.clearRoads();
|
self.clearRoads();
|
||||||
} else if (rl.isKeyReleased(.d)) {
|
} else if (rl.isKeyReleased(.d)) {
|
||||||
self.toggleDeleteMode();
|
self.toggleMode(str.InputMode.delete);
|
||||||
} else if (rl.isKeyReleased(.n)) {
|
} 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 {
|
fn handleMouseInput(self: *RoadManager) !void {
|
||||||
@ -144,7 +161,7 @@ pub const RoadManager = struct {
|
|||||||
|
|
||||||
fn handleLeftClick(self: *RoadManager) !void {
|
fn handleLeftClick(self: *RoadManager) !void {
|
||||||
switch (self.mode) {
|
switch (self.mode) {
|
||||||
.normal => try self.addRoad(rl.getMousePosition()),
|
.normal => {},
|
||||||
.delete => {
|
.delete => {
|
||||||
if (self.selected_road == null) return;
|
if (self.selected_road == null) return;
|
||||||
|
|
||||||
@ -152,27 +169,15 @@ pub const RoadManager = struct {
|
|||||||
self.selected_road = null;
|
self.selected_road = null;
|
||||||
},
|
},
|
||||||
.node => {},
|
.node => {},
|
||||||
|
.build => try self.addRoad(rl.getMousePosition()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggleDeleteMode(self: *RoadManager) void {
|
fn toggleMode(self: *RoadManager, mode: str.InputMode) void {
|
||||||
self.togglePrepare();
|
self.togglePrepare();
|
||||||
|
|
||||||
self.mode = switch (self.mode) {
|
if (self.mode != mode)
|
||||||
.normal => str.InputMode.delete,
|
self.mode = mode;
|
||||||
.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,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn togglePrepare(self: *RoadManager) void {
|
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| {
|
for (self.nodes.items) |node| {
|
||||||
node.draw(true);
|
node.draw(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawMode(self: *const RoadManager) !void {
|
pub fn drawMode(self: *const RoadManager) !void {
|
||||||
const prefix = "Mode: ";
|
|
||||||
const text = @tagName(self.mode); // this turns an enum into string like "normal"
|
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);
|
defer self.allocator.free(full_text);
|
||||||
|
|
||||||
// draw funct
|
|
||||||
rl.drawText(full_text, @divTrunc(globals.getScreenWidth(), 3), 50, 100, .dark_blue);
|
rl.drawText(full_text, @divTrunc(globals.getScreenWidth(), 3), 50, 100, .dark_blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,13 +242,6 @@ pub const RoadManager = struct {
|
|||||||
self.selected_road = null;
|
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 {
|
pub fn updateAreaNodes(self: *RoadManager, areas: area_str.Areas) !void {
|
||||||
const nodes = try areas.getNodes();
|
const nodes = try areas.getNodes();
|
||||||
defer self.allocator.free(nodes);
|
defer self.allocator.free(nodes);
|
||||||
|
@ -11,6 +11,7 @@ pub const InputMode = enum {
|
|||||||
normal,
|
normal,
|
||||||
delete,
|
delete,
|
||||||
node,
|
node,
|
||||||
|
build,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RoadState = enum {
|
pub const RoadState = enum {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user