Skip to content

Commit

Permalink
Add new enemy
Browse files Browse the repository at this point in the history
  • Loading branch information
zyperpl committed Jan 8, 2024
1 parent 43c329a commit 38a062a
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 28 deletions.
Binary file added resources/alien_ship.aseprite
Binary file not shown.
131 changes: 113 additions & 18 deletions src/asteroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "game.hpp"
#include "particle.hpp"
#include "pickable.hpp"
#include "player.hpp"
#include "player_ship.hpp"
#include "utils.hpp"

#include "magic_enum/magic_enum.hpp"
Expand All @@ -14,6 +16,7 @@ static constexpr const float ASTEROIDS_SIZE[]{ 8.0f, 16.0f, 32.0f };
static constexpr const int ASTEROID_SPLIT_COUNT{ 2 };

std::unique_ptr<Sprite> Asteroid::ASTEROID_SPRITE{ nullptr };
std::unique_ptr<Sprite> Asteroid::ALIEN_SHIP_SPRITE{ nullptr };

Particle create_asteroid_particle(const Vector2 &position, unsigned char alpha = 255)
{
Expand Down Expand Up @@ -77,6 +80,34 @@ static std::unordered_map<Asteroid::Type, std::string> type_tag_map{ { Asteroid:
return asteroid;
}

[[nodiscard]] Asteroid Asteroid::create_alien_ship(const Vector2 &position)
{
if (!ALIEN_SHIP_SPRITE)
ALIEN_SHIP_SPRITE = std::make_unique<Sprite>("resources/alien_ship.aseprite");

Asteroid asteroid;
asteroid.position = position;
asteroid.velocity.x = 1.0f;
asteroid.velocity.y = 0.0f;
asteroid.type = Asteroid::Type::AlienShip;
asteroid.mask.shapes.push_back(Circle{ Vector2{ 0.0f, 0.0f }, 16.0f });
return asteroid;
}

[[nodiscard]] Asteroid Asteroid::create_alien_bullet(const Vector2 &position, const Vector2 &direction)
{
if (!ALIEN_SHIP_SPRITE)
ALIEN_SHIP_SPRITE = std::make_unique<Sprite>("resources/alien_ship.aseprite");

Asteroid asteroid;
asteroid.position = position;
asteroid.velocity.x = direction.x * 2.0f;
asteroid.velocity.y = direction.y * 2.0f;
asteroid.type = Asteroid::Type::AlienBullet;
asteroid.mask.shapes.push_back(Circle{ Vector2{ 0.0f, 0.0f }, 4.0f });
return asteroid;
}

bool Asteroid::update()
{
position.x += velocity.x;
Expand Down Expand Up @@ -114,11 +145,53 @@ bool Asteroid::update()
return false;
}

if (type == Type::AlienShip)
{
if (GAME.player)
{
if (GAME.frame % 240 == 0)
{
if (GetRandomValue(0, 1) == 0)
{
const Vector2 direction = Vector2Normalize(Vector2Subtract(GAME.player->position, position));
GAME.asteroids->push(Asteroid::create_alien_bullet(position, direction));
}
}
}
velocity.y = sin(static_cast<float>(GAME.frame) / 100.0f) * 0.5f;
}
if (type == Type::AlienBullet)
{
if (GAME.frame % 10 == 0)
{
for (int i = 0; i < 10; i++)
GAME.particles->push(Particle::create(position, Vector2Scale(velocity, 0.5f), ColorAlpha(RED, 0.9f)));
}
const int r = GetRandomValue(0, 60);
if (GAME.frame % (180 + r) == 0)
{
life--;
}
}

return true;
}

void Asteroid::die()
{
if (type == Type::AlienShip)
{
GAME.score += 1000;
for (int i = 0; i < 100; i++)
GAME.particles->push(Particle::create(
position,
Vector2{ static_cast<float>(GetRandomValue(-1, 1)), static_cast<float>(GetRandomValue(-1, 1)) },
Color{ 200, 255, 55, 250 }));
}

if (type == Type::AlienBullet)
return;

static SMSound sound1 = SoundManager::get("resources/explosion_asteroid1.wav");
static SMSound sound2 = SoundManager::get("resources/explosion_asteroid2.wav");
static SMSound sound3 = SoundManager::get("resources/explosion_asteroid3.wav");
Expand Down Expand Up @@ -202,29 +275,51 @@ void Asteroid::die()

void Asteroid::draw() const noexcept
{
Color color = DARKPURPLE;
if (type == Type::AlienShip)
{
assert(ALIEN_SHIP_SPRITE);
ALIEN_SHIP_SPRITE->set_centered();
ALIEN_SHIP_SPRITE->position = position;

assert(ASTEROID_SPRITE);
assert(type_tag_map.find(type) != type_tag_map.end());
draw_wrapped(ALIEN_SHIP_SPRITE->get_destination_rect(),
[&](const Vector2 &P)
{
ALIEN_SHIP_SPRITE->position = P;
ALIEN_SHIP_SPRITE->draw();
});
}
else if (type == Type::AlienBullet)
{
draw_wrapped(Rectangle{ position.x - 2.0f, position.y - 2.0f, 4.0f, 4.0f },
[&](const Vector2 &P) { DrawCircleV(P, 3.0f, RED); });
}
else
{

ASTEROID_SPRITE->set_centered();
ASTEROID_SPRITE->set_tag(type_tag_map[type]);
ASTEROID_SPRITE->tint = ColorBrightness(color, 0.5f + static_cast<float>(life) / static_cast<float>(max_life) * 0.5f);
ASTEROID_SPRITE->position = position;
Color color = DARKPURPLE;
assert(ASTEROID_SPRITE);
assert(type_tag_map.find(type) != type_tag_map.end());

draw_wrapped(ASTEROID_SPRITE->get_destination_rect(),
[&](const Vector2 &P)
{
ASTEROID_SPRITE->position = P;
ASTEROID_SPRITE->draw();
ASTEROID_SPRITE->set_centered();
ASTEROID_SPRITE->set_tag(type_tag_map[type]);
ASTEROID_SPRITE->tint =
ColorBrightness(color, 0.5f + static_cast<float>(life) / static_cast<float>(max_life) * 0.5f);
ASTEROID_SPRITE->position = position;

if (CONFIG(show_masks))
draw_wrapped(ASTEROID_SPRITE->get_destination_rect(),
[&](const Vector2 &P)
{
Mask mask_copy = mask;
mask_copy.position = P;
mask_copy.draw();
}
});
ASTEROID_SPRITE->position = P;
ASTEROID_SPRITE->draw();

if (CONFIG(show_masks))
{
Mask mask_copy = mask;
mask_copy.position = P;
mask_copy.draw();
}
});
}

if (CONFIG(show_debug))
{
Expand Down
7 changes: 6 additions & 1 deletion src/asteroid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class Asteroid
Size1 = 0,
Size2,
Size3,
Crystal
Crystal,
AlienShip,
AlienBullet
};

Vector2 position{};
Expand All @@ -28,6 +30,8 @@ class Asteroid

[[nodiscard]] static Asteroid create_normal(const Vector2 &position, uint8_t size);
[[nodiscard]] static Asteroid create_crystal(const Vector2 &position);
[[nodiscard]] static Asteroid create_alien_ship(const Vector2 &position);
[[nodiscard]] static Asteroid create_alien_bullet(const Vector2 &position, const Vector2 &direction);

bool update();

Expand All @@ -42,6 +46,7 @@ class Asteroid
DECLARE_FRIEND_OBJECT_CIRCULAR_BUFFER()

static std::unique_ptr<Sprite> ASTEROID_SPRITE;
static std::unique_ptr<Sprite> ALIEN_SHIP_SPRITE;

friend class Game;
};
24 changes: 19 additions & 5 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void Game::init()
.name = "Close Quarters Space",
.description = "Find artifact",
.number_of_asteroids = 12,
.number_of_aliens = 1,
} },
{ 5,
{
Expand All @@ -80,26 +81,32 @@ void Game::init()
{
.name = "Trans-Neptunian Region",
.description = "Destroy all enemies",
.number_of_asteroids = 18,
.number_of_asteroids = 2,
.number_of_aliens = 3,
} },
{ 7,
{
.name = "Interstellar Space",
.description = "Survive enemy attack",
.number_of_asteroids = 20,
.number_of_asteroids = 5,
.survive_time_seconds = 60.0f,
.number_of_aliens = 4,
} },
{ 8,
{
.name = "Galactic Core",
.description = "Destroy all asteroids and enemies",
.number_of_asteroids = 22,
.number_of_asteroids = 10,
.number_of_aliens = 5,
} },
{ 9,
{ .name = "Intergalactic Space",
.description = "Survive",
.number_of_asteroids = 24,
.survive_time_seconds = 120.0f } },
.number_of_asteroids = 20,
.survive_time_seconds = 120.0f,
.number_of_aliens = 1

} },
{ 10, { .name = "_the_end", .description = "The End", .number_of_asteroids = 0 } } };

