diff options
Diffstat (limited to 'src/renderer.c')
-rw-r--r-- | src/renderer.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/renderer.c b/src/renderer.c new file mode 100644 index 0000000..c742e18 --- /dev/null +++ b/src/renderer.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2019-2020, yzrh <yzrh@noema.org> + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include <stdbool.h> + +#include <SDL2/SDL.h> +#include <SDL2/SDL_ttf.h> + +#include "renderer.h" +#include "screen.h" +#include "game.h" + +void +draw_clear(SDL_Renderer *renderer) +{ + SDL_SetRenderDrawColor(renderer, + COLOUR_BACKGROUND_R, + COLOUR_BACKGROUND_G, + COLOUR_BACKGROUND_B, + 255); + SDL_RenderClear(renderer); +} + +void +draw_colour(SDL_Renderer *renderer, Snake_Colour colour) +{ + int r; + int g; + int b; + + switch (colour) { + case SNAKE_FOREGROUND: + r = COLOUR_FOREGROUND_R; + g = COLOUR_FOREGROUND_G; + b = COLOUR_FOREGROUND_B; + break; + case SNAKE_BACKGROUND: + r = COLOUR_BACKGROUND_R; + g = COLOUR_BACKGROUND_G; + b = COLOUR_BACKGROUND_B; + break; + case SNAKE_BACKGROUND_SHADE: + r = COLOUR_BACKGROUND_SHADE_R; + g = COLOUR_BACKGROUND_SHADE_G; + b = COLOUR_BACKGROUND_SHADE_B; + break; + case SNAKE_RED: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + case SNAKE_GREEN: + r = COLOUR_GREEN_R; + g = COLOUR_GREEN_G; + b = COLOUR_GREEN_B; + break; + case SNAKE_BLUE: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + case SNAKE_YELLOW: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + case SNAKE_MAGENTA: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + case SNAKE_CYAN: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + case SNAKE_WHITE: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + case SNAKE_BLACK: + r = COLOUR_RED_R; + g = COLOUR_RED_G; + b = COLOUR_RED_B; + break; + default: + break; + } + + SDL_SetRenderDrawColor(renderer, + r, + g, + b, + 255); +} + +void +draw_text(SDL_Renderer *renderer, TTF_Font *font, + int text_x, int text_y, char *text, + bool centre, bool select, SDL_Color fg, SDL_Color bg, + Snake_Text *message) +{ + if (!message->cache) { + if (message->texture != NULL) + SDL_DestroyTexture(message->texture); + + SDL_Surface *surface = + TTF_RenderUTF8_Shaded(font, text, fg, bg); + message->texture = + SDL_CreateTextureFromSurface(renderer, surface); + SDL_FreeSurface(surface); + + message->pos.x = text_x; + message->pos.y = text_y; + TTF_SizeText(font, text, &message->pos.w, &message->pos.h); + if (centre) + message->pos.x -= message->pos.w / 2; + message->pos.y -= message->pos.h; + + message->cache = 1; + } + + SDL_RenderCopy(renderer, message->texture, NULL, &message->pos); + + if (select) { + SDL_SetRenderDrawColor(renderer, + COLOUR_FOREGROUND_R, + COLOUR_FOREGROUND_G, + COLOUR_FOREGROUND_B, + 255); + SDL_RenderDrawLine(renderer, + message->pos.x, message->pos.y, + message->pos.x, message->pos.y + message->pos.h); + SDL_RenderDrawLine(renderer, + message->pos.x, message->pos.y, + message->pos.x + message->pos.w, message->pos.y); + SDL_RenderDrawLine(renderer, + message->pos.x, message->pos.y + message->pos.h, + message->pos.x + message->pos.w, + message->pos.y + message->pos.h); + SDL_RenderDrawLine(renderer, + message->pos.x + message->pos.w, message->pos.y, + message->pos.x + message->pos.w, + message->pos.y + message->pos.h); + } +} + +void +draw_wall(SDL_Renderer *renderer) +{ + SDL_RenderDrawLine(renderer, + 0, 0, + 0, SCREEN_HEIGHT); + SDL_RenderDrawLine(renderer, + 0, 0, + SCREEN_HEIGHT, 0); + SDL_RenderDrawLine(renderer, + 0, SCREEN_HEIGHT - 1, + SCREEN_HEIGHT, SCREEN_HEIGHT - 1); + SDL_RenderDrawLine(renderer, + SCREEN_HEIGHT, 0, + SCREEN_HEIGHT, SCREEN_HEIGHT); +} + +void +draw_snake(SDL_Renderer *renderer, Snake_Pos **snake) +{ + Snake_Pos *ptr = *snake; + + SDL_Rect pos; + while (ptr != NULL) { + pos.x = ptr->x; + pos.y = ptr->y; + pos.w = SCREEN_UNIT; + pos.h = SCREEN_UNIT; + SDL_RenderFillRect(renderer, &pos); + ptr = ptr->next; + } +} + +void +draw_fruit(SDL_Renderer *renderer, int *fruit) +{ + int rx = fruit[0] + SCREEN_UNIT / 2; + int ry = fruit[1] + SCREEN_UNIT / 2; + + /* Midpoint circle algorithm */ + int x = SCREEN_UNIT / 2; + int y = 0; + int dx = 1; + int dy = 1; + int err = dx - ((SCREEN_UNIT / 2) << 1); + while (x >= y) { + SDL_RenderDrawLine(renderer, + rx - y, ry + x, + rx + y, ry + x); + SDL_RenderDrawLine(renderer, + rx - x, ry + y, + rx + x, ry + y); + SDL_RenderDrawLine(renderer, + rx - x, ry - y, + rx + x, ry - y); + SDL_RenderDrawLine(renderer, + rx - y, ry - x, + rx + y, ry - x); + + if (err <= 0) { + y++; + err += dy; + dy += 2; + } + + if (err > 0) { + x--; + dx += 2; + err += dx - ((SCREEN_UNIT / 2) << 1); + } + } +} + +void +draw_pipe(SDL_Renderer *renderer, Snake_Pos **pipe) +{ + Snake_Pos *ptr = *pipe; + + SDL_Rect pos; + while (ptr != NULL) { + pos.x = ptr->x; + pos.y = 0; + pos.w = SCREEN_UNIT; + if (ptr->x + SCREEN_UNIT > SCREEN_HEIGHT) + pos.w -= ptr->x + SCREEN_UNIT - SCREEN_HEIGHT; + pos.h = ptr->y - PIPE_GAP / 2 * SCREEN_UNIT; + SDL_RenderFillRect(renderer, &pos); + pos.y = ptr->y + PIPE_GAP / 2 * SCREEN_UNIT; + pos.h = SCREEN_HEIGHT - ptr->y - SCREEN_UNIT; + SDL_RenderFillRect(renderer, &pos); + ptr = ptr->next; + } +} |