void keyboard (unsigned char key, int x, int y) { if(key == 'd') { yrot += 1; if (yrot >360) yrot -= 360; } if(key == 'a') { yrot -= 1; if (yrot < -360)yrot += 360; } if (key=='o') { objcount = 0; objgravity = objgrav_init; addObject(20); } if(key=='f') { createFood(1); foodgravity = food_init; linger = linger_init; } if(key=='p') createPredator(1); if(key=='m') { createWalls1(); } if(key=='n') { createWalls2(); } if(key=='-') { objgravity -= 0.01; } }
void snake::createBody(int x,int y) { for(int i=0;i<=HEIGHT+1;i++) for(int j=0;j<=WIDTH+1;j++) { if(i==0||j==0||i==HEIGHT+1||j==WIDTH+1) MAP[i][j]=WALL; else MAP[i][j]=NOTHING; } for(int j=y;j>=1;j--) MAP[x][j]=y-j+1; length=y; head.x=x;head.y=y; trail.x=x;trail.y=1; while(createFood()); }
void snake::getFood() { cout<<"yes i get one!"<<endl; score++; MAP[snakeFood.x][snakeFood.y]=1;head.x=snakeFood.x;head.y=snakeFood.y;//fresh头点 length++;//增加长度 for(int i=1;i<=HEIGHT;i++) for(int j=1;j<=WIDTH;j++) { if( MAP[i][j]>0 && !(i==snakeFood.x && j==snakeFood.y) ) { MAP[i][j]+=1;//除了新的头点所有点编号加1 } } while(createFood()); }
void snake::resetFood() { clearFood(); while(createFood()); }
static pos createFood(int width, int height, posList snake) { // The high level view of how this code works: (1) Creates a list of // open positions (i.e positions not occuipied by the snake) and (2) // grabs a random element from that list. But it does this without // creating a list of open positions. int maxRand = width*height - snake.len; if (maxRand <= 0) { return (pos){ .x = -1, .y = -1 }; } int randIndex = rand() % maxRand; int curRandIndex = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { pos p = { .x = x, .y = y }; if (posList_contains(snake, p)) { continue; } if (curRandIndex == randIndex) { return p; } curRandIndex++; } } // This should never be reached but I added it to get rid of the // compiler warning. return (pos){ .x = -1, .y = -1 }; } static const dir NO_DIRECTION = { .x = 0, .y = 0 }; static dir actionToDirection(playeraction a) { if (a == UP) { return (dir){ .x = 0, .y = -1 }; } if (a == DOWN) { return (dir){ .x = 0, .y = 1 }; } if (a == LEFT) { return (dir){ .x = -1, .y = 0 }; } if (a == RIGHT) { return (dir){ .x = 1, .y = 0 }; } return NO_DIRECTION; } static void initState(int width, int height, posList *snake, pos *food, playeractionQueue *queue, dir *curDirection, bool *paused, int *score) { srand(time(NULL)); snake->len = 4; snake->list[0] = (pos){ .x = 0, .y = 1 }; snake->list[1] = (pos){ .x = 0, .y = 0 }; snake->list[2] = (pos){ .x = 1, .y = 0 }; snake->list[3] = (pos){ .x = 1, .y = 1 }; *food = createFood(width, height, *snake); while (playeractionQueue_dequeue(queue) != NO_ACTION); *curDirection = actionToDirection(DOWN); *paused = false; *score = 0; } static bool gameIsWon(int width, int height, posList snake) { return width*height == snake.len; } static bool gameIsLost(int width, int height, posList snake) { { posList headless = snake; headless.len--; if (posList_contains(headless, snake.list[snake.len-1])) { return true; } } { pos head = snake.list[snake.len-1]; if (head.x < 0 || width <= head.x) { return true; } if (head.y < 0 || height <= head.y) { return true; } } return false; } static void updateGameState(playeraction action, int width, int height, bool *paused, posList *snake, pos *food, dir *d, int *score) { if (action == PAUSE) { *paused = !(*paused); return; } if (*paused) { return; } dir newDir = actionToDirection(action); if (!dir_equal(newDir, NO_DIRECTION)) { *d = newDir; } pos newHead = { .x = snake->list[snake->len-1].x + d->x, .y = snake->list[snake->len-1].y + d->y }; if (pos_equal(newHead, *food)) { *snake = posList_append(*snake, newHead); *food = createFood(width, height, *snake); (*score)++; } else { for (int i = 0; i < snake->len-1; i++) { snake->list[i] = snake->list[i+1]; } snake->list[snake->len-1].x += d->x; snake->list[snake->len-1].y += d->y; } } char *playeraction_toString(playeraction p) { switch (p) { case NO_ACTION: return "no action"; case UP: return "move the snake up"; case DOWN: return "move the snake down"; case LEFT: return "move the snake left"; case RIGHT: return "move the snake right"; case PAUSE: return "pause the game"; case QUIT: return "quit the game"; case NEW_GAME: return "start a new game"; default: return "BUG!!! Unknown player action, please add another case to the switch statement"; } } void playeractionQueue_enqueue(playeractionQueue *q, playeraction c) { if (q->isFull) { return; } pthread_mutex_lock(q->mu); q->arr[q->tail] = c; q->tail = (q->tail+1) % PLAYERACTIONQUEUE_SIZE; if (q->tail == q->head) { q->isFull = 1; } pthread_mutex_unlock(q->mu); } size_t snakeSpaceRequired(int width, int height) { posList snake; return width * height * sizeof(*snake.list); } void snake(int width, int height, struct timespec frameRate, void *snakeMem, playeractionQueue *actionsQueue, void (*render)(int width, int height, posList snake, pos food, bool paused, int score, bool gameIsWon, bool gameIsLost)) { posList snake; pos food; dir curDirection; bool paused; int score; snake.list = snakeMem; initState(width, height, &snake, &food, actionsQueue, &curDirection, &paused, &score); while (true) { bool won = gameIsWon(width, height, snake); bool lost = gameIsLost(width, height, snake); render(width, height, snake, food, paused, score, won, lost); nanosleep(&frameRate, NULL); playeraction action = playeractionQueue_dequeue(actionsQueue); while (!dir_orthogonal(curDirection, actionToDirection(action))) { action = playeractionQueue_dequeue(actionsQueue); } if (action == QUIT) { break; } if (action == NEW_GAME) { initState(width, height, &snake, &food, actionsQueue, &curDirection, &paused, &score); continue; } if (won || lost) { continue; } updateGameState(action, width, height, &paused, &snake, &food, &curDirection, &score); } }
Food getFoodOnPos(FoodRepoDynamic* v, int pos){ if (pos < 0 || pos >= v->length) return createFood("", -1,"",0,0,0); return v->foodstuff[pos]; }