|
|
51c73e |
|
|
|
5497ad |
#include <helianthus.h></helianthus.h>
|
|
|
5497ad |
|
|
|
5497ad |
#define SIZE 32
|
|
|
5497ad |
#define WIDTH 16
|
|
|
5497ad |
#define HEIGHT 16
|
|
|
5497ad |
#define MAXLEN (WIDTH*HEIGHT+1)
|
|
|
5497ad |
#define MAXFOOD 5
|
|
|
5497ad |
#define FRAMERATE 24
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
enum TileType {
|
|
|
5497ad |
NONE,
|
|
|
5497ad |
WALL,
|
|
|
5497ad |
FOOD,
|
|
|
5497ad |
SNAKE
|
|
|
5497ad |
};
|
|
|
5497ad |
|
|
|
5497ad |
enum GameMode {
|
|
|
5497ad |
MENU,
|
|
|
5497ad |
START,
|
|
|
5497ad |
PLAY,
|
|
|
5497ad |
GAMEOVER
|
|
|
5497ad |
};
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
int grid[WIDTH][HEIGHT];
|
|
|
5497ad |
Sprite sprites[WIDTH][HEIGHT];
|
|
|
5497ad |
Group gridGroup, storage;
|
|
|
5497ad |
|
|
|
5497ad |
Sound nom, cut;
|
|
|
5497ad |
|
|
|
5497ad |
int snake[MAXLEN][2];
|
|
|
5497ad |
int len;
|
|
|
5497ad |
int foodCount;
|
|
|
5497ad |
int dx, dy;
|
|
|
5497ad |
int framesRemain;
|
|
|
5497ad |
|
|
|
5497ad |
int optStop;
|
|
|
5497ad |
int optCut;
|
|
|
5497ad |
double optWalls;
|
|
|
5497ad |
int optStepFrames;
|
|
|
5497ad |
|
|
|
5497ad |
int difficulty;
|
|
|
5497ad |
|
|
|
5497ad |
int mode;
|
|
|
5497ad |
|
|
|
5497ad |
Animation tileWall;
|
|
|
5497ad |
Animation tileFood;
|
|
|
5497ad |
Animation tileHead;
|
|
|
5497ad |
Animation tileBody;
|
|
|
5497ad |
Animation tileBend;
|
|
|
5497ad |
Animation tileTail;
|
|
|
5497ad |
|
|
|
5497ad |
Font font;
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void putFood() {
|
|
|
5497ad |
for(int i = 0; i < 100 && foodCount < MAXFOOD; ++i) {
|
|
|
5497ad |
int x = randomNumber(0, WIDTH-1);
|
|
|
5497ad |
int y = randomNumber(0, HEIGHT-1);
|
|
|
5497ad |
if (grid[x][y] == NONE) {
|
|
|
5497ad |
grid[x][y] = FOOD;
|
|
|
5497ad |
spriteSetAnimation(sprites[x][y], tileFood);
|
|
|
5497ad |
++foodCount;
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void setSnakeTile(int i) {
|
|
|
5497ad |
int x = snake[i][0];
|
|
|
5497ad |
int y = snake[i][1];
|
|
|
5497ad |
Sprite s = sprites[x][y];
|
|
|
5497ad |
Animation tile = tileBody;
|
|
|
5497ad |
double rotation = 0;
|
|
|
5497ad |
|
|
|
5497ad |
int left = FALSE;
|
|
|
5497ad |
int right = FALSE;
|
|
|
5497ad |
int top = FALSE;
|
|
|
5497ad |
int bottom = FALSE;
|
|
|
5497ad |
if (i > 0) {
|
|
|
5497ad |
left = left || snake[i-1][0] < x;
|
|
|
5497ad |
right = right || snake[i-1][0] > x;
|
|
|
5497ad |
top = top || snake[i-1][1] < y;
|
|
|
5497ad |
bottom = bottom || snake[i-1][1] > y;
|
|
|
5497ad |
}
|
|
|
5497ad |
if (i < len-1) {
|
|
|
5497ad |
left = left || snake[i+1][0] < x;
|
|
|
5497ad |
right = right || snake[i+1][0] > x;
|
|
|
5497ad |
top = top || snake[i+1][1] < y;
|
|
|
5497ad |
bottom = bottom || snake[i+1][1] > y;
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
if (i == 0) {
|
|
|
5497ad |
tile = tileHead;
|
|
|
5497ad |
if (top) rotation = 90;
|
|
|
5497ad |
if (bottom) rotation = -90;
|
|
|
5497ad |
if (right) rotation = 180;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (i == len-1) {
|
|
|
5497ad |
tile = tileTail;
|
|
|
5497ad |
if (top) rotation = -90;
|
|
|
5497ad |
if (bottom) rotation = 90;
|
|
|
5497ad |
if (left) rotation = 180;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (left && top) {
|
|
|
5497ad |
tile = tileBend;
|
|
|
5497ad |
rotation = 180;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (left && bottom) {
|
|
|
5497ad |
tile = tileBend;
|
|
|
5497ad |
rotation = 90;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (right && top) {
|
|
|
5497ad |
tile = tileBend;
|
|
|
5497ad |
rotation = -90;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (right && bottom) {
|
|
|
5497ad |
tile = tileBend;
|
|
|
5497ad |
rotation = 0;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (top) {
|
|
|
5497ad |
rotation = 90;
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
spriteSetAnimation(s, tile);
|
|
|
5497ad |
spriteSetRotation(s, rotation);
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void resetTile(int x, int y) {
|
|
|
5497ad |
grid[x][y] = NONE;
|
|
|
5497ad |
Sprite s = sprites[x][y];
|
|
|
5497ad |
spriteSetNoAnimation(s);
|
|
|
5497ad |
spriteSetRotation(s, 0);
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void moveSnake() {
|
|
|
5497ad |
int x = snake[0][0] + dx;
|
|
|
5497ad |
int y = snake[0][1] + dy;
|
|
|
5497ad |
int cell = grid[x][y];
|
|
|
5497ad |
|
|
|
5497ad |
if (cell == WALL) {
|
|
|
5497ad |
if (!optStop) mode = GAMEOVER;
|
|
|
5497ad |
dx = snake[0][0] - snake[1][0];
|
|
|
5497ad |
dy = snake[0][1] - snake[1][1];
|
|
|
5497ad |
return;
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
if (cell == SNAKE) {
|
|
|
5497ad |
if (!optCut) { mode = GAMEOVER; return; }
|
|
|
5497ad |
int prevLen = len;
|
|
|
5497ad |
for(int i = 0; i < len; ++i)
|
|
|
5497ad |
if (snake[i][0] == x && snake[i][1] == y)
|
|
|
5497ad |
{ len=i; setSnakeTile(len-1); break; }
|
|
|
5497ad |
for(int i = len; i < prevLen; ++i)
|
|
|
5497ad |
resetTile(snake[i][0], snake[i][1]);
|
|
|
5497ad |
soundPlay(cut, FALSE);
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
if (cell != NONE && cell != FOOD && cell != SNAKE)
|
|
|
5497ad |
{ mode = GAMEOVER; return; }
|
|
|
5497ad |
|
|
|
5497ad |
for(int i = len; i > 0; --i) {
|
|
|
5497ad |
snake[i][0] = snake[i-1][0];
|
|
|
5497ad |
snake[i][1] = snake[i-1][1];
|
|
|
5497ad |
}
|
|
|
5497ad |
snake[0][0] = x;
|
|
|
5497ad |
snake[0][1] = y;
|
|
|
5497ad |
|
|
|
5497ad |
if (cell == FOOD || cell == SNAKE) {
|
|
|
5497ad |
grid[x][y] = SNAKE;
|
|
|
5497ad |
++len;
|
|
|
5497ad |
setSnakeTile(0);
|
|
|
5497ad |
setSnakeTile(1);
|
|
|
5497ad |
} else {
|
|
|
5497ad |
grid[x][y] = SNAKE;
|
|
|
5497ad |
setSnakeTile(0);
|
|
|
5497ad |
setSnakeTile(1);
|
|
|
5497ad |
setSnakeTile(len-1);
|
|
|
5497ad |
resetTile(snake[len][0], snake[len][1]);
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
if (cell == FOOD) {
|
|
|
5497ad |
--foodCount;
|
|
|
5497ad |
soundPlay(nom, FALSE);
|
|
|
5497ad |
putFood();
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void restart() {
|
|
|
5497ad |
optStepFrames = 12;
|
|
|
5497ad |
optWalls = 0;
|
|
|
5497ad |
optCut = TRUE;
|
|
|
5497ad |
optStop = TRUE;
|
|
|
5497ad |
switch(difficulty) {
|
|
|
5497ad |
case 2:
|
|
|
5497ad |
optStepFrames = 12;
|
|
|
5497ad |
optWalls = 0.01;
|
|
|
5497ad |
break;
|
|
|
5497ad |
case 3:
|
|
|
5497ad |
optStepFrames = 10;
|
|
|
5497ad |
optWalls = 0.02;
|
|
|
5497ad |
optCut = FALSE;
|
|
|
5497ad |
break;
|
|
|
5497ad |
case 4:
|
|
|
5497ad |
optStepFrames = 8;
|
|
|
5497ad |
optWalls = 0.04;
|
|
|
5497ad |
optCut = FALSE;
|
|
|
5497ad |
optStop = FALSE;
|
|
|
5497ad |
break;
|
|
|
5497ad |
case 5:
|
|
|
5497ad |
optStepFrames = 6;
|
|
|
5497ad |
optWalls = 0.06;
|
|
|
5497ad |
optCut = FALSE;
|
|
|
5497ad |
optStop = FALSE;
|
|
|
5497ad |
break;
|
|
|
5497ad |
};
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
for(int x = 0; x < WIDTH; ++x) {
|
|
|
5497ad |
for(int y = 0; y < HEIGHT; ++y) {
|
|
|
5497ad |
grid[x][y] = NONE;
|
|
|
5497ad |
Sprite s = sprites[x][y];
|
|
|
5497ad |
spriteSetRotation(s, 0);
|
|
|
5497ad |
spriteSetNoAnimation(s);
|
|
|
5497ad |
if ( x == 0 || y == 0
|
|
|
5497ad |
|| x == WIDTH-1 || y == HEIGHT-1
|
|
|
5497ad |
|| randomFloat() < optWalls )
|
|
|
5497ad |
{
|
|
|
5497ad |
grid[x][y] = WALL;
|
|
|
5497ad |
spriteSetAnimation(s, tileWall);
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
len = 2;
|
|
|
5497ad |
snake[0][0] = WIDTH/2;
|
|
|
5497ad |
snake[0][1] = HEIGHT/2;
|
|
|
5497ad |
snake[1][0] = snake[0][0] - 1;
|
|
|
5497ad |
snake[1][1] = snake[0][1];
|
|
|
5497ad |
for(int i = 0; i < len; ++i)
|
|
|
5497ad |
grid[ snake[i][0] ][ snake[i][1] ] = SNAKE;
|
|
|
5497ad |
for(int i = 0; i < len; ++i)
|
|
|
5497ad |
setSnakeTile(i);
|
|
|
5497ad |
|
|
|
5497ad |
dx = 1;
|
|
|
5497ad |
dy = 0;
|
|
|
5497ad |
|
|
|
5497ad |
foodCount = 0;
|
|
|
5497ad |
putFood();
|
|
|
5497ad |
|
|
|
5497ad |
framesRemain = optStepFrames;
|
|
|
5497ad |
mode = START;
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void init() {
|
|
|
5497ad |
tileWall = createAnimation("data/sprite/bricks.png");
|
|
|
5497ad |
tileFood = createAnimation("data/sprite/apple.png");
|
|
|
5497ad |
tileHead = createAnimation("data/sprite/snake/head.png");
|
|
|
5497ad |
tileBody = createAnimation("data/sprite/snake/body.png");
|
|
|
5497ad |
tileBend = createAnimation("data/sprite/snake/bend.png");
|
|
|
5497ad |
tileTail = createAnimation("data/sprite/snake/tail.png");
|
|
|
5497ad |
|
|
|
5497ad |
font = createFont("data/fonts/blackcry.ttf");
|
|
|
5497ad |
textFont(font);
|
|
|
5497ad |
|
|
|
5497ad |
storage = createGroup();
|
|
|
5497ad |
Animation tiles[6] = { tileWall, tileFood, tileHead, tileBody, tileBend, tileTail };
|
|
|
5497ad |
for(int i = 0; i < 6; ++i) {
|
|
|
5497ad |
Sprite s = createSprite(0, 0);
|
|
|
5497ad |
spriteSetAnimation(s, tiles[i]);
|
|
|
5497ad |
groupAdd(storage, s);
|
|
|
5497ad |
}
|
|
|
5497ad |
groupSetVisibleEach(storage, FALSE);
|
|
|
5497ad |
|
|
|
5497ad |
gridGroup = createGroup();
|
|
|
5497ad |
for(int x = 0; x < WIDTH; ++x) {
|
|
|
5497ad |
for(int y = 0; y < HEIGHT; ++y) {
|
|
|
5497ad |
Sprite s = createSpriteEx((x + 0.5)*SIZE, (y + 0.5)*SIZE, SIZE, SIZE);
|
|
|
5497ad |
spriteSetShapeColor(s, colorByName("transparent"));
|
|
|
5497ad |
groupAdd(gridGroup, s);
|
|
|
5497ad |
sprites[x][y] = s;
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
nom = createSound("data/sound/beep.ogg");
|
|
|
5497ad |
cut = createSound("data/sound/nom.ogg");
|
|
|
5497ad |
|
|
|
5497ad |
mode = MENU;
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
|
|
|
5497ad |
void draw() {
|
|
|
5497ad |
double cx = worldGetWidth()/2.0;
|
|
|
5497ad |
double cy = worldGetHeight()/2.0;
|
|
|
5497ad |
|
|
|
5497ad |
if (mode == PLAY) {
|
|
|
5497ad |
int prevdx = snake[0][0] - snake[1][0];
|
|
|
5497ad |
int prevdy = snake[0][1] - snake[1][1];
|
|
|
5497ad |
|
|
|
5497ad |
if (keyWentDown("left") && (prevdx != 1 || prevdy != 0)) { dx = -1; dy = 0; framesRemain = 0; }
|
|
|
5497ad |
else if (keyWentDown("right") && (prevdx != -1 || prevdy != 0)) { dx = 1; dy = 0; framesRemain = 0; }
|
|
|
5497ad |
else if (keyWentDown("up") && (prevdx != 0 || prevdy != 1)) { dx = 0; dy = -1; framesRemain = 0; }
|
|
|
5497ad |
else if (keyWentDown("down") && (prevdx != 0 || prevdy != -1)) { dx = 0; dy = 1; framesRemain = 0; }
|
|
|
5497ad |
if (--framesRemain <= 0) {
|
|
|
5497ad |
moveSnake();
|
|
|
5497ad |
framesRemain = optStepFrames;
|
|
|
5497ad |
}
|
|
|
5497ad |
drawSprites();
|
|
|
5497ad |
if (keyWentDown("escape")) mode = MENU;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (mode == GAMEOVER) {
|
|
|
5497ad |
drawSprites();
|
|
|
5497ad |
|
|
|
5497ad |
fill(colorByRGBA(1, 1, 1, 0.25));
|
|
|
5497ad |
rect(0, 0, worldGetWidth(), worldGetHeight());
|
|
|
5497ad |
|
|
|
5497ad |
noFill();
|
|
|
5497ad |
textAlign(HALIGN_CENTER, HALIGN_CENTER);
|
|
|
5497ad |
textSize(24);
|
|
|
5497ad |
text("Game Over", cx, cy);
|
|
|
5497ad |
textSize(12);
|
|
|
5497ad |
text("press enter", cx, cy + 24);
|
|
|
5497ad |
if (keyWentDown("return")) mode = MENU;
|
|
|
5497ad |
if (keyWentDown("escape")) mode = MENU;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (mode == START) {
|
|
|
5497ad |
drawSprites();
|
|
|
5497ad |
|
|
|
5497ad |
fill(colorByRGBA(1, 1, 1, 0.25));
|
|
|
5497ad |
rect(0, 0, worldGetWidth(), worldGetHeight());
|
|
|
5497ad |
|
|
|
5497ad |
noFill();
|
|
|
5497ad |
textAlign(HALIGN_CENTER, VALIGN_CENTER);
|
|
|
5497ad |
textSize(24);
|
|
|
5497ad |
text("Press enter to start", cx, cy);
|
|
|
5497ad |
if (keyWentDown("return")) mode = PLAY;
|
|
|
5497ad |
if (keyWentDown("escape")) mode = MENU;
|
|
|
5497ad |
} else
|
|
|
5497ad |
if (mode == MENU) {
|
|
|
5497ad |
noFill();
|
|
|
5497ad |
textAlign(HALIGN_LEFT, VALIGN_CENTER);
|
|
|
5497ad |
textSize(24);
|
|
|
5497ad |
int x = cx - 100;
|
|
|
5497ad |
int y = cy - 24*3;
|
|
|
5497ad |
text("Select difficulty level:", x, y); y += 24;
|
|
|
5497ad |
text("1 - very easy", x, y); y += 24;
|
|
|
5497ad |
text("2 - easy", x, y); y += 24;
|
|
|
5497ad |
text("3 - medium", x, y); y += 24;
|
|
|
5497ad |
text("4 - hard", x, y); y += 24;
|
|
|
5497ad |
text("5 - very hard", x, y); y += 24;
|
|
|
5497ad |
difficulty = 0;
|
|
|
5497ad |
if (keyWentDown("1")) difficulty = 1;
|
|
|
5497ad |
if (keyWentDown("2")) difficulty = 2;
|
|
|
5497ad |
if (keyWentDown("3")) difficulty = 3;
|
|
|
5497ad |
if (keyWentDown("4")) difficulty = 4;
|
|
|
5497ad |
if (keyWentDown("5")) difficulty = 5;
|
|
|
5497ad |
if (difficulty) restart();
|
|
|
5497ad |
if (keyWentDown("escape")) worldStop();
|
|
|
5497ad |
}
|
|
|
5497ad |
}
|
|
|
5497ad |
|
|
|
5497ad |
int main() {
|
|
|
5497ad |
worldSetWidth(SIZE * WIDTH);
|
|
|
5497ad |
worldSetHeight(SIZE * HEIGHT);
|
|
|
5497ad |
worldSetFrameRate(FRAMERATE);
|
|
|
5497ad |
worldSetInit(&init);
|
|
|
5497ad |
worldSetDraw(&draw);
|
|
|
5497ad |
worldRun();
|
|
|
5497ad |
return 0;
|
|
|
5497ad |
}
|