added lives
This commit is contained in:
50
main.cpp
50
main.cpp
@@ -15,6 +15,7 @@ Rectangle walls[] = {
|
|||||||
|
|
||||||
Player player;
|
Player player;
|
||||||
auto player_speed = 5.0f;
|
auto player_speed = 5.0f;
|
||||||
|
auto player_invulnerability = 1.0f;
|
||||||
|
|
||||||
uint32_t score;
|
uint32_t score;
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ double last_fired = 0;
|
|||||||
double fire_rate = .5;
|
double fire_rate = .5;
|
||||||
|
|
||||||
std::mutex enemy_mutex;
|
std::mutex enemy_mutex;
|
||||||
float enemy_max_speed = 2.0;
|
float enemy_max_speed = 3.0;
|
||||||
float enemy_radius = 25.0;
|
float enemy_radius = 25.0;
|
||||||
Enemy enemies[100] = {};
|
Enemy enemies[100] = {};
|
||||||
|
|
||||||
@@ -54,6 +55,14 @@ Vector2 Player::center() const noexcept {
|
|||||||
return {.x = this->x + this->width / 2, .y = this->y + this->height / 2};
|
return {.x = this->x + this->width / 2, .y = this->y + this->height / 2};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle Player::rect() const noexcept {
|
||||||
|
return {.x = x, .y = y, .width = width, .height = height};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::is_invulnerable(const double now) const noexcept {
|
||||||
|
return now < this->last_hit + player_invulnerability;
|
||||||
|
}
|
||||||
|
|
||||||
void Player::move(const float delta_x, const float delta_y) {
|
void Player::move(const float delta_x, const float delta_y) {
|
||||||
const auto x = std::min(
|
const auto x = std::min(
|
||||||
std::max(this->x + delta_x, 0.0f),
|
std::max(this->x + delta_x, 0.0f),
|
||||||
@@ -110,31 +119,25 @@ struct EnemySpawner {
|
|||||||
const auto starting_x = Rng::generate(static_cast<uint32_t>(screen_width));
|
const auto starting_x = Rng::generate(static_cast<uint32_t>(screen_width));
|
||||||
const auto starting_y = Rng::generate(static_cast<uint32_t>(screen_height));
|
const auto starting_y = Rng::generate(static_cast<uint32_t>(screen_height));
|
||||||
|
|
||||||
for (auto &[center, radius, moving, alive]: enemies) {
|
for (auto &[center, radius, speed, alive]: enemies) {
|
||||||
if (alive) continue;
|
if (alive) continue;
|
||||||
alive = true;
|
alive = true;
|
||||||
radius = enemy_radius;
|
radius = enemy_radius;
|
||||||
const float normalized_dir = Rng::generate(-1, 1);
|
|
||||||
if (num < 0.25) {
|
if (num < 0.25) {
|
||||||
center = {.x = starting_x, .y = 0};
|
center = {.x = starting_x, .y = 0};
|
||||||
moving = {.x = normalized_dir, .y = 1};
|
|
||||||
} else if (0.25 <= num && num < 0.5) {
|
} else if (0.25 <= num && num < 0.5) {
|
||||||
center = {
|
center = {
|
||||||
.x = starting_x, .y = (screen_height)
|
.x = starting_x, .y = (screen_height)
|
||||||
};
|
};
|
||||||
moving = {.x = normalized_dir, .y = -1};
|
|
||||||
} else if (0.5 <= num && num < 0.75) {
|
} else if (0.5 <= num && num < 0.75) {
|
||||||
center = {.x = 0, .y = starting_y};
|
center = {.x = 0, .y = starting_y};
|
||||||
moving = {.x = 1, .y = normalized_dir};
|
|
||||||
} else {
|
} else {
|
||||||
center = {
|
center = {
|
||||||
.x = (screen_width), .y = starting_y
|
.x = (screen_width), .y = starting_y
|
||||||
};
|
};
|
||||||
moving = {.x = -1, .y = normalized_dir};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto speed = Rng::generate(static_cast<uint32_t>(enemy_max_speed));
|
speed = Rng::generate(static_cast<uint32_t>(enemy_max_speed));
|
||||||
moving = Vector2Scale(moving, speed);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -210,17 +213,21 @@ int main() {
|
|||||||
InitWindow(800, 600, "Isaac++");
|
InitWindow(800, 600, "Isaac++");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
EnemySpawner spawner{3};
|
EnemySpawner spawner{2};
|
||||||
spawner.start();
|
spawner.start();
|
||||||
|
|
||||||
player.width = 50;
|
player.width = 50;
|
||||||
player.height = 50;
|
player.height = 50;
|
||||||
player.x = screen_width / 2 - player.width / 2;
|
player.x = screen_width / 2 - player.width / 2;
|
||||||
player.y = screen_height / 2 - player.height / 2;
|
player.y = screen_height / 2 - player.height / 2;
|
||||||
|
player.lives = 3;
|
||||||
|
player.last_hit = -10;
|
||||||
|
|
||||||
std::string score_text_buffer{64};
|
std::string score_text_buffer;
|
||||||
score_text_buffer.reserve(64);
|
score_text_buffer.reserve(64);
|
||||||
score_text_buffer.clear();
|
|
||||||
|
std::string lives_text_buffer;
|
||||||
|
lives_text_buffer.reserve(64);
|
||||||
|
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
if (IsWindowResized()) {
|
if (IsWindowResized()) {
|
||||||
@@ -252,7 +259,8 @@ int main() {
|
|||||||
tear_direction = DOWN;
|
tear_direction = DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto now = GetTime(); last_fired + fire_rate < now && tear_direction.has_value()) {
|
const auto now = GetTime();
|
||||||
|
if (last_fired + fire_rate < now && tear_direction.has_value()) {
|
||||||
last_fired = now;
|
last_fired = now;
|
||||||
spawn_tear(player.center(), tear_direction.value());
|
spawn_tear(player.center(), tear_direction.value());
|
||||||
}
|
}
|
||||||
@@ -261,7 +269,7 @@ int main() {
|
|||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
DrawRectangleRec(player, BLUE);
|
DrawRectangleRec(player.rect(), player.is_invulnerable(now) ? GOLD : BLUE);
|
||||||
|
|
||||||
for (const auto wall: walls) {
|
for (const auto wall: walls) {
|
||||||
DrawRectangleRec(wall, GREEN);
|
DrawRectangleRec(wall, GREEN);
|
||||||
@@ -275,15 +283,21 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard enemy_guard{enemy_mutex};
|
std::lock_guard enemy_guard{enemy_mutex};
|
||||||
for (auto &[center, radius, moving, alive]: enemies) {
|
for (auto &[center, radius, speed, alive]: enemies) {
|
||||||
if (alive) {
|
if (alive) {
|
||||||
center = Vector2Add(center, moving);
|
center = Vector2MoveTowards(center, player.center(), speed);
|
||||||
DrawCircleV(center, radius, RED);
|
DrawCircleV(center, radius, RED);
|
||||||
|
|
||||||
if (center.x < 0 || screen_width < center.x ||
|
if (center.x < 0 || screen_width < center.x ||
|
||||||
center.y < 0 || screen_height < center.y) {
|
center.y < 0 || screen_height < center.y) {
|
||||||
alive = false;
|
alive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CheckCollisionCircleRec(center, radius, player.rect()) &&
|
||||||
|
player.last_hit + player_invulnerability < now) {
|
||||||
|
player.lives--;
|
||||||
|
player.last_hit = now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,6 +306,10 @@ int main() {
|
|||||||
DrawText(score_text_buffer.c_str(), 50, static_cast<int>(screen_height) - 100, 20, BLACK);
|
DrawText(score_text_buffer.c_str(), 50, static_cast<int>(screen_height) - 100, 20, BLACK);
|
||||||
score_text_buffer.clear();
|
score_text_buffer.clear();
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(lives_text_buffer), "Lives: {}", player.lives);
|
||||||
|
DrawText(lives_text_buffer.c_str(), 50, static_cast<int>(screen_height) - 50, 20, BLACK);
|
||||||
|
lives_text_buffer.clear();
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
|
|||||||
6
types.h
6
types.h
@@ -8,7 +8,11 @@
|
|||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
struct Player : Rectangle {
|
struct Player : Rectangle {
|
||||||
|
uint8_t lives;
|
||||||
|
double last_hit;
|
||||||
[[nodiscard]] Vector2 center() const noexcept;
|
[[nodiscard]] Vector2 center() const noexcept;
|
||||||
|
[[nodiscard]] Rectangle rect() const noexcept;
|
||||||
|
[[nodiscard]] bool is_invulnerable(double now) const noexcept;
|
||||||
|
|
||||||
void move(float delta_x, float delta_y);
|
void move(float delta_x, float delta_y);
|
||||||
};
|
};
|
||||||
@@ -34,6 +38,6 @@ struct Tear {
|
|||||||
struct Enemy {
|
struct Enemy {
|
||||||
Vector2 center;
|
Vector2 center;
|
||||||
float radius;
|
float radius;
|
||||||
Vector2 moving;
|
float speed;
|
||||||
bool alive;
|
bool alive;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user