-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSimonState.cpp
167 lines (147 loc) · 4.37 KB
/
SimonState.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
* SimonState.cpp
*
* Created on: 15 juil. 2014
* Author: nicolaslambert
*/
#include "SimonState.h"
SimonState::SimonState() :
AbstractStateManager(),
m_lastScoreStep(0),
m_lastSuccessfullScoreStep(-1),
m_introState(new SimonIntroState()),
m_winSequenceState(new SimonWinSequenceState()),
m_failState(new SimonFailState()),
m_winGameState(new SimonWinGameState()),
m_playStates({
new SimonPlayState(COLOR_RED, LED_MASK_TOP_RIGHT_QUARTER, 1),
new SimonPlayState(COLOR_BLUE, LED_MASK_BOTTOM_RIGHT_QUARTER, 2),
new SimonPlayState(COLOR_YELLOW, LED_MASK_BOTTOM_LEFT_QUARTER, 3),
new SimonPlayState(COLOR_GREEN, LED_MASK_TOP_LEFT_QUARTER, 4)}),
m_testStates({
new SimonTestState(BTN_TWEAK, m_playStates[0]),
new SimonTestState(BTN_PESO, m_playStates[1]),
new SimonTestState(BTN_KWAZII, m_playStates[2]),
new SimonTestState(BTN_CPTBARNAC, m_playStates[3])})
{
// Analog input pin 0 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(0));
}
void SimonState::activate() {
// Reset index
m_lastScoreStep = -1;
m_lastSuccessfullScoreStep = -1;
generateMusicScore();
// Go first state
AbstractStateManager::activate();
}
void SimonState::generateMusicScore() {
// Generate new music score
for (uint8_t i = 0; i < STEP_TO_WIN_COUNT; i++) {
m_musicScore[i] = random(4);
}
}
bool SimonState::handleButtonPressed(uint8_t newButtonsStates) {
bool isOnlyOneButtonPressed = (__builtin_popcount(newButtonsStates) == 1);
bool isSimonGameButtonPressed = (newButtonsStates & (BTN_CPTBARNAC | BTN_TWEAK | BTN_KWAZII | BTN_PESO));
if (isOnlyOneButtonPressed && isSimonGameButtonPressed) {
bool shouldStayInCurrentState = AbstractStateManager::handleButtonPressed(newButtonsStates);
// Make it possible to swueeze test sound/anim to increase game speed
if (isTestState(m_currentState) && !shouldStayInCurrentState) {
changeState(getNextState(m_currentState));
m_currentState->handleButtonPressed(newButtonsStates);
}
return true;
}
return false;
}
bool SimonState::isFinished() {
return m_currentState == m_winGameState && m_winGameState->isFinished();
}
AbstractState * SimonState::getNextState(AbstractState * currentState) {
// No state
if (currentState == nullptr) {
return m_introState;
}
// Intro state
if (currentState == m_introState) {
return getNextPlayState();
}
// Play state
if (isPlayState(currentState)) {
if (m_lastScoreStep == m_lastSuccessfullScoreStep + 1) {
// Reset score index
m_lastScoreStep = -1;
return getNextTestState();
} else {
return getNextPlayState();
}
}
// Test state
if (isTestState(currentState)) {
SimonTestState* sts = (SimonTestState*)currentState;
if (sts->isCorrect()) {
if (m_lastScoreStep == m_lastSuccessfullScoreStep + 1) {
if (m_lastSuccessfullScoreStep + 2 == STEP_TO_WIN_COUNT) {
return m_winGameState;
} else {
return m_winSequenceState;
}
} else {
return getNextTestState();
}
} else {
return m_failState;
}
}
// Fail state
if (currentState == m_failState) {
// Reset score index
m_lastScoreStep = -1;
// Reset user score
m_lastSuccessfullScoreStep = -1;
return getNextPlayState();
}
// Win sequence state
if (currentState == m_winSequenceState) {
// The user just reproduce the shown sequence, let's write that
m_lastSuccessfullScoreStep++;
// Reset score index
m_lastScoreStep = -1;
return getNextPlayState();
}
// Should be Win game state
// Should not be called in this state, just return itself to be sure
return m_winGameState;
}
bool SimonState::isTestState(AbstractState * state) {
for (int i=0; i<4;i++) {
if (m_testStates[i]==state) {
return true;
}
}
return false;
}
bool SimonState::isPlayState(AbstractState * state) {
for (int i=0; i<4;i++) {
if (m_playStates[i]==state) {
return true;
}
}
return false;
}
SimonPlayState * SimonState::getNextPlayState() {
// Play next note
m_lastScoreStep++;
return m_playStates[m_musicScore[m_lastScoreStep]];;
}
SimonTestState * SimonState::getNextTestState() {
// Go next test
m_lastScoreStep++;
SimonTestState * nextState = m_testStates[m_musicScore[m_lastScoreStep]];
nextState->m_canBeSqueezed = (m_lastScoreStep < m_lastSuccessfullScoreStep + 1);
return nextState;
}