Room::load();
Expand Down Expand Up @@ -520,6 +527,13 @@ void Game::set_state(GameState new_state) noexcept
particles->push(Particle::create(particle_position, particle_velocity, particle_color));
}

for (size_t i = 0; i < param.number_of_aliens; ++i)
{
const Vector2 position = { static_cast<float>(GetRandomValue(0, width)),
static_cast<float>(GetRandomValue(0, height)) };
asteroids->push(Asteroid::create_alien_ship(position));
}

room = std::make_shared<Room>(); // NOTE: Asteroids room is not loaded from file
room->rect = Rectangle{ 0.0f, 0.0f, static_cast<float>(width), static_cast<float>(height) };
room->interactables.push_back(std::make_unique<Station>());
Expand Down
1 change: 1 addition & 0 deletions src/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct MissionParameters
size_t number_of_asteroids{ 1 };
size_t number_of_asteroid_crystals{ 0 };
float survive_time_seconds{ 0 };
float number_of_aliens{ 0 };

void unlock() noexcept;
[[nodiscard]] bool is_unlocked() const noexcept { return unlocked; }
Expand Down
9 changes: 5 additions & 4 deletions src/particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,24 @@ bool Particle::update() noexcept
if ((GAME.frame % 2 == 0 && object_id % 2 == 0) || (GAME.frame % 2 == 1 && object_id % 2 == 1))
{
GAME.asteroids->for_each(
[&](Asteroid &asteroid) -> bool
[&](Asteroid &asteroid)
{
if (asteroid.size() >= 3)
return;

const Vector2 &asteroid_position = asteroid.position;
const float x_diff = position.x - asteroid_position.x;
const float y_diff = position.y - asteroid_position.y;
const float distance_sqr = x_diff * x_diff + y_diff * y_diff;
if (distance_sqr < 25.0f)
return true;
return;

if (distance_sqr < asteroid_size_threshold[asteroid.size()])
{
const float factor = 0.1f / sqrt(distance_sqr);
velocity.x += x_diff * factor;
velocity.y += y_diff * factor;
}

return true;
});
}
}
Expand Down

0 comments on commit 38a062a

Please sign in to comment.