add enemy

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

View File

@ -29,19 +29,47 @@ const Game = @This();
const RNGState = std.Random.DefaultPrng;
const Player = struct {
const Kinetic = struct {
pos: Vec2 = .zero,
vel: 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
};
const Bullet = struct {
pos: Vec2 = .zero,
vel: Vec2 = .zero,
size: f32 = 5
kinetic: Kinetic,
size: f32 = 5,
dir: Vec2,
speed: f32
};
const Enemy = struct {
kinetic: Kinetic,
speed: f32,
size: f32,
};
arena: std.heap.ArenaAllocator,
gpa: Allocator,
rng: RNGState,
@ -49,6 +77,7 @@ assets: *Assets,
player: Player = .{},
bullets: std.ArrayList(Bullet) = .empty,
enemies: std.ArrayList(Enemy) = .empty,
pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
var arena = std.heap.ArenaAllocator.init(gpa);
@ -59,7 +88,9 @@ pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
.gpa = gpa,
.assets = assets,
.player = .{
.pos = .init(50, 50),
.kinetic = .{
.pos = .init(50, 50),
}
},
.rng = RNGState.init(seed),
};
@ -68,6 +99,7 @@ pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
pub fn deinit(self: *Game) void {
self.arena.deinit();
self.bullets.deinit(self.gpa);
self.enemies.deinit(self.gpa);
}
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();
const max_speed = 400;
const acceleration = 1500;
const friction_coef = 0.99988;
self.player.acc = dir.multiplyScalar(acceleration);
self.player.vel = self.player.vel.add(self.player.acc.multiplyScalar(dt));
self.player.vel = self.player.vel.limitLength(max_speed);
const friction_force = std.math.pow(f32, 1 - friction_coef, dt);
self.player.vel = self.player.vel.multiplyScalar(friction_force);
self.player.pos = self.player.pos.add(self.player.vel.multiplyScalar(dt));
self.player.kinetic.acc = dir.multiplyScalar(acceleration);
self.player.kinetic.update(dt, .{
.friction = 0.99988,
.max_speed = 400
});
if (frame.input.mouse_position) |mouse| {
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)
});
const bullet_dir = mouse.sub(self.player.pos).normalized();
const bullet_dir = mouse.sub(self.player.kinetic.pos).normalized();
var cooldown_complete = true;
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) {
self.player.last_shot_at = frame.time_ns;
try self.bullets.append(self.gpa, .{
.pos = self.player.pos,
.vel = bullet_dir.multiplyScalar(50)
.kinetic = .{
.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;
frame.drawRectangle(.{
.rect = .{
.pos = self.player.pos.sub(size.divideScalar(2)),
.pos = self.player.kinetic.pos.sub(size.divideScalar(2)),
.size = size,
},
.color = rgb(255, 255, 255)
});
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(.{
.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),
},
.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 {