From 02fb9356b9e1c46dac62bdcd991611bed4972fd8 Mon Sep 17 00:00:00 2001 From: Nikolai Wuttke Date: Mon, 1 Jun 2020 10:29:13 +0200 Subject: [PATCH 1/7] Fix: Prevent red bird from gettting stuck --- src/game_logic/enemies/red_bird.cpp | 22 +++++++++++++++------- src/game_logic/enemies/red_bird.hpp | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/game_logic/enemies/red_bird.cpp b/src/game_logic/enemies/red_bird.cpp index 3c116dfca..a6225dc1c 100644 --- a/src/game_logic/enemies/red_bird.cpp +++ b/src/game_logic/enemies/red_bird.cpp @@ -95,8 +95,11 @@ void RedBird::update( } }, - [&](const PlungingDown&) { - // no-op, state transition handled by collision event handler + [&](const PlungingDown& state) { + const auto bbox = *entity.component(); + if (d.mpCollisionChecker->isOnSolidGround(position, bbox)) { + startRisingUp(state.mInitialHeight, entity); + } }, [&, this](RisingUp& state) { @@ -128,8 +131,6 @@ void RedBird::onCollision( ) { using namespace red_bird; - auto& body = *entity.component(); - base::match(mState, [&](const Flying&) { if (event.mCollidedLeft || event.mCollidedRight) { @@ -139,9 +140,7 @@ void RedBird::onCollision( [&, this](const PlungingDown& state) { if (event.mCollidedBottom) { - mState = RisingUp{state.mInitialHeight}; - body.mGravityAffected = false; - engine::startAnimationSequence(entity, HOVER_ANIMATION, 0, true); + startRisingUp(state.mInitialHeight, entity); } }, @@ -149,4 +148,13 @@ void RedBird::onCollision( [](const RisingUp&) {}); } + +void RedBird::startRisingUp(const int initialHeight, entityx::Entity entity) { + auto& body = *entity.component(); + + mState = red_bird::RisingUp{initialHeight}; + body.mGravityAffected = false; + engine::startAnimationSequence(entity, HOVER_ANIMATION, 0, true); +} + } diff --git a/src/game_logic/enemies/red_bird.hpp b/src/game_logic/enemies/red_bird.hpp index 0d51c0ae8..30f48089c 100644 --- a/src/game_logic/enemies/red_bird.hpp +++ b/src/game_logic/enemies/red_bird.hpp @@ -76,6 +76,8 @@ struct RedBird { const engine::events::CollidedWithWorld& event, entityx::Entity entity); + void startRisingUp(int initialHeight, entityx::Entity entity); + red_bird::State mState; }; From ca7c0083322c434c7cb14c00bdd077b71291b5b7 Mon Sep 17 00:00:00 2001 From: Nikolai Wuttke Date: Mon, 1 Jun 2020 12:23:04 +0200 Subject: [PATCH 2/7] Cleanup: Move state structs into class --- src/game_logic/enemies/red_bird.cpp | 6 +--- src/game_logic/enemies/red_bird.hpp | 55 ++++++++++++----------------- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/game_logic/enemies/red_bird.cpp b/src/game_logic/enemies/red_bird.cpp index a6225dc1c..5e70c3a55 100644 --- a/src/game_logic/enemies/red_bird.cpp +++ b/src/game_logic/enemies/red_bird.cpp @@ -65,8 +65,6 @@ void RedBird::update( const bool isOnScreen, entityx::Entity entity ) { - using namespace red_bird; - auto& position = *entity.component(); auto& body = *entity.component(); auto& sprite = *entity.component(); @@ -129,8 +127,6 @@ void RedBird::onCollision( const engine::events::CollidedWithWorld& event, entityx::Entity entity ) { - using namespace red_bird; - base::match(mState, [&](const Flying&) { if (event.mCollidedLeft || event.mCollidedRight) { @@ -152,7 +148,7 @@ void RedBird::onCollision( void RedBird::startRisingUp(const int initialHeight, entityx::Entity entity) { auto& body = *entity.component(); - mState = red_bird::RisingUp{initialHeight}; + mState = RisingUp{initialHeight}; body.mGravityAffected = false; engine::startAnimationSequence(entity, HOVER_ANIMATION, 0, true); } diff --git a/src/game_logic/enemies/red_bird.hpp b/src/game_logic/enemies/red_bird.hpp index 30f48089c..39d85cd91 100644 --- a/src/game_logic/enemies/red_bird.hpp +++ b/src/game_logic/enemies/red_bird.hpp @@ -32,37 +32,6 @@ void configureRedBird(entityx::Entity entity); namespace rigel::game_logic::behaviors { -namespace red_bird { - -struct Flying {}; - - -struct Hovering { - int mFramesElapsed = 0; -}; - - -struct PlungingDown { - int mInitialHeight; -}; - - -struct RisingUp { - explicit RisingUp(const int initialHeight) - : mInitialHeight(initialHeight) - { - } - - int mInitialHeight; - bool mBackAtOriginalHeight = false; -}; - - -using State = std::variant; - -} - - struct RedBird { void update( GlobalDependencies&, @@ -78,7 +47,29 @@ struct RedBird { void startRisingUp(int initialHeight, entityx::Entity entity); - red_bird::State mState; + + struct Flying {}; + + struct Hovering { + int mFramesElapsed = 0; + }; + + struct PlungingDown { + int mInitialHeight; + }; + + struct RisingUp { + explicit RisingUp(const int initialHeight) + : mInitialHeight(initialHeight) + { + } + + int mInitialHeight; + bool mBackAtOriginalHeight = false; + }; + + using State = std::variant; + State mState; }; } From 39c1e653c8f01936bd25a5344a7d16131c50db34 Mon Sep 17 00:00:00 2001 From: Nikolai Wuttke Date: Mon, 1 Jun 2020 14:33:43 +0200 Subject: [PATCH 3/7] Overhaul red bird enemy This improves consistency with the original game. --- src/game_logic/enemies/red_bird.cpp | 68 ++++++++++++++++------------- src/game_logic/enemies/red_bird.hpp | 13 +++++- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/game_logic/enemies/red_bird.cpp b/src/game_logic/enemies/red_bird.cpp index 5e70c3a55..de79c9917 100644 --- a/src/game_logic/enemies/red_bird.cpp +++ b/src/game_logic/enemies/red_bird.cpp @@ -27,33 +27,23 @@ using namespace rigel::engine::components; -namespace { -const int FLY_ANIMATION_L[] = {0, 1, 2, 1}; -const int FLY_ANIMATION_R[] = {3, 4, 5, 4}; -const int HOVER_ANIMATION[] = {6, 7}; +namespace { +constexpr int FLY_ANIMATION[] = {0, 1, 2, 1}; +constexpr int HOVER_ANIMATION[] = {6, 7}; -void fly(entityx::Entity entity, const bool left) { - rigel::engine::startAnimationSequence( - entity, - left ? FLY_ANIMATION_L : FLY_ANIMATION_R, - 0, - true); - entity.component()->mVelocity.x = left ? -1.0f : 1.0f; -} +constexpr int FLY_ANIMATION_ORIENTATION_OFFSET = 3; } void rigel::game_logic::configureRedBird(entityx::Entity entity) { using namespace engine::components::parameter_aliases; - entity.assign(Velocity{-1.0f, 0.0f}, GravityAffected{false}); + entity.assign(Velocity{}, GravityAffected{false}); entity.assign( ActivationSettings::Policy::AlwaysAfterFirstActivation); entity.assign(behaviors::RedBird{}); - - engine::startAnimationSequence(entity, FLY_ANIMATION_L, 0, true); } @@ -71,24 +61,42 @@ void RedBird::update( const auto& playerPosition = s.mpPlayer->orientedPosition(); base::match(mState, - [&, this](const Flying&) { + [&, this](Flying& state) { const auto wantsToAttack = position.y + 2 < playerPosition.y && position.x > playerPosition.x && position.x < playerPosition.x + 2; if (wantsToAttack) { + sprite.mFramesToRender[0] = + HOVER_ANIMATION[int(s.mpPerFrameState->mIsOddFrame)]; mState = Hovering{}; - body.mVelocity = {}; - engine::startAnimationSequence(entity, HOVER_ANIMATION, 0, true); + } else { + const auto result = engine::moveHorizontally( + *d.mpCollisionChecker, + entity, + engine::orientation::toMovement(state.mOrientation)); + if (result != engine::MovementResult::Completed) { + state.mOrientation = + engine::orientation::opposite(state.mOrientation); + } else { + // Animate flying + ++state.mAnimStep; + sprite.mFramesToRender[0] = + FLY_ANIMATION[state.mAnimStep % 4] + + (state.mOrientation == Orientation::Right + ? FLY_ANIMATION_ORIENTATION_OFFSET : 0); + } } }, [&, this](Hovering& state) { + sprite.mFramesToRender[0] = + HOVER_ANIMATION[int(s.mpPerFrameState->mIsOddFrame)]; + ++state.mFramesElapsed; - if (state.mFramesElapsed >= 6) { + if (state.mFramesElapsed >= 7) { mState = PlungingDown{position.y}; body.mGravityAffected = true; - entity.remove(); sprite.mFramesToRender[0] = 6; } }, @@ -102,12 +110,16 @@ void RedBird::update( [&, this](RisingUp& state) { if (state.mBackAtOriginalHeight) { - mState = Flying{}; const auto flyingLeft = !s.mpPerFrameState->mIsOddFrame; - fly(entity, flyingLeft); + const auto newOrientation = + flyingLeft ? Orientation::Left : Orientation::Right; + mState = Flying{newOrientation}; return; } + sprite.mFramesToRender[0] = + HOVER_ANIMATION[int(s.mpPerFrameState->mIsOddFrame)]; + if (position.y > state.mInitialHeight) { --position.y; } else { @@ -118,6 +130,8 @@ void RedBird::update( state.mBackAtOriginalHeight = true; } }); + + engine::synchronizeBoundingBoxToSprite(entity); } @@ -128,20 +142,13 @@ void RedBird::onCollision( entityx::Entity entity ) { base::match(mState, - [&](const Flying&) { - if (event.mCollidedLeft || event.mCollidedRight) { - fly(entity, !event.mCollidedLeft); - } - }, - [&, this](const PlungingDown& state) { if (event.mCollidedBottom) { startRisingUp(state.mInitialHeight, entity); } }, - [](const Hovering&) {}, - [](const RisingUp&) {}); + [](const auto&) {}); } @@ -150,7 +157,6 @@ void RedBird::startRisingUp(const int initialHeight, entityx::Entity entity) { mState = RisingUp{initialHeight}; body.mGravityAffected = false; - engine::startAnimationSequence(entity, HOVER_ANIMATION, 0, true); } } diff --git a/src/game_logic/enemies/red_bird.hpp b/src/game_logic/enemies/red_bird.hpp index 39d85cd91..932e3913c 100644 --- a/src/game_logic/enemies/red_bird.hpp +++ b/src/game_logic/enemies/red_bird.hpp @@ -16,6 +16,7 @@ #pragma once +#include "engine/base_components.hpp" #include "game_logic/global_dependencies.hpp" #include @@ -48,7 +49,17 @@ struct RedBird { void startRisingUp(int initialHeight, entityx::Entity entity); - struct Flying {}; + struct Flying { + Flying() noexcept = default; + explicit Flying(const engine::components::Orientation orientation) + : mOrientation(orientation) + { + } + + engine::components::Orientation mOrientation = + engine::components::Orientation::Left; + unsigned int mAnimStep = 0; + }; struct Hovering { int mFramesElapsed = 0; From ed68349afe43f59806703a5f500e09ddd6c195d6 Mon Sep 17 00:00:00 2001 From: Nikolai Wuttke Date: Mon, 1 Jun 2020 14:44:52 +0200 Subject: [PATCH 4/7] Refactor: Extract helper function --- src/game_logic/camera.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/game_logic/camera.cpp b/src/game_logic/camera.cpp index 408b70a11..4a719d5ca 100644 --- a/src/game_logic/camera.cpp +++ b/src/game_logic/camera.cpp @@ -85,23 +85,42 @@ base::Rect deadZoneRect(const Player& player) { } -base::Vector offsetToDeadZone( +/** Calculate 'normalized' player bounds + * + * Returns player collision box in world space, adjusted to always be in the + * center of the screen with regards to the original game's horizontal screen + * size. + * + * This makes the camera code work correctly when in widescreen mode. The + * dead zone is tailored towards normal (i.e. not widescreen) mode, which + * would cause the player to be constrained to move inside the left half of + * the screen when in widescreen mode. By shifting the player position, we + * effectively move the dead zone to the center of the screen instead. + * + * When the view port is not wide, the result is identical with the player's + * world space collision box. + */ +base::Rect normalizedPlayerBounds( const Player& player, - const base::Vector& cameraPosition, const base::Extents& viewPortSize ) { const auto extraTiles = viewPortSize.width - data::GameTraits::mapViewPortSize.width; const auto offsetToCenter = extraTiles / 2; - auto playerBounds = player.worldSpaceCollisionBox(); - // This makes the camera code work correctly when in widescreen mode. The - // dead zone is tailored towards normal (i.e. not widescreen) mode, which - // would cause the player to be constrained to move inside the left half of - // the screen when in widescreen mode. By shifting the player position, we - // effectively move the dead zone to the center of the screen instead. + auto playerBounds = player.worldSpaceCollisionBox(); playerBounds.topLeft.x -= offsetToCenter; + return playerBounds; +} + + +base::Vector offsetToDeadZone( + const Player& player, + const base::Vector& cameraPosition, + const base::Extents& viewPortSize +) { + const auto playerBounds = normalizedPlayerBounds(player, viewPortSize); auto worldSpaceDeadZone = deadZoneRect(player); worldSpaceDeadZone.topLeft += cameraPosition; From c4e84e530a945b0a064ffb7dfb73212c7fcaa345 Mon Sep 17 00:00:00 2001 From: Nikolai Wuttke Date: Mon, 1 Jun 2020 14:52:14 +0200 Subject: [PATCH 5/7] Run one frame of game logic before fade-in after teleportation The revised centerViewOnPlayer which will be introduced in the next commit depends on this. --- src/game_logic/game_world.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game_logic/game_world.cpp b/src/game_logic/game_world.cpp index 17c83b15e..8535068b9 100644 --- a/src/game_logic/game_world.cpp +++ b/src/game_logic/game_world.cpp @@ -786,6 +786,7 @@ void GameWorld::handleTeleporter() { } mpSystems->centerViewOnPlayer(); + updateGameLogic({}); render(); mpServiceProvider->fadeInScreen(); } From f3329b4e69145bb212e603aafd900fbc4733c51e Mon Sep 17 00:00:00 2001 From: lethal-guitar Date: Mon, 1 Jun 2020 16:39:14 +0200 Subject: [PATCH 6/7] Fix initial camera offset --- src/game_logic/camera.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/game_logic/camera.cpp b/src/game_logic/camera.cpp index 4a719d5ca..1a5fbba59 100644 --- a/src/game_logic/camera.cpp +++ b/src/game_logic/camera.cpp @@ -54,6 +54,8 @@ constexpr auto DEAD_ZONE_END_X = 21; constexpr auto DEFAULT_VERTICAL_DEAD_ZONE = VerticalDeadZone{2, 19}; constexpr auto TIGHT_VERTICAL_DEAD_ZONE = VerticalDeadZone{7, 13}; +constexpr auto INITIAL_CAMERA_OFFSET = base::Vector{15, 19}; + constexpr auto MANUAL_SROLL_COOLDOWN_AFTER_SHOOTING = 4; @@ -221,7 +223,12 @@ void Camera::setPosition(const base::Vector position) { void Camera::centerViewOnPlayer() { - setPosition(offsetToDeadZone(*mpPlayer, {}, mViewPortSize)); + auto playerPos = normalizedPlayerBounds(*mpPlayer, mViewPortSize).bottomLeft(); + if (mpPlayer->orientation() == Orientation::Left) { + playerPos.x -= 1; + } + + setPosition(playerPos - INITIAL_CAMERA_OFFSET); } From c9e0c654110f53539d3736c8ba9baf619896a740 Mon Sep 17 00:00:00 2001 From: lethal-guitar Date: Mon, 1 Jun 2020 17:12:02 +0200 Subject: [PATCH 7/7] Fix: Take away cloak when dying --- src/game_logic/player.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game_logic/player.cpp b/src/game_logic/player.cpp index b4932b22e..f4b560c6f 100644 --- a/src/game_logic/player.cpp +++ b/src/game_logic/player.cpp @@ -534,7 +534,13 @@ void Player::die() { } mpPlayerModel->takeFatalDamage(); - mEntity.component()->mShow = true; + mpPlayerModel->removeItem(data::InventoryItemType::CloakingDevice); + mpEvents->emit(rigel::events::CloakExpired{}); + + auto& sprite = *mEntity.component(); + sprite.mTranslucent = false; + sprite.mShow = true; + mState = Dieing{}; setVisualState(VisualState::Dieing); mpServiceProvider->playSound(data::SoundId::DukeDeath);