This repository has been archived by the owner on Dec 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.cpp
230 lines (197 loc) · 4.92 KB
/
main.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/*
Author: Hai Yang Xu
Student ID: <redacted>
Author: John Beckingham
Student ID: <redacted>
Tetris 2 bootstrapper.
*/
#include <Arduino.h>
#include <Adafruit_ILI9341.h>
#include "constants.h"
#include "assets.h"
#include "engine.h"
#include "graphics.h"
// Set up display controller instance
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// Implemented later
void setup();
void loop();
// The entry point of the program
int main() {
setup();
while (true) {
loop();
}
return 0;
}
// Draw a simple splash screen
void splashScreen() {
// Clear the screen
tft.fillScreen(ILI9341_BLACK);
// Draw one random block on each of the quarters of the screen
bool tempBlock[4 * 4];
uint16_t tempColor;
getRandomBlock(tempBlock);
getRandomColor(tempColor);
drawBlock(
random(0, SCREEN_WIDTH / 2), random(0, SCREEN_HEIGHT / 2),
tempBlock, tempColor, tft
);
getRandomBlock(tempBlock);
getRandomColor(tempColor);
drawBlock(
random(0, SCREEN_WIDTH / 2), random(SCREEN_HEIGHT / 2, SCREEN_HEIGHT),
tempBlock, tempColor, tft
);
getRandomBlock(tempBlock);
getRandomColor(tempColor);
drawBlock(
random(SCREEN_WIDTH / 2, SCREEN_WIDTH), random(0, SCREEN_HEIGHT / 2),
tempBlock, tempColor, tft
);
getRandomBlock(tempBlock);
getRandomColor(tempColor);
drawBlock(
random(SCREEN_WIDTH / 2, SCREEN_WIDTH),
random(SCREEN_HEIGHT / 2, SCREEN_HEIGHT),
tempBlock, tempColor, tft
);
// Draw prompt text
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 200);
tft.print("RIGHT - One-Player");
tft.setCursor(10, 250);
tft.print("LEFT - Two-Player");
}
// Initialization
void setup() {
init();
// Serial is only used for debug logs (if there are any)
#ifdef DEBUG
Serial.begin(9600);
#endif
// Serial3 is for two-player mode
Serial3.begin(9600);
// Initialize display
tft.begin();
tft.setRotation(0);
// Initialize joystick button
pinMode(JOY_BTN, INPUT_PULLUP);
// Seed random number generator, the seed is pinned in debug mode to
// facilitate debugging
#ifdef DEBUG
randomSeed(123);
#else
randomSeed(analogRead(15));
#endif
// Run tests if needed
#if defined(DEBUG) && defined(RUN_TESTS)
testMoveBlock(tft);
#endif
// Draw splash screen for the first time
splashScreen();
}
// Main loop
void loop() {
// System state
enum State {
SPLASH_SCREEN,
ONE_PLAYER, ONE_PLAYER_END,
TWO_PLAYER_HANDSHAKE, TWO_PLAYER, TWO_PLAYER_END
};
static State state = SPLASH_SCREEN;
// Process joystick input
int joyX = analogRead(JOY_HORIZ);
int joyY = analogRead(JOY_VERT);
bool up, down, left, right, btn;
if (joyY < (JOY_CENTER - JOY_DEADZONE)) { // Y axis
up = true; down = false;
} else if (joyY > (JOY_CENTER + JOY_DEADZONE)) {
up = false; down = true;
} else {
up = false; down = false;
}
if (joyX < (JOY_CENTER - JOY_DEADZONE)) { // X axis
left = true; right = false;
} else if (joyX > (JOY_CENTER + JOY_DEADZONE)) {
left = false; right = true;
} else {
left = false; right = false;
}
btn = digitalRead(JOY_BTN) == LOW; // Button
if (state == SPLASH_SCREEN) {
if (right) {
// One-player mode
initOnePlayer(tft);
state = ONE_PLAYER;
}
if (left) {
// Two-player mode
state = TWO_PLAYER_HANDSHAKE;
}
} else if (state == ONE_PLAYER) {
if (onePlayerTick(up, down, left, right, btn, tft)) {
// Return true means game ended, draw end screen
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 150);
tft.print("Game Over, Score:");
tft.setCursor(10, 200);
tft.print(getCurrentScore());
// Wait a bit to prevent misclick
delay(2500);
tft.setCursor(10, 250);
tft.print("Press Joystick...");
// Move to end game wait mode
state = ONE_PLAYER_END;
}
} else if (state == ONE_PLAYER_END || state == TWO_PLAYER_END) {
if (btn) { // Press joystick to return to main screen
splashScreen();
state = SPLASH_SCREEN;
}
} else if (state == TWO_PLAYER_HANDSHAKE) {
// Show wait screen
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 150);
tft.print("Connecting...");
// Wait for the other player to enter two-player mode
int otherReady = 0; // The number of continuous 'R' we received
// Send 'R's
Serial3.print("RRR");
// Wait for 3 'R's
while (otherReady < 3) {
while (Serial3.available() == 0) {
delay(1);
}
if (Serial3.read() == 'R') {
otherReady++;
} else {
otherReady = 0;
}
}
// Game start
initTwoPlayer(tft);
state = TWO_PLAYER;
} else if (state == TWO_PLAYER) {
// Pretty much the same as one-player mode, just slightly different
// end game screen
if (twoPlayerTick(up, down, left, right, btn, tft)) {
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 150);
if (getIfLost()) {
tft.print("You LOST");
} else {
tft.print("You WON!");
}
delay(2500);
tft.setCursor(10, 250);
tft.print("Press Joystick...");
state = TWO_PLAYER_END;
}
}
}