ENIB 2024 : Space Invador de l'espace
Space Invador de l'espace
Sommaire
Introduction
L'objectif de notre jeu est de tuer l'ennemi. Notre Space Invador se compose de 16x16 leds représentant un vaisseau et des ennemis à abattre. Grâce aux boutons poussoirs, nous pouvons commander la position du vaisseau et donc diriger les tirs.
Outil et matériel
· Carte arduino
· 16x16 leds
· Boutons poussoirs
· Câbles électroniques
· Planches de chêne
fichiers à joindre
Code Arduino
1
2 #include <FastLED.h>
3 #include <SPI.h>
4
5 #define NUM_STRIPS 1
6 #define NUM_LEDS_PER_STRIP 256
7 CRGB leds[NUM_STRIPS][NUM_LEDS_PER_STRIP];
8
9 int color[5] {0x000000,0x000001,0x010000,0x000100,0x010100};
10 int position, position_vaisseau = 4, delay_tire = 0, level = 1;
11 bool vivant = true, en_partie = true, ennemi = true;
12
13 int level_actuelle[16][16];
14
15 const int level_1[16][16] { \
16 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
17 {0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0}, \
18 {0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0}, \
19 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
20 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
21 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
22 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
23 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
24 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
25 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
26 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
27 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
28 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
29 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
30 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
31 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} \
32 };
33
34 const int level_2[16][16] { \
35 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
36 {0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0}, \
37 {0, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0}, \
38 {0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0}, \
39 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
40 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
41 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
42 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
43 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
44 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
45 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
46 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
47 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
48 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
49 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
50 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} \
51 };
52
53 const int level_3[16][16] { \
54 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
55 {0, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 0}, \
56 {0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 0}, \
57 {0, 0, 2, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 2, 0, 0}, \
58 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
59 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
60 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
61 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
62 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
63 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
64 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
65 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
66 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
67 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
68 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
69 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} \
70 };
71
72 const int level_4[16][16] { \
73 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
74 {0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0}, \
75 {0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0}, \
76 {0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0}, \
77 {0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0}, \
78 {0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0}, \
79 {0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0}, \
80 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
81 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
82 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
83 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
84 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
85 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
86 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
87 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
88 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} \
89 };
90
91 const int game_over[16][16] { \
92 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
93 {2, 2, 2, 0, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 2, 0}, \
94 {2, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 0, 2, 0, 0, 0}, \
95 {2, 0, 2, 0, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 0, 0}, \
96 {2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0}, \
97 {2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 0}, \
98 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
99 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
100 {0, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 2, 0, 2, 2, 2}, \
101 {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2}, \
102 {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 2, 0, 0, 2, 2, 0}, \
103 {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2}, \
104 {0, 2, 2, 2, 0, 0, 2, 0, 0, 2, 2, 2, 0, 2, 0, 2}, \
105 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
106 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
107 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} \
108 };
109
110 const int win[16][16] { \
111 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
112 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
113 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
114 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
115 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
116 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
117 {0, 2, 0, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 0, 2, 0}, \
118 {0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 2, 0, 2, 0}, \
119 {0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 0, 2, 2, 0}, \
120 {0, 0, 2, 0, 2, 0, 0, 2, 2, 2, 0, 2, 0, 0, 2, 0}, \
121 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
122 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
123 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
124 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
125 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
126 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} \
127 };
128
129
130 void setup() {
131 // tell FastLED there's 60 NEOPIXEL leds on pin 2
132 FastLED.addLeds<NEOPIXEL, 2>(leds[0], NUM_LEDS_PER_STRIP);
133
134 // tell FastLED there's 60 NEOPIXEL leds on pin 3
135 FastLED.addLeds<NEOPIXEL, 3>(leds[1], NUM_LEDS_PER_STRIP);
136
137 // tell FastLED there's 60 NEOPIXEL leds on pin 4
138 FastLED.addLeds<NEOPIXEL, 4>(leds[2], NUM_LEDS_PER_STRIP);
139 Serial.begin(9600);
140
141 memcpy(level_actuelle,level_1,sizeof(level_1));
142
143 pinMode(A0,INPUT);
144 pinMode(D7,INPUT);
145 }
146
147
148 void affiche() {
149 //carte
150 for(int x = 0; x < 16; x++) {
151 for(int y = 0; y < 16;y++){
152 if (x%2 == 1){
153 position = x*16+y;
154 }
155 else{
156 position = x*16+15-y;
157 }
158 leds[0][position] = color[level_actuelle[x][y]];
159 }
160 }
161
162 FastLED.show();
163 }
164
165 void create_vaisseau(){
166 //pos entre 2 et 15
167 clear();
168 level_actuelle[13][position_vaisseau] = 1;
169 level_actuelle[13][position_vaisseau-1] = 1;
170 level_actuelle[12][position_vaisseau-1] = 1;
171 level_actuelle[13][position_vaisseau-2] = 1;
172 level_actuelle[14][position_vaisseau-2] = 1;
173 level_actuelle[14][position_vaisseau] = 1;
174 FastLED.show();
175 }
176
177 void clear(){
178 for(int x = 10; x < 15; x++) {
179 for(int y = 0; y < 16;y++){
180 if (level_actuelle[x][y] == 1){
181 level_actuelle[x][y] = 0;
182 }
183 }
184 }
185 }
186
187
188 void move(){
189 position_vaisseau = int(analogRead(A0)*16/1024);
190 if (position_vaisseau >= 16){
191 position_vaisseau = 15;
192 }
193 else if (position_vaisseau <= 1){
194 position_vaisseau = 2;
195 }
196 }
197
198 void tirer() {
199 if (true) {
200 level_actuelle[11][position_vaisseau-1] = 103;
201 }
202 }
203
204 void tick(){
205 ennemi = false;
206 for(int x = 0; x < 16; x++) {
207 for(int y = 0; y < 16;y++){
208 if (level_actuelle[x][y] == 3){ //tire joueur
209 if (x==0){
210 level_actuelle[x][y] = 0;
211 }
212 else if ((level_actuelle[x-1][y]==4) || (level_actuelle[x-1][y]==104)){
213 level_actuelle[x-1][y] = 3;
214 level_actuelle[x][y] = 104;
215 }
216 else if (level_actuelle[x-1][y]!=0){
217 level_actuelle[x-1][y] = 0;
218 level_actuelle[x][y] = 0;
219 }
220 else{
221 level_actuelle[x-1][y] = 3;
222 level_actuelle[x][y] = 0;
223 }
224 }
225
226 else if (level_actuelle[x][y] == 2){ //vaisseau enemi
227 ennemi = true;
228 if ((level_actuelle[x+1][y] == 0)&(random(0,40)==1)){
229 level_actuelle[x+1][y] = 104; //chiffre temporaire pour pas refaire son action
230 }
231 }
232 else if (level_actuelle[x][y] == 104){
233 level_actuelle[x][y] = 4;
234 }
235 else if (level_actuelle[x][y] == 103){
236 level_actuelle[x][y] = 3;
237 }
238 else if (level_actuelle[x][y]== 4){
239 if (x==15){
240 level_actuelle[x][y] = 0;
241 }
242 if ((level_actuelle[x+1][y] == 0) &(x<15)){
243 level_actuelle[x+1][y] = 104;
244 level_actuelle[x][y] = 0;
245 }
246 else if (level_actuelle[x+1][y] == 3){
247 level_actuelle[x+1][y] = 104;
248 level_actuelle[x][y] = 3;
249 }
250 else if (level_actuelle[x+1][y] == 1){
251 level_actuelle[x][y] = 0;
252 //game over
253 en_partie = false;
254 vivant = false;
255 }
256 }
257 }
258 }
259 }
260
261 void loop() {
262 while (en_partie){
263 tick();
264 affiche();
265 create_vaisseau();
266 if ((digitalRead(D7)) & (delay_tire == 0)){
267 tirer();
268 delay_tire = 2;
269 }
270 else if (delay_tire !=0){
271 delay_tire -= 1;
272 }
273 move();
274 if (!ennemi){
275 if (level == 4){
276 en_partie = false;
277
278 }
279 else{
280 level +=1;
281 }
282
283 if(level==2){
284 memcpy(level_actuelle,level_2,sizeof(level_2));
285 }
286 else if(level==3){
287 memcpy(level_actuelle,level_3,sizeof(level_3));
288 }
289 else if(level==4){
290 memcpy(level_actuelle,level_4,sizeof(level_4));
291 }
292 }
293 delay(75);
294 }
295 if (vivant){
296 memcpy(level_actuelle,win,sizeof(win));
297 }
298 else{
299 memcpy(level_actuelle,game_over,sizeof(game_over));
300 }
301 affiche();
302 delay(200);
303 if (digitalRead(D7)){
304 memcpy(level_actuelle,level_1,sizeof(level_1));
305 level = 1;
306 vivant = true;
307 en_partie = true;
308 }
309 }
étapes de fabrication
étape 1
Création du code arduino et test de celui-ci sur la carte. Toutes nos leds s'allument.
étape 2
Création de la maquette en carton. Ce n'est pas la version finale, juste le prototype.
Création de la maquette finale en bois.
étape 3
Test du jeu.
Troubleshouting
Difficultés rencontrées : création du code arduino
Solutions : test du code, analyse des erreurs, aide des intervenants
Sources et documentation complémentaire
- https://www.makercase.com/#/
- https://www.festi.info/boxes.py/
- https://boxdesigner.connectionlab.org/