diff --git a/include/game_entity_Entity.h b/include/game_entity_Entity.h index f90602d..537b65e 100644 --- a/include/game_entity_Entity.h +++ b/include/game_entity_Entity.h @@ -1,13 +1,29 @@ #pragma once +#include +#include +#include +#include + namespace sym::game::entity { class Entity { public: - virtual void FreeGraphicResources() = 0; - virtual void AllocateGraphicResources() = 0; + virtual ~Entity() = 0; + + Entity(bn::fixed_point position, bn::fixed_rect collider, const bn::sprite_item* const spriteItem = nullptr); + Entity(Entity&& other) noexcept; + + void FreeGraphicResource(); + virtual void AllocateGraphicResource(); + +protected: + bn::fixed_point position_; + bn::fixed_rect collider_; + bn::optional sprite_; + const bn::sprite_item* const spriteItem_; }; } // namespace sym::game::entity diff --git a/include/game_entity_Symbol.h b/include/game_entity_Symbol.h index 7cda478..93b4388 100644 --- a/include/game_entity_Symbol.h +++ b/include/game_entity_Symbol.h @@ -2,20 +2,38 @@ #include "game_entity_Entity.h" -#include -#include - namespace sym::game::entity { class Symbol final : Entity { public: - void FreeGraphicResources() final; - void AllocateGraphicResources() final; + static constexpr int COMPLEX_SYMBOL_START_NUM = 100; + /** + * @brief Symbol type + * + * If `[enum value] >= COMPLEX_SYMBOL_START_NUM`, it is a complex symbol. + * otherwise, it is a basic symbol. + */ + enum Type + { + BAR, + XOR, + UP = COMPLEX_SYMBOL_START_NUM, + VV, + PLUS + }; + + Symbol(bn::fixed_point position, Symbol::Type type); + Symbol(Symbol&& other) noexcept; + + void AllocateGraphicResource() final; + + Type GetType() const; + void SetType(Type); private: - bn::optional sprite_; + Symbol::Type type_; }; } // namespace sym::game::entity diff --git a/include/game_stage_ZoneInfo.h b/include/game_stage_ZoneInfo.h index e829eb9..25ce9b5 100644 --- a/include/game_stage_ZoneInfo.h +++ b/include/game_stage_ZoneInfo.h @@ -3,12 +3,13 @@ #include #include #include -#include #include #include #include "helper_tilemap.h" +#include "game_entity_Symbol.h" + namespace sym::game::stage { @@ -21,23 +22,8 @@ struct ZoneInfo { struct SymbolInfo { - /** - * @brief Symbol types - * - * If value >= 100, it is a complex symbol. - * otherwise, it is a basic symbol. - */ - enum Type - { - BAR, - XOR, - UP = 100, - VV, - PLUS - }; - bn::fixed_point position; - Type symbolType; + entity::Symbol::Type symbolType; }; struct ButtonInfo @@ -61,32 +47,44 @@ struct ZoneInfo int entranceOfZoneIndex; }; + struct ShutterInfo + { + bn::fixed_point position; + }; + + struct EntranceInfo + { + bn::fixed_point position; + }; + /** * @brief Constructor. * * @param zoneBoundary_a anchor is center of bg */ - constexpr ZoneInfo(const bn::affine_bg_item& mapBg_a, helper::tilemap::IndexRect zoneBoundary_a, - bn::span symbols_a, bn::span hoverButtons_a, - bn::span pressureButtons_a, bn::span doors_a, bn::span exits_a, - bn::span entrances_a) + constexpr ZoneInfo(const bn::affine_bg_item& mapBg_a, const helper::tilemap::IndexRect zoneBoundary_a, + bn::span symbols_a, bn::span hoverButtons_a, + bn::span pressureButtons_a, bn::span doors_a, + bn::span exits_a, bn::span shutters_a, + bn::span entrances_a) : mapBg(mapBg_a), symbols(symbols_a), hoverButtons(hoverButtons_a), pressureButtons(pressureButtons_a), - zoneBoundary(zoneBoundary_a), doors(doors_a), exits(exits_a), entrances(entrances_a) + zoneBoundary(zoneBoundary_a), doors(doors_a), exits(exits_a), shutters(shutters_a), entrances(entrances_a) { } const bn::affine_bg_item& mapBg; // Mutable things. Only for initialize. - const bn::span symbols; - const bn::span hoverButtons; - const bn::span pressureButtons; + const bn::span symbols; + const bn::span hoverButtons; + const bn::span pressureButtons; // Constant things. Constantly referenced. const bn::fixed_rect zoneBoundary; - const bn::span doors; - const bn::span exits; - const bn::span entrances; + const bn::span doors; + const bn::span exits; + const bn::span shutters; + const bn::span entrances; }; } // namespace sym::game::stage diff --git a/include/helper_rect.h b/include/helper_rect.h new file mode 100644 index 0000000..9f2dd01 --- /dev/null +++ b/include/helper_rect.h @@ -0,0 +1,19 @@ +#include + +namespace sym::helper::rect +{ + +[[nodiscard]] constexpr bn::fixed_rect MakeFixedRectByTopLeftAndSize(bn::fixed_point topLeft, bn::fixed_size size) +{ + const bn::fixed_point centerPos = topLeft + bn::fixed_point(size.width() / 2, size.height() / 2); + return bn::fixed_rect(centerPos, size); +} + +[[nodiscard]] constexpr bn::fixed_rect MakeFixedRectByTopLeftAndBottomRightPosition(bn::fixed_point topLeft, + bn::fixed_point bottomRight) +{ + const bn::fixed_size size(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()); + return MakeFixedRectByTopLeftAndSize(topLeft, size); +} + +} // namespace sym::helper::rect diff --git a/include/helper_tilemap.h b/include/helper_tilemap.h index 2760aa7..f21960e 100644 --- a/include/helper_tilemap.h +++ b/include/helper_tilemap.h @@ -5,6 +5,8 @@ #include #include +#include "helper_rect.h" + namespace sym::helper::tilemap { @@ -17,9 +19,7 @@ using IndexPoint = bn::fixed_point; [[nodiscard]] constexpr IndexRect MakeIndexRectByTopLeftAndBottomRight(IndexPoint topLeft, IndexPoint bottomRight) { - const bn::fixed_size size(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()); - const IndexPoint centerPos = topLeft + IndexPoint(size.width() / 2, size.height() / 2); - return {centerPos, size}; + return rect::MakeFixedRectByTopLeftAndBottomRightPosition(topLeft, bottomRight); } /** diff --git a/include/scene_Game.h b/include/scene_Game.h index 2d5348c..b112a26 100644 --- a/include/scene_Game.h +++ b/include/scene_Game.h @@ -2,11 +2,18 @@ #include "scene_IScene.h" +#include +#include +#include +#include #include +#include #include +#include #include "effect_Transition.h" #include "game_Status.h" +#include "game_entity_Symbol.h" #include "game_stage_Id.h" #include "game_stage_StageInfo.h" @@ -17,17 +24,46 @@ class Game final : public IScene { public: Game(game::Status& status); + ~Game(); + [[nodiscard]] bn::optional Update() final; private: static constexpr int FADE_IN_UPDATE_COUNT = 30; static constexpr int FADE_OUT_UPDATE_COUNT = 30; - game::Status status_; + static constexpr int ZONE_MAX_COUNT = 8; + static constexpr int STAGE_SYMBOL_MAX_COUNT = 16; + static constexpr int ZONE_HOVER_BUTTON_MAX_COUNT = 4; + static constexpr int ZONE_PRESSURE_BUTTON_MAX_COUNT = 4; + static constexpr int ZONE_DOOR_MAX_COUNT = 4; + static constexpr int ZONE_EXIT_MAX_COUNT = 4; + static constexpr int ZONE_SHUTTER_MAX_COUNT = 4; + static constexpr int ZONE_ENTRANCE_MAX_COUNT = ZONE_DOOR_MAX_COUNT + ZONE_EXIT_MAX_COUNT; + + game::Status& status_; const game::stage::StageInfo& stageInfo_; effect::Transition fadeIn_; effect::Transition fadeOut_; + + int currentZoneIdx_; + bn::affine_bg_ptr currentMapBg_; + + // Movable entities. + bn::vector, ZONE_MAX_COUNT> symbolsOfZones_; + bn::array, 2> symbolsInHands_; + + // Fixed entities. + // bn::vector, ZONE_MAX_COUNT> + // hoverButtonsOfZones_; bn::vector, + // ZONE_MAX_COUNT> pressureButtonsOfZones_; bn::vector, + // ZONE_MAX_COUNT> doorsOfZones_; + // bn::vector, ZONE_MAX_COUNT> exitsOfZones_; + // bn::vector, ZONE_MAX_COUNT> shuttersOfZones_; + // bn::vector, ZONE_MAX_COUNT> entrancesOfZones_; + + void SetCurrentZone_(int zoneIdx); }; } // namespace sym::scene diff --git a/include/scene_Title.h b/include/scene_Title.h index 296fe52..b287ae2 100644 --- a/include/scene_Title.h +++ b/include/scene_Title.h @@ -21,7 +21,7 @@ class Title final : public IScene { public: Title(); - ~Title() = default; + ~Title(); [[nodiscard]] bn::optional Update() final; private: diff --git a/src/game_entity_Entity.cpp b/src/game_entity_Entity.cpp new file mode 100644 index 0000000..cd93e8b --- /dev/null +++ b/src/game_entity_Entity.cpp @@ -0,0 +1,29 @@ +#include "game_entity_Entity.h" + +namespace sym::game::entity +{ + +Entity::~Entity() = default; + +Entity::Entity(bn::fixed_point position, bn::fixed_rect collider, const bn::sprite_item* const spriteItem) + : position_(position), collider_(collider), spriteItem_(spriteItem) +{ +} + +Entity::Entity(Entity&& other) noexcept + : collider_(other.collider_), sprite_(bn::move(other.sprite_)), spriteItem_(other.spriteItem_) +{ +} + +void Entity::FreeGraphicResource() +{ + sprite_.reset(); +} + +void Entity::AllocateGraphicResource() +{ + if (spriteItem_) + sprite_ = spriteItem_->create_sprite(collider_.position()); +} + +} // namespace sym::game::entity diff --git a/src/game_entity_Symbol.cpp b/src/game_entity_Symbol.cpp new file mode 100644 index 0000000..a0d02b7 --- /dev/null +++ b/src/game_entity_Symbol.cpp @@ -0,0 +1,105 @@ +#include "game_entity_Symbol.h" + +#include +#include + +#include "helper_rect.h" + +#include "bn_sprite_items_spr_basic_symbols.h" +#include "bn_sprite_items_spr_complex_symbols.h" + +namespace sym::game::entity +{ + +namespace +{ + +bool IsComplexSymbol_(Symbol::Type type) +{ + return static_cast(type) >= Symbol::COMPLEX_SYMBOL_START_NUM; +} + +bn::fixed_rect GenerateColliderFromSymbolType_(bn::fixed_point position, Symbol::Type symbolType, + bn::sprite_shape_size spriteShapeSize) +{ + const bn::fixed_rect spriteRect(position, {spriteShapeSize.width(), spriteShapeSize.height()}); + const bn::fixed_point topLeft = spriteRect.top_left(); + + bn::fixed_point resultTopLeft = topLeft; + bn::fixed_size resultSize; + + switch (symbolType) + { + case Symbol::Type::BAR: + resultTopLeft += {7, 2}; + resultSize = {2, 12}; + break; + case Symbol::Type::XOR: + resultTopLeft += {2, 4}; + resultSize = {12, 7}; + break; + case Symbol::Type::UP: + resultTopLeft += {2, 1}; + resultSize = {12, 14}; + break; + case Symbol::Type::VV: + resultTopLeft += {0, 2}; + resultSize = {16, 12}; + break; + case Symbol::Type::PLUS: + resultTopLeft += {2, 2}; + resultSize = {12, 12}; + break; + default: + BN_ERROR("Unknown Symbol::Type : ", static_cast(symbolType)); + break; + } + return helper::rect::MakeFixedRectByTopLeftAndSize(resultTopLeft, resultSize); +} + +} // namespace + +Symbol::Symbol(bn::fixed_point position, Symbol::Type type) + : Entity(position, + GenerateColliderFromSymbolType_(position, type, + IsComplexSymbol_(type) ? bn::sprite_items::spr_complex_symbols.shape_size() + : bn::sprite_items::spr_basic_symbols.shape_size()), + IsComplexSymbol_(type) ? &bn::sprite_items::spr_complex_symbols : &bn::sprite_items::spr_basic_symbols), + type_(type) +{ + AllocateGraphicResource(); +} + +Symbol::Symbol(Symbol&& other) noexcept : Entity(bn::move(other)) +{ +} + +void Symbol::AllocateGraphicResource() +{ + int spriteIdx = static_cast(type_); + if (IsComplexSymbol_(type_)) + spriteIdx -= COMPLEX_SYMBOL_START_NUM; + + const bn::sprite_item& spriteItem = + IsComplexSymbol_(type_) ? bn::sprite_items::spr_complex_symbols : bn::sprite_items::spr_basic_symbols; + if (!sprite_) + sprite_ = spriteItem.create_sprite(position_); + sprite_->set_item(spriteItem); + sprite_->set_tiles(spriteItem.tiles_item().create_tiles(spriteIdx)); +} + +Symbol::Type Symbol::GetType() const +{ + return type_; +} + +void Symbol::SetType(Symbol::Type newType) +{ + if (type_ != newType) + { + type_ = newType; + AllocateGraphicResource(); + } +} + +} // namespace sym::game::entity diff --git a/src/game_stage_W0_S0.cpp b/src/game_stage_W0_S0.cpp index 2b54a5d..c67a524 100644 --- a/src/game_stage_W0_S0.cpp +++ b/src/game_stage_W0_S0.cpp @@ -9,10 +9,13 @@ namespace sym::game::stage namespace { +constexpr ZoneInfo::SymbolInfo symbolInfos_[] = {{{0, 0}, entity::Symbol::Type::BAR}, + {{30, 30}, entity::Symbol::Type::XOR}}; + constexpr ZoneInfo zoneInfos_[1] = {ZoneInfo( bn::affine_bg_items::bg_w0_s0_0, helper::tilemap::MakeIndexRectByTopLeftAndBottomRight({0, 82}, {127, 127}), - bn::span(), bn::span(), bn::span(), - bn::span(), bn::span(), bn::span())}; + symbolInfos_, bn::span(), bn::span(), bn::span(), + bn::span(), bn::span(), bn::span())}; constexpr StageInfo w0_s0_("W0-0", "Test stage", zoneInfos_); diff --git a/src/scene_Game.cpp b/src/scene_Game.cpp index 7f9c845..6cea4bb 100644 --- a/src/scene_Game.cpp +++ b/src/scene_Game.cpp @@ -1,6 +1,7 @@ #include "scene_Game.h" #include +#include #include "bn_optional.h" #include "game_stage_getter.h" @@ -41,17 +42,38 @@ Game::Game(game::Status& status) fadeIn_(Transition::Types::FADE | Transition::Types::BG_MOSAIC | effect::Transition::Types::SPRITE_MOSAIC, Transition::Direction::IN, FADE_IN_UPDATE_COUNT), fadeOut_(Transition::Types::FADE | Transition::Types::BG_MOSAIC | effect::Transition::Types::SPRITE_MOSAIC, - Transition::Direction::OUT, FADE_OUT_UPDATE_COUNT) + Transition::Direction::OUT, FADE_OUT_UPDATE_COUNT), + currentMapBg_(stageInfo_.zoneInfos[0].mapBg.create_bg({512 - 120, -512 + 80})) { - // test - BN_LOG(stageInfo_.stageName, ", ", stageInfo_.stageSubName, ", ", - stageInfo_.zoneInfos[0].zoneBoundary.top_left().y()); + currentZoneIdx_ = 0; + currentMapBg_.set_wrapping_enabled(false); + + symbolsOfZones_.resize(stageInfo_.zoneInfos.size()); + + for (auto& symbolInfo : stageInfo_.zoneInfos[currentZoneIdx_].symbols) + { + symbolsOfZones_[currentZoneIdx_].emplace_front(symbolInfo.position, symbolInfo.symbolType); + } +} + +Game::~Game() +{ + bn::blending::set_fade_alpha(0); } bn::optional Game::Update() { + // TODO return bn::nullopt; } +void Game::SetCurrentZone_(int zoneIdx) +{ + BN_ASSERT(0 <= zoneIdx && zoneIdx < stageInfo_.zoneInfos.size(), "Zone index out of range!"); + + currentMapBg_ = stageInfo_.zoneInfos[zoneIdx].mapBg.create_bg({0, 0}); + currentMapBg_.set_wrapping_enabled(false); +} + } // namespace sym::scene diff --git a/src/scene_Title.cpp b/src/scene_Title.cpp index 9fe9cae..a681fb0 100644 --- a/src/scene_Title.cpp +++ b/src/scene_Title.cpp @@ -4,6 +4,7 @@ #include #include +#include "bn_blending.h" #include "global.h" #include "bn_optional.h" @@ -37,6 +38,11 @@ Title::Title() fadeIn_.Init(); } +Title::~Title() +{ + bn::blending::set_fade_alpha(0); +} + bn::optional Title::Update() { using Transition = effect::Transition;