From 5d6557a49f2440dc2f83504660856877f70a710c Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Mon, 9 Dec 2013 16:50:51 +0100 Subject: [PATCH 1/3] Add easing to task list and fix a bug where opening the task list a second time was not possible --- projects/mtg/include/Tasks.h | 13 ++++++++++-- projects/mtg/src/GameStateShop.cpp | 2 +- projects/mtg/src/Tasks.cpp | 32 +++++++++++++++++------------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/projects/mtg/include/Tasks.h b/projects/mtg/include/Tasks.h index b257752a6..290b8218e 100644 --- a/projects/mtg/include/Tasks.h +++ b/projects/mtg/include/Tasks.h @@ -2,8 +2,15 @@ #define TASK_H #include +#include + +#include "Easing.h" + +using namespace std; class GameObserver; +class JQuad; +class JTexture; // Task type constant @@ -72,8 +79,11 @@ class TaskList { protected: string fileName; + float vPos; - float mElapsed; + InOutQuadEasing vPosInEasing; + InOutQuadEasing vPosOutEasing; + int mState; JQuad * mBg[9]; JTexture * mBgTex; @@ -97,7 +107,6 @@ public: { return mState; } - ; void addTask(string params, bool rand = false); void addTask(Task *task); void addRandomTask(int diff = 100); diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 34ddfa558..7055ed9f5 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -496,7 +496,7 @@ void GameStateShop::Update(float dt) } break; case STAGE_SHOP_TASKS: - if (menu) + if (menu && !menu->isClosed()) { menu->Update(dt); return; diff --git a/projects/mtg/src/Tasks.cpp b/projects/mtg/src/Tasks.cpp index d1e32a63b..a2399f1e9 100644 --- a/projects/mtg/src/Tasks.cpp +++ b/projects/mtg/src/Tasks.cpp @@ -258,9 +258,10 @@ Task* Task::createFromStr(const string params, bool rand) /*---------------- TaskList -----------------*/ -TaskList::TaskList(string _fileName) +TaskList::TaskList(string _fileName): + fileName(_fileName), vPos(-SCREEN_HEIGHT), vPosInEasing(vPos), vPosOutEasing(vPos) { - fileName = _fileName; + if (fileName == "") { fileName = options.profileFile(PLAYER_TASKS).c_str(); @@ -378,9 +379,10 @@ void TaskList::removeTask(Task *task) void TaskList::Start() { - vPos = -SCREEN_HEIGHT; //Offscreen - mElapsed = 0; mState = TASKS_IN; + vPos = -SCREEN_HEIGHT; //Offscreen + vPosInEasing.start(0.0f, 2.0f); + if (!mBgTex) { mBgTex = WResourceManager::Instance()->RetrieveTexture("taskboard.png", RETRIEVE_LOCK); @@ -410,7 +412,7 @@ void TaskList::Start() void TaskList::End() { mState = TASKS_OUT; - mElapsed = 0; + vPosOutEasing.start(float(-SCREEN_HEIGHT), 2.0f); } void TaskList::passOneDay() @@ -451,21 +453,23 @@ int TaskList::getTaskCount() void TaskList::Update(float dt) { - mElapsed += dt; - - if (mState == TASKS_IN && vPos < 0) + if(!vPosInEasing.finished()) { - vPos = -SCREEN_HEIGHT + (SCREEN_HEIGHT * mElapsed / 0.75f); //Todo: more physical drop-in. - if (vPos >= 0) + vPosInEasing.update(dt); + + if(vPosInEasing.finished()) { - vPos = 0; mState = TaskList::TASKS_ACTIVE; } } - else if (mState == TASKS_OUT && vPos > -SCREEN_HEIGHT) + else if(!vPosOutEasing.finished()) { - vPos = -(SCREEN_HEIGHT * mElapsed / 0.75f); - if (vPos <= -SCREEN_HEIGHT) mState = TASKS_INACTIVE; + vPosOutEasing.update(dt); + + if(vPosOutEasing.finished()) + { + mState = TASKS_INACTIVE; + } } } From 1e610ff6530d091de821d52d11a5f31d7f071a81 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Mon, 9 Dec 2013 17:21:36 +0100 Subject: [PATCH 2/3] Add InQuadEasing and OutQuadEasing and make tasklists... easing more natural --- projects/mtg/include/Easing.h | 44 +++++++++++++++++++++++++++++++++++ projects/mtg/include/Tasks.h | 4 ++-- projects/mtg/src/Tasks.cpp | 4 ++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/projects/mtg/include/Easing.h b/projects/mtg/include/Easing.h index ccacd4a78..1b5cf35a9 100644 --- a/projects/mtg/include/Easing.h +++ b/projects/mtg/include/Easing.h @@ -167,6 +167,50 @@ public: } }; +/*! \brief This class defines an easing with quadratic acceleration + */ +class InQuadEasing : public Easing +{ +public: + /*! \brief Calls Easing::Easing(val). + * + * \see Easing::Easing(float& val) + */ + InQuadEasing(float& val): Easing(val) {} + + /*! \brief Implements the value calculation. + * + * \see Easing::updateValue() + */ + void updateValue() + { + float time_tmp = time_acc / duration; + value = delta_value * time_tmp * time_tmp + start_value; + } +}; + +/*! \brief This class defines an easing with quadratic decceleration + */ +class OutQuadEasing : public Easing +{ +public: + /*! \brief Calls Easing::Easing(val). + * + * \see Easing::Easing(float& val) + */ + OutQuadEasing(float& val): Easing(val) {} + + /*! \brief Implements the value calculation. + * + * \see Easing::updateValue() + */ + void updateValue() + { + float time_tmp = time_acc / duration; + value = (-delta_value) * time_tmp * (time_tmp - 2.0f) + start_value; + } +}; + /*! \brief This class defines an easing with quadratic acceleration and decceleration. */ class InOutQuadEasing : public Easing diff --git a/projects/mtg/include/Tasks.h b/projects/mtg/include/Tasks.h index 290b8218e..2d96430db 100644 --- a/projects/mtg/include/Tasks.h +++ b/projects/mtg/include/Tasks.h @@ -81,8 +81,8 @@ protected: string fileName; float vPos; - InOutQuadEasing vPosInEasing; - InOutQuadEasing vPosOutEasing; + OutQuadEasing vPosInEasing; + InQuadEasing vPosOutEasing; int mState; JQuad * mBg[9]; diff --git a/projects/mtg/src/Tasks.cpp b/projects/mtg/src/Tasks.cpp index a2399f1e9..48bc9c790 100644 --- a/projects/mtg/src/Tasks.cpp +++ b/projects/mtg/src/Tasks.cpp @@ -381,7 +381,7 @@ void TaskList::Start() { mState = TASKS_IN; vPos = -SCREEN_HEIGHT; //Offscreen - vPosInEasing.start(0.0f, 2.0f); + vPosInEasing.start(0.0f, 1.0f); if (!mBgTex) { @@ -412,7 +412,7 @@ void TaskList::Start() void TaskList::End() { mState = TASKS_OUT; - vPosOutEasing.start(float(-SCREEN_HEIGHT), 2.0f); + vPosOutEasing.start(float(-SCREEN_HEIGHT), 0.9f); } void TaskList::passOneDay() From 4c627f74b6f9d486fd8d368668f8618caca0e36d Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Mon, 9 Dec 2013 22:17:19 +0100 Subject: [PATCH 3/3] Add easing to GuiPhaseBar, simplify math a bit. --- projects/mtg/include/Easing.h | 2 +- projects/mtg/include/GameStateShop.h | 1 - projects/mtg/include/GuiPhaseBar.h | 16 ++++- projects/mtg/src/GameStateShop.cpp | 6 +- projects/mtg/src/GuiPhaseBar.cpp | 95 +++++++++++----------------- 5 files changed, 53 insertions(+), 67 deletions(-) diff --git a/projects/mtg/include/Easing.h b/projects/mtg/include/Easing.h index 1b5cf35a9..49d574026 100644 --- a/projects/mtg/include/Easing.h +++ b/projects/mtg/include/Easing.h @@ -95,7 +95,7 @@ public: */ void update(float dt) { - if(duration > 0) + if(time_acc < duration) { time_acc += dt; diff --git a/projects/mtg/include/GameStateShop.h b/projects/mtg/include/GameStateShop.h index 1de196b5f..f6765ab74 100644 --- a/projects/mtg/include/GameStateShop.h +++ b/projects/mtg/include/GameStateShop.h @@ -65,7 +65,6 @@ private: JQuadPtr pspIcons[8]; WSrcCards * srcCards; TaskList * taskList; - float mElapsed; WGuiMenu * shopMenu; WGuiFilters * filterMenu; //Filter menu slides in sideways from right, or up from bottom. WGuiCardImage * bigDisplay; diff --git a/projects/mtg/include/GuiPhaseBar.h b/projects/mtg/include/GuiPhaseBar.h index 49dafac6e..78cec2677 100644 --- a/projects/mtg/include/GuiPhaseBar.h +++ b/projects/mtg/include/GuiPhaseBar.h @@ -4,15 +4,25 @@ #include "GuiLayers.h" #include "PhaseRing.h" #include "WEvent.h" +#include "PlayGuiObject.h" + +#include "Easing.h" class GuiPhaseBar: public GuiLayer, public PlayGuiObject { -protected: - Phase* phase; +private: + static const float zoom_big; + static const float zoom_small; + static const float step; + + int displayedPhaseId; float angle; float zoomFactor; - DuelLayers* mpDuelLayers; + OutQuadEasing angleEasing; + InOutQuadEasing zoomFactorEasing; + DuelLayers* mpDuelLayers; + void DrawGlyph(JQuad *inQuad, int phaseId, float x, float y, float scale); public: GuiPhaseBar(DuelLayers* duelLayers); ~GuiPhaseBar(); diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 7055ed9f5..84ca3f6e4 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -102,7 +102,6 @@ void GameStateShop::Start() bListCards = false; mTouched = false; mStage = STAGE_FADE_IN; - mElapsed = 0; needLoad = true; booster = NULL; srcCards = NEW WSrcUnlockedCards(0); @@ -427,7 +426,7 @@ void GameStateShop::End() { save(); JRenderer::GetInstance()->EnableVSync(false); - mElapsed = 0; + SAFE_DELETE(shopMenu); SAFE_DELETE(bigDisplay); SAFE_DELETE(srcCards); @@ -469,9 +468,6 @@ void GameStateShop::Update(float dt) if (lightAlpha > 50) lightAlpha = 50; - if (mStage != STAGE_FADE_IN) - mElapsed += dt; - JButton btn; switch (mStage) { diff --git a/projects/mtg/src/GuiPhaseBar.cpp b/projects/mtg/src/GuiPhaseBar.cpp index 0accc8a08..8d36cb0f9 100644 --- a/projects/mtg/src/GuiPhaseBar.cpp +++ b/projects/mtg/src/GuiPhaseBar.cpp @@ -24,26 +24,28 @@ }; */ +const float GuiPhaseBar::zoom_big = 1.5 * 1.4; +const float GuiPhaseBar::zoom_small = 1.5; +const float GuiPhaseBar::step = M_PI/6.0f; + namespace { + //width and height of the phase symbol textures const float kWidth = 28; const float kHeight = kWidth; - const unsigned kPhases = 12; + const unsigned kPhases = NB_MTG_PHASES - 2; //there are two phases we do not show +} - const float ICONSCALE = 1.5; - const float CENTER = SCREEN_HEIGHT_F / 2 + 10; - - void DrawGlyph(JQuad* inQuad, int inGlyph, float inY, float, unsigned int inP, float inScale) - { - float xPos = static_cast ((inP + inGlyph * (int) (kWidth + 1)) % (kPhases * (int) (kWidth + 1))); - inQuad->SetTextureRect(xPos, 0, kWidth, kHeight); - JRenderer::GetInstance()->RenderQuad(inQuad, 0, inY, 0.0, inScale, inScale); - } +void GuiPhaseBar::DrawGlyph(JQuad *inQuad, int phaseId, float x, float y, float scale) +{ + inQuad->SetTextureRect(phaseId * (kWidth + 1), 0, kWidth, kHeight); + JRenderer::GetInstance()->RenderQuad(inQuad, x, y - scale * kWidth/2, 0.0f, scale, scale); } GuiPhaseBar::GuiPhaseBar(DuelLayers* duelLayers) : - GuiLayer(duelLayers->getObserver()), PlayGuiObject(0, 0, 106, 0, false), - phase(NULL), angle(0.0f), zoomFactor(ICONSCALE), mpDuelLayers(duelLayers) + GuiLayer(duelLayers->getObserver()), PlayGuiObject(80, 0, 106, 0, false), + displayedPhaseId(0), angle(0.0f), zoomFactor(zoom_small), angleEasing(angle), + zoomFactorEasing(zoomFactor), mpDuelLayers(duelLayers) { if(duelLayers->getObserver()->getResourceManager()) { @@ -57,10 +59,7 @@ GuiPhaseBar::GuiPhaseBar(DuelLayers* duelLayers) : GameApp::systemError = "Error loading phasebar texture : " __FILE__; } - - zoom = ICONSCALE; mpDuelLayers->getCardSelector()->Add(this); - } GuiPhaseBar::~GuiPhaseBar() @@ -69,32 +68,27 @@ GuiPhaseBar::~GuiPhaseBar() void GuiPhaseBar::Update(float dt) { - if (angle > 3 * dt) - angle -= 3 * dt; - else - angle = 0; + angleEasing.update(dt); - if (dt > 0.05f) dt = 0.05f; - if(zoomFactor + 0.05f < zoom) + if(angle <= -step) { - zoomFactor += dt; - } - else if (zoomFactor - 0.05f > zoom) - { - zoomFactor -= dt; + displayedPhaseId = (displayedPhaseId + 1) % kPhases; + angleEasing.translate(step); } + + zoomFactorEasing.update(dt); } void GuiPhaseBar::Entering() { mHasFocus = true; - zoom = 1.4f*ICONSCALE; + zoomFactorEasing.start(zoom_big, 0.3f); } bool GuiPhaseBar::Leaving(JButton) { mHasFocus = false; - zoom = ICONSCALE; + zoomFactorEasing.start(zoom_small, 0.6f); return true; } @@ -102,41 +96,28 @@ void GuiPhaseBar::Render() { JQuadPtr quad = WResourceManager::Instance()->GetQuad("phasebar"); //uncomment to draw a hideous line across hires screens. - // JRenderer::GetInstance()->DrawLine(0, CENTER, SCREEN_WIDTH, CENTER, ARGB(255, 255, 255, 255)); + // JRenderer::GetInstance()->DrawLine(0, CENTER, SCREEN_WIDTH, CENTER, ARGB(255, 255, 255, 255)); - unsigned int p = (phase->id + kPhases - 4) * (int) (kWidth + 1); - float centerYPosition = CENTER + (kWidth / 2) * angle * zoomFactor / (M_PI / 6) - zoomFactor * kWidth / 4; - float yPos = centerYPosition; - float scale = 0; - for (int glyph = 3; glyph < 6; ++glyph) - { - scale = zoomFactor * sinf(angle + glyph * M_PI / 6) / 2; - DrawGlyph(quad.get(), glyph, yPos, angle, p, scale); - yPos += kWidth * scale; - } + const float radius = 25 * zoomFactor; - yPos = centerYPosition; - for (int glyph = 2; glyph > 0; --glyph) + for(int i = 0; i < 6; ++i) { - scale = zoomFactor * sinf(angle + glyph * M_PI / 6) / 2; - yPos -= kWidth * scale; - DrawGlyph(quad.get(), glyph, yPos, angle, p, scale); - } + //the position of the glyphe in the circle + const float circPos = (i - 2) * step + angle; + const float glyphY = this->y + this->mHeight / 2 + sin(circPos) * radius; - if (angle > 0) - { - scale = zoomFactor * sinf(angle) / 2; - yPos -= kWidth * scale; - float xPos = static_cast (p % (kPhases * (int) (kWidth + 1))); - quad->SetTextureRect(xPos, kHeight, kWidth, kHeight); - JRenderer::GetInstance()->RenderQuad(quad.get(), 0, yPos, 0.0, scale, scale); + //the scale is computed so that the glyphes touch each other + //hint: sin(circPos + PI/2) = cos(circPos) + const float glyphScale = zoomFactor * cosf(circPos) * 0.5; + + DrawGlyph(quad.get(), (displayedPhaseId - 3 + kPhases + i) % kPhases, 0, glyphY, glyphScale); } //print phase name WFont * font = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); string currentP = _("your turn"); string interrupt = ""; - if (observer->currentPlayer == mpDuelLayers->getRenderedPlayerOpponent()) + if (observer->currentPlayer == mpDuelLayers->getRenderedPlayerOpponent()) { currentP = _("opponent's turn"); } @@ -147,7 +128,7 @@ void GuiPhaseBar::Render() } if (observer->currentlyActing() != observer->currentPlayer) { - if (observer->currentPlayer == mpDuelLayers->getRenderedPlayer()) + if (observer->currentPlayer == mpDuelLayers->getRenderedPlayer()) { interrupt = _(" - ") + _("opponent plays"); } @@ -159,7 +140,7 @@ void GuiPhaseBar::Render() char buf[200]; //running this string through translate returns gibberish even though we defined the variables in the lang.txt - string phaseNameToTranslate = observer->phaseRing->phaseName(phase->id); + string phaseNameToTranslate = observer->phaseRing->phaseName(displayedPhaseId); phaseNameToTranslate = _(phaseNameToTranslate); sprintf(buf, _("(%s%s) %s").c_str(), currentP.c_str(), interrupt.c_str(),phaseNameToTranslate.c_str()); font->DrawString(buf, SCREEN_WIDTH - 5, 2, JGETEXT_RIGHT); @@ -170,8 +151,8 @@ int GuiPhaseBar::receiveEventMinus(WEvent *e) WEventPhaseChange *event = dynamic_cast (e); if (event) { - angle = M_PI / 6; - phase = event->to; + int phasesToAnimate = (event->to->id - displayedPhaseId + kPhases) % kPhases; + angleEasing.start(float(phasesToAnimate * (- step)), 0.3f * float(sqrt(phasesToAnimate))); } return 1; }