Files
spacefarer/src/entity.zig
2025-07-07 21:11:55 +05:00

119 lines
3.5 KiB
Zig

const std = @import("std");
const sdl = @import("sdl");
const Game = @import("game.zig");
const Graphics = @import("graphics.zig");
const Time = @import("time.zig");
const World = @import("world.zig");
const math = @import("math.zig");
position: @Vector(2, i32),
player: bool = false,
enemy: bool = false,
controller: Controller = .{},
next_update: Time = Time.ZERO,
const Controller = struct {
const Action = union(enum) {
move: @Vector(2, i32),
};
wanted_action: ?Action = null,
move_units: f32 = 0.125,
};
const Self = @This();
pub fn update(self: *Self) void {
if (!World.time.past(self.next_update)) return;
if (self.player) self.updatePlayer();
if (self.enemy) self.updateEnemy();
self.updateController();
}
pub fn updatePlayer(self: *Self) void {
var delta: @Vector(2, i32) = .{ 0, 0 };
if (Game.keyboard.keys.is_pressed(sdl.SCANCODE_UP)) {
delta[1] += 1;
}
if (Game.keyboard.keys.is_pressed(sdl.SCANCODE_DOWN)) {
delta[1] -= 1;
}
if (Game.keyboard.keys.is_pressed(sdl.SCANCODE_RIGHT)) {
delta[0] += 1;
}
if (Game.keyboard.keys.is_pressed(sdl.SCANCODE_LEFT)) {
delta[0] -= 1;
}
if (@reduce(.Or, delta != @Vector(2, i32){ 0, 0 }))
self.controller.wanted_action = .{ .move = delta }
else
self.controller.wanted_action = null;
}
fn updateEnemy(self: *Self) void {
if (World.getPlayer()) |player| {
var delta = player.position - self.position;
if (@reduce(.And, @abs(delta) <= @Vector(2, i64){ 1, 1 })) {
self.controller.wanted_action = null;
} else {
delta[0] = @max(-1, @min(1, delta[0]));
delta[1] = @max(-1, @min(1, delta[1]));
self.controller.wanted_action = .{ .move = delta };
}
}
}
fn updateController(self: *Self) void {
if (self.controller.wanted_action) |action| {
switch (action) {
.move => |delta| {
const target = self.position + delta;
if (World.isFree(target)) {
self.next_update = World.time.offset(self.controller.move_units * math.lengthInt(delta));
self.position[0] += delta[0];
self.position[1] += delta[1];
}
},
}
}
}
pub fn draw(self: *Self, delta: f32) void {
const transform = Graphics.Transform{
.position = .{
@floatFromInt(self.position[0]),
@floatFromInt(self.position[1]),
0.5,
},
};
Graphics.drawMesh(World.cube_mesh, World.texture, transform);
if (!self.player) return;
Graphics.camera.transform.position = math.lerpTimeLn(
Graphics.camera.transform.position,
transform.position + @Vector(3, f32){ 0.0, -2.0, 5.0 },
delta,
-25,
);
const ORIGIN_DIR = @Vector(3, f32){ 0.0, 0.0, -1.0 };
const INIT_ROTATION = Graphics.Transform.rotationByAxis(.{ 1.0, 0.0, 0.0 }, std.math.pi * 0.5);
const ROTATED_DIR = Graphics.Transform.rotateVector(ORIGIN_DIR, INIT_ROTATION);
const target_rotation = Graphics.Transform.combineRotations(
INIT_ROTATION,
Graphics.Transform.rotationToward(
ROTATED_DIR,
transform.position - Graphics.camera.transform.position,
.{ .normalize_to = true },
),
);
Graphics.camera.transform.rotation = Graphics.Transform.normalizeRotation(math.slerpTimeLn(
Graphics.camera.transform.rotation,
target_rotation,
delta,
-2,
));
}