biscio/biscio.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);
}