Keyboard and rotation!
This commit is contained in:
@@ -8,6 +8,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
// of this build script using `b.option()`. All defined flags (including
|
// of this build script using `b.option()`. All defined flags (including
|
||||||
// target and optimize options) will be listed when running `zig build --help`
|
// target and optimize options) will be listed when running `zig build --help`
|
||||||
// in this directory.
|
// in this directory.
|
||||||
|
const llvm = b.option(bool, "llvm", "Build with llvm");
|
||||||
|
|
||||||
const mod = b.addModule("puzzle", .{
|
const mod = b.addModule("puzzle", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
@@ -16,6 +17,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "wl-main",
|
.name = "wl-main",
|
||||||
|
.use_llvm = llvm,
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
.root_source_file = b.path("src/main.zig"),
|
.root_source_file = b.path("src/main.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
@@ -27,6 +29,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
});
|
});
|
||||||
exe.root_module.link_libc = true;
|
exe.root_module.link_libc = true;
|
||||||
exe.root_module.linkSystemLibrary("wayland-client", .{});
|
exe.root_module.linkSystemLibrary("wayland-client", .{});
|
||||||
|
exe.root_module.linkSystemLibrary("xkbcommon", .{});
|
||||||
|
|
||||||
exe.root_module.addIncludePath(b.path("src"));
|
exe.root_module.addIncludePath(b.path("src"));
|
||||||
exe.root_module.addCSourceFiles(.{
|
exe.root_module.addCSourceFiles(.{
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ mkShell {
|
|||||||
zig
|
zig
|
||||||
zls
|
zls
|
||||||
wayland-scanner
|
wayland-scanner
|
||||||
|
gdb
|
||||||
|
lldb
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
wayland
|
wayland
|
||||||
|
libxkbcommon
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
+128
-6
@@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const linux = std.os.linux;
|
||||||
|
|
||||||
const puzzle = @import("puzzle");
|
const puzzle = @import("puzzle");
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ const c = @cImport({
|
|||||||
@cInclude("wayland-client-core.h");
|
@cInclude("wayland-client-core.h");
|
||||||
@cInclude("xdg-shell.h");
|
@cInclude("xdg-shell.h");
|
||||||
@cInclude("linux/input-event-codes.h");
|
@cInclude("linux/input-event-codes.h");
|
||||||
|
@cInclude("xkbcommon/xkbcommon.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
const WlPointerEventMask = packed struct(u16) {
|
const WlPointerEventMask = packed struct(u16) {
|
||||||
@@ -45,6 +47,10 @@ const WaylandState = struct {
|
|||||||
shared_memory: ?*c.wl_shm,
|
shared_memory: ?*c.wl_shm,
|
||||||
xdg_wm_base: ?*c.xdg_wm_base,
|
xdg_wm_base: ?*c.xdg_wm_base,
|
||||||
|
|
||||||
|
xkb_context: ?*c.xkb_context,
|
||||||
|
xkb_keymap: ?*c.xkb_keymap,
|
||||||
|
xkb_state: ?*c.xkb_state,
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
resize: bool,
|
resize: bool,
|
||||||
@@ -88,8 +94,8 @@ fn createSharedMemoryPool(wl_state: WaylandState) !MemoryPool {
|
|||||||
|
|
||||||
const fd: c_int = try createShmFile(pool_size);
|
const fd: c_int = try createShmFile(pool_size);
|
||||||
|
|
||||||
const prot = std.os.linux.PROT.READ | std.os.linux.PROT.WRITE;
|
const prot = linux.PROT.READ | std.os.linux.PROT.WRITE;
|
||||||
const flags: std.os.linux.MAP = .{ .TYPE = .SHARED };
|
const flags: linux.MAP = .{ .TYPE = .SHARED };
|
||||||
const ret = try std.posix.mmap(null, pool_size, prot, flags, fd, 0);
|
const ret = try std.posix.mmap(null, pool_size, prot, flags, fd, 0);
|
||||||
|
|
||||||
const pool = c.wl_shm_create_pool(wl_state.shared_memory, fd, @intCast(pool_size));
|
const pool = c.wl_shm_create_pool(wl_state.shared_memory, fd, @intCast(pool_size));
|
||||||
@@ -585,14 +591,124 @@ const wl_pointer_listener: c.struct_wl_pointer_listener = .{
|
|||||||
.frame = wlPointerHandleFrame,
|
.frame = wlPointerHandleFrame,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn wlKeyboardHandleKeymap(
|
||||||
|
data: ?*anyopaque,
|
||||||
|
wl_keyboard: ?*c.struct_wl_keyboard,
|
||||||
|
format: u32,
|
||||||
|
fd: i32,
|
||||||
|
size: u32,
|
||||||
|
) callconv(.c) void {
|
||||||
|
_ = wl_keyboard;
|
||||||
|
std.debug.assert(format == c.WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
|
||||||
|
const wl_state: *WaylandState = @ptrCast(@alignCast(data));
|
||||||
|
|
||||||
|
const map_shm: []align(4096) const u8 = std.posix.mmap(null, size, linux.PROT.READ, .{ .TYPE = .SHARED }, fd, 0) catch {
|
||||||
|
std.debug.panic("[Wayland] Keyboard keymap handler failed mmap", .{});
|
||||||
|
};
|
||||||
|
|
||||||
|
const keymap: ?*c.struct_xkb_keymap = c.xkb_keymap_new_from_string(wl_state.xkb_context, @ptrCast(map_shm), c.XKB_KEYMAP_FORMAT_TEXT_V1, c.XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
std.posix.munmap(map_shm);
|
||||||
|
std.posix.close(fd);
|
||||||
|
|
||||||
|
const xkb_state: ?*c.struct_xkb_state = c.xkb_state_new(keymap);
|
||||||
|
|
||||||
|
// NOTE: Unmap existing ones
|
||||||
|
if (wl_state.xkb_keymap != null) c.xkb_keymap_unref(wl_state.xkb_keymap);
|
||||||
|
if (wl_state.xkb_state != null) c.xkb_state_unref(wl_state.xkb_state);
|
||||||
|
|
||||||
|
wl_state.xkb_keymap = keymap;
|
||||||
|
wl_state.xkb_state = xkb_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wlKeyboardHandleEnter(data: ?*anyopaque, keyboard: ?*c.wl_keyboard, serial: u32, surface: ?*c.wl_surface, keys: [*c]c.wl_array) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = keyboard;
|
||||||
|
_ = serial;
|
||||||
|
_ = surface;
|
||||||
|
_ = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wlKeyboardHandleLeave(data: ?*anyopaque, keyboard: ?*c.wl_keyboard, serial: u32, surface: ?*c.wl_surface) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = keyboard;
|
||||||
|
_ = serial;
|
||||||
|
_ = surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wlKeyboardHandleKey(data: ?*anyopaque, keyboard: ?*c.wl_keyboard, serial: u32, time: u32, key: u32, state: u32) callconv(.c) void {
|
||||||
|
_ = keyboard;
|
||||||
|
_ = serial;
|
||||||
|
_ = time;
|
||||||
|
|
||||||
|
const wl_state: *WaylandState = @ptrCast(@alignCast(data));
|
||||||
|
var buf: [32:0]u8 = undefined;
|
||||||
|
const keycode: u32 = key + 8;
|
||||||
|
|
||||||
|
const sym: c.xkb_keysym_t = c.xkb_state_key_get_one_sym(wl_state.xkb_state, keycode);
|
||||||
|
_ = c.xkb_keysym_get_name(sym, &buf, buf.len);
|
||||||
|
|
||||||
|
const pressed = state == c.WL_KEYBOARD_KEY_STATE_PRESSED or state == c.WL_KEYBOARD_KEY_STATE_REPEATED;
|
||||||
|
|
||||||
|
std.debug.print("{s} {any}\n", .{buf, pressed});
|
||||||
|
|
||||||
|
switch (sym) {
|
||||||
|
c.XKB_KEY_Escape => {
|
||||||
|
wl_state.running = false;
|
||||||
|
},
|
||||||
|
c.XKB_KEY_space => {
|
||||||
|
wl_state.app_input.key.space.down = pressed;
|
||||||
|
},
|
||||||
|
c.XKB_KEY_r => {
|
||||||
|
wl_state.app_input.key.r.down = pressed;
|
||||||
|
},
|
||||||
|
c.XKB_KEY_q => {
|
||||||
|
wl_state.app_input.key.q.down = pressed;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wlKeyboardHandleModifiers(data: ?*anyopaque, keyboard: ?*c.wl_keyboard, serial: u32, mods_depressed: u32, mods_latched: u32, mods_locked: u32, group: u32) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = keyboard;
|
||||||
|
_ = serial;
|
||||||
|
_ = mods_depressed;
|
||||||
|
_ = mods_latched;
|
||||||
|
_ = mods_locked;
|
||||||
|
_ = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wlKeyboardHandleRepeatInfo(data: ?*anyopaque, keyboard: ?*c.wl_keyboard, rate: i32, delay: i32) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = keyboard;
|
||||||
|
_ = rate;
|
||||||
|
_ = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wl_keyboard_listener: c.wl_keyboard_listener = .{
|
||||||
|
.keymap = wlKeyboardHandleKeymap,
|
||||||
|
.enter = wlKeyboardHandleEnter,
|
||||||
|
.leave = wlKeyboardHandleLeave,
|
||||||
|
.key = wlKeyboardHandleKey,
|
||||||
|
.modifiers = wlKeyboardHandleModifiers,
|
||||||
|
.repeat_info = wlKeyboardHandleRepeatInfo,
|
||||||
|
};
|
||||||
|
|
||||||
fn wlSeatHandleCapabilities(data: ?*anyopaque, wl_seat: ?*c.struct_wl_seat, capabilities: u32) callconv(.c) void {
|
fn wlSeatHandleCapabilities(data: ?*anyopaque, wl_seat: ?*c.struct_wl_seat, capabilities: u32) callconv(.c) void {
|
||||||
const wl_state: *WaylandState = @ptrCast(@alignCast(data));
|
const wl_state: *WaylandState = @ptrCast(@alignCast(data));
|
||||||
|
|
||||||
if (capabilities & c.WL_SEAT_CAPABILITY_POINTER == 1) {
|
if (capabilities & c.WL_SEAT_CAPABILITY_POINTER == c.WL_SEAT_CAPABILITY_POINTER) {
|
||||||
std.debug.print("[Wayland] wl_seat: got pointer capability\n", .{});
|
std.debug.print("[Wayland] wl_seat: got pointer capability\n", .{});
|
||||||
const pointer: ?*c.struct_wl_pointer = c.wl_seat_get_pointer(wl_seat);
|
const pointer: ?*c.struct_wl_pointer = c.wl_seat_get_pointer(wl_seat);
|
||||||
_ = c.wl_pointer_add_listener(pointer, &wl_pointer_listener, wl_state);
|
_ = c.wl_pointer_add_listener(pointer, &wl_pointer_listener, wl_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (capabilities & c.WL_SEAT_CAPABILITY_KEYBOARD == c.WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||||
|
std.debug.print("[Wayland] wl_seat: got keyboard capability\n", .{});
|
||||||
|
const keyboard = c.wl_seat_get_keyboard(wl_seat);
|
||||||
|
_ = c.wl_keyboard_add_listener(keyboard, &wl_keyboard_listener, wl_state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wlSeatHandleName(data: ?*anyopaque, wl_seat: ?*c.struct_wl_seat, name: [*c]const u8) callconv(.c) void {
|
fn wlSeatHandleName(data: ?*anyopaque, wl_seat: ?*c.struct_wl_seat, name: [*c]const u8) callconv(.c) void {
|
||||||
@@ -647,6 +763,9 @@ pub fn main() u8 {
|
|||||||
std.debug.print("[Wayland] Connection established.\n", .{});
|
std.debug.print("[Wayland] Connection established.\n", .{});
|
||||||
|
|
||||||
var wl_state: WaylandState = undefined;
|
var wl_state: WaylandState = undefined;
|
||||||
|
wl_state.xkb_context = null;
|
||||||
|
wl_state.xkb_state = null;
|
||||||
|
wl_state.xkb_keymap = null;
|
||||||
|
|
||||||
const registry = c.wl_display_get_registry(display);
|
const registry = c.wl_display_get_registry(display);
|
||||||
if (registry == null) {
|
if (registry == null) {
|
||||||
@@ -656,6 +775,8 @@ pub fn main() u8 {
|
|||||||
|
|
||||||
_ = c.wl_registry_add_listener(registry, ®istry_listener, &wl_state);
|
_ = c.wl_registry_add_listener(registry, ®istry_listener, &wl_state);
|
||||||
|
|
||||||
|
wl_state.xkb_context = c.xkb_context_new(c.XKB_CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
_ = c.wl_display_roundtrip(display);
|
_ = c.wl_display_roundtrip(display);
|
||||||
if (wl_state.compositor == null or wl_state.shared_memory == null or wl_state.seat == null) {
|
if (wl_state.compositor == null or wl_state.shared_memory == null or wl_state.seat == null) {
|
||||||
std.debug.print("ERROR: Wayland compositor, seat, or shm not bound.\n", .{});
|
std.debug.print("ERROR: Wayland compositor, seat, or shm not bound.\n", .{});
|
||||||
@@ -835,13 +956,14 @@ pub fn main() u8 {
|
|||||||
|
|
||||||
_ = c.wl_display_roundtrip(display);
|
_ = c.wl_display_roundtrip(display);
|
||||||
|
|
||||||
std.posix.nanosleep(0, std.time.ns_per_ms * 32);
|
// std.posix.nanosleep(0, std.time.ns_per_ms * 32);
|
||||||
|
|
||||||
const current = timer.lap();
|
const current = timer.lap();
|
||||||
|
const current_ms = current / std.time.ns_per_ms;
|
||||||
const sleep_time_ms: f64 = @as(f64, @floatFromInt(sleep_time)) / @as(f64, @floatFromInt(std.time.ns_per_ms));
|
const sleep_time_ms: f64 = @as(f64, @floatFromInt(sleep_time)) / @as(f64, @floatFromInt(std.time.ns_per_ms));
|
||||||
std.debug.print(
|
std.debug.print(
|
||||||
"Render: {d}ms, Sleeping: {d}ms, Frame: {d}ms.\n",
|
"Render: {d:.3}ms, Sleeping: {d:.3}ms, Frame: {d}ms.\n",
|
||||||
.{ render_time_ms, sleep_time_ms, current / std.time.ns_per_ms },
|
.{ render_time_ms, sleep_time_ms, current_ms },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,16 @@ pub fn megaBytes(bytes: usize) usize {
|
|||||||
return kiloBytes(bytes) * 1024;
|
return kiloBytes(bytes) * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Key = struct {
|
||||||
|
down: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Keyboard = struct {
|
||||||
|
r: Key,
|
||||||
|
q: Key,
|
||||||
|
space: Key,
|
||||||
|
};
|
||||||
|
|
||||||
pub const AppInput = struct {
|
pub const AppInput = struct {
|
||||||
mouse_present: bool = false,
|
mouse_present: bool = false,
|
||||||
mouse_left_down: bool = false,
|
mouse_left_down: bool = false,
|
||||||
@@ -15,6 +25,8 @@ pub const AppInput = struct {
|
|||||||
mouse_y: f64,
|
mouse_y: f64,
|
||||||
|
|
||||||
scroll_y: f64,
|
scroll_y: f64,
|
||||||
|
|
||||||
|
key: Keyboard,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Buffer the platform creates and hands off to the app
|
/// Buffer the platform creates and hands off to the app
|
||||||
|
|||||||
+99
-47
@@ -30,8 +30,28 @@ const Camera = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Brick = struct {
|
const Brick = struct {
|
||||||
|
rotating: bool,
|
||||||
pos: V2,
|
pos: V2,
|
||||||
|
color: u32,
|
||||||
tiles: [4][4]u32,
|
tiles: [4][4]u32,
|
||||||
|
|
||||||
|
fn rotate(self: Brick) [4][4]u32 {
|
||||||
|
var result = [4][4]u32{
|
||||||
|
.{ 0, 0, 0, 0 },
|
||||||
|
.{ 0, 0, 0, 0 },
|
||||||
|
.{ 0, 0, 0, 0 },
|
||||||
|
.{ 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (0..self.tiles.len) |i| {
|
||||||
|
const row = self.tiles[i];
|
||||||
|
for (0..row.len) |j| {
|
||||||
|
result[j][row.len - i - 1] = self.tiles[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const State = struct {
|
const State = struct {
|
||||||
@@ -74,8 +94,8 @@ fn fillRect(
|
|||||||
if (buffer.width < end_x) end_x = buffer.width;
|
if (buffer.width < end_x) end_x = buffer.width;
|
||||||
if (buffer.height < end_y) end_y = buffer.height;
|
if (buffer.height < end_y) end_y = buffer.height;
|
||||||
|
|
||||||
for (@intCast(start_y) .. @intCast(end_y)) |y| {
|
for (@intCast(start_y)..@intCast(end_y)) |y| {
|
||||||
for (@intCast(start_x) .. @intCast(end_x)) |x| {
|
for (@intCast(start_x)..@intCast(end_x)) |x| {
|
||||||
const idx: usize = y * @as(usize, @intCast(buffer.width)) + x;
|
const idx: usize = y * @as(usize, @intCast(buffer.width)) + x;
|
||||||
|
|
||||||
pixels[idx] = color;
|
pixels[idx] = color;
|
||||||
@@ -96,91 +116,109 @@ fn fillSquare(
|
|||||||
pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBuffer, input: platform.AppInput) void {
|
pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBuffer, input: platform.AppInput) void {
|
||||||
var state: *State = @ptrCast(@alignCast(memory.permanent_storage));
|
var state: *State = @ptrCast(@alignCast(memory.permanent_storage));
|
||||||
|
|
||||||
const mid = V2{ .x = @floatFromInt(@divTrunc(buffer.width, 2)), .y = @floatFromInt(@divTrunc(buffer.height, 2)), };
|
const mid = V2{
|
||||||
|
.x = @floatFromInt(@divTrunc(buffer.width, 2)),
|
||||||
|
.y = @floatFromInt(@divTrunc(buffer.height, 2)),
|
||||||
|
};
|
||||||
if (!memory.initialized) {
|
if (!memory.initialized) {
|
||||||
state.camera.offset = mid;
|
state.camera.offset = mid;
|
||||||
|
|
||||||
state.bricks[0] = Brick{
|
state.bricks[0] = Brick{
|
||||||
.pos = V2{ .x = 0, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 0, .y = 50 },
|
||||||
|
.color = 0xFFFF0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{1, 1, 1, 1},
|
.{ 1, 1, 1, 1 },
|
||||||
.{1, 0, 0, 0},
|
.{ 1, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[1] = Brick{
|
state.bricks[1] = Brick{
|
||||||
.pos = V2{ .x = 32, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 32, .y = 50 },
|
||||||
|
.color = 0xFFEF0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{2, 2, 2, 0},
|
.{ 2, 2, 2, 0 },
|
||||||
.{2, 2, 0, 0},
|
.{ 2, 2, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[2] = Brick{
|
state.bricks[2] = Brick{
|
||||||
.pos = V2{ .x = 64, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 64, .y = 50 },
|
||||||
|
.color = 0xFFDF0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{3, 3, 3, 0},
|
.{ 3, 3, 3, 0 },
|
||||||
.{0, 0, 3, 3},
|
.{ 0, 0, 3, 3 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[3] = Brick{
|
state.bricks[3] = Brick{
|
||||||
.pos = V2{ .x = 96, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 96, .y = 50 },
|
||||||
|
.color = 0xFFCF0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{4, 0, 0, 0},
|
.{ 4, 0, 0, 0 },
|
||||||
.{4, 4, 4, 0},
|
.{ 4, 4, 4, 0 },
|
||||||
.{0, 0, 4, 0},
|
.{ 0, 0, 4, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[4] = Brick{
|
state.bricks[4] = Brick{
|
||||||
.pos = V2{ .x = 128, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 128, .y = 150 },
|
||||||
|
.color = 0xFFBF0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{5, 5, 5, 5},
|
.{ 5, 5, 5, 5 },
|
||||||
.{0, 5, 0, 0},
|
.{ 0, 5, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[5] = Brick{
|
state.bricks[5] = Brick{
|
||||||
.pos = V2{ .x = 160, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 160, .y = 250 },
|
||||||
|
.color = 0xFFAF0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{6, 6, 6, 0},
|
.{ 6, 6, 6, 0 },
|
||||||
.{6, 0, 0, 0},
|
.{ 6, 0, 0, 0 },
|
||||||
.{6, 0, 0, 0},
|
.{ 6, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[6] = Brick{
|
state.bricks[6] = Brick{
|
||||||
.pos = V2{ .x = 192, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 192, .y = 350 },
|
||||||
|
.color = 0xFF9F0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{7, 7, 7, 0},
|
.{ 7, 7, 7, 0 },
|
||||||
.{7, 7, 7, 0},
|
.{ 7, 7, 7, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.bricks[7] = Brick{
|
state.bricks[7] = Brick{
|
||||||
.pos = V2{ .x = 224, .y = 50},
|
.rotating = false,
|
||||||
|
.pos = V2{ .x = 224, .y = 450 },
|
||||||
|
.color = 0xFF8F0000,
|
||||||
.tiles = [4][4]u32{
|
.tiles = [4][4]u32{
|
||||||
.{8, 8, 8, 0},
|
.{ 8, 8, 8, 0 },
|
||||||
.{8, 0, 8, 0},
|
.{ 8, 0, 8, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
.{0, 0, 0, 0},
|
.{ 0, 0, 0, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
memory.initialized = true;
|
memory.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +232,8 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
|||||||
|
|
||||||
var mouse_on_brick = false;
|
var mouse_on_brick = false;
|
||||||
for (&state.bricks) |*brick| {
|
for (&state.bricks) |*brick| {
|
||||||
|
brick.rotating = false;
|
||||||
|
|
||||||
for (brick.tiles, 0..) |row, i| {
|
for (brick.tiles, 0..) |row, i| {
|
||||||
for (row, 0..) |tile, j| {
|
for (row, 0..) |tile, j| {
|
||||||
if (tile > 0) {
|
if (tile > 0) {
|
||||||
@@ -208,6 +248,14 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
|||||||
if (input.mouse_left_down) {
|
if (input.mouse_left_down) {
|
||||||
const diff = mouse_pos.sub(state.mouse_pos);
|
const diff = mouse_pos.sub(state.mouse_pos);
|
||||||
brick.pos = brick.pos.add(diff);
|
brick.pos = brick.pos.add(diff);
|
||||||
|
|
||||||
|
if (input.key.space.down and !brick.rotating) {
|
||||||
|
// TODO: Rotate
|
||||||
|
brick.rotating = true;
|
||||||
|
const rotated = brick.rotate();
|
||||||
|
brick.tiles = rotated;
|
||||||
|
}
|
||||||
|
|
||||||
mouse_on_brick = true;
|
mouse_on_brick = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +269,6 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
|||||||
state.camera.pos = state.camera.pos.add(diff);
|
state.camera.pos = state.camera.pos.add(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
state.mouse_pos = mouse_pos;
|
state.mouse_pos = mouse_pos;
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
@@ -255,7 +302,13 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
|||||||
.y = @floatFromInt(i * TILE_SIZE),
|
.y = @floatFromInt(i * TILE_SIZE),
|
||||||
};
|
};
|
||||||
const camera_pos = brick.pos.add(pos).add(state.camera.pos);
|
const camera_pos = brick.pos.add(pos).add(state.camera.pos);
|
||||||
fillSquare(buffer, @intFromFloat(camera_pos.x), @intFromFloat(camera_pos.y), 30, 0xFFFF0000);
|
fillSquare(
|
||||||
|
buffer,
|
||||||
|
@intFromFloat(camera_pos.x),
|
||||||
|
@intFromFloat(camera_pos.y),
|
||||||
|
30,
|
||||||
|
if (brick.rotating) 0xFF00FF00 else brick.color ,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,4 +316,3 @@ pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBu
|
|||||||
|
|
||||||
state.frame_count += 1;
|
state.frame_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user