add different kinds of enemies

This commit is contained in:
Rokas Puzonas 2024-02-12 23:05:13 +02:00
parent eb305add94
commit 28b5a476bf

View File

@ -8,9 +8,55 @@ const friction = 0.99;
const walkForce = 4000;
const maxSpeed = 200;
const handDistance = 50;
const deathBallSize: f32 = 10;
const playerSize = 20;
const enemyFriction = friction;
const Enemy = struct {
position: rl.Vector2,
health: f32,
color: rl.Color,
size: f32,
acceleration: f32,
maxSpeed: f32,
invincibility: f32 = 0,
stunned: f32 = 0,
velocity: rl.Vector2 = .{ .x = 0, .y = 0 },
fn initWeak(position: rl.Vector2) Enemy {
return Enemy{
.position = position,
.health = 1.0,
.color = rl.YELLOW,
.size = 10.0,
.acceleration = 5000.0,
.maxSpeed = 150,
};
}
fn initNormal(position: rl.Vector2) Enemy {
return Enemy{
.position = position,
.health = 2.0,
.color = rl.ORANGE,
.size = 20.0,
.acceleration = 4000,
.maxSpeed = 100,
};
}
fn initStrong(position: rl.Vector2) Enemy {
return Enemy{
.position = position,
.health = 5.0,
.color = rl.ORANGE,
.size = 50.0,
.acceleration = 3000,
.maxSpeed = 50,
};
}
};
const Player = struct {
@ -147,6 +193,69 @@ pub fn deinit(self: Self) void {
self.enemies.deinit();
}
fn tickEnemies(self: *Self) !void {
var rng = self.prng.random();
const dt = rl.GetFrameTime();
var enemies = &self.enemies;
var player = &self.player;
var rope = &self.rope;
self.enemyTimer -= dt;
if (self.enemyTimer <= 0) {
self.enemyTimer = 0.5 + rng.float(f32) * 2;
self.spawnedEnemiesCount += 1;
const enemyPosition = rl.Vector2.randomOnUnitCircle(rng).scale(400);
try enemies.append(Enemy.initNormal(enemyPosition));
}
for (enemies.items) |*enemy| {
const toPlayer = player.position.sub(enemy.position);
if (toPlayer.length() <= playerSize + enemy.size) {
self.reset();
return;
}
if (enemy.stunned == 0) {
const directionToPlayer = toPlayer.normalize();
enemy.velocity = enemy.velocity.add(directionToPlayer.scale(enemy.acceleration * dt));
}
enemy.velocity = rl.Vector2ClampValue(enemy.velocity, 0, enemy.maxSpeed);
enemy.velocity = rl.Vector2Scale(enemy.velocity, std.math.pow(f32, (1 - enemyFriction), dt));
enemy.position = enemy.position.add(enemy.velocity.scale(dt));
enemy.invincibility = @max(0, enemy.invincibility - dt);
enemy.stunned = @max(0, enemy.stunned - dt);
}
const deathBallPosition = rope.nodePositions.get(rope.nodePositions.len-1);
const deathBallVelocity = rope.nodeVelocities.get(rope.nodePositions.len-1);
{
var i: usize = 0;
while (i < enemies.items.len) {
const enemy = &enemies.items[i];
if (enemy.invincibility == 0) {
if (rl.Vector2Distance(enemy.position, deathBallPosition) < enemy.size + deathBallSize) {
enemy.health -= 1;
enemy.invincibility = 0.5;
enemy.stunned = 0.75;
enemy.velocity = deathBallVelocity.scale(20000);
}
if (enemy.health == 0) {
self.killCount += 1;
_ = enemies.swapRemove(i);
continue;
}
}
i += 1;
}
}
}
pub fn tick(self: *Self) !void {
rl.ClearBackground(rl.BLACK);
@ -158,21 +267,11 @@ pub fn tick(self: *Self) !void {
self.camera.target = self.player.position;
const dt = rl.GetFrameTime();
var rng = self.prng.random();
var player = &self.player;
var enemies = &self.enemies;
var rope = &self.rope;
var allocator = self.allocator;
self.enemyTimer -= dt;
if (self.enemyTimer <= 0) {
self.enemyTimer = 0.5 + rng.float(f32) * 2;
self.spawnedEnemiesCount += 1;
try enemies.append(Enemy{
.position = rl.Vector2.randomOnUnitCircle(rng).scale(400)
});
}
player.handDirection = PlayerInput.getHandPosition();
const moveDir = PlayerInput.getWalkDirection();
@ -185,45 +284,16 @@ pub fn tick(self: *Self) !void {
player.position = rl.Vector2Add(player.position, rl.Vector2Scale(player.velocity, dt));
const enemySize: f32 = 20;
const deathBallSize: f32 = 10;
const playerSize = 20;
const enemySpeed = 100;
for (enemies.items) |*enemy| {
const toPlayer = player.position.sub(enemy.position);
if (toPlayer.length() <= playerSize + enemySize) {
self.reset();
return;
}
const directionToPlayer = toPlayer.normalize();
enemy.position = enemy.position.add(directionToPlayer.scale(enemySpeed * dt));
}
const handPosition = player.position.add(player.handDirection.scale(handDistance));
const rope_root_node: rl.Vector2 = rope.nodePositions.get(0);
rope.nodePositions.set(0, rope_root_node.lerp(handPosition, 0.25));
// rope.nodePositions.set(0, handPosition);
rope.update(dt);
const deathBallPosition = rope.nodePositions.get(rope.nodePositions.len-1);
{
var i: usize = 0;
while (i < enemies.items.len) {
const enemy = &enemies.items[i];
const distanceToDeathBall = enemy.position.sub(deathBallPosition).length();
if (distanceToDeathBall < enemySize + deathBallSize) {
self.killCount += 1;
_ = enemies.swapRemove(i);
continue;
}
i += 1;
}
}
try self.tickEnemies();
{ // UI
const enemyCountText = try std.fmt.allocPrintZ(allocator, "{d}", .{self.spawnedEnemiesCount});
@ -267,11 +337,16 @@ pub fn tick(self: *Self) !void {
);
for (enemies.items) |*enemy| {
var color = enemy.color;
if (enemy.invincibility > 0 and @rem(enemy.invincibility, 0.2) < 0.1) {
color = rl.LIGHTGRAY;
}
rl.DrawCircle(
@intFromFloat(enemy.position.x),
@intFromFloat(enemy.position.y),
enemySize,
rl.RED
enemy.size,
color
);
}