261 lines
4.6 KiB
C
261 lines
4.6 KiB
C
#include "biscio.h"
|
|
#include <stdlib.h>
|
|
|
|
/* macros */
|
|
#define MAX_TURNS 100
|
|
|
|
enum cardinal {
|
|
north = 0,
|
|
east = 1,
|
|
south = 2,
|
|
west = 3
|
|
};
|
|
|
|
struct point {
|
|
int x;
|
|
int y;
|
|
};
|
|
|
|
struct snake {
|
|
struct point ass;
|
|
struct color color;
|
|
enum cardinal direction;
|
|
struct point head;
|
|
unsigned int length;
|
|
unsigned int speed;
|
|
struct point turns[MAX_TURNS];
|
|
unsigned int width;
|
|
};
|
|
|
|
/* function declarations */
|
|
static int add_turn(struct snake *s, const struct point *p);
|
|
static unsigned int dist(const struct point *a, const struct point *b);
|
|
static void draw_snake(struct snake *s);
|
|
static void draw_snake_part(const struct snake *s, const struct point *a, const struct point *b);
|
|
static void move_snake(struct snake *s);
|
|
static void render(void);
|
|
static void update_turns(struct snake *s, const unsigned int i);
|
|
static void update_world(void);
|
|
|
|
/* variables */
|
|
static struct snake biscio;
|
|
int pause = 0;
|
|
int running = 1;
|
|
|
|
/* function implementations */
|
|
int
|
|
add_turn(struct snake *s, const struct point *p)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < MAX_TURNS; i++) {
|
|
if (s->turns[i].x == -1 && s->turns[i].y == -1) {
|
|
s->turns[i] = *p;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned int
|
|
dist(const struct point *a, const struct point *b)
|
|
{
|
|
int n1, n2;
|
|
|
|
if (a->x == b->x) {
|
|
n1 = a->y < b->y ? a->y : b->y;
|
|
n2 = a->y > b->y ? a->y : b->y;
|
|
} else {
|
|
n1 = a->x < b->x ? a->x : b->x;
|
|
n2 = a->x > b->x ? a->x : b->x;
|
|
}
|
|
|
|
return n2 - n1;
|
|
}
|
|
|
|
void
|
|
draw_snake(struct snake *s)
|
|
{
|
|
unsigned int d, l;
|
|
int i;
|
|
struct point p;
|
|
|
|
l = s->length;
|
|
p = s->head;
|
|
|
|
for (i = MAX_TURNS - 1; i >= 0; i--) {
|
|
if (s->turns[i].x != -1 && s->turns[i].y != -1) {
|
|
d = dist(&s->turns[i], &p);
|
|
if (d <= l) {
|
|
draw_snake_part(s, &p, &s->turns[i]);
|
|
l -= d;
|
|
p = s->turns[i];
|
|
} else {
|
|
update_turns(s, i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
draw_snake_part(s, &p, &s->ass);
|
|
}
|
|
|
|
void
|
|
draw_snake_part(const struct snake *s, const struct point *a, const struct point *b)
|
|
{
|
|
struct rect r;
|
|
|
|
r.x = a->x > b->x ? b->x : a->x;
|
|
r.y = a->y > b->y ? b->y : a->y;
|
|
if (a->x == b->x) {
|
|
r.w = s->width;
|
|
r.h = a->y > b->y ? a->y - b->y : b->y - a->y;
|
|
} else {
|
|
r.w = a->x > b->x ? a->x - b->x : b->x - a->x;
|
|
r.h = s->width;
|
|
}
|
|
|
|
draw_rect(&r, &s->color);
|
|
}
|
|
|
|
void
|
|
move_snake(struct snake *s)
|
|
{
|
|
struct point p;
|
|
|
|
switch (s->direction) {
|
|
case north:
|
|
s->head.y -= s->speed;
|
|
break;
|
|
case east:
|
|
s->head.x += s->speed;
|
|
break;
|
|
case south:
|
|
s->head.y += s->speed;
|
|
break;
|
|
case west:
|
|
s->head.x -= s->speed;
|
|
break;
|
|
}
|
|
|
|
p = s->turns[0].x != -1 && s->turns[0].y != -1 ? s->turns[0] : s->head;
|
|
if (s->ass.x == p.x) { /* north or south */
|
|
if (s->ass.y > p.y) { /* north */
|
|
s->ass.y -= s->speed;
|
|
} else { /* south */
|
|
s->ass.y += s->speed;
|
|
}
|
|
} else { /* east or west */
|
|
if (s->ass.x > p.x) { /* west */
|
|
s->ass.x -= s->speed;
|
|
} else { /* east */
|
|
s->ass.x += s->speed;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
handle_input(const struct input *i) {
|
|
if (i->type == IGNORE_INPUT)
|
|
return;
|
|
|
|
switch(i->type) {
|
|
case INPUT_DOWN:
|
|
if (biscio.direction == north || biscio.direction == south)
|
|
return;
|
|
if (add_turn(&biscio, &biscio.head))
|
|
biscio.direction = south;
|
|
break;
|
|
case INPUT_ESC:
|
|
running = 0;
|
|
break;
|
|
case INPUT_LEFT:
|
|
if (biscio.direction == east || biscio.direction == west)
|
|
return;
|
|
if (add_turn(&biscio, &biscio.head))
|
|
biscio.direction = west;
|
|
break;
|
|
case INPUT_PAUSE:
|
|
pause = !pause;
|
|
break;
|
|
case INPUT_RIGHT:
|
|
if (biscio.direction == east || biscio.direction == west)
|
|
return;
|
|
if (add_turn(&biscio, &biscio.head))
|
|
biscio.direction = east;
|
|
break;
|
|
case INPUT_UP:
|
|
if (biscio.direction == south)
|
|
return;
|
|
if (add_turn(&biscio, &biscio.head))
|
|
biscio.direction = north;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
unsigned int i;
|
|
|
|
init();
|
|
|
|
biscio.color.r = 255;
|
|
biscio.color.g = 255;
|
|
biscio.color.b = 255;
|
|
biscio.color.a = 255;
|
|
biscio.head.x = 100;
|
|
biscio.head.y = 80;
|
|
biscio.length = 50;
|
|
biscio.ass.x = biscio.head.x - biscio.length;
|
|
biscio.ass.y = biscio.head.y;
|
|
biscio.direction = east;
|
|
biscio.speed = 1;
|
|
biscio.width = 2;
|
|
|
|
for (i = 0; i < MAX_TURNS; i++) {
|
|
biscio.turns[i].x = -1;
|
|
biscio.turns[i].y = -1;
|
|
}
|
|
|
|
while (running) {
|
|
handle_events();
|
|
if (!pause)
|
|
update_world();
|
|
render();
|
|
sleep(16);
|
|
}
|
|
|
|
quit();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
render(void)
|
|
{
|
|
draw_background();
|
|
draw_snake(&biscio);
|
|
update_screen();
|
|
}
|
|
|
|
void
|
|
update_turns(struct snake *s, const unsigned int i)
|
|
{
|
|
unsigned int x;
|
|
|
|
for (x = i + 1; x < MAX_TURNS; x++)
|
|
s->turns[x - i - 1] = s->turns[x];
|
|
|
|
for (x = MAX_TURNS - 1 - i; x < MAX_TURNS; x++) {
|
|
s->turns[x].x = -1;
|
|
s->turns[x].y = -1;
|
|
}
|
|
}
|
|
|
|
void
|
|
update_world(void)
|
|
{
|
|
move_snake(&biscio);
|
|
}
|