aboutsummaryrefslogblamecommitdiffstats
path: root/src/renderer.c
blob: 16948cb0d2629e13f31312479e90b696f58672ba (plain) (tree)
1
2
  
                                                 

















































































































































































































































                                                                           
/*
 * Copyright (c) 2019-2021, 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;
	}
}