Skip to content

Commit

Permalink
Add heat/cooldown mechanic (#57)
Browse files Browse the repository at this point in the history
* Add heat/cooldown mechanics

* Add more health to enemies

* Cleanup.

---------

Co-authored-by: Karn Kaul <karnkaul@gmail.com>
  • Loading branch information
aleokdev and karnkaul authored Jul 14, 2024
1 parent 2428ed7 commit a7aded0
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 12 deletions.
5 changes: 3 additions & 2 deletions assets/assets/styles.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"gun_beam": "#bc96e6ff",
"exhaust": "#36bbf5ff",
"bg_top": "#10020eff",
"bg_bottom": "#040003ff"
"bg_bottom": "#040003ff",
"ship_heat": "#ac3939ff"
},
"buttons": {
"default": {
Expand Down Expand Up @@ -81,4 +82,4 @@
"padding": 20
}
}
}
}
10 changes: 7 additions & 3 deletions src/spaced/spaced/game/arsenal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ auto Arsenal::get_weapon() -> Weapon& {
return const_cast<Weapon&>(std::as_const(*this).get_weapon()); // NOLINT(cppcoreguidelines-pro-type-const-cast)
}

void Arsenal::tick(IWeaponRound::State const& round_state, bool const fire, Seconds const dt) {
auto Arsenal::tick(IWeaponRound::State const& round_state, bool const fire, Seconds const dt) -> bool {
tick_weapons(dt);
check_switch_weapon();
if (round_state.in_play && fire) { fire_weapon(round_state.muzzle_position); }
bool has_fired = false;
if (round_state.in_play && fire) { has_fired = fire_weapon(round_state.muzzle_position); }
tick_rounds(round_state, dt);
return has_fired;
}

void Arsenal::draw(Shader& shader) const {
Expand Down Expand Up @@ -53,11 +55,13 @@ void Arsenal::check_switch_weapon() {
}
}

void Arsenal::fire_weapon(glm::vec2 const muzzle_position) {
auto Arsenal::fire_weapon(glm::vec2 const muzzle_position) -> bool {
if (auto round = get_weapon().fire(muzzle_position)) {
m_rounds.push_back(std::move(round));
++m_stats->player.shots_fired;
return true;
}
return false;
}

void Arsenal::tick_rounds(IWeaponRound::State const& round_state, Seconds const dt) {
Expand Down
5 changes: 3 additions & 2 deletions src/spaced/spaced/game/arsenal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ class Arsenal {

void set_special(std::unique_ptr<Weapon> weapon) { m_next = std::move(weapon); }

void tick(IWeaponRound::State const& round_state, bool fire, bave::Seconds dt);
// returns whether a round was fired this frame
auto tick(IWeaponRound::State const& round_state, bool fire, bave::Seconds dt) -> bool;
void draw(bave::Shader& shader) const;

private:
void tick_weapons(bave::Seconds dt);
void check_switch_weapon();
void fire_weapon(glm::vec2 muzzle_position);
auto fire_weapon(glm::vec2 muzzle_position) -> bool;
void tick_rounds(IWeaponRound::State const& round_state, bave::Seconds dt);

bave::NotNull<Stats*> m_stats;
Expand Down
2 changes: 1 addition & 1 deletion src/spaced/spaced/game/enemies/creep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Creep::Creep(bave::Services const& services) : Enemy(services, "Creep") {
m_sprite.set_texture(std::move(texture));
}

health = 1.0f;
health = 2.0f;
speed = 100.0f;
points = 10;
}
Expand Down
2 changes: 1 addition & 1 deletion src/spaced/spaced/game/enemies/gunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Gunner::Gunner(bave::Services const& services, bave::NotNull<GunKinetic*> gun) :
m_sprite.set_texture(std::move(texture));
}

health = 2.0f;
health = 3.0f;
speed = 120.0f;
points = 20;
}
Expand Down
2 changes: 1 addition & 1 deletion src/spaced/spaced/game/enemies/trooper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Trooper::Trooper(Services const& services, NotNull<GunKinetic*> gun) : GunnerBas

m_direction = random_in_range(0, 1) == 0 ? 1.0f : -1.0f;

health = 3.0f;
health = 4.0f;
speed = 150.0f;
points = 30;
}
Expand Down
21 changes: 20 additions & 1 deletion src/spaced/spaced/game/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Player::Player(Services const& services, std::unique_ptr<IController> controller

if (auto const death = resources.get<ParticleEmitter>("assets/particles/explode.json")) { m_death_source = *death; }
m_death_source.config.respawn = false;

m_heat_color = rgbas.get_or("ship_heat", bave::red_v);
}

