Skip to content

bgf updates, star field, signals. #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 24, 2024
Merged
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ include(FetchContent)
FetchContent_Declare(
bgf
GIT_REPOSITORY https://github.com/karnkaul/bgf
GIT_TAG v0.1.4

# GIT_TAG v0.1.5
GIT_TAG adc217f
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/bgf"
)

Expand Down
Binary file added assets/images/beam_round.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/star_blue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/star_red.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/star_yellow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/music/game.mp3
Binary file not shown.
8 changes: 4 additions & 4 deletions assets/particles/explode.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
}
},
"angular": {
"lo": -90.000000,
"hi": 90.000000
"lo": -360.000000,
"hi": 360.000000
}
},
"lerp": {
Expand All @@ -52,8 +52,8 @@
"hi": 0.800000
},
"quad_size": [
100.000000,
100.000000
150.000000,
150.000000
],
"count": 40,
"respawn": true
Expand Down
4 changes: 3 additions & 1 deletion assets/styles.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"milk": "#e5cdaeff",
"ice": "#d6dbe1e1",
"orange": "#f75c03ff",
"gun_beam": "#bc96e6ff"
"gun_beam": "#bc96e6ff",
"bg_top": "#10020eff",
"bg_bottom": "#040003ff"
},
"buttons": {
"default": {
Expand Down
16 changes: 13 additions & 3 deletions src/spaced/spaced/game/arsenal.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#include <spaced/game/arsenal.hpp>
#include <spaced/services/game_signals.hpp>
#include <spaced/services/stats.hpp>

namespace spaced {
using bave::Seconds;
using bave::Services;
using bave::Shader;

Arsenal::Arsenal(Services const& services) : m_primary(services), m_stats(&services.get<Stats>()) {}
Arsenal::Arsenal(Services const& services)
: m_stats(&services.get<Stats>()), m_weapon_changed_signal(&services.get<GameSignals>().weapon_changed), m_primary(services) {
m_weapon_changed_signal->dispatch(get_weapon());
}

auto Arsenal::get_weapon() const -> Weapon const& {
if (m_special) { return *m_special; }
Expand Down Expand Up @@ -34,13 +38,19 @@ void Arsenal::tick_weapons(Seconds const dt) {
if (m_special) {
m_special->tick(dt);
// if the special weapon has no more rounds and is idle, reset it.
if (m_special->get_rounds_remaining() == 0 && m_special->is_idle()) { m_special.reset(); }
if (m_special->get_rounds_remaining() == 0 && m_special->is_idle()) {
m_special.reset();
m_weapon_changed_signal->dispatch(get_weapon());
}
}
}

void Arsenal::check_switch_weapon() {
// if there is a next weapon on standby and the current weapon is idle, switch to the next weapon.
if (m_next && get_weapon().is_idle()) { m_special = std::move(m_next); }
if (m_next && get_weapon().is_idle()) {
m_special = std::move(m_next);
m_weapon_changed_signal->dispatch(get_weapon());
}
}

void Arsenal::fire_weapon(glm::vec2 const muzzle_position) {
Expand Down
5 changes: 4 additions & 1 deletion src/spaced/spaced/game/arsenal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace spaced {
struct Stats;
struct SigWeaponChanged;

// Arsenal models a main/primary weapon, and an possible special weapon.
// Weapons only switch when they are idle.
Expand All @@ -26,8 +27,10 @@ class Arsenal {
void fire_weapon(glm::vec2 muzzle_position);
void tick_rounds(IWeaponRound::State const& round_state, bave::Seconds dt);

GunKinetic m_primary; // main weapon
bave::NotNull<Stats*> m_stats;
bave::NotNull<SigWeaponChanged*> m_weapon_changed_signal;

GunKinetic m_primary; // main weapon
std::unique_ptr<Weapon> m_special{}; // special weapon
std::unique_ptr<Weapon> m_next{}; // next special weapon (on standby until current weapon is idle)
std::vector<std::unique_ptr<Weapon::Round>> m_rounds{};
Expand Down
11 changes: 5 additions & 6 deletions src/spaced/spaced/game/controllers/player_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@ using bave::Action;
using bave::EnumArray;
using bave::GamepadAxis;
using bave::GamepadButton;
using bave::IDisplay;
using bave::im_text;
using bave::PointerMove;
using bave::PointerTap;
using bave::Seconds;
using bave::Services;

PlayerController::PlayerController(Services const& services) : m_display(&services.get<IDisplay>()), m_gamepad_provider(&services.get<IGamepadProvider>()) {
max_y = 0.5f * m_display->get_world_space().y;
PlayerController::PlayerController(Services const& services) : m_layout(&services.get<Layout>()), m_gamepad_provider(&services.get<IGamepadProvider>()) {
max_y = 0.5f * m_layout->world_space.y;
min_y = -max_y; // NOLINT(cppcoreguidelines-prefer-member-initializer)
}

void PlayerController::on_move(PointerMove const& pointer_move) {
auto const world_pos = m_display->project_to_world(pointer_move.pointer.position);
auto const world_pos = m_layout->project(pointer_move.pointer.position);

if (m_type == Type::eTouch) {
if (!is_in_move_area(world_pos)) {
Expand All @@ -41,7 +40,7 @@ void PlayerController::on_move(PointerMove const& pointer_move) {
}

void PlayerController::on_tap(PointerTap const& pointer_tap) {
auto const world_pos = m_display->project_to_world(pointer_tap.pointer.position);
auto const world_pos = m_layout->project(pointer_tap.pointer.position);
if (m_type == Type::eTouch && is_in_move_area(world_pos)) {
// pointer tap in move area is ingored
return;
Expand All @@ -68,7 +67,7 @@ void PlayerController::stop_firing() {
}

auto PlayerController::is_in_move_area(glm::vec2 const position) const -> bool {
auto const width = m_display->get_world_space().x;
auto const width = m_layout->world_space.x;
auto const n_pos = (position.x + 0.5f * width) / width;
return n_pos <= n_move_area;
}
Expand Down
6 changes: 3 additions & 3 deletions src/spaced/spaced/game/controllers/player_controller.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma once
#include <bave/core/ptr.hpp>
#include <bave/input/gamepad.hpp>
#include <bave/services/display.hpp>
#include <bave/services/services.hpp>
#include <spaced/game/controllers/follow_controller.hpp>
#include <spaced/game/spring_arm.hpp>
#include <spaced/services/gamepad_provider.hpp>
#include <spaced/services/layout.hpp>

namespace spaced {
class PlayerController : public FollowController {
Expand Down Expand Up @@ -45,8 +45,8 @@ class PlayerController : public FollowController {
auto tick_y(bave::Seconds dt) -> float final;
void do_inspect() final;

bave::Ptr<bave::IDisplay const> m_display{};
bave::Ptr<IGamepadProvider const> m_gamepad_provider{};
bave::NotNull<Layout const*> m_layout;
bave::NotNull<IGamepadProvider const*> m_gamepad_provider;

Type m_type{};
float m_y{};
Expand Down
103 changes: 55 additions & 48 deletions src/spaced/spaced/game/hud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,54 @@
#include <bave/services/styles.hpp>
#include <bave/ui/button.hpp>
#include <spaced/game/hud.hpp>
#include <spaced/services/game_signals.hpp>
#include <spaced/services/layout.hpp>

namespace spaced {
using bave::IDisplay;
using bave::Display;
using bave::Resources;
using bave::Seconds;
using bave::Services;
using bave::Shader;
using bave::Styles;
using bave::Text;
using bave::TextHeight;
using bave::Texture;

namespace ui = bave::ui;

Hud::Hud(Services const& services)
: ui::View(services), m_display(&services.get<IDisplay>()), m_layout(&services.get<Layout>()), m_styles(&services.get<Styles>()) {
Hud::Hud(Services const& services) : ui::View(services), m_layout(&services.get<Layout>()), m_styles(&services.get<Styles>()) {
create_background();
create_score(services);
create_lives_icon(services);
create_lives(services);
create_weapon(services);

block_input_events = false;
render_view = m_display->get_world_view();
}

void Hud::set_lives(int const lives) {
if (lives <= 0) {
m_lives_icon.instances.clear();
return;
}
render_view = services.get<Display>().world.render_view;

m_lives_icon.instances.resize(static_cast<std::size_t>(lives));
auto x_offset = 0.0f;
for (auto& instance : m_lives_icon.instances) {
instance.transform.position.x += x_offset;
x_offset += 2.0f * m_lives_icon.get_shape().size.x;
}
m_on_weapon_changed = services.get<GameSignals>().weapon_changed.connect([this](Weapon const& weapon) { set_weapon(weapon.get_icon()); });
}

void Hud::on_death() {
if (m_lives_icon.instances.empty()) { return; }
m_lives_icon.instances.pop_back();
void Hud::set_lives(int lives) {
lives = std::clamp(lives, 0, 99); // TODO: max_lives
m_lives_count->text.set_string(fmt::format("x{}", lives));
}

void Hud::set_score(std::int64_t const score) { m_score->text.set_string(fmt::format("{}", score)); }

void Hud::set_hi_score(std::int64_t const score) { m_hi_score->text.set_string(fmt::format("HI {}", score)); }

void Hud::render(Shader& shader) const {
View::render(shader);
m_lives_icon.draw(shader);
void Hud::set_weapon(std::shared_ptr<Texture const> texture) {
if (texture) { m_weapon_icon->sprite.set_size(texture->get_size()); }
m_weapon_icon->sprite.set_texture(std::move(texture));
}

auto Hud::make_text(Services const& services) const -> std::unique_ptr<ui::Text> {
auto const& rgbas = m_styles->rgbas;
auto text = std::make_unique<ui::Text>(services);
text->text.set_height(TextHeight{60});
text->text.transform.position = m_layout->hud_area.centre();
text->text.tint = rgbas["grey"];
return text;
}

void Hud::create_background() {
Expand All @@ -66,45 +64,54 @@ void Hud::create_background() {
}

void Hud::create_score(Services const& services) {
auto const& rgbas = m_styles->rgbas;

auto make_text = [&] {
auto text = std::make_unique<ui::Text>(services);
text->text.set_height(TextHeight{60});
text->text.transform.position = m_layout->hud_area.centre();
text->text.tint = rgbas["grey"];
return text;
};

auto text = make_text();
auto text = make_text(services);
m_score = text.get();
text->text.set_string("9999999999");
m_text_bounds_size = text->text.get_bounds().size();
text->text.transform.position.y -= 0.5f * m_text_bounds_size.y;
set_score(0);

push(std::move(text));

text = make_text();
text = make_text(services);
m_hi_score = text.get();
text->text.transform.position.x = m_layout->hud_area.rb.x - 50.0f;
text->text.transform.position.y -= 0.5f * m_text_bounds_size.y;
text->text.set_align(bave::Text::Align::eLeft);
text->text.set_align(Text::Align::eLeft);
set_hi_score(0);

push(std::move(text));
}

void Hud::create_lives_icon(Services const& services) {
auto quad = m_lives_icon.get_shape();
quad.size = glm::vec2{20.0f};
void Hud::create_lives(Services const& services) {
auto sprite = std::make_unique<ui::Sprite>();
m_lives_icon = sprite.get();
m_lives_icon->sprite.set_size(glm::vec2{20.0f});
auto const& resources = services.get<Resources>();
if (auto const texture = resources.get<Texture>("images/player_ship_icon.png")) {
quad.size = texture->get_size();
m_lives_icon.set_texture(texture);
m_lives_icon->sprite.set_texture(texture);
m_lives_icon->sprite.set_size(texture->get_size());
}
m_lives_icon.set_shape(quad);
m_lives_icon.transform.position = m_layout->hud_area.centre();
m_lives_icon.transform.position.x = m_layout->hud_area.lt.x + 100.0f;
auto position = m_layout->hud_area.centre();
position.x = m_layout->hud_area.lt.x + 100.0f;
m_lives_icon->set_position(position);
push(std::move(sprite));

auto text = make_text(services);
text->text.transform.position.y -= 0.5f * m_text_bounds_size.y;
text->text.transform.position.x = m_lives_icon->get_position().x + m_lives_icon->get_size().x;
text->text.set_align(Text::Align::eRight);
text->text.set_string("0");
m_lives_count = text.get();
push(std::move(text));
}

void Hud::create_weapon(Services const& /*services*/) {
auto sprite = std::make_unique<ui::Sprite>();
m_weapon_icon = sprite.get();
sprite->sprite.set_size(glm::vec2{50.0f});
auto position = m_lives_icon->get_position();
position.y -= 5.0f;
position.x = m_lives_count->get_position().x + 200.0f;
sprite->set_position(position);
push(std::move(sprite));
}
} // namespace spaced
18 changes: 12 additions & 6 deletions src/spaced/spaced/game/hud.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once
#include <bave/graphics/instanced.hpp>
#include <bave/services/styles.hpp>
#include <bave/ui/outline_quad.hpp>
#include <bave/ui/sprite.hpp>
#include <bave/ui/text.hpp>
#include <bave/ui/view.hpp>
#include <spaced/signal.hpp>

namespace spaced {
struct Layout;
Expand All @@ -13,26 +14,31 @@ class Hud : public bave::ui::View {
explicit Hud(bave::Services const& services);

void set_lives(int lives);
void on_death();
void set_score(std::int64_t score);
void set_hi_score(std::int64_t score);
void set_weapon(std::shared_ptr<bave::Texture const> texture);

private:
void render(bave::Shader& shader) const final;
[[nodiscard]] auto make_text(bave::Services const& services) const -> std::unique_ptr<bave::ui::Text>;

void create_background();
void create_score(bave::Services const& services);
void create_lives_icon(bave::Services const& services);
void create_lives(bave::Services const& services);
void create_weapon(bave::Services const& services);

bave::NotNull<bave::IDisplay const*> m_display;
bave::NotNull<Layout const*> m_layout;
bave::NotNull<bave::Styles const*> m_styles;
glm::vec2 m_text_bounds_size{};

SignalHandle m_on_weapon_changed{};

bave::Ptr<bave::ui::OutlineQuad> m_background{};
bave::Ptr<bave::ui::Text> m_score{};
bave::Ptr<bave::ui::Text> m_hi_score{};

bave::Instanced<bave::QuadShape> m_lives_icon{};
bave::Ptr<bave::ui::Sprite> m_lives_icon{};
bave::Ptr<bave::ui::Text> m_lives_count{};

bave::Ptr<bave::ui::Sprite> m_weapon_icon{};
};
} // namespace spaced
2 changes: 1 addition & 1 deletion src/spaced/spaced/game/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ using bave::Shader;
using bave::Texture;

Player::Player(Services const& services, std::unique_ptr<IController> controller)
: m_services(&services), m_stats(&services.get<Stats>()), m_controller(std::move(controller)), m_shield(services) {
: m_services(&services), m_stats(&services.get<Stats>()), m_controller(std::move(controller)), m_shield(services), m_arsenal(services) {
auto const& layout = services.get<Layout>();
ship.transform.position.x = layout.player_x;

Expand Down
Loading