Skip to content

Commit 1231e92

Browse files
author
Joerg Jungermann
committed
Merge PR rad1o#143 of 'dos1/snake'
Conflicts: l0dables/Makefile
2 parents 9661ea6 + c1c474e commit 1231e92

File tree

3 files changed

+158
-412
lines changed

3 files changed

+158
-412
lines changed

l0dables/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
C1D=cube.c1d blinky.c1d invaders.c1d mandel.c1d snake.c1d snake2.c1d bricks.c1d schedule.c1d ws2812b.c1d battery.c1d fire.c1d colorp.c1d tetris.c1d sysinfo.c1d colors.c1d 0xb.c1d blurn.c1d
1+
C1D=cube.c1d blinky.c1d invaders.c1d mandel.c1d snake.c1d bricks.c1d schedule.c1d ws2812b.c1d battery.c1d fire.c1d colorp.c1d tetris.c1d sysinfo.c1d colors.c1d 0xb.c1d blurn.c1d
22

33
N1K=nick_scr0ll.n1k nick_w0rpcore.n1k nick_matrix.n1k nick_plain.n1k nick_invaders.n1k nick_anim.n1k nick_image.n1k nick_netz39.n1k nick_life.n1k nick_colplasm.n1k nick_ledbow.n1k
44

l0dables/snake.c

Lines changed: 157 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
********
44
* a snake clone for the r0ket
55
* created by Flori4n (DrivenHoliday) & MascH (CCCHB tent)
6+
* snake II implementation by ElSjaako and OriginalSouth
67
***************************************/
78

89
#include <string.h>
@@ -14,6 +15,7 @@
1415
#include <r0ketlib/print.h>
1516
#include <r0ketlib/keyin.h>
1617
#include <r0ketlib/select.h>
18+
#include <rad1olib/systick.h>
1719

1820
#include "invfont.c"
1921

@@ -23,10 +25,10 @@
2325
#define SNAKE_DIM (3)
2426
#define MIN_SPEED (25)
2527
#define MAX_SPEED (3)
26-
#define MIN_X 2
27-
#define MAX_X (RESX-3)
28-
#define MIN_Y 8
29-
#define MAX_Y (RESY-2)
28+
#define MIN_X 3
29+
#define MAX_X (RESX-5)
30+
#define MIN_Y 12
31+
#define MAX_Y (RESY-5)
3032
#define SIZE_X ((MAX_X-MIN_X)/SNAKE_DIM)
3133
#define SIZE_Y ((MAX_Y-MIN_Y)/SNAKE_DIM)
3234

@@ -35,6 +37,14 @@
3537
#define UP 3
3638
#define DOWN 1
3739

40+
//define how long you have to hold down the button to quit
41+
#define QUIT_DELAY 1000
42+
43+
typedef enum {
44+
SNAKE_STANDARD,
45+
SNAKE_WRAPPING
46+
} gametype_e;
47+
3848
struct pos_s {
3949
int x,y;
4050
};
@@ -48,7 +58,7 @@ static void reset();
4858
static void next_level();
4959
static void render_level();
5060
static void draw_block();
51-
static void handle_input();
61+
static int handle_input();
5262
static void death_anim();
5363
static struct pos_s getFood(void);
5464
static int hitWall();
@@ -57,70 +67,114 @@ static int hitSelf();
5767
static void renderHighscore();
5868
static int showHighscore();
5969
static uint32_t highscore_get();
70+
static char* highscore_filename();
6071

6172
int points = 0;
6273
int highscore = 0;
74+
gametype_e gametype = SNAKE_STANDARD;
6375
struct snake_s snake = { NULL, 3, 0, MIN_SPEED, 2};
6476
struct pos_s food;
6577

