aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
authoryzrh <yzrh@noema.org>2020-12-30 15:54:00 +0000
committeryzrh <yzrh@noema.org>2020-12-30 22:12:33 +0000
commitcb2376a82f1f556f23c47d435cd60af2abfc0138 (patch)
treeb19529823e9314d8db88ea09d64d22461c355336 /src/main.c
parent74a79ac0236e90ebf0520b08448643d3ba55a1ed (diff)
downloadsnake-sdl-cb2376a82f1f556f23c47d435cd60af2abfc0138.tar.gz
snake-sdl-cb2376a82f1f556f23c47d435cd60af2abfc0138.tar.zst
Rename binary.
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c1542
1 files changed, 0 insertions, 1542 deletions
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 48b8fc8..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,1542 +0,0 @@
-/*
- * Copyright (c) 2019-2020, yzrh <yzrh@noema.org>
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#ifdef __linux__
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <poll.h>
-
-#endif /* __linux__ */
-
-#include <SDL2/SDL.h>
-#include <SDL2/SDL_ttf.h>
-
-#ifdef SOUND
-
-#include <SDL2/SDL_mixer.h>
-
-#endif /* SOUND */
-
-#include "version.h"
-#include "extern.h"
-#include "screen.h"
-
-#ifdef GPIO
-
-#include "gpio.h"
-
-#endif /* GPIO */
-
-static pthread_mutex_t mutex;
-static pthread_cond_t cond;
-
-static SDL_Renderer *renderer;
-static TTF_Font *font_20;
-static TTF_Font *font_24;
-
-/*
- * Default to keyboard,
- * GPIO inputs are mapped to controller keys
- */
-static Snake_Device device = SNAKE_KEYBOARD;
-static int selection = 0;
-
-static Snake_Text text_title;
-static Snake_Text text_help_top;
-static Snake_Text text_help_0;
-static Snake_Text text_help_1;
-static Snake_Text text_help_2;
-static Snake_Text text_help_3;
-static Snake_Text text_help_4;
-static Snake_Text text_help_5;
-static Snake_Text text_help_6;
-static Snake_Text text_help_7;
-
-static Snake_Text text_score;
-
-static Snake_Text text_prompt_start;
-static Snake_Text text_prompt_resume;
-
-static Snake_Text text_prompt_0;
-static Snake_Text text_prompt_1;
-static Snake_Text text_prompt_2;
-
-static bool start = 1;
-static bool end = 0;
-static bool begin = 0;
-
-static bool god = 0;
-static bool reset = 0;
-static bool wait = 0;
-static bool multiplayer = 0;
-static bool flappy = 0;
-
-static struct timespec delay = {
- .tv_sec = 0,
- .tv_nsec = TICK_TIME_INIT
-};
-
-static int score;
-static int result;
-static int distance;
-static int speed;
-
-static Snake_Input input = SNAKE_EMPTY;
-static Snake_Input head[2][2];
-
-static Snake_Pos *snake0 = NULL;
-static Snake_Pos *snake1 = NULL;
-
-static int fruit[2];
-
-static Snake_Pos *gap = NULL;
-
-static void*
-handler_rendering(void *args)
-{
- const SDL_Color fg = {
- COLOUR_FOREGROUND_R,
- COLOUR_FOREGROUND_G,
- COLOUR_FOREGROUND_B
- };
- const SDL_Color bg = {
- COLOUR_BACKGROUND_R,
- COLOUR_BACKGROUND_G,
- COLOUR_BACKGROUND_B
- };
- const SDL_Color bg_s = {
- COLOUR_BACKGROUND_SHADE_R,
- COLOUR_BACKGROUND_SHADE_G,
- COLOUR_BACKGROUND_SHADE_B
- };
-
- char result_str[23];
- char score_str[11];
-
- Snake_Text text_result;
-
- Snake_Text text_welcome;
- Snake_Text text_clear;
- Snake_Text text_gameover;
- Snake_Text text_pause;
-
- while (!end) {
- draw_clear(renderer);
- draw_colour(renderer, SNAKE_FOREGROUND);
-
- draw_wall(renderer);
-
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + 4 * SCREEN_UNIT_X,
- SCREEN_UNIT_Y,
- "Snake",
- 1,
- 0,
- fg,
- bg,
- &text_title);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + 4 * SCREEN_UNIT_X,
- 2 * SCREEN_UNIT_Y,
- "Help",
- 1,
- 0,
- fg,
- bg,
- &text_help_top);
- if (god)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 2.5 * SCREEN_UNIT_Y,
- "0. Don't forget to cheat",
- 0,
- 0,
- fg,
- bg,
- &text_help_0);
- if (device == SNAKE_KEYBOARD) {
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 3 * SCREEN_UNIT_Y,
- "1. Classic: use arrow keys to move",
- 0,
- 0,
- fg,
- bg,
- &text_help_1);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 3.5 * SCREEN_UNIT_Y,
- "2. Multiplayer: use s, e, d, f keys",
- 0,
- 0,
- fg,
- bg,
- &text_help_2);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 4 * SCREEN_UNIT_Y,
- "3. Flappy: SPACE key to jump",
- 0,
- 0,
- fg,
- bg,
- &text_help_3);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 4.5 * SCREEN_UNIT_Y,
- "4. ESCAPE key to pause",
- 0,
- 0,
- fg,
- bg,
- &text_help_4);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 5 * SCREEN_UNIT_Y,
- "5. r key to reset",
- 0,
- 0,
- fg,
- bg,
- &text_help_5);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 5.5 * SCREEN_UNIT_Y,
- "6. m key to toggle music",
- 0,
- 0,
- fg,
- bg,
- &text_help_6);
- } else if (device == SNAKE_TOUCHSCREEN) {
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 3 * SCREEN_UNIT_Y,
- "1. Classic: swipe to move",
- 0,
- 0,
- fg,
- bg,
- &text_help_1);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 3.5 * SCREEN_UNIT_Y,
- "2. Multiplayer: use different side",
- 0,
- 0,
- fg,
- bg,
- &text_help_2);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 4 * SCREEN_UNIT_Y,
- "3. Flappy: tap to jump",
- 0,
- 0,
- fg,
- bg,
- &text_help_3);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 4.5 * SCREEN_UNIT_Y,
- "4. Tap here to pause",
- 0,
- 1,
- fg,
- bg,
- &text_help_4);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 5 * SCREEN_UNIT_Y,
- "5. Tap here to reset",
- 0,
- 1,
- fg,
- bg,
- &text_help_5);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 5.5 * SCREEN_UNIT_Y,
- "6. Tap here to toggle music",
- 0,
- 1,
- fg,
- bg,
- &text_help_6);
- } else if (device == SNAKE_CONTROLLER) {
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 3 * SCREEN_UNIT_Y,
- "1. Classic: use D-pad to move",
- 0,
- 0,
- fg,
- bg,
- &text_help_1);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 3.5 * SCREEN_UNIT_Y,
- "2. Multiplayer: second controller",
- 0,
- 0,
- fg,
- bg,
- &text_help_2);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 4 * SCREEN_UNIT_Y,
- "3. Flappy: Press A to jump",
- 0,
- 0,
- fg,
- bg,
- &text_help_3);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 4.5 * SCREEN_UNIT_Y,
- "4. Press BACK to pause",
- 0,
- 0,
- fg,
- bg,
- &text_help_4);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 5 * SCREEN_UNIT_Y,
- "5. Press X to reset",
- 0,
- 0,
- fg,
- bg,
- &text_help_5);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 5.5 * SCREEN_UNIT_Y,
- "6. Press Y to toggle music",
- 0,
- 0,
- fg,
- bg,
- &text_help_6);
- }
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + SCREEN_UNIT_X / 4,
- 6 * SCREEN_UNIT_Y,
- "7. Have fun",
- 0,
- 0,
- fg,
- bg,
- &text_help_7);
-
- snprintf(score_str, 11, "Score: %d", score);
-
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT + 4 * SCREEN_UNIT_X,
- 7 * SCREEN_UNIT_Y,
- score_str,
- 1,
- 0,
- fg,
- bg,
- &text_score);
-
- draw_snake(renderer, &snake0);
-
- if (flappy) {
- draw_pipe(renderer, &gap);
- } else if (multiplayer)
- draw_snake(renderer, &snake1);
- else if (!start)
- draw_fruit(renderer, fruit);
-
- if (start || reset) {
- if (multiplayer) {
- if (result == 3)
- snprintf(result_str, 23, "Draw");
- else if (result > 0)
- snprintf(result_str, 23,
- "%s is the winner",
- result == 1 ?
- "Player 2" : "Player 1");
- else
- snprintf(result_str, 23, "Reset");
- text_result.cache = 0;
-
- draw_text(renderer,
- font_24,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 -
- 0.75 * SCREEN_UNIT_Y,
- result_str,
- 1,
- 0,
- fg,
- bg_s,
- &text_result);
- }
- if (start)
- draw_text(renderer,
- font_24,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2,
- "Welcome",
- 1,
- 0,
- fg,
- bg_s,
- &text_welcome);
- else if (!flappy && !multiplayer &&
- score == SCREEN_BLOCK / 2)
- draw_text(renderer,
- font_24,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2,
- "Why don't you have legs?",
- 1,
- 0,
- fg,
- bg_s,
- &text_clear);
- else
- draw_text(renderer,
- font_24,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2,
- "Game over!",
- 1,
- 0,
- fg,
- bg_s,
- &text_gameover);
- if (device == SNAKE_KEYBOARD)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 +
- 0.75 * SCREEN_UNIT_Y,
- "Press RETURN key for selection",
- 1,
- 0,
- fg,
- bg_s,
- &text_prompt_start);
- else if (device == SNAKE_TOUCHSCREEN)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 +
- 0.75 * SCREEN_UNIT_Y,
- "Tap the option to select",
- 1,
- 0,
- fg,
- bg_s,
- &text_prompt_start);
- else if (device == SNAKE_CONTROLLER)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 +
- 0.75 * SCREEN_UNIT_Y,
- "Press START to select",
- 1,
- 0,
- fg,
- bg_s,
- &text_prompt_start);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 + 1.5 * SCREEN_UNIT_Y,
- "Classic",
- 1,
- device == SNAKE_TOUCHSCREEN ||
- selection == 0 ? 1 : 0,
- fg,
- bg_s,
- &text_prompt_0);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 + 2.25 * SCREEN_UNIT_Y,
- "Multiplayer",
- 1,
- device == SNAKE_TOUCHSCREEN ||
- selection == 1 ? 1 : 0,
- fg,
- bg_s,
- &text_prompt_1);
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 + 3 * SCREEN_UNIT_Y,
- "Flappy",
- 1,
- device == SNAKE_TOUCHSCREEN ||
- selection == 2 ? 1 : 0,
- fg,
- bg_s,
- &text_prompt_2);
- } else if (wait) {
- draw_text(renderer,
- font_24,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2,
- "Paused",
- 1,
- 0,
- fg,
- bg_s,
- &text_pause);
- if (device == SNAKE_KEYBOARD)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 +
- 0.75 * SCREEN_UNIT_Y,
- "Press ESCAPE key to resume",
- 1,
- 0,
- fg,
- bg_s,
- &text_prompt_resume);
- else if (device == SNAKE_TOUCHSCREEN)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 +
- 0.75 * SCREEN_UNIT_Y,
- "Tap here to resume",
- 1,
- 1,
- fg,
- bg_s,
- &text_prompt_resume);
- else if (device == SNAKE_CONTROLLER)
- draw_text(renderer,
- font_20,
- SCREEN_HEIGHT / 2,
- SCREEN_HEIGHT / 2 +
- 0.75 * SCREEN_UNIT_Y,
- "Press START to resume",
- 1,
- 0,
- fg,
- bg_s,
- &text_prompt_resume);
- }
-
- SDL_RenderPresent(renderer);
- }
- return 0;
-}
-
-static void*
-handler_logic(void *args)
-{
- struct timespec clock_start;
- struct timespec clock_end;
- double clock_pass = 0;
- int pipe_dim[6];
- int pipe_pos = 0;
-
- clock_gettime(CLOCK_MONOTONIC, &clock_start);
-
- for (;;) {
- pthread_mutex_lock(&mutex);
- while (start || reset || wait) {
- if (!wait) {
- clock_pass = 0;
- pipe_pos = 0;
- }
- pthread_cond_wait(&cond, &mutex);
- clock_gettime(CLOCK_MONOTONIC, &clock_start);
- }
- pthread_mutex_unlock(&mutex);
-
- if (end)
- return 0;
-
- if (flappy) {
- pthread_mutex_lock(&mutex);
- while (!begin)
- pthread_cond_wait(&cond, &mutex);
- pthread_mutex_unlock(&mutex);
-
- game_pipe_bound(&gap, pipe_dim);
-
- if (pipe_pos - SCREEN_UNIT > pipe_dim[0]) {
- score++;
- text_score.cache = 0;
- }
- pipe_pos = pipe_dim[0];
-
- if (!god && (collision(
- (int[]) {snake0->next->x, snake0->next->y,
- 2 * SCREEN_UNIT, SCREEN_UNIT},
- (int[]) {pipe_dim[0], pipe_dim[2],
- pipe_dim[1], pipe_dim[3]}) ||
- collision(
- (int[]) {snake0->next->x, snake0->next->y,
- 2 * SCREEN_UNIT, SCREEN_UNIT},
- (int[]) {pipe_dim[0], pipe_dim[4],
- pipe_dim[1], pipe_dim[5]}) ||
- snake0->y < 0 ||
- snake0->y + SCREEN_UNIT > SCREEN_HEIGHT)) {
- pthread_mutex_lock(&mutex);
- reset = 1;
- pthread_mutex_unlock(&mutex);
- } else {
- game_pipe_move(&gap);
-
- game_pipe_pos(&gap, &result);
- if (result == 3) {
- game_pipe_del(&gap);
- game_pipe_add(&gap);
- } else if (result == 2) {
- game_pipe_add(&gap);
- } else if (result == 1) {
- game_pipe_del(&gap);
- }
- }
- } else if (!multiplayer) {
- game_snake_move(&snake0, NULL,
- head[0], !god, &result);
-
- if (result == 0 || god) {
- head[1][0] = head[0][0];
-
- if (collision_block(fruit,
- (int[]) {snake0->x, snake0->y})) {
- score++;
- text_score.cache = 0;
- game_snake_grow(&snake0);
-
- if (score == SCREEN_BLOCK / 2) {
- pthread_mutex_lock(&mutex);
- reset = 1;
- pthread_mutex_unlock(&mutex);
- }
-
- game_fruit(fruit, &snake0);
-
- if (delay.tv_nsec - TICK_TIME_DEC >=
- TICK_TIME_MIN)
- delay.tv_nsec -= TICK_TIME_DEC;
- }
- } else {
- pthread_mutex_lock(&mutex);
- reset = 1;
- pthread_mutex_unlock(&mutex);
- }
- } else {
- game_snake_move(&snake0, &snake1,
- head[0], !god, &result);
-
- if (result == 0 || god) {
- head[1][0] = head[0][0];
- head[1][1] = head[0][1];
-
- clock_gettime(CLOCK_MONOTONIC, &clock_end);
- clock_pass += (clock_end.tv_sec -
- clock_start.tv_sec) +
- (clock_end.tv_nsec -
- clock_start.tv_nsec) * 0.000000001;
- clock_gettime(CLOCK_MONOTONIC, &clock_start);
-
- score = clock_pass;
- text_score.cache = 0;
- game_snake_grow(&snake0);
- game_snake_grow(&snake1);
- } else {
- pthread_mutex_lock(&mutex);
- reset = 1;
- pthread_mutex_unlock(&mutex);
- }
- }
-
- nanosleep(&delay, NULL);
- }
-}
-
-static void*
-handler_gravity(void *args)
-{
- const struct timespec delay = {
- .tv_sec = 0,
- .tv_nsec = 1000000000 / SCREEN_UNIT
- };
-
- for (;;) {
- pthread_mutex_lock(&mutex);
- while (!flappy || !begin || start || reset || wait)
- pthread_cond_wait(&cond, &mutex);
- pthread_mutex_unlock(&mutex);
-
- if (end)
- return 0;
-
- if (distance > 0) {
- game_snake_fall(&snake0, 0,
- distance > speed ? speed : distance);
- speed++;
-
- pthread_mutex_lock(&mutex);
- distance -= distance > speed ? speed : distance;
- if (distance == 0)
- speed = 1;
- pthread_mutex_unlock(&mutex);
- } else {
- game_snake_fall(&snake0, 1, speed);
- speed++;
- }
-
- nanosleep(&delay, NULL);
- }
-}
-
-#ifdef GPIO
-
-#ifdef __FreeBSD__
-
-static void*
-handler_gpio(void *args)
-{
- const struct timespec delay = {
- .tv_sec = 0,
- .tv_nsec = 50000000
- };
-
- SDL_Event event;
- event.type = SDL_CONTROLLERBUTTONUP;
-
- while (!end) {
- if (gpio_read(GPIO_PIN_IN0) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_LEFT;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN1) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_UP;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN2) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_DOWN;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN3) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN4) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_BACK;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN5) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_GUIDE;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN6) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_START;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN7) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_A;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN8) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_B;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN9) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_X;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN10) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_Y;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN11) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN12) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN13) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_LEFTSTICK;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN14) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_RIGHTSTICK;
- event.cbutton.which = 0;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN15) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_LEFT;
- event.cbutton.which = 1;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN16) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_UP;
- event.cbutton.which = 1;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN17) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_DOWN;
- event.cbutton.which = 1;
- SDL_PushEvent(&event);
- } else if (gpio_read(GPIO_PIN_IN18) == 0) {
- event.cbutton.button =
- SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
- event.cbutton.which = 1;
- SDL_PushEvent(&event);
- }
-
- nanosleep(&delay, NULL);
- }
- return 0;
-}
-
-#elif __linux__
-
-static void*
-handler_gpio(void *args)
-{
- struct pollfd pfd[19];
- char path[29];
-
- for (int i = 0; i < 19; i++)
- pfd[i].events = POLLPRI | POLLERR;
-
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN0);
- pfd[0].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN1);
- pfd[1].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN2);
- pfd[2].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN3);
- pfd[3].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN4);
- pfd[4].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN5);
- pfd[5].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN6);
- pfd[6].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN7);
- pfd[7].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN8);
- pfd[8].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN9);
- pfd[9].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN10);
- pfd[10].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN11);
- pfd[11].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN12);
- pfd[12].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN13);
- pfd[13].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN14);
- pfd[14].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN15);
- pfd[15].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN16);
- pfd[16].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN17);
- pfd[17].fd = open(path, O_RDONLY);
- snprintf(path, 29, "/sys/class/gpio/gpio%d/value", GPIO_PIN_IN18);
- pfd[18].fd = open(path, O_RDONLY);
-
- SDL_Event event;
- event.type = SDL_CONTROLLERBUTTONUP;
-
- char val[2];
-
- while (!end) {
- poll(pfd, 19, -1);
-
- for (int i = 0; i < 19; i++) {
- if (pfd[i].revents & (POLLPRI | POLLERR)) {
- pfd[i].revents &= ~(POLLPRI | POLLERR);
- read(pfd[i].fd, val, 2);
- lseek(pfd[i].fd, 0, SEEK_SET);
-
- if (atoi(val) != 0)
- continue;
-
- input_gpio(i % 15, &event.cbutton.button);
-
- if (i < 15)
- event.cbutton.which = 0;
- else
- event.cbutton.which = 1;
-
- SDL_PushEvent(&event);
- break;
- }
- }
- }
- return 0;
-}
-
-#endif /* __FreeBSD__ */
-
-#endif /* GPIO */
-
-int
-main(void)
-{
- printf("Snake " VERSION "." RELEASE "." PATCH EXTRA "\n"
- "Copyright (c) 2019-2020, yzrh <yzrh@noema.org>\n");
-
- if (SDL_Init(SDL_INIT_VIDEO |
- SDL_INIT_AUDIO |
- SDL_INIT_GAMECONTROLLER) != 0) {
- fprintf(stderr, "SDL initialisation failure: %s\n",
- SDL_GetError());
- return 1;
- }
-
- SDL_Window *window = SDL_CreateWindow(
- "Snake " VERSION "." RELEASE "." PATCH EXTRA,
- SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED,
- SCREEN_WIDTH,
- SCREEN_HEIGHT,
- SDL_WINDOW_OPENGL);
-
- if (window == NULL) {
- fprintf(stderr, "Window creation failure: %s\n",
- SDL_GetError());
- return 1;
- }
-
- renderer = SDL_CreateRenderer(
- window,
- -1,
- SDL_RENDERER_ACCELERATED |
- SDL_RENDERER_PRESENTVSYNC);
-
- if (renderer == NULL) {
- fprintf(stderr, "Renderer creation failure: %s\n",
- SDL_GetError());
- return 1;
- }
-
- if (TTF_Init() != 0) {
- fprintf(stderr, "TTF initialisation failure: %s\n",
- TTF_GetError());
- return 1;
- }
-
- font_20 = TTF_OpenFont("../contrib/font.ttf", 20);
- font_24 = TTF_OpenFont("../contrib/font.ttf", 24);
-
- if (font_20 == NULL) {
- font_20 = TTF_OpenFont("/usr/local/share/snake/font.ttf", 20);
- font_24 = TTF_OpenFont("/usr/local/share/snake/font.ttf", 24);
- }
-
- if (font_20 == NULL) {
- font_20 = TTF_OpenFont("/usr/share/snake/font.ttf", 20);
- font_24 = TTF_OpenFont("/usr/share/snake/font.ttf", 24);
- }
-
- if (font_20 == NULL) {
- fprintf(stderr, "%s\n", TTF_GetError());
- return 1;
- }
-
-#ifdef SOUND
-
- if ((Mix_Init(MIX_INIT_FLAC) & MIX_INIT_FLAC) != MIX_INIT_FLAC)
- fprintf(stderr, "Mixer initialisation failure: %s\n",
- Mix_GetError());
-
- if (Mix_OpenAudio(48000, AUDIO_S16SYS, 2, 4096) == -1)
- fprintf(stderr, "%s\n", Mix_GetError());
-
- Mix_Music *music = Mix_LoadMUS("../contrib/music.flac");
-
- if (music == NULL)
- music = Mix_LoadMUS("/usr/local/share/snake/music.flac");
-
- if (music == NULL)
- music = Mix_LoadMUS("/usr/share/snake/music.flac");
-
- if (music == NULL)
- fprintf(stderr, "%s\n", Mix_GetError());
-
- if (Mix_PlayMusic(music, -1) == -1)
- fprintf(stderr, "Audio playback failure: %s\n",
- Mix_GetError());
-
-#endif /* SOUND */
-
-#ifdef GPIO
-
-#ifdef __linux__
-
- gpio_export(GPIO_PIN_IN0);
- gpio_export(GPIO_PIN_IN1);
- gpio_export(GPIO_PIN_IN2);
- gpio_export(GPIO_PIN_IN3);
- gpio_export(GPIO_PIN_IN4);
- gpio_export(GPIO_PIN_IN5);
- gpio_export(GPIO_PIN_IN6);
- gpio_export(GPIO_PIN_IN7);
- gpio_export(GPIO_PIN_IN8);
- gpio_export(GPIO_PIN_IN9);
- gpio_export(GPIO_PIN_IN10);
- gpio_export(GPIO_PIN_IN11);
- gpio_export(GPIO_PIN_IN12);
- gpio_export(GPIO_PIN_IN13);
- gpio_export(GPIO_PIN_IN14);
- gpio_export(GPIO_PIN_IN15);
- gpio_export(GPIO_PIN_IN16);
- gpio_export(GPIO_PIN_IN17);
- gpio_export(GPIO_PIN_IN18);
-
- /* Wait for sysfs directory to show up */
- sleep(1);
-
-#endif /* __linux__ */
-
- gpio_config(GPIO_PIN_IN0, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN1, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN2, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN3, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN4, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN5, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN6, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN7, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN8, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN9, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN10, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN11, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN12, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN13, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN14, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN15, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN16, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN17, GPIO_IN, GPIO_INT);
- gpio_config(GPIO_PIN_IN18, GPIO_IN, GPIO_INT);
-
-#endif /* GPIO */
-
- int seed;
- int random = open("/dev/random", O_RDONLY);
- if (read(random, &seed, sizeof(int)) > 0)
- srand(seed);
- close(random);
-
- SDL_JoystickID player = 0;
- SDL_Event event;
-
- pthread_mutex_init(&mutex, NULL);
- pthread_cond_init(&cond, NULL);
- pthread_t th_renderer;
- pthread_t th_logic;
- pthread_t th_gravity;
-
- #ifdef GPIO
-
- pthread_t th_gpio;
-
- #endif /* GPIO */
-
- pthread_create(&th_renderer, NULL, handler_rendering, NULL);
- pthread_create(&th_logic, NULL, handler_logic, NULL);
- pthread_create(&th_gravity, NULL, handler_gravity, NULL);
-
- #ifdef GPIO
-
- pthread_create(&th_gpio, NULL, handler_gpio, NULL);
-
- #endif /* GPIO */
-
- while (SDL_WaitEvent(&event)) {
- if (event.type == SDL_QUIT)
- break;
-
- switch (event.type) {
- case SDL_KEYUP:
- if (device != SNAKE_KEYBOARD) {
- device = SNAKE_KEYBOARD;
- text_help_1.cache = 0;
- text_help_2.cache = 0;
- text_help_3.cache = 0;
- text_help_4.cache = 0;
- text_help_5.cache = 0;
- text_help_6.cache = 0;
- text_prompt_start.cache = 0;
- text_prompt_resume.cache = 0;
- }
- input_keyboard(event.key.keysym.sym, &input);
- if (multiplayer &&
- (event.key.keysym.sym ==
- SDLK_s ||
- event.key.keysym.sym ==
- SDLK_e ||
- event.key.keysym.sym ==
- SDLK_d ||
- event.key.keysym.sym ==
- SDLK_f))
- player = 1;
- else
- player = 0;
- break;
- case SDL_FINGERUP:
- if (device != SNAKE_TOUCHSCREEN) {
- device = SNAKE_TOUCHSCREEN;
- text_help_1.cache = 0;
- text_help_2.cache = 0;
- text_help_3.cache = 0;
- text_help_4.cache = 0;
- text_help_5.cache = 0;
- text_help_6.cache = 0;
- text_prompt_start.cache = 0;
- text_prompt_resume.cache = 0;
- }
- if (start || reset || wait) {
- if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_5)) {
- input = SNAKE_RESET;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_6)) {
- input = SNAKE_MUSIC;
- } else if (wait) {
- if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_prompt_resume))
- input = SNAKE_PAUSE;
- } else {
- if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_prompt_0)) {
- selection = 0;
- input = SNAKE_SELECT;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_prompt_1)) {
- selection = 1;
- input = SNAKE_SELECT;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_prompt_2)) {
- selection = 2;
- input = SNAKE_SELECT;
- }
- }
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_4)) {
- input = SNAKE_PAUSE;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_5)) {
- input = SNAKE_RESET;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_6)) {
- input = SNAKE_MUSIC;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_top)) {
- input = SNAKE_GOD;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_score)) {
- input = SNAKE_GROW;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_title)) {
- input = SNAKE_TELEPORT;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_1)) {
- input = SNAKE_TICK_DECREASE;
- } else if (collision_bound(
- event.tfinger.x,
- event.tfinger.y,
- &text_help_7)) {
- input = SNAKE_TICK_INCREASE;
- } else if (flappy) {
- input = SNAKE_JUMP;
- } else {
- input = SNAKE_EMPTY;
- }
- break;
- case SDL_FINGERMOTION:
- if (device != SNAKE_TOUCHSCREEN) {
- device = SNAKE_TOUCHSCREEN;
- text_help_1.cache = 0;
- text_help_2.cache = 0;
- text_help_3.cache = 0;
- text_help_4.cache = 0;
- text_help_5.cache = 0;
- text_help_6.cache = 0;
- text_prompt_start.cache = 0;
- text_prompt_resume.cache = 0;
- }
- if ((event.tfinger.dx *
- event.tfinger.dx) >
- (event.tfinger.dy *
- event.tfinger.dy)) {
- if (event.tfinger.dx > 1)
- input = SNAKE_RIGHT;
- else if (event.tfinger.dx < -1)
- input = SNAKE_LEFT;
- } else {
- if (event.tfinger.dy > 1)
- input = SNAKE_DOWN;
- else if (event.tfinger.dy < -1)
- input = SNAKE_UP;
- }
- if (multiplayer &&
- event.tfinger.x > SCREEN_HEIGHT / 2)
- player = 1;
- else
- player = 0;
- break;
- case SDL_CONTROLLERBUTTONUP:
- if (device != SNAKE_CONTROLLER) {
- device = SNAKE_CONTROLLER;
- text_help_1.cache = 0;
- text_help_2.cache = 0;
- text_help_3.cache = 0;
- text_help_4.cache = 0;
- text_help_5.cache = 0;
- text_help_6.cache = 0;
- text_prompt_start.cache = 0;
- text_prompt_resume.cache = 0;
- }
- input_controller(event.cbutton.button, &input);
- player = event.cbutton.which;
- break;
- default:
- break;
- }
-
- if (!start && !reset && !wait) {
- switch (input) {
- case SNAKE_LEFT:
- if (head[1][player] != SNAKE_RIGHT)
- head[0][player] = SNAKE_LEFT;
- break;
- case SNAKE_UP:
- if (head[1][player] != SNAKE_DOWN)
- head[0][player] = SNAKE_UP;
- break;
- case SNAKE_DOWN:
- if (head[1][player] != SNAKE_UP)
- head[0][player] = SNAKE_DOWN;
- break;
- case SNAKE_RIGHT:
- if (head[1][player] != SNAKE_LEFT)
- head[0][player] = SNAKE_RIGHT;
- break;
- case SNAKE_JUMP:
- if (!begin) {
- pthread_mutex_lock(&mutex);
- begin = 1;
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mutex);
- }
- if (flappy) {
- pthread_mutex_lock(&mutex);
- distance += PIPE_GAP / 2 *
- SCREEN_UNIT;
- if (distance == 0)
- speed = 1;
- pthread_mutex_unlock(&mutex);
- }
- break;
- case SNAKE_RESET:
- pthread_mutex_lock(&mutex);
- reset = 1;
- pthread_mutex_unlock(&mutex);
- break;
- case SNAKE_GOD:
- god = 1;
- break;
- case SNAKE_GROW:
- if (god && !flappy && !multiplayer)
- game_snake_grow(&snake0);
- break;
- case SNAKE_TELEPORT:
- if (god) {
- snake0->x = snake0->y =
- SCREEN_HEIGHT / 2;
- if (flappy) {
- snake0->next->x =
- SCREEN_HEIGHT /
- 2 - SCREEN_UNIT;
- snake0->next->y =
- SCREEN_HEIGHT /
- 2;
- }
- }
- break;
- case SNAKE_MUSIC:
-#ifdef SOUND
- if (Mix_PausedMusic())
- Mix_ResumeMusic();
- else
- Mix_PauseMusic();
-#endif /* SOUND */
- break;
- case SNAKE_TICK_DECREASE:
- if (god && !flappy && delay.tv_nsec -
- TICK_TIME_DEC >= TICK_TIME_MIN)
- delay.tv_nsec -= TICK_TIME_DEC;
- break;
- case SNAKE_TICK_INCREASE:
- if (god && !flappy)
- delay.tv_nsec += TICK_TIME_DEC;
- break;
- case SNAKE_PAUSE:
- wait = 1;
- break;
- default:
- break;
- }
- } else {
- switch (input) {
- case SNAKE_RESET:
- wait = 0;
-
- pthread_mutex_lock(&mutex);
- reset = 1;
- pthread_mutex_unlock(&mutex);
- break;
- case SNAKE_MUSIC:
-#ifdef SOUND
- if (Mix_PausedMusic())
- Mix_ResumeMusic();
- else
- Mix_PauseMusic();
-#endif /* SOUND */
- break;
- case SNAKE_SELECT:
- if (wait)
- break;
-
- if (selection == 0) {
- flappy = 0;
- multiplayer = 0;
- } else if (selection == 1) {
- flappy = 0;
- multiplayer = 1;
- } else if (selection == 2) {
- multiplayer = 0;
- flappy = 1;
- }
-
- delay.tv_nsec = TICK_TIME_INIT;
-
- god = 0;
-
- head[0][0] = head[0][1] =
- SNAKE_UP;
- head[1][0] = head[1][1] =
- SNAKE_EMPTY;
-
- score = 0;
- text_score.cache = 0;
-
- if (flappy) {
- delay.tv_nsec = TICK_TIME_INIT /
- SCREEN_UNIT;
-
- game_snake_init(&snake0, 0);
-
- snake0->next->x =
- SCREEN_HEIGHT / 2 -
- SCREEN_UNIT;
- snake0->next->y =
- SCREEN_HEIGHT / 2;
-
- game_pipe_init(&gap);
-
- pthread_mutex_lock(&mutex);
- begin = 0;
- distance = 0;
- speed = 1;
- pthread_mutex_unlock(&mutex);
- } else if (!multiplayer) {
- game_snake_init(
- &snake0, 0);
- game_fruit(
- fruit,
- &snake0);
- } else {
- game_snake_init(
- &snake0,
- -4 *
- SCREEN_UNIT);
- game_snake_init(
- &snake1,
- 4 *
- SCREEN_UNIT);
- }
- start = 0;
-
- pthread_mutex_lock(&mutex);
- reset = 0;
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mutex);
- break;
- case SNAKE_PAUSE:
- wait = 0;
-
- pthread_mutex_lock(&mutex);
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mutex);
- break;
- case SNAKE_UP:
- if ((start || reset) &&
- selection - 1 >= 0)
- selection--;
- break;
- case SNAKE_DOWN:
- if ((start || reset) &&
- selection + 1 <= 2)
- selection++;
- break;
- default:
- break;
- }
- }
- input = SNAKE_EMPTY;
- }
-
- start = 0;
- end = 1;
-
- wait = 0;
- flappy = 1;
-
- pthread_mutex_lock(&mutex);
- reset = 0;
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mutex);
-
- #ifdef GPIO
-
- pthread_join(th_gpio, NULL);
-
- #endif /* GPIO */
-
- pthread_join(th_gravity, NULL);
- pthread_join(th_logic, NULL);
- pthread_join(th_renderer, NULL);
- pthread_cond_destroy(&cond);
- pthread_mutex_destroy(&mutex);
-
-#ifdef GPIO
-
-#ifdef __linux__
-
- gpio_unexport(GPIO_PIN_IN0);
- gpio_unexport(GPIO_PIN_IN1);
- gpio_unexport(GPIO_PIN_IN2);
- gpio_unexport(GPIO_PIN_IN3);
- gpio_unexport(GPIO_PIN_IN4);
- gpio_unexport(GPIO_PIN_IN5);
- gpio_unexport(GPIO_PIN_IN6);
- gpio_unexport(GPIO_PIN_IN7);
- gpio_unexport(GPIO_PIN_IN8);
- gpio_unexport(GPIO_PIN_IN9);
- gpio_unexport(GPIO_PIN_IN10);
- gpio_unexport(GPIO_PIN_IN11);
- gpio_unexport(GPIO_PIN_IN12);
- gpio_unexport(GPIO_PIN_IN13);
- gpio_unexport(GPIO_PIN_IN14);
- gpio_unexport(GPIO_PIN_IN15);
- gpio_unexport(GPIO_PIN_IN16);
- gpio_unexport(GPIO_PIN_IN17);
- gpio_unexport(GPIO_PIN_IN18);
-
-#endif /* __linux__ */
-
-#endif /* GPIO */
-
-#ifdef SOUND
- Mix_Quit();
-#endif /* SOUND */
-
- TTF_Quit();
- SDL_DestroyRenderer(renderer);
- SDL_DestroyWindow(window);
- SDL_Quit();
-}