diff options
Diffstat (limited to 'apps/recorder/tetris.c')
-rw-r--r-- | apps/recorder/tetris.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/apps/recorder/tetris.c b/apps/recorder/tetris.c new file mode 100644 index 0000000000..24090eb67e --- /dev/null +++ b/apps/recorder/tetris.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 1999 Mattis Wadman (nappe@sudac.org) | ||
11 | * | ||
12 | * Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se) | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifdef HAVE_LCD_BITMAP | ||
23 | #include <stdbool.h> | ||
24 | #include "lcd.h" | ||
25 | #include "button.h" | ||
26 | #include "kernel.h" | ||
27 | |||
28 | #ifdef SIMULATOR | ||
29 | #include <stdio.h> | ||
30 | #endif | ||
31 | |||
32 | #define TETRIS_TITLE "Tetris!" | ||
33 | #define TETRIS_TITLE_FONT 2 | ||
34 | #define TETRIS_TITLE_XLOC 10 | ||
35 | #define TETRIS_TITLE_YLOC 32 | ||
36 | |||
37 | int start_x = 1; | ||
38 | int start_y = 1; | ||
39 | int max_x = 14; | ||
40 | int max_y = 24; | ||
41 | int current_x = 0; | ||
42 | int current_y = 0; | ||
43 | int current_f = 0; | ||
44 | int current_b = 0; | ||
45 | int level = 0; | ||
46 | short lines = 0; | ||
47 | int score = 0; | ||
48 | int next_b = 0; | ||
49 | int next_f = 0; | ||
50 | char virtual[LCD_WIDTH*LCD_HEIGHT]; | ||
51 | short level_speeds[10] = {1000,900,800,700,600,500,400,300,250,200}; | ||
52 | int blocks = 7; | ||
53 | int block_frames[7] = {1,2,2,2,4,4,4}; | ||
54 | |||
55 | /* | ||
56 | block_data is built up the following way | ||
57 | |||
58 | first array index specifies the block number | ||
59 | second array index specifies the rotation of the block | ||
60 | third array index specifies: | ||
61 | 0: x-coordinates of pixels | ||
62 | 1: y-coordinates of pixels | ||
63 | fourth array index specifies the coordinate of a pixel | ||
64 | |||
65 | each block consists of four pixels whose relative coordinates are given | ||
66 | with block_data | ||
67 | */ | ||
68 | |||
69 | int block_data[7][4][2][4] = | ||
70 | { | ||
71 | { | ||
72 | {{0,1,0,1},{0,0,1,1}} | ||
73 | }, | ||
74 | { | ||
75 | {{0,1,1,2},{1,1,0,0}}, | ||
76 | {{0,0,1,1},{0,1,1,2}} | ||
77 | }, | ||
78 | { | ||
79 | {{0,1,1,2},{0,0,1,1}}, | ||
80 | {{1,1,0,0},{0,1,1,2}} | ||
81 | }, | ||
82 | { | ||
83 | {{1,1,1,1},{0,1,2,3}}, | ||
84 | {{0,1,2,3},{2,2,2,2}} | ||
85 | }, | ||
86 | { | ||
87 | {{1,1,1,2},{2,1,0,0}}, | ||
88 | {{0,1,2,2},{1,1,1,2}}, | ||
89 | {{0,1,1,1},{2,2,1,0}}, | ||
90 | {{0,0,1,2},{0,1,1,1}} | ||
91 | }, | ||
92 | { | ||
93 | {{0,1,1,1},{0,0,1,2}}, | ||
94 | {{0,1,2,2},{1,1,1,0}}, | ||
95 | {{1,1,1,2},{0,1,2,2}}, | ||
96 | {{0,0,1,2},{2,1,1,1}} | ||
97 | }, | ||
98 | { | ||
99 | {{1,0,1,2},{0,1,1,1}}, | ||
100 | {{2,1,1,1},{1,0,1,2}}, | ||
101 | {{1,0,1,2},{2,1,1,1}}, | ||
102 | {{0,1,1,1},{1,0,1,2}} | ||
103 | } | ||
104 | }; | ||
105 | |||
106 | /* not even pseudo random :) */ | ||
107 | int t_rand(int range) | ||
108 | { | ||
109 | static int count; | ||
110 | count++; | ||
111 | return count % range; | ||
112 | } | ||
113 | |||
114 | void draw_frame(int fstart_x,int fstop_x,int fstart_y,int fstop_y) | ||
115 | { | ||
116 | lcd_drawline(fstart_x, fstart_y, fstop_x, fstart_y); | ||
117 | lcd_drawline(fstart_x, fstop_y, fstop_x, fstop_y); | ||
118 | |||
119 | lcd_drawline(fstart_x, fstart_y, fstart_x, fstop_y); | ||
120 | lcd_drawline(fstop_x, fstart_y, fstop_x, fstop_y); | ||
121 | } | ||
122 | |||
123 | void draw_block(int x,int y,int block,int frame,bool clear) | ||
124 | { | ||
125 | int i; | ||
126 | for(i=0;i < 4;i++) { | ||
127 | if (clear) | ||
128 | lcd_clearpixel(start_x+x+block_data[block][frame][0][i], | ||
129 | start_y+y+block_data[block][frame][1][i]); | ||
130 | else | ||
131 | lcd_drawpixel(start_x+x+block_data[block][frame][0][i], | ||
132 | start_y+y+block_data[block][frame][1][i]); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | void to_virtual() | ||
137 | { | ||
138 | int i; | ||
139 | for(i=0;i < 4;i++) | ||
140 | *(virtual+ | ||
141 | ((current_y+block_data[current_b][current_f][1][i])*max_x)+ | ||
142 | (current_x+block_data[current_b][current_f][0][i])) = current_b+1; | ||
143 | } | ||
144 | |||
145 | bool gameover() | ||
146 | { | ||
147 | int i; | ||
148 | int frame, block, y, x; | ||
149 | |||
150 | x = current_x; | ||
151 | y = current_y; | ||
152 | block = current_b; | ||
153 | frame = current_f; | ||
154 | |||
155 | for(i=0;i < 4; i++){ | ||
156 | /* Do we have blocks touching? */ | ||
157 | if(*(virtual+((y+block_data[block][frame][1][i])*max_x)+x+ | ||
158 | block_data[block][frame][0][i]) != 0) | ||
159 | { | ||
160 | /* Are we at the top of the frame? */ | ||
161 | if(y+block_data[block][frame][1][i] < start_y) | ||
162 | { | ||
163 | /* Game over ;) */ | ||
164 | return true; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | return false; | ||
169 | } | ||
170 | |||
171 | bool valid_position(int x,int y,int block,int frame) | ||
172 | { | ||
173 | int i; | ||
174 | for(i=0;i < 4;i++) | ||
175 | if( (*(virtual+((y+block_data[block][frame][1][i])*max_x)+x+ | ||
176 | block_data[block][frame][0][i]) != 0) || | ||
177 | (x+block_data[block][frame][0][i] < 0) || | ||
178 | (x+block_data[block][frame][0][i] > max_x-1) || | ||
179 | (y+block_data[block][frame][1][i] < 0) || | ||
180 | (y+block_data[block][frame][1][i] > max_y-1)) | ||
181 | return false; | ||
182 | return true; | ||
183 | } | ||
184 | |||
185 | void from_virtual() | ||
186 | { | ||
187 | int x,y; | ||
188 | for(y=0;y < max_y;y++) | ||
189 | for(x=0;x < max_x;x++) | ||
190 | if(*(virtual+(y*max_x)+x)) | ||
191 | lcd_drawpixel(start_x+x,start_y+y); | ||
192 | else | ||
193 | lcd_clearpixel(start_x+x,start_y+y); | ||
194 | } | ||
195 | |||
196 | void move_block(int x,int y,int f) | ||
197 | { | ||
198 | int last_frame = current_f; | ||
199 | if(f != 0) | ||
200 | { | ||
201 | current_f += f; | ||
202 | if(current_f > block_frames[current_b]-1) | ||
203 | current_f = 0; | ||
204 | if(current_f < 0) | ||
205 | current_f = block_frames[current_b]-1; | ||
206 | } | ||
207 | if(valid_position(current_x+x,current_y+y,current_b,current_f)) | ||
208 | { | ||
209 | draw_block(current_x,current_y,current_b,last_frame,true); | ||
210 | current_x += x; | ||
211 | current_y += y; | ||
212 | draw_block(current_x,current_y,current_b,current_f,false); | ||
213 | lcd_update(); | ||
214 | } | ||
215 | else | ||
216 | current_f = last_frame; | ||
217 | } | ||
218 | |||
219 | void new_block() | ||
220 | { | ||
221 | current_b = next_b; | ||
222 | current_f = next_f; | ||
223 | current_x = (int)((max_x)/2)-1; | ||
224 | current_y = 0; | ||
225 | next_b = t_rand(blocks); | ||
226 | next_f = t_rand(block_frames[next_b]); | ||
227 | draw_block(max_x+2,start_y-1,current_b,current_f,true); | ||
228 | draw_block(max_x+2,start_y-1,next_b,next_f,false); | ||
229 | if(!valid_position(current_x,current_y,current_b,current_f)) | ||
230 | { | ||
231 | draw_block(current_x,current_y,current_b,current_f,false); | ||
232 | lcd_update(); | ||
233 | } | ||
234 | else | ||
235 | draw_block(current_x,current_y,current_b,current_f,false); | ||
236 | } | ||
237 | |||
238 | int check_lines() | ||
239 | { | ||
240 | int x,y,i; | ||
241 | bool line; | ||
242 | int lines = 0; | ||
243 | for(y=0;y < max_y;y++) | ||
244 | { | ||
245 | line = true; | ||
246 | for(x=0;x < max_x;x++) | ||
247 | if(virtual[y*max_x+x] == 0) | ||
248 | line = false; | ||
249 | if(line) | ||
250 | { | ||
251 | lines++; | ||
252 | for(i=y;i > 1;i--) | ||
253 | for (x=0;x<max_x;x++) | ||
254 | virtual[i*max_x] = virtual[((i-1)*max_x)]; | ||
255 | for (x=0;x<max_x;x++) | ||
256 | virtual[max_x] = 0; | ||
257 | } | ||
258 | } | ||
259 | return lines; | ||
260 | } | ||
261 | |||
262 | void move_down() | ||
263 | { | ||
264 | int l; | ||
265 | if(!valid_position(current_x,current_y+1,current_b,current_f)) | ||
266 | { | ||
267 | to_virtual(); | ||
268 | l = check_lines(); | ||
269 | if(l) | ||
270 | { | ||
271 | lines += l; | ||
272 | level = (int)lines/10; | ||
273 | if(level > 9) | ||
274 | level = 9; | ||
275 | from_virtual(); | ||
276 | score += l*l; | ||
277 | } | ||
278 | new_block(); | ||
279 | move_block(0,0,0); | ||
280 | } | ||
281 | else | ||
282 | move_block(0,1,0); | ||
283 | } | ||
284 | |||
285 | void game_loop(void) | ||
286 | { | ||
287 | while(1) | ||
288 | { | ||
289 | int b=0; | ||
290 | int count = 0; | ||
291 | /* while(count*20 < level_speeds[level]) */ | ||
292 | { | ||
293 | b = button_get(); | ||
294 | if ( b & BUTTON_OFF ) | ||
295 | return; /* get out of here */ | ||
296 | |||
297 | if ( b & BUTTON_LEFT ) { | ||
298 | move_block(-1,0,0); | ||
299 | } | ||
300 | if ( b & BUTTON_RIGHT ) { | ||
301 | move_block(1,0,0); | ||
302 | } | ||
303 | if ( b & BUTTON_UP ) { | ||
304 | move_block(0,0,1); | ||
305 | } | ||
306 | if ( b & BUTTON_DOWN ) { | ||
307 | move_down(); | ||
308 | } | ||
309 | count++; | ||
310 | sleep(10); | ||
311 | } | ||
312 | if(gameover()) { | ||
313 | int w, h; | ||
314 | |||
315 | lcd_getfontsize(TETRIS_TITLE_FONT, &w, &h); | ||
316 | lcd_clearrect(TETRIS_TITLE_XLOC, TETRIS_TITLE_YLOC, | ||
317 | TETRIS_TITLE_XLOC+(w*sizeof(TETRIS_TITLE)), | ||
318 | TETRIS_TITLE_YLOC-h); | ||
319 | lcd_putsxy(TETRIS_TITLE_XLOC, TETRIS_TITLE_YLOC, "You lose!", | ||
320 | TETRIS_TITLE_FONT); | ||
321 | lcd_update(); | ||
322 | sleep(2); | ||
323 | return; | ||
324 | } | ||
325 | move_down(); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | void init_tetris() | ||
330 | { | ||
331 | memset(&virtual, 0, sizeof(virtual)); | ||
332 | start_x = 1; | ||
333 | start_y = 1; | ||
334 | max_x = 14; | ||
335 | max_y = 24; | ||
336 | current_x = 0; | ||
337 | current_y = 0; | ||
338 | current_f = 0; | ||
339 | current_b = 0; | ||
340 | level = 0; | ||
341 | lines = 0; | ||
342 | score = 0; | ||
343 | next_b = 0; | ||
344 | next_f = 0; | ||
345 | } | ||
346 | |||
347 | void tetris(void) | ||
348 | { | ||
349 | init_tetris(); | ||
350 | |||
351 | draw_frame(start_x-1,start_x+max_x,start_y-1,start_y+max_y); | ||
352 | lcd_putsxy(TETRIS_TITLE_XLOC, TETRIS_TITLE_YLOC, TETRIS_TITLE, | ||
353 | TETRIS_TITLE_FONT); | ||
354 | lcd_update(); | ||
355 | |||
356 | next_b = t_rand(blocks); | ||
357 | next_f = t_rand(block_frames[next_b]); | ||
358 | new_block(); | ||
359 | game_loop(); | ||
360 | } | ||
361 | |||
362 | #endif | ||