Skip to content

Commit a7aded0

Browse files
aleokdevkarnkaul
andauthored
Add heat/cooldown mechanic (#57)
* Add heat/cooldown mechanics * Add more health to enemies * Cleanup. --------- Co-authored-by: Karn Kaul <karnkaul@gmail.com>
1 parent 2428ed7 commit a7aded0

File tree

10 files changed

+47
-12
lines changed

10 files changed

+47
-12
lines changed

assets/assets/styles.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"gun_beam": "#bc96e6ff",
1010
"exhaust": "#36bbf5ff",
1111
"bg_top": "#10020eff",
12-
"bg_bottom": "#040003ff"
12+
"bg_bottom": "#040003ff",
13+
"ship_heat": "#ac3939ff"
1314
},
1415
"buttons": {
1516
"default": {
@@ -81,4 +82,4 @@
8182
"padding": 20
8283
}
8384
}
84-
}
85+
}

src/spaced/spaced/game/arsenal.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ auto Arsenal::get_weapon() -> Weapon& {
2121
return const_cast<Weapon&>(std::as_const(*this).get_weapon()); // NOLINT(cppcoreguidelines-pro-type-const-cast)
2222
}
2323

24-
void Arsenal::tick(IWeaponRound::State const& round_state, bool const fire, Seconds const dt) {
24+
auto Arsenal::tick(IWeaponRound::State const& round_state, bool const fire, Seconds const dt) -> bool {
2525
tick_weapons(dt);
2626
check_switch_weapon();
27-
if (round_state.in_play && fire) { fire_weapon(round_state.muzzle_position); }
27+
bool has_fired = false;
28+
if (round_state.in_play && fire) { has_fired = fire_weapon(round_state.muzzle_position); }
2829
tick_rounds(round_state, dt);
30+
return has_fired;
2931
}
3032

3133
void Arsenal::draw(Shader& shader) const {
@@ -53,11 +55,13 @@ void Arsenal::check_switch_weapon() {
5355
}
5456
}
5557

56-
void Arsenal::fire_weapon(glm::vec2 const muzzle_position) {
58+
auto Arsenal::fire_weapon(glm::vec2 const muzzle_position) -> bool {
5759
if (auto round = get_weapon().fire(muzzle_position)) {
5860
m_rounds.push_back(std::move(round));
5961
++m_stats->player.shots_fired;
62+
return true;
6063
}
64+
return false;
6165
}
6266

6367
void Arsenal::tick_rounds(IWeaponRound::State const& round_state, Seconds const dt) {

src/spaced/spaced/game/arsenal.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ class Arsenal {
1818

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

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

2425
private:
2526
void tick_weapons(bave::Seconds dt);
2627
void check_switch_weapon();
27-
void fire_weapon(glm::vec2 muzzle_position);
28+
auto fire_weapon(glm::vec2 muzzle_position) -> bool;
2829
void tick_rounds(IWeaponRound::State const& round_state, bave::Seconds dt);
2930

3031
bave::NotNull<Stats*> m_stats;

src/spaced/spaced/game/enemies/creep.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Creep::Creep(bave::Services const& services) : Enemy(services, "Creep") {
1111
m_sprite.set_texture(std::move(texture));
1212
}
1313

14-
health = 1.0f;
14+
health = 2.0f;
1515
speed = 100.0f;
1616
points = 10;
1717
}

src/spaced/spaced/game/enemies/gunner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Gunner::Gunner(bave::Services const& services, bave::NotNull<GunKinetic*> gun) :
1111
m_sprite.set_texture(std::move(texture));
1212
}
1313

14-
health = 2.0f;
14+
health = 3.0f;
1515
speed = 120.0f;
1616
points = 20;
1717
}

src/spaced/spaced/game/enemies/trooper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Trooper::Trooper(Services const& services, NotNull<GunKinetic*> gun) : GunnerBas
1818

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

21-
health = 3.0f;
21+
health = 4.0f;
2222
speed = 150.0f;
2323
points = 30;
2424
}

