Getting around to cleaning drawing code finally.

This commit is contained in:
2024-10-06 16:28:34 -05:00
parent 40b0395552
commit 0224ddd36b
14 changed files with 406 additions and 156 deletions

View File

@ -0,0 +1,15 @@
# Copyright (c) 2024 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Subdirs
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
drawmap.c
drawtext.c
drawshape.c
drawui.c
)

View File

@ -0,0 +1,91 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "drawmap.h"
#include "assert/assert.h"
#include "display/symbol.h"
void drawMap(
const map_t *map,
const uint16_t cameraX,
const uint16_t cameraY,
const uint16_t drawX,
const uint16_t drawY,
const uint16_t drawWidth,
const uint16_t drawHeight
) {
assertNotNull(map, "Map cannot be NULL.");
assertTrue(drawX < FRAME_WIDTH, "Map is too far right.");
assertTrue(drawY < FRAME_HEIGHT, "Map is too far down.");
assertTrue(drawWidth > 0, "Map is too narrow.");
assertTrue(drawHeight > 0, "Map is too short.");
assertTrue(drawX + drawWidth <= FRAME_WIDTH, "Map is too wide.");
assertTrue(drawY + drawHeight <= FRAME_HEIGHT, "Map is too tall.");
entity_t *ent;
tile_t tile;
uint32_t i;
char_t *bufferDest;
uint8_t *colorDest;
// If the size of the map's smaller than the frame, center it, otherwise use
// the cameraPosition as the center point.
int16_t offsetX = 0, offsetY = 0;
if(map->width < drawWidth) {
offsetX = (drawWidth - map->width) / 2;
} else {
// Clamp to map bounds
if(cameraX < drawWidth / 2) {
offsetX = 0;
} else if(cameraX >= map->width - (drawWidth / 2)) {
offsetX = -(map->width - drawWidth);
} else {
offsetX = -(cameraX - (drawWidth / 2));
}
}
if(map->height < drawHeight) {
offsetY = (drawHeight - map->height) / 2;
} else {
// Clamp to map bounds
if(cameraY < drawHeight / 2) {
offsetY = 0;
} else if(cameraY >= map->height - (drawHeight / 2)) {
offsetY = -(map->height - drawHeight);
} else {
offsetY = -(cameraY - (drawHeight / 2));
}
}
// Draw the map
i = 0;
for(uint16_t y = 0; y < drawHeight; y++) {
bufferDest = &FRAME_BUFFER[(drawY + y) * FRAME_WIDTH + drawX];
colorDest = &FRAME_COLOR[(drawY + y) * FRAME_WIDTH + drawX];
for(uint16_t x = 0; x < drawWidth; x++) {
if(x < offsetX || y < offsetY || x >= map->width + offsetX || y >= map->height + offsetY) {
colorDest[x] = COLOR_BLACK;
bufferDest[x] = ' ';
continue;
}
// Entity?
ent = mapEntityGetByPosition(map, x - offsetX, y - offsetY);
if(ent != NULL) {
colorDest[x] = symbolGetColorByEntity(ent);
bufferDest[x] = symbolGetCharByEntity(ent);
continue;
}
// Tile?
tile = mapTileGetByPosition(map, x - offsetX, y - offsetY, 0);
colorDest[x] = symbolGetColorByTile(tile);
bufferDest[x] = symbolGetCharByTile(tile);
}
}
}

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/frame.h"
#include "rpg/world/map.h"
/**
* Draws a map to a region of the screen.
*
* @param map Map to draw.
* @param cameraX X position of the camera.
* @param cameraY Y position of the camera.
* @param drawX X position to draw the map.
* @param drawY Y position to draw the map.
* @param drawWidth Width of the map to draw.
* @param drawHeight Height of the map to draw.
*/
void drawMap(
const map_t *map,
const uint16_t cameraX,
const uint16_t cameraY,
const uint16_t drawX,
const uint16_t drawY,
const uint16_t drawWidth,
const uint16_t drawHeight
);

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "drawshape.h"
#include "assert/assert.h"
void drawClear(
const char_t c,
const uint8_t color
) {
memset(FRAME_BUFFER, c, FRAME_HEIGHT * FRAME_WIDTH);
memset(FRAME_COLOR, color, FRAME_HEIGHT * FRAME_WIDTH);
}
void drawBox(
const uint16_t x,
const uint16_t y,
const uint16_t width,
const uint16_t height,
const char_t c,
const uint8_t color
) {
assertTrue(x < FRAME_WIDTH, "Box is too far right.");
assertTrue(y < FRAME_HEIGHT, "Box is too far down.");
if(width == 0 || height == 0) return;
assertTrue(x + width <= FRAME_WIDTH, "Box is too wide.");
assertTrue(y + height <= FRAME_HEIGHT, "Box is too tall.");
if(width == FRAME_WIDTH) {
memset(&FRAME_BUFFER[y * FRAME_WIDTH + x], c, height * width);
memset(&FRAME_COLOR[y * FRAME_WIDTH + x], color, height * width);
return;
}
for(uint16_t iy = 0; iy < height; iy++) {
memset(&FRAME_BUFFER[(y + iy) * FRAME_WIDTH + x], c, width);
memset(&FRAME_COLOR[(y + iy) * FRAME_WIDTH + x], color, width);
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/frame.h"
/**
* Clears the frame buffer with a character and color.
*
* @param c Character to clear the frame buffer with.
* @param color Color to clear the frame buffer with.
*/
void drawClear(
const char_t c,
const uint8_t color
);
/**
* Draws a box to the frame buffer.
*
* @param x The x position to draw the box.
* @param y The y position to draw the box.
* @param width The width of the box.
* @param height The height of the box.
* @param c The character to draw the box with.
* @param color The color to draw the box.
*/
void drawBox(
const uint16_t x,
const uint16_t y,
const uint16_t width,
const uint16_t height,
const char_t c,
const uint8_t color
);

View File

@ -0,0 +1,26 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "drawtext.h"
#include "assert/assert.h"
void drawText(
const char_t *text,
const uint16_t x,
const uint16_t y,
const uint8_t color
) {
size_t len = strlen(text);
if(len == 0) return;
assertTrue(x + len <= FRAME_WIDTH, "Text is too long.");
assertTrue(y < FRAME_HEIGHT, "Text is too low.");
uint16_t i = y * FRAME_WIDTH + x;
memcpy(&FRAME_BUFFER[i], text, len);
memset(&FRAME_COLOR[i], color, len);
}

View File

@ -0,0 +1,24 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/frame.h"
/**
* Draws some text to the frame buffer.
*
* @param text The text to draw.
* @param x The x position to draw the text.
* @param y The y position to draw the text.
* @param color The color to draw the text.
*/
void drawText(
const char_t *text,
const uint16_t x,
const uint16_t y,
const uint8_t color
);

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "drawui.h"
#include "drawshape.h"
#include "assert/assert.h"
void drawUIBox(
const uint16_t x,
const uint16_t y,
const uint16_t width,
const uint16_t height,
const uint8_t color,
const bool_t fill
) {
assertTrue(x < FRAME_WIDTH, "Box is too far right.");
assertTrue(y < FRAME_HEIGHT, "Box is too far down.");
assertTrue(width > 2, "Box is too narrow.");
assertTrue(height > 2, "Box is too short.");
assertTrue(x + width <= FRAME_WIDTH, "Box is too wide.");
assertTrue(y + height <= FRAME_HEIGHT, "Box is too tall.");
// Draw the top and bottom borders
for(uint16_t i = 0; i < width; i++) {
FRAME_BUFFER[y * FRAME_WIDTH + x + i] = '-';
FRAME_BUFFER[(y + height - 1) * FRAME_WIDTH + x + i] = '-';
FRAME_COLOR[y * FRAME_WIDTH + x + i] = color;
FRAME_COLOR[(y + height - 1) * FRAME_WIDTH + x + i] = color;
}
// Draw the left and right borders
for(uint16_t i = 0; i < height; i++) {
FRAME_BUFFER[(y + i) * FRAME_WIDTH + x] = '|';
FRAME_BUFFER[(y + i) * FRAME_WIDTH + x + width - 1] = '|';
FRAME_COLOR[(y + i) * FRAME_WIDTH + x] = color;
FRAME_COLOR[(y + i) * FRAME_WIDTH + x + width - 1] = color;
}
// Draw the corners
FRAME_BUFFER[y * FRAME_WIDTH + x] = '+';
FRAME_BUFFER[y * FRAME_WIDTH + x + width - 1] = '+';
FRAME_BUFFER[(y + height - 1) * FRAME_WIDTH + x] = '+';
FRAME_BUFFER[(y + height - 1) * FRAME_WIDTH + x + width - 1] = '+';
FRAME_COLOR[y * FRAME_WIDTH + x] = color;
FRAME_COLOR[y * FRAME_WIDTH + x + width - 1] = color;
FRAME_COLOR[(y + height - 1) * FRAME_WIDTH + x] = color;
FRAME_COLOR[(y + height - 1) * FRAME_WIDTH + x + width - 1] = color;
// Fill the inside
if(!fill) return;
drawBox(x + 1, y + 1, width - 2, height - 2, ' ', COLOR_BLACK);
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/frame.h"
/**
* Draws a UI box to the frame buffer.
*
* @param x The x position to draw the border.
* @param y The y position to draw the border.
* @param width The width of the border.
* @param height The height of the border.
* @param color The color to draw the border.
* @param fill Whether or not to fill the inside of the border.
*/
void drawUIBox(
const uint16_t x,
const uint16_t y,
const uint16_t width,
const uint16_t height,
const uint8_t color,
const bool_t fill
);