#include #include #include "helpers.c" #define WIDTH 60 #define HEIGHT 40 #define DEBUG false unsigned int startLength = 0; unsigned int startApples = 0; unsigned int currentTick; int snake[WIDTH*HEIGHT]; unsigned int snakeLength; unsigned int snakeX; unsigned int snakeY; int snakeDirX; int snakeDirY; unsigned int numApples; void spawnApple(); void tick(); void draw(); // start_game // ========== void start_game(int len, int n_apples) { if (startLength == 0) startLength = len; if (startApples == 0) startApples = n_apples; // Initialize variables currentTick = 0; snakeLength = len; numApples = n_apples; nib_init(); // Initialize the snake array // Set every cell to a time value greater than the snake length for (unsigned int i = 0; i < WIDTH*HEIGHT; ++i) { snake[i] = snakeLength; } // Place the snake head in the middle snakeX = WIDTH / 2; snakeY = HEIGHT / 2; snakeDirX = 0; snakeDirY = -1; // Place the initial snake segments, downwards or something for (unsigned int i = 0; i < snakeLength; ++i) { unsigned int x = snakeX % WIDTH; unsigned int y = (snakeY + i) % HEIGHT; snake[x + y*WIDTH] = i; } // Place apples srand(time(0)); for (unsigned int i = 0; i < numApples; ++i) { spawnApple(); } while (true) { tick(); draw(); } } // spawnApple // ========== void spawnApple() { unsigned int x = rand() % WIDTH; unsigned int y = rand() % HEIGHT; while (snake[x + y*WIDTH] < snakeLength) { x = rand() % WIDTH; y = rand() % HEIGHT; } snake[x + y*WIDTH] = -1; } // tick // ==== void tick() { currentTick++; // Increment cell times // -------------------- for (unsigned int i = 0; i < WIDTH*HEIGHT; ++i) { int val = snake[i]; if (val < 0) { // Apple lifetime /* snake[i]--; */ } else if (val >= 0 && val <= snakeLength) { // Other cells snake[i]++; } } // Input // ----- int key = nib_poll_kbd(); if (key == 'w' && snakeDirY != 1) { snakeDirX = 0; snakeDirY = -1; } if (key == 's' && snakeDirY != -1) { snakeDirX = 0; snakeDirY = 1; } if (key == 'a' && snakeDirX != 1) { snakeDirX = -1; snakeDirY = 0; } if (key == 'd' && snakeDirX != -1) { snakeDirX = 1; snakeDirY = 0; } // Move snake // ---------- snakeX = (snakeX + snakeDirX + WIDTH) % WIDTH; snakeY = (snakeY + snakeDirY + HEIGHT) % HEIGHT; // Collision // --------- // On collision with self int val = snake[snakeX + snakeY*WIDTH]; if (val < snakeLength && val >= 0) { //nib_end(); start_game(startLength, startApples); } // ON collision with apple if (val < 0) { // Spawn a new apple somewhere spawnApple(); // Increase our length! snakeLength++; } // Update world // ------------ snake[snakeX + snakeY*WIDTH] = 0; } // draw // ==== void draw() { char body[] = "NIBBLES"; for (int y = -1; y <= HEIGHT; ++y) { for (int x = -1; x <= WIDTH; ++x) { // Draw a border outside the playing field if (x == -1 || y == -1 || x == WIDTH || y == HEIGHT) { unsigned int screenX = x + 1; unsigned int screenY = y + 1; nib_put_scr(screenX, screenY, '#'); } else { int snakeVal = snake[x + y*WIDTH]; unsigned int screenX = x + 1; unsigned int screenY = y + 1; // If the `DEBUG` flag is set, draw the raw ASCII-value for debugging purposes if (DEBUG) { nib_put_scr(screenX, screenY, '0' + snakeVal); continue; } // If the value is greater than `0` and less than `snakeLength`, it's part of the snake if (snakeVal >= 0 && snakeVal < snakeLength) { if (x == snakeX && y == snakeY) { // Draw the head nib_put_scr(screenX, screenY, '@'); } else { // Draw the body nib_put_scr(screenX, screenY, body[(snakeVal - 1) % 7]); } } else if (snakeVal < 0) { // If the value is less than `0`, it's an apple nib_put_scr(screenX, screenY, 'o'); } else { // Otherwise it's empty. nib_put_scr(screenX, screenY, ' '); } } } } }