Decks
The code is getting real messy...
This commit is contained in:
163
src/world.zig
163
src/world.zig
@@ -12,10 +12,10 @@ const Order = i32;
|
|||||||
pub var object_map: std.AutoHashMapUnmanaged(Id, usize) = .{};
|
pub var object_map: std.AutoHashMapUnmanaged(Id, usize) = .{};
|
||||||
pub var objects: std.ArrayListUnmanaged(Object) = .{};
|
pub var objects: std.ArrayListUnmanaged(Object) = .{};
|
||||||
|
|
||||||
pub var plane_mesh: Graphics.Mesh = undefined;
|
pub var hand_mesh: Graphics.Mesh = undefined;
|
||||||
pub var cube_mesh: Graphics.Mesh = undefined;
|
pub var cube_mesh: Graphics.Mesh = undefined;
|
||||||
pub var table_mesh: Graphics.Mesh = undefined;
|
pub var table_mesh: Graphics.Mesh = undefined;
|
||||||
pub var texture: Assets.Texture = undefined;
|
pub var table_texture: Assets.Texture = undefined;
|
||||||
pub var hand_texture: Assets.Texture = undefined;
|
pub var hand_texture: Assets.Texture = undefined;
|
||||||
|
|
||||||
pub var camera_position: @Vector(2, f32) = @splat(0);
|
pub var camera_position: @Vector(2, f32) = @splat(0);
|
||||||
@@ -34,7 +34,12 @@ pub var dock_spacing: f32 = 0;
|
|||||||
pub var min_order: Order = undefined;
|
pub var min_order: Order = undefined;
|
||||||
pub var max_order: Order = undefined;
|
pub var max_order: Order = undefined;
|
||||||
|
|
||||||
|
const DOCK_TILT = 0.03;
|
||||||
|
const DOCK_TILT_SIN = std.math.sin(DOCK_TILT);
|
||||||
|
const DOCK_TILT_COS = std.math.cos(DOCK_TILT);
|
||||||
|
|
||||||
const Object = struct {
|
const Object = struct {
|
||||||
|
type: Type,
|
||||||
transform: Graphics.Transform = .{},
|
transform: Graphics.Transform = .{},
|
||||||
target_transform: Graphics.Transform = .{},
|
target_transform: Graphics.Transform = .{},
|
||||||
width: f32,
|
width: f32,
|
||||||
@@ -44,14 +49,21 @@ const Object = struct {
|
|||||||
order: Order,
|
order: Order,
|
||||||
id: Id,
|
id: Id,
|
||||||
index: u32,
|
index: u32,
|
||||||
|
z: u32 = 0,
|
||||||
parent: Parent = .none,
|
parent: Parent = .none,
|
||||||
parent_index: u32 = 0,
|
parent_index: u32 = 0,
|
||||||
|
child_last_id: u32 = 0,
|
||||||
influence: f32 = 0,
|
influence: f32 = 0,
|
||||||
|
|
||||||
const Parent = enum {
|
const Type = enum {
|
||||||
|
card,
|
||||||
|
deck,
|
||||||
|
};
|
||||||
|
const Parent = union(enum) {
|
||||||
none,
|
none,
|
||||||
hand,
|
hand,
|
||||||
dock,
|
dock,
|
||||||
|
deck: Id,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn reparent(self: *@This(), new_parent: Parent) void {
|
pub fn reparent(self: *@This(), new_parent: Parent) void {
|
||||||
@@ -64,7 +76,8 @@ const Object = struct {
|
|||||||
const parent_transform = switch (self.parent) {
|
const parent_transform = switch (self.parent) {
|
||||||
.hand => World.hand_transform,
|
.hand => World.hand_transform,
|
||||||
.dock => World.dock_transform,
|
.dock => World.dock_transform,
|
||||||
else => return transform,
|
.deck => |deck| if (World.getObject(deck)) |object| object.drawingTransform() else Graphics.Transform{},
|
||||||
|
.none => return transform,
|
||||||
};
|
};
|
||||||
return Graphics.Transform.combineTransforms(
|
return Graphics.Transform.combineTransforms(
|
||||||
transform,
|
transform,
|
||||||
@@ -80,22 +93,48 @@ const Object = struct {
|
|||||||
const World = @This();
|
const World = @This();
|
||||||
pub fn initDebug() void {
|
pub fn initDebug() void {
|
||||||
for (0..10) |i| {
|
for (0..10) |i| {
|
||||||
(World.objects.addOne(Game.alloc) catch err.oom()).* = .{
|
World.objects.append(Game.alloc, .{
|
||||||
|
.type = .card,
|
||||||
.width = 0.5,
|
.width = 0.5,
|
||||||
.height = 0.5,
|
.height = 0.5,
|
||||||
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(15.0 / 16.0, @as(f32, @floatFromInt(i)) / 16.0, 16.0 / 16.0, @as(f32, @floatFromInt(i + 1)) / 16.0, 0.5, 0.5))),
|
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
|
||||||
|
15.0 / 16.0,
|
||||||
|
@as(f32, @floatFromInt(i)) / 16.0,
|
||||||
|
16.0 / 16.0,
|
||||||
|
@as(f32, @floatFromInt(i + 1)) / 16.0,
|
||||||
|
0.5,
|
||||||
|
0.5,
|
||||||
|
))),
|
||||||
.texture = Assets.load(.texture, "data/yakuza.png"),
|
.texture = Assets.load(.texture, "data/yakuza.png"),
|
||||||
.order = @intCast(i),
|
.order = @intCast(i),
|
||||||
.id = @intCast(i),
|
.id = @intCast(i),
|
||||||
.index = @intCast(i),
|
.index = @intCast(i),
|
||||||
};
|
.parent = .{ .deck = 10 },
|
||||||
|
}) catch err.oom();
|
||||||
World.object_map.put(Game.alloc, @intCast(i), i) catch err.oom();
|
World.object_map.put(Game.alloc, @intCast(i), i) catch err.oom();
|
||||||
}
|
}
|
||||||
Assets.free(Assets.load(.texture, "data/yakuza.png"));
|
World.objects.append(Game.alloc, .{
|
||||||
|
.type = .deck,
|
||||||
|
.width = 1,
|
||||||
|
.height = 1,
|
||||||
|
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
|
||||||
|
0.0 / 8.0,
|
||||||
|
4.0 / 8.0,
|
||||||
|
1.0 / 8.0,
|
||||||
|
5.0 / 8.0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
))),
|
||||||
|
.texture = Assets.load(.texture, "data/yakuza.png"),
|
||||||
|
.order = 10,
|
||||||
|
.id = 10,
|
||||||
|
.index = 10,
|
||||||
|
}) catch err.oom();
|
||||||
|
World.object_map.put(Game.alloc, 10, 10) catch err.oom();
|
||||||
|
|
||||||
World.plane_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
|
|
||||||
World.table_mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(0, 0, 0.5, 0.5, 8, 8)));
|
World.table_mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(0, 0, 0.5, 0.5, 8, 8)));
|
||||||
World.texture = Assets.load(.texture, "data/yakuza.png");
|
World.hand_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
|
||||||
|
World.table_texture = Assets.load(.texture, "data/yakuza.png");
|
||||||
World.hand_texture = Assets.load(.texture, "data/hand.png");
|
World.hand_texture = Assets.load(.texture, "data/hand.png");
|
||||||
|
|
||||||
World.camera_position = @splat(0);
|
World.camera_position = @splat(0);
|
||||||
@@ -110,13 +149,13 @@ pub fn initDebug() void {
|
|||||||
World.panning = false;
|
World.panning = false;
|
||||||
World.dock_focused = false;
|
World.dock_focused = false;
|
||||||
World.min_order = 0;
|
World.min_order = 0;
|
||||||
World.max_order = 9;
|
World.max_order = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub fn deinit() void {
|
||||||
Graphics.unloadMesh(World.plane_mesh);
|
|
||||||
Graphics.unloadMesh(World.table_mesh);
|
Graphics.unloadMesh(World.table_mesh);
|
||||||
Assets.free(World.texture);
|
Graphics.unloadMesh(World.hand_mesh);
|
||||||
|
Assets.free(World.table_texture);
|
||||||
Assets.free(World.hand_texture);
|
Assets.free(World.hand_texture);
|
||||||
for (World.objects.items) |*object| {
|
for (World.objects.items) |*object| {
|
||||||
Assets.free(object.texture);
|
Assets.free(object.texture);
|
||||||
@@ -166,7 +205,6 @@ pub fn update(delta: f32) void {
|
|||||||
|
|
||||||
pub fn updateControls() void {
|
pub fn updateControls() void {
|
||||||
if (Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
|
if (Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
|
||||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) World.panning = true;
|
|
||||||
if (Game.mouse.wheel > 0 and World.hand_objects > 0) {
|
if (Game.mouse.wheel > 0 and World.hand_objects > 0) {
|
||||||
var left_to_scroll = @rem(Game.mouse.wheel, @as(i32, @intCast(World.hand_objects)));
|
var left_to_scroll = @rem(Game.mouse.wheel, @as(i32, @intCast(World.hand_objects)));
|
||||||
var i = World.objects.items.len - 1;
|
var i = World.objects.items.len - 1;
|
||||||
@@ -190,14 +228,14 @@ pub fn updateControls() void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) {
|
|
||||||
World.panning = !World.tryPick();
|
|
||||||
}
|
|
||||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_RIGHT)) {
|
|
||||||
_ = World.tryRelease();
|
|
||||||
}
|
|
||||||
World.zoom = std.math.clamp(World.zoom + Game.mouse.wheel, -4, 8);
|
World.zoom = std.math.clamp(World.zoom + Game.mouse.wheel, -4, 8);
|
||||||
}
|
}
|
||||||
|
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) {
|
||||||
|
World.panning = !World.tryPick();
|
||||||
|
}
|
||||||
|
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_RIGHT)) {
|
||||||
|
_ = World.tryRelease();
|
||||||
|
}
|
||||||
if (Game.mouse.y_norm <= -0.8) {
|
if (Game.mouse.y_norm <= -0.8) {
|
||||||
World.dock_focused = true;
|
World.dock_focused = true;
|
||||||
}
|
}
|
||||||
@@ -208,7 +246,19 @@ pub fn updateControls() void {
|
|||||||
|
|
||||||
pub fn tryPick() bool {
|
pub fn tryPick() bool {
|
||||||
const hover_id = World.hover orelse return false;
|
const hover_id = World.hover orelse return false;
|
||||||
const object = World.getObject(hover_id) orelse return false;
|
var object = World.getObject(hover_id) orelse return false;
|
||||||
|
switch (object.type) {
|
||||||
|
.card => {},
|
||||||
|
.deck => {
|
||||||
|
if (!Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
|
||||||
|
for (World.objects.items) |*child| {
|
||||||
|
if (child.parent == .deck and child.parent.deck == object.id and child.id == object.child_last_id) {
|
||||||
|
object = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
World.panning = false;
|
World.panning = false;
|
||||||
object.reparent(.hand);
|
object.reparent(.hand);
|
||||||
World.bringToTop(object);
|
World.bringToTop(object);
|
||||||
@@ -230,18 +280,35 @@ pub fn tryRelease() bool {
|
|||||||
};
|
};
|
||||||
object.target_transform.position = World.hand_transform.position;
|
object.target_transform.position = World.hand_transform.position;
|
||||||
World.bringToTop(object);
|
World.bringToTop(object);
|
||||||
if (World.dock_focused)
|
if (!Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
|
||||||
object.reparent(.dock)
|
if (World.hover) |hover_id| {
|
||||||
else
|
if (World.getObject(hover_id)) |hover_object| {
|
||||||
|
if (hover_object.type == .deck) {
|
||||||
|
object.reparent(.{ .deck = hover_id });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (World.dock_focused) {
|
||||||
|
object.reparent(.dock);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
object.reparent(.none);
|
object.reparent(.none);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateHover(object: *Object) void {
|
pub fn updateHover(object: *Object) void {
|
||||||
switch (object.parent) {
|
switch (object.parent) {
|
||||||
|
.deck => |id| {
|
||||||
|
if (World.getObject(id)) |deck| {
|
||||||
|
deck.child_last_id = object.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
.none => {
|
.none => {
|
||||||
if (!World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform, object.width, object.height)) {
|
if (!World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.drawingTransform(), object.width, object.height)) {
|
||||||
if (World.hover == null or World.getObject(World.hover.?).?.index < object.index) {
|
if (World.hover == null or World.getObject(World.hover.?).?.z < object.z) {
|
||||||
World.hover = object.id;
|
World.hover = object.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,7 +322,7 @@ pub fn updateHover(object: *Object) void {
|
|||||||
World.dock_last_width = object.width * object.target_transform.scale;
|
World.dock_last_width = object.width * object.target_transform.scale;
|
||||||
World.dock_objects += 1;
|
World.dock_objects += 1;
|
||||||
if (World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform.combineTransforms(World.dock_transform), object.width, object.height)) {
|
if (World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform.combineTransforms(World.dock_transform), object.width, object.height)) {
|
||||||
if (World.hover == null or World.getObject(World.hover.?).?.index < object.index) {
|
if (World.hover == null or World.getObject(World.hover.?).?.z < object.z) {
|
||||||
World.hover = object.id;
|
World.hover = object.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,8 +333,8 @@ pub fn updateHover(object: *Object) void {
|
|||||||
pub fn updateObject(object: *Object, delta: f32) void {
|
pub fn updateObject(object: *Object, delta: f32) void {
|
||||||
switch (object.parent) {
|
switch (object.parent) {
|
||||||
.none => {
|
.none => {
|
||||||
object.target_transform.position[2] = if (World.hover == object.id) @as(f32, 0.1) else @as(f32, 0.001) * @as(f32, @floatFromInt(object.index + 1));
|
object.target_transform.position[2] = @as(f32, 0.001) * @as(f32, @floatFromInt(object.index + 1));
|
||||||
object.target_transform.scale = 1.0;
|
object.target_transform.scale = if (World.hover == object.id) @as(f32, 1.1) else @as(f32, 1);
|
||||||
},
|
},
|
||||||
.hand => {
|
.hand => {
|
||||||
var target_position = @as(@Vector(3, f32), @splat(0));
|
var target_position = @as(@Vector(3, f32), @splat(0));
|
||||||
@@ -287,24 +354,32 @@ pub fn updateObject(object: *Object, delta: f32) void {
|
|||||||
object.target_transform.scale = target_scale;
|
object.target_transform.scale = target_scale;
|
||||||
},
|
},
|
||||||
.dock => {
|
.dock => {
|
||||||
var topleft_x = -World.dock_last_width * 0.5 + World.dock_spacing * (@as(f32, @floatFromInt(object.parent_index)) - @as(f32, @floatFromInt(World.dock_objects - 1)) * 0.5);
|
var topleft_x = -World.dock_last_width * 0.5 * DOCK_TILT_COS + World.dock_spacing * (@as(f32, @floatFromInt(object.parent_index)) - @as(f32, @floatFromInt(World.dock_objects - 1)) * 0.5);
|
||||||
const total_w = @as(f32, @floatFromInt(World.dock_objects - 1)) * World.dock_spacing + World.dock_last_width;
|
const total_w = @as(f32, @floatFromInt(World.dock_objects - 1)) * World.dock_spacing + World.dock_last_width * DOCK_TILT_COS;
|
||||||
if (total_w > Graphics.camera.aspect * 2) {
|
if (total_w > Graphics.camera.aspect * 2) {
|
||||||
topleft_x += math.lerp(0, Graphics.camera.aspect - total_w * 0.5, Game.mouse.x_norm);
|
topleft_x += math.lerp(0, Graphics.camera.aspect - total_w * 0.5, Game.mouse.x_norm);
|
||||||
}
|
}
|
||||||
const hit = World.hover == object.id;
|
const hit = World.hover == object.id;
|
||||||
const topleft_y = if (World.dock_focused) if (hit) @as(f32, 0.5) else @as(f32, 0.3) else @as(f32, 0.2);
|
const topleft_y = if (World.dock_focused) if (hit) @as(f32, 0.5) else @as(f32, 0.3) else @as(f32, 0.2);
|
||||||
object.target_transform.position = .{
|
object.target_transform.position = .{
|
||||||
topleft_x + object.width * 0.5 * object.target_transform.scale,
|
topleft_x + object.width * 0.5 * object.target_transform.scale * DOCK_TILT_COS,
|
||||||
topleft_y - object.height * 0.5 * object.target_transform.scale,
|
topleft_y - object.height * 0.5 * object.target_transform.scale,
|
||||||
if (hit) @as(f32, 0.02) else @as(f32, 0),
|
if (hit) @as(f32, 0.02) else -object.width * 0.5 * DOCK_TILT_SIN,
|
||||||
};
|
};
|
||||||
object.target_transform.rotation = if (hit)
|
object.target_transform.rotation = if (hit)
|
||||||
Graphics.Transform.ZERO.rotation
|
Graphics.Transform.ZERO.rotation
|
||||||
else
|
else
|
||||||
Graphics.Transform.rotationByAxis(.{ 0, 1, 0 }, 0.001);
|
Graphics.Transform.rotationByAxis(.{ 0, 1, 0 }, DOCK_TILT);
|
||||||
|
},
|
||||||
|
.deck => {
|
||||||
|
object.target_transform.position = .{ 0, 0, @as(f32, 0.001) };
|
||||||
|
object.target_transform.scale = if (World.hover == object.id) @as(f32, 1.1) else @as(f32, 1);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
object.z = switch (object.parent) {
|
||||||
|
.deck => |deck_id| if (World.getObject(deck_id)) |deck| deck.z + object.index else object.index,
|
||||||
|
.none, .hand, .dock => object.index,
|
||||||
|
};
|
||||||
if (object.parent != .none) {
|
if (object.parent != .none) {
|
||||||
object.influence = math.lerpTimeLn(
|
object.influence = math.lerpTimeLn(
|
||||||
object.influence,
|
object.influence,
|
||||||
@@ -322,15 +397,25 @@ pub fn updateObject(object: *Object, delta: f32) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw() void {
|
pub fn draw() void {
|
||||||
Graphics.drawMesh(World.table_mesh, &World.texture, .{});
|
Graphics.drawMesh(World.table_mesh, &World.table_texture, .{});
|
||||||
|
|
||||||
for (World.objects.items) |*object| {
|
for (World.objects.items) |*object| {
|
||||||
if (object.parent != .dock)
|
sw: switch (object.parent) {
|
||||||
Graphics.drawMesh(object.mesh, &object.texture, object.drawingTransform());
|
.none, .hand => {
|
||||||
|
Graphics.drawMesh(object.mesh, &object.texture, object.drawingTransform());
|
||||||
|
},
|
||||||
|
.dock => {},
|
||||||
|
.deck => |id| {
|
||||||
|
if (World.getObject(id)) |deck| {
|
||||||
|
if (deck.child_last_id != object.id) continue;
|
||||||
|
}
|
||||||
|
continue :sw .none;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics.drawMesh(
|
Graphics.drawMesh(
|
||||||
World.plane_mesh,
|
World.hand_mesh,
|
||||||
&World.hand_texture,
|
&World.hand_texture,
|
||||||
Graphics.Transform.combineTransforms(
|
Graphics.Transform.combineTransforms(
|
||||||
.{
|
.{
|
||||||
|
Reference in New Issue
Block a user