From 28b5a476bf11fef0987ab802acf5a964e90bcfb3 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Mon, 12 Feb 2024 23:05:13 +0200 Subject: [PATCH] add different kinds of enemies --- src/main-scene.zig | 159 +++++++++++++++++++++++++++++++++------------ 1 file changed, 117 insertions(+), 42 deletions(-) diff --git a/src/main-scene.zig b/src/main-scene.zig index f5a371e..7e7d1c2 100644 --- a/src/main-scene.zig +++ b/src/main-scene.zig @@ -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 ); }