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 walkForce = 4000;
const maxSpeed = 200; const maxSpeed = 200;
const handDistance = 50; const handDistance = 50;
const deathBallSize: f32 = 10;
const playerSize = 20;
const enemyFriction = friction;
const Enemy = struct { const Enemy = struct {
position: rl.Vector2, 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 { const Player = struct {
@ -147,6 +193,69 @@ pub fn deinit(self: Self) void {
self.enemies.deinit(); 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 { pub fn tick(self: *Self) !void {
rl.ClearBackground(rl.BLACK); rl.ClearBackground(rl.BLACK);
@ -158,21 +267,11 @@ pub fn tick(self: *Self) !void {
self.camera.target = self.player.position; self.camera.target = self.player.position;
const dt = rl.GetFrameTime(); const dt = rl.GetFrameTime();
var rng = self.prng.random();
var player = &self.player; var player = &self.player;
var enemies = &self.enemies; var enemies = &self.enemies;
var rope = &self.rope; var rope = &self.rope;
var allocator = self.allocator; 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(); player.handDirection = PlayerInput.getHandPosition();
const moveDir = PlayerInput.getWalkDirection(); 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)); 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 handPosition = player.position.add(player.handDirection.scale(handDistance));
const rope_root_node: rl.Vector2 = rope.nodePositions.get(0); 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, rope_root_node.lerp(handPosition, 0.25));
// rope.nodePositions.set(0, handPosition);
rope.update(dt); rope.update(dt);
const deathBallPosition = rope.nodePositions.get(rope.nodePositions.len-1); const deathBallPosition = rope.nodePositions.get(rope.nodePositions.len-1);
{ try self.tickEnemies();
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;
}
}
{ // UI { // UI
const enemyCountText = try std.fmt.allocPrintZ(allocator, "{d}", .{self.spawnedEnemiesCount}); const enemyCountText = try std.fmt.allocPrintZ(allocator, "{d}", .{self.spawnedEnemiesCount});
@ -267,11 +337,16 @@ pub fn tick(self: *Self) !void {
); );
for (enemies.items) |*enemy| { 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( rl.DrawCircle(
@intFromFloat(enemy.position.x), @intFromFloat(enemy.position.x),
@intFromFloat(enemy.position.y), @intFromFloat(enemy.position.y),
enemySize, enemy.size,
rl.RED color
); );
} }