add border

This commit is contained in:
Rokas Puzonas 2024-02-18 23:12:38 +02:00
parent 2941d9a39c
commit f58f3d0f86

View File

@ -11,10 +11,14 @@ const friction = 0.99;
const walkForce = 4000;
const maxSpeed = 200;
const handDistance = 50;
const deathBallSize: f32 = 10;
const deathBallSize: f32 = 13;
const playerSize = 20;
const virtualWidth = 300;
const virtualHeight = 300;
const virtualWidth = 350;
const virtualHeight = 350;
const safeRadius = 500;
const spawnAreaWidth = 400;
const arenaRadius = safeRadius + spawnAreaWidth;
const enemyFriction = friction;
@ -244,7 +248,7 @@ pub fn deinit(self: *Self) void {
self.pixel_effect.deinit();
}
fn tickPlayer(self: *Self) void {
fn updatePlayer(self: *Self) void {
const dt = rl.GetFrameTime();
var player = &self.player;
var rope = &self.rope;
@ -260,6 +264,12 @@ fn tickPlayer(self: *Self) void {
player.acceleration = rl.Vector2Scale(player.acceleration, walkForce);
}
if (player.position.length() > arenaRadius) {
const push_strength = std.math.pow(f32, player.position.length() - arenaRadius + 10, 2);
const push_direction = player.position.normalize().neg();
player.acceleration = player.acceleration.add(push_direction.scale(push_strength));
}
player.velocity = rl.Vector2Add(player.velocity, rl.Vector2Scale(player.acceleration, dt));
player.velocity = rl.Vector2ClampValue(player.velocity, 0, maxSpeed);
player.velocity = rl.Vector2Scale(player.velocity, std.math.pow(f32, (1 - friction), dt));
@ -274,7 +284,7 @@ fn tickPlayer(self: *Self) void {
rope.update(dt);
}
fn tickEnemies(self: *Self) !void {
fn updateEnemies(self: *Self) !void {
var rng = self.prng.random();
const dt = rl.GetFrameTime();
var enemies = &self.enemies;
@ -282,7 +292,7 @@ fn tickEnemies(self: *Self) !void {
var rope = &self.rope;
self.enemyTimer -= dt;
if (self.enemyTimer <= 0) {
if (self.enemyTimer <= 0 and player.alive()) {
self.enemyTimer = 0.5 + rng.float(f32) * 2;
self.spawnedEnemiesCount += 1;
const enemyPosition = rl.Vector2.randomOnUnitCircle(rng).scale(400);
@ -297,7 +307,7 @@ fn tickEnemies(self: *Self) !void {
self.damagePlayer();
}
if (enemy.vulnerable() and rl.Vector2Distance(enemy.position, deathBallPosition) < enemy.size + deathBallSize) {
if (enemy.vulnerable() and player.alive() and rl.Vector2Distance(enemy.position, deathBallPosition) < enemy.size + deathBallSize) {
self.damageEnemy(enemy);
}
@ -402,8 +412,8 @@ fn tickUI(self: *Self) !void {
const screen_box = UIBox.init(0 ,0, virtualWidth, virtualHeight);
const font = rl.GetFontDefault();
try allocDrawText(allocator, "{d}", .{self.spawnedEnemiesCount}, 10, 10, 12, rl.RED);
try allocDrawText(allocator, "{d}", .{self.killCount}, 10, 30, 12, rl.GREEN);
// try allocDrawText(allocator, "{d}", .{self.spawnedEnemiesCount}, 10, 10, 12, rl.RED);
// try allocDrawText(allocator, "{d}", .{self.killCount}, 10, 30, 12, rl.GREEN);
const minutes_text = try std.fmt.allocPrint(allocator, "{d:.0}", .{self.timePassed/60});
defer allocator.free(minutes_text);
@ -417,9 +427,9 @@ fn tickUI(self: *Self) !void {
const minutes_text_z = try std.mem.concatWithSentinel(allocator, u8, &.{ minutes_text }, 0);
defer allocator.free(minutes_text_z);
const font_size = 12;
const font_size = 20;
const time_passed_width: f32 = @floatFromInt(rl.MeasureText(minutes_text_z, font_size) + rl.MeasureText(":000", font_size));
const time_passed_pos = screen_box.center_top().add(.{ .x = -time_passed_width/2, .y = 30 });
const time_passed_pos = screen_box.center_top().add(.{ .x = -time_passed_width/2, .y = 10 });
rl.DrawTextEx(
font,
time_passed_text,
@ -430,7 +440,7 @@ fn tickUI(self: *Self) !void {
);
if (!self.player.alive()) {
const modal_size = rl.Vector2{ .x = 200, .y = 400 };
const modal_size = rl.Vector2{ .x = 200, .y = 200 };
const modal = screen_box.box(
screen_box.center() - modal_size.x/2,
screen_box.middle() - modal_size.y/2,
@ -448,11 +458,20 @@ fn tickUI(self: *Self) !void {
rl.BLACK
);
if (self.ui.button("Restart?", content.left(), content.top() + 70, content.width, 30)) {
try allocDrawText(
allocator,
"Kills: {d}", .{self.killCount},
@intFromFloat(content.left() + 10),
@intFromFloat(content.top() + 60),
30,
rl.BLACK
);
if (self.ui.button("Restart?", content.left(), content.bottom() - 70, content.width, 30)) {
self.reset();
}
if (self.ui.button("Exit?", content.left(), content.top() + 120, content.width, 30)) {
if (self.ui.button("Exit?", content.left(), content.bottom() - 30, content.width, 30)) {
self.should_close = true;
}
} else if (self.paused) {
@ -497,7 +516,7 @@ fn drawPlayer(self: *Self) void {
var player = &self.player;
const handPosition = player.getHandPosition();
const healthWidth = 5;
const healthWidth = 7;
const healthPercent = @as(f32, @floatFromInt(player.health)) / @as(f32, @floatFromInt(player.maxHealth));
var healthColor = rl.GREEN;
if (player.invincibility > 0 and @rem(player.invincibility, 0.2) < 0.1) {
@ -513,9 +532,10 @@ fn drawPlayer(self: *Self) void {
);
for (0..(player.health+1)) |i| {
const percent = @as(f32, @floatFromInt(i)) / @as(f32, @floatFromInt(player.maxHealth));
rl.DrawLineV(
rl.DrawLineEx(
player.position,
player.position.add((rl.Vector2{ .x = playerSize + healthWidth, .y = 0 }).rotate(percent * 2 * rl.PI)),
5,
rl.BLACK
);
}
@ -533,83 +553,100 @@ fn drawPlayer(self: *Self) void {
);
}
fn rgba(r: u8, g: u8, b: u8, a: u8) rl.Color {
return rl.Color{ .r = r, .g = g, .b = b, .a = a };
}
fn rgb(r: u8, g: u8, b: u8) rl.Color {
return rgba(r, g, b, 255);
}
fn drawWorld(self: *Self) void {
rl.rlSetLineWidth(1);
var enemies = &self.enemies;
var rope = &self.rope;
const deathBallPosition = rope.nodePositions.get(rope.nodePositions.len-1);
rl.ClearBackground(rl.BLACK);
rl.DrawCircle(0, 0, arenaRadius, rl.BROWN);
rl.DrawCircle(0, 0, 5, rl.GOLD);
rl.DrawCircleLines(0, 0, safeRadius, rl.WHITE);
rl.DrawCircleLines(0, 0, safeRadius + spawnAreaWidth, rl.WHITE);
self.drawPlayer();
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),
enemy.size,
color
);
}
rl.rlDrawRenderBatchActive();
rl.rlSetLineWidth(3);
for (0..(rope.nodePositions.len-1)) |i| {
var node1: rl.Vector2 = rope.nodePositions.get(i);
var node2: rl.Vector2 = rope.nodePositions.get(i+1);
rl.DrawLine(
@intFromFloat(node1.x),
@intFromFloat(node1.y),
@intFromFloat(node2.x),
@intFromFloat(node2.y),
rgb(106, 7, 17)
);
}
rl.rlDrawRenderBatchActive();
rl.rlSetLineWidth(1);
for (rope.nodePositions.slice()) |node| {
rl.DrawCircle(
@intFromFloat(node.x),
@intFromFloat(node.y),
5,
rgb(194, 12, 30)
);
}
rl.DrawCircle(
@intFromFloat(deathBallPosition.x),
@intFromFloat(deathBallPosition.y),
deathBallSize,
rgb(239, 48, 67)
);
}
pub fn tick(self: *Self) !void {
const dt = rl.GetFrameTime();
self.camera.offset.x = virtualWidth/2;
self.camera.offset.y = virtualHeight/2;
self.camera.zoom = 0.4;
self.camera.target = rl.Vector2Lerp(self.camera.target, self.player.position, 10 * dt);
var enemies = &self.enemies;
var rope = &self.rope;
if (self.player.input.isPausePressed()) {
if (self.player.input.isPausePressed() and self.player.alive()) {
self.togglePaused();
}
if (!self.paused) {
self.tickPlayer();
try self.tickEnemies();
self.camera.offset.x = virtualWidth/2;
self.camera.offset.y = virtualHeight/2;
self.camera.zoom = 0.4;
self.camera.target = rl.Vector2Lerp(self.camera.target, self.player.position, 10 * dt);
self.updatePlayer();
try self.updateEnemies();
if (self.player.alive()) {
self.timePassed += rl.GetFrameTime();
}
}
const deathBallPosition = rope.nodePositions.get(rope.nodePositions.len-1);
self.pixel_effect.begin();
rl.ClearBackground(rl.BROWN);
rl.BeginMode2D(self.camera);
{
rl.DrawCircle(0, 0, 5, rl.GOLD);
self.drawPlayer();
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),
enemy.size,
color
);
}
const rope_color = rl.PURPLE;
for (0..(rope.nodePositions.len-1)) |i| {
var node1: rl.Vector2 = rope.nodePositions.get(i);
var node2: rl.Vector2 = rope.nodePositions.get(i+1);
rl.DrawLine(
@intFromFloat(node1.x),
@intFromFloat(node1.y),
@intFromFloat(node2.x),
@intFromFloat(node2.y),
rope_color
);
}
for (rope.nodePositions.slice()) |node| {
rl.DrawCircle(
@intFromFloat(node.x),
@intFromFloat(node.y),
5,
rope_color
);
}
rl.DrawCircle(
@intFromFloat(deathBallPosition.x),
@intFromFloat(deathBallPosition.y),
deathBallSize,
rl.RED
);
}
self.drawWorld();
rl.EndMode2D();
self.pixel_effect.end();