1 // This file is part of Dust Racing 2D.
2 // Copyright (C) 2015 Jussi Lind <jussi.lind@iki.fi>
3 //
4 // Dust Racing 2D is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 // Dust Racing 2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Dust Racing 2D. If not, see <http://www.gnu.org/licenses/>.
15
16 #include "statemachine.hpp"
17 #include "inputhandler.hpp"
18
19 #include <MenuManager>
20 #include <cassert>
21
22 StateMachine * StateMachine::m_instance = nullptr;
23
StateMachine(InputHandler & inputHandler)24 StateMachine::StateMachine(InputHandler & inputHandler)
25 : m_state(State::Init)
26 , m_oldState(State::Init)
27 , m_raceFinished(false)
28 , m_inputHandler(inputHandler)
29 {
30 assert(!StateMachine::m_instance);
31 StateMachine::m_instance = this;
32
33 m_stateToFunctionMap[State::Init] = std::bind(&StateMachine::stateInit, this);
34 m_stateToFunctionMap[State::DoIntro] = std::bind(&StateMachine::stateDoIntro, this);
35 m_stateToFunctionMap[State::Menu] = std::bind(&StateMachine::stateMenu, this);
36 m_stateToFunctionMap[State::MenuTransitionIn] = std::bind(&StateMachine::stateMenuTransitionIn, this);
37 m_stateToFunctionMap[State::MenuTransitionOut] = std::bind(&StateMachine::stateMenuTransitionOut, this);
38 m_stateToFunctionMap[State::GameTransitionIn] = std::bind(&StateMachine::stateGameTransitionIn, this);
39 m_stateToFunctionMap[State::GameTransitionOut] = std::bind(&StateMachine::stateGameTransitionOut, this);
40 m_stateToFunctionMap[State::DoStartlights] = std::bind(&StateMachine::stateDoStartlights, this);
41 m_stateToFunctionMap[State::Play] = std::bind(&StateMachine::statePlay, this);
42 }
43
~StateMachine()44 StateMachine::~StateMachine()
45 {
46 StateMachine::m_instance = nullptr;
47 }
48
instance()49 StateMachine & StateMachine::instance()
50 {
51 assert(StateMachine::m_instance);
52 return *StateMachine::m_instance;
53 }
54
quit()55 void StateMachine::quit()
56 {
57 if (m_state == StateMachine::State::Play)
58 {
59 m_state = State::GameTransitionOut;
60 }
61 else if (m_state == StateMachine::State::Menu)
62 {
63 emit exitGameRequested();
64 }
65 }
66
update()67 bool StateMachine::update()
68 {
69 // Run the state function on transition
70 if (m_state == State::Init || m_oldState != m_state)
71 {
72 m_oldState = m_state;
73 m_stateToFunctionMap[m_state]();
74 }
75
76 // Transition logic that needs to be constantly updated
77 if (m_state == State::Menu)
78 {
79 if (MTFH::MenuManager::instance().isDone())
80 {
81 m_state = State::MenuTransitionOut;
82 }
83 }
84
85 return true;
86 }
87
endFadeIn()88 void StateMachine::endFadeIn()
89 {
90 switch (m_state)
91 {
92 case State::GameTransitionIn:
93 m_state = State::DoStartlights;
94 break;
95 case State::MenuTransitionIn:
96 m_state = State::Menu;
97 break;
98 default:
99 break;
100 }
101 }
102
endFadeOut()103 void StateMachine::endFadeOut()
104 {
105 switch (m_state)
106 {
107 case State::MenuTransitionOut:
108 m_state = State::GameTransitionIn;
109 break;
110 case State::GameTransitionOut:
111 m_state = State::MenuTransitionIn;
112 break;
113 default:
114 break;
115 }
116 }
117
endStartlightAnimation()118 void StateMachine::endStartlightAnimation()
119 {
120 m_state = State::Play;
121 }
122
stateInit()123 void StateMachine::stateInit()
124 {
125 m_state = State::DoIntro;
126 }
127
stateDoIntro()128 void StateMachine::stateDoIntro()
129 {
130 m_timer.singleShot(3000, [&]() {
131 if (m_state == State::DoIntro)
132 {
133 m_state = State::Menu;
134 }
135 });
136
137 emit renderingEnabled(true);
138 }
139
stateMenu()140 void StateMachine::stateMenu()
141 {
142 // Re-init the current menu
143 MTFH::MenuManager::instance().enterCurrentMenu();
144 }
145
stateMenuTransitionIn()146 void StateMachine::stateMenuTransitionIn()
147 {
148 emit fadeInRequested(0, 2000, 0);
149 emit soundsStopped();
150 }
151
stateMenuTransitionOut()152 void StateMachine::stateMenuTransitionOut()
153 {
154 emit fadeOutFlashRequested(0, 2000, 0);
155 }
156
stateGameTransitionIn()157 void StateMachine::stateGameTransitionIn()
158 {
159 emit fadeInRequested(0, 2000, 0);
160
161 m_inputHandler.reset();
162 }
163
stateGameTransitionOut()164 void StateMachine::stateGameTransitionOut()
165 {
166 if (m_raceFinished)
167 {
168 emit fadeOutRequested(10000, 10000, 0);
169 }
170 else
171 {
172 emit fadeOutRequested(0, 2000, 0);
173 }
174 }
175
stateDoStartlights()176 void StateMachine::stateDoStartlights()
177 {
178 emit startlightAnimationRequested();
179 }
180
statePlay()181 void StateMachine::statePlay()
182 {
183 m_raceFinished = false;
184 }
185
finishRace()186 void StateMachine::finishRace()
187 {
188 m_state = State::GameTransitionOut;
189 m_raceFinished = true;
190 }
191
state() const192 StateMachine::State StateMachine::state() const
193 {
194 return m_state;
195 }
196
reset()197 void StateMachine::reset()
198 {
199 m_state = State::Init;
200 }
201