Added font drawing support, and one font

This commit is contained in:
Bobby Lucero 2024-05-10 15:17:47 -04:00
parent 7c4c6d5bcb
commit f788fffac7
10 changed files with 263 additions and 20 deletions

View File

@ -9,6 +9,7 @@ set(FETCHCONTENT_QUIET FALSE)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples
set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games
#raylib
FetchContent_Declare( FetchContent_Declare(
raylib raylib
GIT_REPOSITORY "https://github.com/raysan5/raylib.git" GIT_REPOSITORY "https://github.com/raysan5/raylib.git"
@ -18,6 +19,10 @@ FetchContent_Declare(
FetchContent_MakeAvailable(raylib) FetchContent_MakeAvailable(raylib)
#json
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
FetchContent_MakeAvailable(json)
# Adding our source files # Adding our source files
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/sources/*.c") # Define PROJECT_SOURCES as a list of all source files file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/sources/*.c") # Define PROJECT_SOURCES as a list of all source files
set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/sources/") # Define PROJECT_INCLUDE to be the path to the include directory of the project set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/sources/") # Define PROJECT_INCLUDE to be the path to the include directory of the project
@ -34,13 +39,15 @@ add_executable(Pycron src/main.cpp
src/StateManager.h src/StateManager.h
src/State.h src/State.h
src/States/GameState.cpp src/States/GameState.cpp
src/States/GameState.h) src/States/GameState.h
src/Graphics/Font.cpp
src/Graphics/Font.h)
add_subdirectory(dependencies/pocketpy) add_subdirectory(dependencies/pocketpy)
# Declaring our executable # Declaring our executable
target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES}) target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE}) target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE})
target_link_libraries(${PROJECT_NAME} PRIVATE raylib pocketpy) target_link_libraries(${PROJECT_NAME} PRIVATE raylib nlohmann_json::nlohmann_json pocketpy)
# Setting ASSETS_PATH # Setting ASSETS_PATH

View File

@ -6,6 +6,7 @@ class Palette(Scene):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.title = "Palette"
def update(self): def update(self):
pass pass
@ -43,8 +44,8 @@ def update():
if(not scenes[current_scene].paused): if(not scenes[current_scene].paused):
scenes[current_scene].update() scenes[current_scene].update()
scenes[current_scene].draw() scenes[current_scene].draw()
text("if(x != 22.252f && y % 2 == 0) { break; }", 2, 40, 32)
text(scenes[current_scene].title, 2, 15, 63) #text("Test" + scenes[current_scene].title, 2, 15, 32)

View File

@ -50,6 +50,7 @@ class Particles(Scene):
self.waterParts.append(Particle(width/2, height/2, rnd(-1, 1), rnd(-1, 1))) self.waterParts.append(Particle(width/2, height/2, rnd(-1, 1), rnd(-1, 1)))
self.counter = 0 self.counter = 0
self.title = "Particles"
def update(self): def update(self):

View File

@ -7,7 +7,7 @@ def draw_line(x0, y0, x1, y1, c):
y0 = int(y0) y0 = int(y0)
x1 = int(x1) x1 = int(x1)
y1 = int(y1) y1 = int(y1)
"Bresenham's line algorithm"
dx = abs(x1 - x0) dx = abs(x1 - x0)
dy = abs(y1 - y0) dy = abs(y1 - y0)
x, y = x0, y0 x, y = x0, y0
@ -61,6 +61,7 @@ class Triangles(Scene):
self.count = 0 self.count = 0
self.tpo3 = (2 * 3.141592654)/3 self.tpo3 = (2 * 3.141592654)/3
self.skip = False self.skip = False
self.title = "Flying Triangles"
@ -76,7 +77,7 @@ class Triangles(Scene):
y = rnd(0, height) y = rnd(0, height)
c = 0 c = 0
if(rnd(0,9) < 5): if(rnd(0,9) < 5):
c = get_pixel(x,y-3) c = get_pixel(x -3 ,y-3)
else: else:
c = 0 c = 0

113
resources/fonts/main.font Normal file
View File

@ -0,0 +1,113 @@
{
"asciiTable": {
"1234567": "11111100010101000100010101000111111",
"32": "00000000000000000000000000000000000",
"33": "00100001000010000100001000000000100",
"34": "01010010100000000000000000000000000",
"35": "01010111110101001010111110101000000",
"36": "00100011111010001110001011111000100",
"37": "11001110010001000100010001001110011",
"38": "00100010100101001100100101001001101",
"39": "00100001000000000000000000000000000",
"40": "00100010000100001000010000100000100",
"41": "00100000100001000010000100001000100",
"42": "01010001000101000000000000000000000",
"43": "00000001000010011111001000010000000",
"44": "00000000000000000000000000010001000",
"45": "00000000000000011111000000000000000",
"46": "00000000000000000000000000000000100",
"47": "00010000100010000100001000100001000",
"48": "01110100011000110001100011000101110",
"49": "00100011000010000100001000010011111",
"50": "01110100010000100010001000100011111",
"51": "01110100010000100110000011000101110",
"52": "00010001100101010010111110001000010",
"53": "11111100001111000001000010000111110",
"54": "01110100001111010001100011000101110",
"55": "11111000010000100010000100010000100",
"56": "01110100011000101110100011000101110",
"57": "01110100011000110001011110000101110",
"58": "00000000000010000000000000010000000",
"59": "00000000000010000000000000010001000",
"60": "00000001000100010000010000010000000",
"61": "00000000001111100000111110000000000",
"62": "00000001000001000001000100010000000",
"63": "01110100010000100010001000000000100",
"64": "01111100011011110101101111000001111",
"65": "01110100011000110001111111000110001",
"66": "11110100011111010001100011000111110",
"67": "00111010001000010000100001000001111",
"68": "11100100101000110001100011000111110",
"69": "01111100001111010000100001000001111",
"70": "01111100001111010000100001000010000",
"71": "01110100011000010111100011000101110",
"72": "10001100011111110001100011000110001",
"73": "11111001000010000100001000010011111",
"74": "11111000010000100001000010001011100",
"75": "10001100011001011100100101000110001",
"76": "10000100001000010000100001000001111",
"77": "01010101011010110101101011010110001",
"78": "11100100101000110001100011000110001",
"79": "01110100011000110001100011000101110",
"80": "11110100011000110001111101000010000",
"81": "01110100011000110001101011001001101",
"82": "11110100011000110001111101000110001",
"83": "01111100001000001110000010000111110",
"84": "11111001000010000100001000010000100",
"85": "10001100011000110001100011000101110",
"86": "10001100011000110001100010101000100",
"87": "10001100011010110101101011010101010",
"88": "10001100010101000100010101000110001",
"89": "10001100011000101010001000010000100",
"90": "11111000010001000100010001000011111",
"91": "01100010000100001000010000100001100",
"92": "01000010000010000100001000001000010",
"93": "00110000100001000010000100001000110",
"94": "00100010101000100000000000000000000",
"95": "00000000000000000000000000000011111",
"96": "01000001000000000000000000000000000",
"97": "00000000000111000001011111000101111",
"98": "10000100001111010001100011000111110",
"99": "00000000000111010000100001000001110",
"100": "00001000010111110001100011000101111",
"101": "00000000000111010001111111000001110",
"102": "00000001110100011111010000100001000",
"103": "00000000000111010001011110000101110",
"104": "00000100001000011110100011000110001",
"105": "00000001000000001100001000010000100",
"106": "00000001000000001100001000010011000",
"107": "00000100001001010100110001010010010",
"108": "00000001000010000100001000010000010",
"109": "00000000001111010101101011010110101",
"110": "00000000001011011001100011000110001",
"111": "00000000000111010001100011000101110",
"112": "00000000001111010001100011111010000",
"113": "00000000000111110001100010111100001",
"114": "00000000001011011000100001000010000",
"115": "00000000000111110000011100000111110",
"116": "01000010001111001000010000100000110",
"117": "00000000001000110001100011001101101",
"118": "00000000001000110001100010101000100",
"119": "00000000001000110101101011010101010",
"120": "00000000001000101010001000101010001",
"121": "00000100011000110001011110000101110",
"122": "00000000001111100010001000100011111",
"123": "01100010000100011000010000100001100",
"124": "00100001000010000100001000010000100",
"125": "00110000100001000011000100001000110",
"126": "00000000000100010101000100000000000"
},
"height": 7,
"width": 5
}

67
src/Graphics/Font.cpp Normal file
View File

@ -0,0 +1,67 @@
//
// Created by Bobby on 5/10/2024.
//
#include "Font.h"
#include <nlohmann/json.hpp>
#include <utility>
#include <fstream>
#include <iostream>
using json = nlohmann::json;
PixelFont::PixelFont(int width, int height, std::string path) : m_width(width), m_height(height), m_filePath(std::move(path)){
std::cout << Dump() << std::endl;
ReadFontFile();
}
int PixelFont::GetWidth() {
return this->m_width;
}
int PixelFont::GetHeight() {
return this->m_height;
}
std::string PixelFont::Dump() {
json j;
j["width"] = this->m_width;
j["height"] = this->m_height;
for(const auto& pair : this->m_asciiTable){
j["asciiTable"][std::to_string(pair.first)] = pair.second;
}
return j.dump(4);
}
void PixelFont::ReadFontFile() {
std::ifstream json_file(m_filePath);
if(!json_file.is_open()){
std::cerr << "Could not open font file: " << m_filePath << std::endl;
return;
}
std::stringstream buffer;
buffer << json_file.rdbuf();
json data = json::parse(buffer.str());
this->m_width = data["width"].template get<int>();
this->m_height = data["height"].template get<int>();
json asciiJson = data["asciiTable"];
for(auto it = asciiJson.begin(); it != asciiJson.end(); ++it){
int key = std::stoi(it.key());
m_asciiTable[key] = it.value();
}
}
std::string PixelFont::GetCharData(int asciiValue) {
if(!m_asciiTable.count(asciiValue)){
return m_asciiTable[MISSING_CHAR];
}
return m_asciiTable[asciiValue];
}

25
src/Graphics/Font.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <string>
#include <cstdint>
#include <unordered_map>
class PixelFont {
private:
int m_width;
int m_height;
std::string m_filePath;
std::unordered_map<int, std::string> m_asciiTable;
const int MISSING_CHAR = 1234567;
public:
PixelFont(int width, int height, std::string path);
public:
int GetWidth();
int GetHeight();
std::string GetCharData(int asciiValue);
std::string Dump();
void ReadFontFile();
};

View File

@ -2,13 +2,18 @@
// Created by Bobby Lucero on 4/20/24. // Created by Bobby Lucero on 4/20/24.
// //
#include <fstream>
#include "Graphics.h" #include "Graphics.h"
#include "../Utilities.h" #include "../Utilities.h"
#include <raymath.h> #include <raymath.h>
#include <fstream>
Graphics::Graphics(int screenWidth, int screenHeight, int startupScale) : m_screenWidth(screenWidth), m_screenHeight(screenHeight){ Graphics::Graphics(int screenWidth, int screenHeight, int startupScale) : m_screenWidth(screenWidth), m_screenHeight(screenHeight){
m_NormalFont = new PixelFont(5, 7, "resources/fonts/main.font");
m_currentFont = m_NormalFont;
m_startupScreenWidth = screenWidth * startupScale; m_startupScreenWidth = screenWidth * startupScale;
m_startupScreenHeight = screenHeight * startupScale; m_startupScreenHeight = screenHeight * startupScale;
m_windowWidth = m_startupScreenWidth; m_windowWidth = m_startupScreenWidth;
@ -25,16 +30,19 @@ Graphics::Graphics(int screenWidth, int screenHeight, int startupScale) : m_scre
m_virtualScreenImageBuffer = GenImageColor(m_screenWidth, m_screenHeight, BLACK); m_virtualScreenImageBuffer = GenImageColor(m_screenWidth, m_screenHeight, BLACK);
m_virtualScreenColorBuffer = {}; m_virtualScreenColorBuffer = {};
m_virtualScreenColorBuffer.resize(screenWidth * screenHeight);
for (int i = 0; i < screenWidth * screenHeight; ++i) {
m_virtualScreenColorBuffer.push_back(GetRandomValue(0, 5));
}
calculateScreenPositionInWindow(); calculateScreenPositionInWindow();
}
Graphics::~Graphics() {
delete m_NormalFont;
m_NormalFont = nullptr;
m_currentFont = nullptr;
} }
void Graphics::draw(StateManager* stateManager) { void Graphics::draw(StateManager* stateManager) {
m_windowShouldClose = WindowShouldClose(); m_windowShouldClose = WindowShouldClose();
if (IsWindowResized()) { if (IsWindowResized()) {
@ -320,8 +328,19 @@ void Graphics::RectBorder(int x, int y, int width, int height, int paletteIndex)
v_line(x + width - 1, y + 1, y + height - 2, paletteIndex); v_line(x + width - 1, y + 1, y + height - 2, paletteIndex);
} }
void Graphics::Text(std::string s, int x, int y, int paletteIndex) { void Graphics::Text(const std::string& s, int x, int y, int paletteIndex) {
for (int i = 0; i < s.size(); ++i) {
char c = s[i];
std::string bitData = m_currentFont->GetCharData((int)c);
//std::cout << c << ": " << (int)c << " = " << bitData << std::endl;
for (int j = 0; j < bitData.size(); ++j) {
if(bitData[j] == '1')
Pixel(x + (j % m_currentFont->GetWidth()) + ((m_currentFont->GetWidth() + 1) * i), y + (j / m_currentFont->GetWidth()), paletteIndex);
}
}
} }
void Graphics::updateVMVars(pkpy::VM* vm) { void Graphics::updateVMVars(pkpy::VM* vm) {
@ -512,3 +531,5 @@ void Graphics::swap(float &a, float &b) {

View File

@ -2,11 +2,14 @@
#include "raylib.h" #include "raylib.h"
#include "pocketpy/vm.h" #include "pocketpy/vm.h"
#include "../StateManager.h" #include "../StateManager.h"
#include "Font.h"
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <array> #include <array>
class StateManager; class StateManager;
class Graphics { class Graphics {
@ -25,6 +28,8 @@ private:
RenderTexture2D m_virtualScreen; RenderTexture2D m_virtualScreen;
std::vector<uint8_t> m_virtualScreenColorBuffer; std::vector<uint8_t> m_virtualScreenColorBuffer;
Image m_virtualScreenImageBuffer; Image m_virtualScreenImageBuffer;
PixelFont* m_currentFont;
PixelFont* m_NormalFont;
static void swap(float &a, float &b); static void swap(float &a, float &b);
@ -35,8 +40,7 @@ private:
void h_line(int x1, int y, int x2, int paletteIndex); void h_line(int x1, int y, int x2, int paletteIndex);
void v_line(int x, int y1, int y2, int paletteIndex); void v_line(int x, int y1, int y2, int paletteIndex);
void fillBottomFlatTriangle(float x1, float y1, float x2, float y2, float x3, float y3, int paletteIndex);
void fillTopFlatTriangle(float x1, float y1, float x2, float y2, float x3, float y3, int paletteIndex);
public: public:
// virtual screen // virtual screen
int m_screenWidth = 0; int m_screenWidth = 0;
@ -52,6 +56,7 @@ public:
public: public:
Graphics(int screenWidth, int screenHeight, int startupScale); Graphics(int screenWidth, int screenHeight, int startupScale);
~Graphics();
void draw(StateManager* stateManager); void draw(StateManager* stateManager);
@ -73,7 +78,7 @@ public:
void EllipseBorder(int x, int y, int width, int height, int paletteIndex); void EllipseBorder(int x, int y, int width, int height, int paletteIndex);
void Rect(int x, int y, int width, int height, int paletteIndex); void Rect(int x, int y, int width, int height, int paletteIndex);
void RectBorder(int x, int y, int width, int height, int paletteIndex); void RectBorder(int x, int y, int width, int height, int paletteIndex);
void Text(std::string s, int x, int y, int paletteIndex); void Text(const std::string& s, int x, int y, int paletteIndex);
void Triangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, int paletteIndex); void Triangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, int paletteIndex);
int GetPixel(int x, int y); int GetPixel(int x, int y);

View File

@ -10,6 +10,12 @@ StateManager::StateManager(Pycron *pycron) : m_pycron(pycron){
RequestStateChange(GAME); RequestStateChange(GAME);
} }
StateManager::~StateManager() {
m_currentState = nullptr;
delete m_gameState;
}
void StateManager::RequestStateChange(StateManager::StateType state) { void StateManager::RequestStateChange(StateManager::StateType state) {
if(m_currentState){ if(m_currentState){
m_currentState->OnExit(); m_currentState->OnExit();
@ -47,7 +53,3 @@ void StateManager::Draw(Graphics *graphics) {
} }
} }
StateManager::~StateManager() {
m_currentState = nullptr;
delete m_gameState;
}