diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | body.c | 147 | ||||
-rw-r--r-- | draw.c | 71 | ||||
-rw-r--r-- | include/body.h | 18 |
4 files changed, 237 insertions, 6 deletions
@@ -2,10 +2,11 @@ CC = gcc NAME = free_snake LIBS = -lncurses -lm -$(NAME): draw.o - $(CC) -o $(NAME) draw.o $(LIBS) +$(NAME): draw.o body.o + $(CC) -o $(NAME) draw.o body.o $(LIBS) -draw.o: draw.c +draw.o: draw.c include/body.h +body.o: body.c include/body.h .PHONY: clean clean: @@ -0,0 +1,147 @@ +#include <assert.h> +#include <stdlib.h> + +#include "include/body.h" + +typedef struct node{ + int x; + int y; + struct node *next; +} NODE; + +typedef struct snake{ + NODE *head; //"head" will be the physical tail of the snake + NODE *tail; //"tail" will be the physical head of the snake + int length; +} SNAKE; + +//private prototypes +NODE *makeNode(int x, int y); +void deleteNode(NODE *np); + +//public functions +SNAKE *makeSnake(int startx, int starty, int len){ + SNAKE *new = malloc(sizeof(SNAKE)); + NODE *np; + + assert(new != NULL); + + new->length = len; + + new->head = makeNode(startx-len+1, starty); + np = new->head; + len--; + + while(len > 0){ + np->next = makeNode(startx-len+1, starty); + np = np->next; + len--; + } + + new->tail = np; + + return new; +} + +void deleteSnake(SNAKE *sp){ + NODE *hold; + + if(sp != NULL){ + while(sp->head != NULL){ + hold = sp->head; + sp->head = sp->head->next; + deleteNode(hold); + } + } + + free(sp); + return; +} + +void updateSnake(SNAKE *sp, int dir){ + NODE *np; + + if(sp == NULL) return; + + //move the "back" to the "front" (note that sp->tail will not be set until after np->x and np->y are set) + np = sp->head; + sp->head = sp->head->next; + sp->tail->next = np; + np->next = NULL; + + //dir decides direction the snake is moving + switch(dir){ + case(0): //snake is moving up + np->x = sp->tail->x; + np->y = sp->tail->y-1; + break; + + case(1): //snake is moving right + np->x = sp->tail->x+1; + np->y = sp->tail->y; + break; + + case(2): //snake is moving down + np->x = sp->tail->x; + np->y = sp->tail->y+1; + break; + + case(3): //snake is moving left + np->x = sp->tail->x-1; + np->y = sp->tail->y; + } + + //update tail pointer + sp->tail = np; + + //TODO write checkSnake() which will check to see if the snake had a collision + + return; +} + + +int getSnakeTailx(SNAKE *sp){ + + if(sp != NULL && sp->tail != NULL) return sp->tail->x; + return -1; + +} +int getSnakeTaily(SNAKE *sp){ + + if(sp != NULL && sp->tail != NULL) return sp->tail->y; + return -1; + +} + +int getSnakeHeadx(SNAKE *sp){ + + if(sp != NULL && sp->head != NULL) return sp->head->x; + return -1; + +} + +int getSnakeHeady(SNAKE *sp){ + + if(sp != NULL && sp->head != NULL) return sp->head->y; + return -1; + +} + +//private functions +NODE *makeNode(int x, int y){ + NODE *new = malloc(sizeof(NODE)); + assert(new != NULL); + + new->x = x; + new->y = y; + new->next = NULL; + + return new; +} + +void deleteNode(NODE *np){ + + if(np != NULL) free(np); + + return; +} @@ -3,9 +3,14 @@ #include <stdlib.h> #include <unistd.h> -#define DEBUG 1 +#include "include/body.h" + +#define SPEED 50000 //global refresh rate (for usleep()) + +//#define DEBUG 1 void updateScore(int which, int score); +void updateScreen(SNAKE *sp, int dir); #ifdef DEBUG void count_up(void); @@ -16,6 +21,8 @@ int main(){ int score2 = 0; int highscore; + //TODO consider removing score2 altogether + //TODO implement code to retreive existing high score highscore = 0; @@ -23,18 +30,47 @@ int main(){ cbreak(); keypad(stdscr, true); noecho(); - //TODO consider adding color + curs_set(0); //draw current score, and high score updateScore(0, score); updateScore(1, highscore); updateScore(2, score2); + //the snake will be initially drawn without calling to body.h + //functions in body.h will update the snake and check for collision + //updateScreen() will actually draw the snake on each update (and update the scoreboard) + + //initialize and draw starting snake + SNAKE *player = makeSnake(6, getmaxy(stdscr)/2, 4); + //TODO consider various choices for drawing the snake (the below sets reverse video and draws spaces) + attron(A_REVERSE); + mvaddch(getmaxy(stdscr)/2, 6, ':'); + mvaddch(getmaxy(stdscr)/2, 5, ' '); + mvaddch(getmaxy(stdscr)/2, 4, ' '); + mvaddch(getmaxy(stdscr)/2, 3, ' '); + attroff(A_REVERSE); + + //TODO add something like "press any key to start!" getch(); + //TODO replace '1' with conditional to check if there was a collision + while(1){ + //TODO elaborate on the updated score each loop with conditionals and such + updateScore(0, score); + updateScore(1, highscore); + updateScore(2, score2); + updateScreen(player, 0); + refresh(); + //TODO consider changing SPEED depending on if moving horizontally or vertically + usleep(SPEED); + } + //DEBUG #ifdef DEBUG - count_up(); + //count_up(); + snakeTest(); + getch(); #endif endwin(); @@ -73,6 +109,35 @@ void updateScore(int which, int score){ return; } +void updateScreen(SNAKE *sp, int dir){ + char eyes; + + //switch case to decide "eyes" char + switch(dir){ + case 0: + eyes = '"'; + break; + case 2: + eyes = '.'; + break; + default: + eyes = ':'; + } + + //turn off "back" + mvaddch(getSnakeHeady(sp), getSnakeHeadx(sp), ' '); + //fix previous "front" (no more eyes) + attron(A_REVERSE); + mvaddch(getSnakeTaily(sp), getSnakeTailx(sp), ' '); + //update the snake position + updateSnake(sp, dir); + //turn on front + mvaddch(getSnakeTaily(sp), getSnakeTailx(sp), eyes); + attroff(A_REVERSE); + + return; +} + //debug functions start here #ifdef DEBUG void count_up(){ diff --git a/include/body.h b/include/body.h new file mode 100644 index 0000000..cfb6f5a --- /dev/null +++ b/include/body.h @@ -0,0 +1,18 @@ +#ifndef BODY_H +#define BODY_H + +typedef struct node NODE; + +typedef struct snake SNAKE; + +SNAKE *makeSnake(int startx, int starty, int len); +void deleteSnake(SNAKE *sp); + +void updateSnake(SNAKE *sp, int dir); + +int getSnakeTailx(SNAKE *sp); +int getSnakeTaily(SNAKE *sp); +int getSnakeHeadx(SNAKE *sp); +int getSnakeHeady(SNAKE *sp); + +#endif |