void Player::on_focus(bave::FocusChange const& /*focus_changed*/) { m_controller->untap(); }
Expand All @@ -65,7 +67,20 @@ void Player::tick(State const& state, Seconds const dt) {
.muzzle_position = get_muzzle_position(),
.in_play = !m_health.is_dead(),
};
m_arsenal.tick(round_state, m_controller->is_firing(), dt);

auto const has_fired = m_arsenal.tick(round_state, m_controller->is_firing() && !m_is_cooling_down, dt);

if (has_fired) {
m_heat += m_heat_increment;
} else {
m_heat -= (m_is_cooling_down ? m_heat_dissipated * 0.5f : m_heat_dissipated) * dt.count();
}
if (m_heat >= 1.0f) { m_is_cooling_down = true; }
if (m_heat <= m_cooldown_threshold) { m_is_cooling_down = false; }
m_heat = std::clamp(m_heat, 0.f, 1.0f);

m_heat_being_rendered = glm::mix(m_heat_being_rendered, m_heat, 0.5f);
ship.tint = bave::Rgba::from(glm::mix(bave::white_v.to_vec4(), m_heat_color.to_vec4(), m_heat_being_rendered));

m_shield.set_position(ship.transform.position);
m_shield.tick(dt);
Expand Down Expand Up @@ -188,6 +203,10 @@ void Player::do_inspect() {
}

if (ImGui::Button("1up")) { one_up(); }

ImGui::DragFloat("heat dissipated per sec", &m_heat_dissipated, 0.05f, 0.f, 1.f);
ImGui::DragFloat("heat per round fired", &m_heat_increment, 0.1f, 0.f, 1.f);
ImGui::DragFloat("cooldown threshold", &m_cooldown_threshold, 0.1f, 0.f, 0.9f);
}
}
} // namespace spaced
8 changes: 8 additions & 0 deletions src/spaced/spaced/game/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ class Player : public IDamageable, public bave::IDrawable {
bave::ParticleEmitter m_exhaust{};
Shield m_shield;

float m_heat_being_rendered{};
float m_heat{};
float m_heat_increment{0.1f};
float m_heat_dissipated{0.4f}; // per second
bave::Rgba m_heat_color{};
bool m_is_cooling_down{};
float m_cooldown_threshold{0.5f};

bave::ParticleEmitter m_death_source{};
std::optional<bave::ParticleEmitter> m_death{};

Expand Down
2 changes: 2 additions & 0 deletions src/spaced/spaced/game/weapons/gun_kinetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ void GunKinetic::do_inspect() {
auto tint = projectile_config.tint.to_vec4();
if (ImGui::ColorEdit4("projectile tint", &tint.x)) { projectile_config.tint = Rgba::from(tint); }
ImGui::DragFloat("damage", &projectile_config.damage, 0.25f, 0.25f, 10.0f);
auto reload_delay_s = reload_delay.count();
if (ImGui::DragFloat("reload delay", &reload_delay_s, 0.05f, 0.1f, 1.f)) { reload_delay = Seconds{reload_delay_s}; }
}
}
} // namespace spaced
2 changes: 1 addition & 1 deletion src/spaced/spaced/game/weapons/gun_kinetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GunKinetic final : public Weapon {

Projectile::Config projectile_config{};
std::string_view fire_sfx{"assets/sfx/kinetic_fire.wav"};
bave::Seconds reload_delay{0.25s};
bave::Seconds reload_delay{0.15s};

private:
auto do_fire(glm::vec2 muzzle_position) -> std::unique_ptr<Round> final;
Expand Down

0 comments on commit a7aded0

Please sign in to comment.