6678
void ram(void)
6779
{
68-
int c=0, pos=0,del=0;
80+
while (1) {
6981

70-
struct pos_s tail[MAX_SNAKE_LEN];
71-
snake.tail = tail;
82+
int c=0, pos=0,del=0;
7283

73-
// load the highscore
74-
highscore = highscore_get();
84+
struct pos_s tail[MAX_SNAKE_LEN];
85+
snake.tail = tail;
7586

76-
// initially reset everything
77-
reset();
87+
lcdClear();
7888

79-
while (1) {
80-
if(!(++c % snake.speed)) {
81-
handle_input();
82-
83-
pos = (snake.t_start+1) % MAX_SNAKE_LEN;
84-
snake.tail[pos].x = snake.tail[snake.t_start].x;
85-
snake.tail[pos].y = snake.tail[snake.t_start].y;
86-
87-
if(snake.dir == 0)
88-
snake.tail[pos].x++;
89-
else if(snake.dir == 1)
90-
snake.tail[pos].y++;
91-
else if(snake.dir == 2)
92-
snake.tail[pos].x--;
93-
else if(snake.dir == 3)
94-
snake.tail[pos].y--;
95-
96-
snake.t_start = pos;
97-
98-
if (pos < snake.len) {
99-
del = MAX_SNAKE_LEN - (snake.len - pos);
100-
} else
101-
del = pos - snake.len;
89+
setTextColor(0xff,0b11100000);
90+
DoString(0,10, " SNAKE");
10291

103-
// remove last, add first line
104-
draw_block(snake.tail[del].x, snake.tail[del].y, 0xFF);
105-
draw_block(snake.tail[pos].x, snake.tail[pos].y, 0b00011000);
92+
setTextColor(0xff,0x00);
93+
DoString(0,RESY/2-33, " Choose the");
94+
DoString(0,RESY/2-25, " game type:");
10695

107-
// check for obstacle hit..
108-
if (hitWall() || hitSelf()) {
109-
death_anim();
110-
if (showHighscore())
111-
break;
112-
reset();
113-
} else if (hitFood())
114-
next_level();
96+
setTextColor(0xff,0x00);
97+
DoString(0, RESY/2+10, " LEFT: standard");
98+
DoString(0, RESY/2+18, " RIGHT: wrapping ");
99+
DoString(0, RESY/2+26, " DOWN: quit ");
115100

116-
lcdDisplay();
101+
lcdDisplay();
102+
103+
int key = getInputRaw();
104+
105+
while(1) {
106+
key = getInputWait();
107+
getInputWaitRelease();
108+
109+
if (key&BTN_DOWN) {
110+
return;
111+
} else if (key&BTN_LEFT) {
112+
gametype = SNAKE_STANDARD;
113+
break;
114+
} else if (key&BTN_RIGHT) {
115+
gametype = SNAKE_WRAPPING;
116+
break;
117+
}
117118
}
118119

120+
// load the highscore
121+
highscore = highscore_get();
122+
123+
// initially reset everything
124+
reset();
125+
126+
while (1) {
127+
if(!(++c % snake.speed)) {
128+
if (handle_input()) { //handle_input returns 1 to quit
129+
break;
130+
}
131+
132+
pos = (snake.t_start+1) % MAX_SNAKE_LEN;
133+
snake.tail[pos].x = snake.tail[snake.t_start].x;
134+
snake.tail[pos].y = snake.tail[snake.t_start].y;
135+
136+
if(snake.dir == 0) {
137+
snake.tail[pos].x++;
138+
if(gametype == SNAKE_WRAPPING && snake.tail[pos].x>SIZE_X) snake.tail[pos].x=0;
139+
} else if(snake.dir == 1) {
140+
snake.tail[pos].y++;
141+
if(gametype == SNAKE_WRAPPING && snake.tail[pos].y>SIZE_Y) snake.tail[pos].y=0;
142+
} else if(snake.dir == 2) {
143+
snake.tail[pos].x--;
144+
if(gametype == SNAKE_WRAPPING && snake.tail[pos].x<0) snake.tail[pos].x=SIZE_X;
145+
} else if(snake.dir == 3) {
146+
snake.tail[pos].y--;
147+
if(gametype == SNAKE_WRAPPING && snake.tail[pos].y<0) snake.tail[pos].y=SIZE_Y;
148+
}
149+
150+
snake.t_start = pos;
151+
152+
del = pos - snake.len;
153+
if (pos < snake.len) del += MAX_SNAKE_LEN;
154+
155+
// remove last, add first line
156+
draw_block(snake.tail[del].x, snake.tail[del].y, 0xFF);
157+
draw_block(snake.tail[pos].x, snake.tail[pos].y, 0b00011000);
158+
159+
// check for obstacle hit..
160+
if (hitWall() || hitSelf()) {
161+
death_anim();
162+
if (showHighscore())
163+
break;
164+
highscore = highscore_get();
165+
reset();
166+
} else if (hitFood())
167+
next_level();
168+
169+
lcdDisplay();
170+
}
171+
119172
#ifdef SIMULATOR
120-
delayms(50);
173+
delayms(50);
121174
#else
122-
delayms(3);
175+
delayms(3);
123176
#endif
177+
}
124178
}
125179
}
126180

@@ -130,8 +184,8 @@ static struct pos_s getFood(void)
130184
struct pos_s res;
131185

132186
tryagain:
133-
res.x = (getRandom() % (SIZE_X-1)) + 1;
134-
res.y = (getRandom() % (SIZE_Y-3)) + 3;
187+
res.x = (getRandom() % (SIZE_X+1));
188+
res.y = (getRandom() % (SIZE_Y+1));
135189

136190
for(i=0; i<snake.len; i++) {
137191
pos = (snake.t_start < i) ? (MAX_SNAKE_LEN - (i-snake.t_start)) : (snake.t_start-i);
@@ -148,14 +202,22 @@ static void reset()
148202

149203
// setup the screen
150204
lcdClear();
151-
for (i=MIN_X; i<MAX_X; i++) {
152-
lcdSetPixel(i,MIN_Y,0b000101011);
153-
lcdSetPixel(i,MAX_Y,0b000101011);
205+
for (i=MIN_X-2; i<MAX_X+2; i++) {
206+
lcdSetPixel(i,MIN_Y-2,0b000101011);
207+
lcdSetPixel(i,MAX_Y+2,0b000101011);
208+
if (gametype != SNAKE_WRAPPING) {
209+
lcdSetPixel(i,MIN_Y-1,0b000101011);
210+
lcdSetPixel(i,MAX_Y+1,0b000101011);
211+
}
154212
}
155213

156-
for (i=MIN_Y; i<MAX_Y; i++) {
157-
lcdSetPixel(MIN_X,i,0b000101011);
158-
lcdSetPixel(MAX_X,i,0b000101011);
214+
for (i=MIN_Y-2; i<MAX_Y+2; i++) {
215+
lcdSetPixel(MIN_X-2,i,0b000101011);
216+
lcdSetPixel(MAX_X+2,i,0b000101011);
217+
if (gametype != SNAKE_WRAPPING) {
218+
lcdSetPixel(MIN_X-1,i,0b000101011);
219+
lcdSetPixel(MAX_X+1,i,0b000101011);
220+
}
159221
}
160222

161223
snake.speed = MIN_SPEED;
@@ -165,8 +227,6 @@ static void reset()
165227

166228
points = 0;
167229

168-
food = getFood();
169-
170230
// create snake in the middle of the field
171231
snake.tail[0].x = SIZE_X/2;
172232
snake.tail[0].y = SIZE_Y/2;
@@ -175,6 +235,8 @@ static void reset()
175235
snake.tail[2].x = SIZE_X/2 +2;
176236
snake.tail[2].y = SIZE_Y/2;
177237

238+
food = getFood();
239+
178240
// print initail tail
179241
draw_block(snake.tail[0].x, snake.tail[0].y, 0b00011000);
180242
draw_block(snake.tail[1].x, snake.tail[1].y, 0b00011000);
@@ -187,7 +249,9 @@ static void reset()
187249
static void draw_block(int x, int y, int set)
188250
{
189251
x *= SNAKE_DIM;
252+
x += MIN_X;
190253
y *= SNAKE_DIM;
254+
y += MIN_Y;
191255

192256
lcdSetPixel(x , y, set);
193257
lcdSetPixel(x+1, y, set);
@@ -237,14 +301,15 @@ static void render_level()
237301
// Dark Green
238302
setTextColor(0xff,0b00011000);
239303
}
240-
DoString(0,0,points_string);
304+
DoString(1,1,points_string);
241305
setTextColor(0xff,0b00000011);
242-
DoString(MAX_X-44,0,highscore_string);
306+
DoString(MAX_X-44,1,highscore_string);
243307
}
244308

245-
static void handle_input()
309+
static int handle_input()
246310
{
247311
int key = getInputRaw(), dir_old = snake.dir;
312+
static int quitWhen = 0;
248313

249314
if (key&BTN_UP && dir_old != 1)
250315
snake.dir = 3;
@@ -254,15 +319,26 @@ static void handle_input()
254319
snake.dir = 2;
255320
else if (key&BTN_RIGHT && dir_old !=2)
256321
snake.dir = 0;
322+
else if (key&BTN_ENTER) {
323+
if (quitWhen == 0) {
324+
quitWhen = _timectr + QUIT_DELAY/SYSTICKSPEED;
325+
} else if (_timectr > quitWhen) {
326+
return 1; //indicate program should quit
327+
}
328+
return 0;
329+
}
330+
quitWhen = 0;
331+
return 0; // program should continue running
257332
}
258333

259334
static int hitWall()
260335
{
261-
return ( (snake.tail[snake.t_start].x*3 <= MIN_X)
262-
|| (snake.tail[snake.t_start].x*3 >= MAX_X)
263-
|| (snake.tail[snake.t_start].y*3 <= MIN_Y)
264-
|| (snake.tail[snake.t_start].y*3 >= MAX_Y) ) ?
265-
1 : 0;
336+
if (gametype == SNAKE_WRAPPING) return false;
337+
338+
return ( (snake.tail[snake.t_start].x < 0)
339+
|| (snake.tail[snake.t_start].x > SIZE_X)
340+
|| (snake.tail[snake.t_start].y < 0)
341+
|| (snake.tail[snake.t_start].y > SIZE_Y) );
266342

267343
}
268344

@@ -300,9 +376,19 @@ static void death_anim()
300376

301377
}
302378

379+
static char* highscore_filename()
380+
{
381+
switch (gametype) {
382+
case SNAKE_WRAPPING:
383+
return "snake2.5cr";
384+
default:
385+
return "snake.5cr";
386+
}
387+
}
388+
303389
static bool highscore_set(uint32_t score)
304390
{
305-
writeFile("snake.5cr", &score , sizeof(uint32_t));
391+
writeFile(highscore_filename(), &score , sizeof(uint32_t));
306392

307393
// old r0ket code to get highscore from the world
308394
#if 0
@@ -323,7 +409,7 @@ static bool highscore_set(uint32_t score)
323409
static uint32_t highscore_get()
324410
{
325411
uint32_t score = 0;
326-
readFile("snake.5cr", &score, sizeof(score));
412+
readFile(highscore_filename(), &score, sizeof(score));
327413

328414
// old r0ket code to send highscore to the world
329415
#if 0
@@ -364,9 +450,9 @@ static void renderHighscore()
364450
setTextColor(0xff,0b00000011);
365451
DoString(RESX/2-4, RESY/2-2, IntToStr(highscore,6,0));
366452
setTextColor(0xff,0x00);
367-
DoString(0, RESY/2+18, " UP to play ");
453+
DoString(0, RESY/2+18, " UP to play");
368454
DoString(0, RESY/2+26, "RIGHT to reset HI ");
369-
DoString(0, RESY/2+34, "DOWN to quit ");
455+
DoString(0, RESY/2+34, " DOWN to quit ");
370456

371457
lcdDisplay();
372458
}

0 commit comments

Comments
 (0)