kble/src/main.zig

138 lines
4.6 KiB
Zig

// SPDX-License-Identifier: MIT
// Copyright (c) 2021 KikooDX
// This file is part of [KBLE](https://sr.ht/~kikoodx/kble), which is
// MIT licensed. The MIT license requires this copyright notice to be
// included in all copies and substantial portions of the software.
const ray = @cImport({
@cInclude("raylib.h");
});
const std = @import("std");
const assert = std.debug.assert;
const format = std.fmt.format;
const log = std.log.default.debug;
const maxInt = std.math.maxInt;
const Level = @import("level.zig");
const Vec2 = @import("vec2.zig");
const movement = @import("movement.zig");
pub fn main() !void {
// Create allocator
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = &arena.allocator;
// Create window.
ray.SetConfigFlags(ray.FLAG_WINDOW_RESIZABLE);
ray.InitWindow(640, 480, "KBLE");
defer ray.CloseWindow();
// Limit FPS for performance.
ray.SetTargetFPS(60);
// Create level.
var level: Level = try Level.init(allocator, 16, 16);
defer level.deinit(allocator);
// Create camera.
var camera: Vec2 = Vec2.init(0, 0);
// Scale, used by drawing code.
const scale_type = u16;
const scale_default = 16;
var scale: scale_type = scale_default;
// Create cursor.
var cursor: Vec2 = Vec2.init(0, 0);
// Create input buffer (ASCII).
const input_buffer_len = 255;
var input_buffer: [input_buffer_len]u32 = undefined;
comptime {
var i: u8 = 0;
while (i < input_buffer_len) : (i += 1) {
input_buffer[i] = 0;
}
}
var input_cursor: u8 = 0;
while (!ray.WindowShouldClose()) {
// Get keyboard input.
var key = ray.GetCharPressed();
// Check if more characters have been pressed.
while (key != 0) {
// Add key to buffer.
input_buffer[input_cursor] = @intCast(u32, key);
input_cursor += 1;
// Avoid writing out of memory.
if (input_cursor >= input_buffer_len)
input_cursor = input_buffer_len - 1;
key = ray.GetCharPressed();
}
// Process buffer content.
// Read the buffer backwards. This is placeholder logic.
while (input_cursor > 0) {
input_cursor -= 1;
const action = input_buffer[input_cursor];
const movement_command = switch (action) {
'A'...'Z' => action - 'A' + 'a',
else => action,
};
const was_lowercase: bool = movement_command == action;
// Check for movement.
const selection_update: movement.SelectionUpdate = switch (movement_command) {
// Movement.
'h' => movement.move_left(&cursor, 1, was_lowercase),
'j' => movement.move_down(&cursor, 1, was_lowercase),
'k' => movement.move_up(&cursor, 1, was_lowercase),
'l' => movement.move_right(&cursor, 1, was_lowercase),
// Diagonals and rectangle selection.
'y' => movement.move_up_left(&cursor, 1, was_lowercase),
'u' => movement.move_up_right(&cursor, 1, was_lowercase),
'b' => movement.move_down_left(&cursor, 1, was_lowercase),
'n' => movement.move_down_right(&cursor, 1, was_lowercase),
else => blk: {
break :blk movement.SelectionUpdate{
.active = false,
.area = undefined,
.exclusive = undefined,
.state = undefined,
};
},
};
if (selection_update.active) {
level.apply_selection_update(selection_update);
} else {
// If didn't input movement, check for action.
switch (action) {
// Actions.
'd' => level.action_delete(),
// Zoom (pog feature).
'-' => if (scale > 3) {
scale -= 1;
},
'+' => if (scale < comptime maxInt(scale_type)) {
scale += 1;
},
// Reset zoom.
'=' => scale = scale_default,
else => log("No action for {} key.", .{action}),
}
}
}
ray.BeginDrawing();
defer ray.EndDrawing();
ray.ClearBackground(ray.BLACK);
level.draw(scale, camera);
level.draw_selection(scale, camera);
//ray.DrawFPS(0, 0);
}
}