add enemy

This commit is contained in:
Rokas Puzonas 2026-01-31 00:00:25 +02:00
parent 5c2b60b6e2
commit 82fa2a03e0

View File

@ -29,17 +29,45 @@ const Game = @This();
const RNGState = std.Random.DefaultPrng; const RNGState = std.Random.DefaultPrng;
const Player = struct { const Kinetic = struct {
pos: Vec2 = .zero, pos: Vec2 = .zero,
vel: Vec2 = .zero, vel: Vec2 = .zero,
acc: Vec2 = .zero, acc: Vec2 = .zero,
const UpdateOptions = struct {
max_speed: ?f32 = null,
friction: ?f32 = null,
};
pub fn update(self: *Kinetic, dt: f32, opts: UpdateOptions) void {
self.vel = self.vel.add(self.acc.multiplyScalar(dt));
if (opts.max_speed) |max_speed| {
self.vel = self.vel.limitLength(max_speed);
}
if (opts.friction) |friction| {
const friction_force = std.math.pow(f32, 1 - friction, dt);
self.vel = self.vel.multiplyScalar(friction_force);
}
self.pos = self.pos.add(self.vel.multiplyScalar(dt));
}
};
const Player = struct {
kinetic: Kinetic = .{},
last_shot_at: ?Nanoseconds = null last_shot_at: ?Nanoseconds = null
}; };
const Bullet = struct { const Bullet = struct {
pos: Vec2 = .zero, kinetic: Kinetic,
vel: Vec2 = .zero, size: f32 = 5,
size: f32 = 5 dir: Vec2,
speed: f32
};
const Enemy = struct {
kinetic: Kinetic,
speed: f32,
size: f32,
}; };
arena: std.heap.ArenaAllocator, arena: std.heap.ArenaAllocator,
@ -49,6 +77,7 @@ assets: *Assets,
player: Player = .{}, player: Player = .{},
bullets: std.ArrayList(Bullet) = .empty, bullets: std.ArrayList(Bullet) = .empty,
enemies: std.ArrayList(Enemy) = .empty,
pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game { pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
var arena = std.heap.ArenaAllocator.init(gpa); var arena = std.heap.ArenaAllocator.init(gpa);
@ -59,7 +88,9 @@ pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
.gpa = gpa, .gpa = gpa,
.assets = assets, .assets = assets,
.player = .{ .player = .{
.kinetic = .{
.pos = .init(50, 50), .pos = .init(50, 50),
}
}, },
.rng = RNGState.init(seed), .rng = RNGState.init(seed),
}; };
@ -68,6 +99,7 @@ pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
pub fn deinit(self: *Game) void { pub fn deinit(self: *Game) void {
self.arena.deinit(); self.arena.deinit();
self.bullets.deinit(self.gpa); self.bullets.deinit(self.gpa);
self.enemies.deinit(self.gpa);
} }
pub fn tick(self: *Game, frame: *Engine.Frame) !void { pub fn tick(self: *Game, frame: *Engine.Frame) !void {
@ -104,16 +136,13 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
} }
dir = dir.normalized(); dir = dir.normalized();
const max_speed = 400;
const acceleration = 1500; const acceleration = 1500;
const friction_coef = 0.99988;
self.player.acc = dir.multiplyScalar(acceleration); self.player.kinetic.acc = dir.multiplyScalar(acceleration);
self.player.vel = self.player.vel.add(self.player.acc.multiplyScalar(dt)); self.player.kinetic.update(dt, .{
self.player.vel = self.player.vel.limitLength(max_speed); .friction = 0.99988,
const friction_force = std.math.pow(f32, 1 - friction_coef, dt); .max_speed = 400
self.player.vel = self.player.vel.multiplyScalar(friction_force); });
self.player.pos = self.player.pos.add(self.player.vel.multiplyScalar(dt));
if (frame.input.mouse_position) |mouse| { if (frame.input.mouse_position) |mouse| {
const cursor_size = Vec2.init(10, 10); const cursor_size = Vec2.init(10, 10);
@ -125,7 +154,7 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
.color = rgba(255, 200, 200, 0.5) .color = rgba(255, 200, 200, 0.5)
}); });
const bullet_dir = mouse.sub(self.player.pos).normalized(); const bullet_dir = mouse.sub(self.player.kinetic.pos).normalized();
var cooldown_complete = true; var cooldown_complete = true;
if (self.player.last_shot_at) |last_shot_at| { if (self.player.last_shot_at) |last_shot_at| {
@ -136,8 +165,21 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
if (frame.isMouseDown(.left) and cooldown_complete) { if (frame.isMouseDown(.left) and cooldown_complete) {
self.player.last_shot_at = frame.time_ns; self.player.last_shot_at = frame.time_ns;
try self.bullets.append(self.gpa, .{ try self.bullets.append(self.gpa, .{
.pos = self.player.pos, .kinetic = .{
.vel = bullet_dir.multiplyScalar(50) .pos = self.player.kinetic.pos,
},
.dir = bullet_dir,
.speed = 50
});
}
if (frame.isMousePressed(.right)) {
try self.enemies.append(self.gpa, .{
.kinetic = .{
.pos = mouse,
},
.speed = 10,
.size = 20
}); });
} }
} }
@ -145,23 +187,38 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
var size = self.assets.players_tilemap.tile_size; var size = self.assets.players_tilemap.tile_size;
frame.drawRectangle(.{ frame.drawRectangle(.{
.rect = .{ .rect = .{
.pos = self.player.pos.sub(size.divideScalar(2)), .pos = self.player.kinetic.pos.sub(size.divideScalar(2)),
.size = size, .size = size,
}, },
.color = rgb(255, 255, 255) .color = rgb(255, 255, 255)
}); });
for (self.bullets.items) |*bullet| { for (self.bullets.items) |*bullet| {
bullet.pos = bullet.pos.add(bullet.vel.multiplyScalar(dt)); bullet.kinetic.vel = bullet.dir.multiplyScalar(bullet.speed);
bullet.kinetic.update(dt, .{});
frame.drawRectangle(.{ frame.drawRectangle(.{
.rect = .{ .rect = .{
.pos = bullet.pos.sub(.init(bullet.size, bullet.size)), .pos = bullet.kinetic.pos.sub(Vec2.init(bullet.size, bullet.size).multiplyScalar(0.5)),
.size = .init(bullet.size, bullet.size), .size = .init(bullet.size, bullet.size),
}, },
.color = rgb(200, 20, 255) .color = rgb(200, 20, 255)
}); });
} }
for (self.enemies.items) |*enemy| {
const dir_to_player = self.player.kinetic.pos.sub(enemy.kinetic.pos).normalized();
enemy.kinetic.vel = dir_to_player.multiplyScalar(50);
enemy.kinetic.update(dt, .{});
frame.drawRectangle(.{
.rect = .{
.pos = enemy.kinetic.pos.sub(Vec2.init(enemy.size, enemy.size).multiplyScalar(0.5)),
.size = .init(enemy.size, enemy.size),
},
.color = rgb(20, 200, 20)
});
}
} }
pub fn debug(self: *Game) !void { pub fn debug(self: *Game) !void {