src/spaced/spaced/game/player.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Player::Player(Services const& services, std::unique_ptr<IController> controller
4646

4747
if (auto const death = resources.get<ParticleEmitter>("assets/particles/explode.json")) { m_death_source = *death; }
4848
m_death_source.config.respawn = false;
49+
50+
m_heat_color = rgbas.get_or("ship_heat", bave::red_v);
4951
}
5052

5153
void Player::on_focus(bave::FocusChange const& /*focus_changed*/) { m_controller->untap(); }
@@ -65,7 +67,20 @@ void Player::tick(State const& state, Seconds const dt) {
6567
.muzzle_position = get_muzzle_position(),
6668
.in_play = !m_health.is_dead(),
6769
};
68-
m_arsenal.tick(round_state, m_controller->is_firing(), dt);
70+
71+
auto const has_fired = m_arsenal.tick(round_state, m_controller->is_firing() && !m_is_cooling_down, dt);
72+
73+
if (has_fired) {
74+
m_heat += m_heat_increment;
75+
} else {
76+
m_heat -= (m_is_cooling_down ? m_heat_dissipated * 0.5f : m_heat_dissipated) * dt.count();
77+
}
78+
if (m_heat >= 1.0f) { m_is_cooling_down = true; }
79+
if (m_heat <= m_cooldown_threshold) { m_is_cooling_down = false; }
80+
m_heat = std::clamp(m_heat, 0.f, 1.0f);
81+
82+
m_heat_being_rendered = glm::mix(m_heat_being_rendered, m_heat, 0.5f);
83+
ship.tint = bave::Rgba::from(glm::mix(bave::white_v.to_vec4(), m_heat_color.to_vec4(), m_heat_being_rendered));
6984

7085
m_shield.set_position(ship.transform.position);
7186
m_shield.tick(dt);
@@ -188,6 +203,10 @@ void Player::do_inspect() {
188203
}
189204

190205
if (ImGui::Button("1up")) { one_up(); }
206+
207+
ImGui::DragFloat("heat dissipated per sec", &m_heat_dissipated, 0.05f, 0.f, 1.f);
208+
ImGui::DragFloat("heat per round fired", &m_heat_increment, 0.1f, 0.f, 1.f);
209+
ImGui::DragFloat("cooldown threshold", &m_cooldown_threshold, 0.1f, 0.f, 0.9f);
191210
}
192211
}
193212
} // namespace spaced

src/spaced/spaced/game/player.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ class Player : public IDamageable, public bave::IDrawable {
7474
bave::ParticleEmitter m_exhaust{};
7575
Shield m_shield;
7676

77+
float m_heat_being_rendered{};
78+
float m_heat{};
79+
float m_heat_increment{0.1f};
80+
float m_heat_dissipated{0.4f}; // per second
81+
bave::Rgba m_heat_color{};
82+
bool m_is_cooling_down{};
83+
float m_cooldown_threshold{0.5f};
84+
7785
bave::ParticleEmitter m_death_source{};
7886
std::optional<bave::ParticleEmitter> m_death{};
7987

src/spaced/spaced/game/weapons/gun_kinetic.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ void GunKinetic::do_inspect() {
3838
auto tint = projectile_config.tint.to_vec4();
3939
if (ImGui::ColorEdit4("projectile tint", &tint.x)) { projectile_config.tint = Rgba::from(tint); }
4040
ImGui::DragFloat("damage", &projectile_config.damage, 0.25f, 0.25f, 10.0f);
41+
auto reload_delay_s = reload_delay.count();
42+
if (ImGui::DragFloat("reload delay", &reload_delay_s, 0.05f, 0.1f, 1.f)) { reload_delay = Seconds{reload_delay_s}; }
4143
}
4244
}
4345
} // namespace spaced

src/spaced/spaced/game/weapons/gun_kinetic.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class GunKinetic final : public Weapon {
1515

1616
Projectile::Config projectile_config{};
1717
std::string_view fire_sfx{"assets/sfx/kinetic_fire.wav"};
18-
bave::Seconds reload_delay{0.25s};
18+
bave::Seconds reload_delay{0.15s};
1919

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

0 commit comments

Comments
 (0)