StateManager and States now have their own reference to Graphics instead of being passed into Draw(), Added image class and test images

Image class is just array of palette indices converted from the rgb data of any image by using euclidian distance between palette rgb and pixel rgb. Works well.
This commit is contained in:
Xenthera 2024-05-22 16:09:19 -04:00
parent 798ac17939
commit e23be1cd58
20 changed files with 99 additions and 31 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ cmake-build-debug
.vscode .vscode
cmake-build-release cmake-build-release
build build
.DS_Store

View File

@ -43,7 +43,9 @@ add_executable(Pycron src/main.cpp
src/Graphics/Font.cpp src/Graphics/Font.cpp
src/Graphics/Font.h src/Graphics/Font.h
src/States/EditorState.cpp src/States/EditorState.cpp
src/States/EditorState.h) src/States/EditorState.h
src/Graphics/PycronImage.h
src/Graphics/PycronImage.cpp)
add_subdirectory(dependencies/pocketpy) add_subdirectory(dependencies/pocketpy)
# Declaring our executable # Declaring our executable

BIN
resources/Sprite-0001.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
resources/pc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
resources/plane.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
resources/plane2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

BIN
resources/rgb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

View File

@ -3,10 +3,15 @@
// //
#include "Graphics.h" #include "Graphics.h"
#include "PycronImage.h"
#include "Font.h"
#include "../Utilities.h" #include "../Utilities.h"
#include <raymath.h>
#include "../StateManager.h" #include "../StateManager.h"
#include <fstream> #include <fstream>
#include <raymath.h>
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){
@ -51,7 +56,7 @@ void Graphics::draw(StateManager* stateManager) {
calculateScreenPositionInWindow(); calculateScreenPositionInWindow();
} }
stateManager->Draw(this); stateManager->Draw();
copyBufferToGPU(); copyBufferToGPU();
renderVirtualScreen(); renderVirtualScreen();
} }
@ -540,6 +545,30 @@ void Graphics::Triangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t
} }
PycronImage* Graphics::loadImage(std::string path) {
Image img = LoadImage(path.c_str());
ImageRotateCW(&img);
ImageFlipHorizontal(&img);
if(img.width == 0 && img.height == 0) std::cerr << "Image at path " << path << " is empty\n";
Color* colors = LoadImageColors(img);
auto* idImg = new PycronImage(img.width, img.height);
for (int i = 0; i < idImg->data.size(); ++i) {
if(colors[i].a == 0){
idImg->data[i] = -1;
}else{
idImg->data[i] = (int8_t)rgbToID(colors[i].r, colors[i].g, colors[i].b);
}
}
return idImg;
}
void Graphics::Img(PycronImage* img, int x, int y) {
for (int i = 0; i < img->data.size(); ++i) {
if(img->data[i] == -1) continue;
Pixel(x + i / img->width, y + i % img->width, img->data[i]);
}
}

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "raylib.h" #include "raylib.h"
#include "pocketpy/vm.h" #include "pocketpy/vm.h"
#include "Font.h"
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
@ -10,6 +9,8 @@
class StateManager; class StateManager;
class PycronImage;
class PixelFont;
class Graphics { class Graphics {
@ -46,18 +47,18 @@ public:
std::unordered_map<unsigned int, unsigned int> m_paletteByID; // <id, hex color> std::unordered_map<unsigned int, unsigned int> m_paletteByID; // <id, hex color>
public: public:
Graphics(int screenWidth, int screenHeight, int startupScale); Graphics(int screenWidth, int screenHeight, int startupScale);
~Graphics(); ~Graphics();
void draw(StateManager* stateManager); void draw(StateManager* stateManager);
int rgbToID(int r, int g, int b); int rgbToID(int r, int g, int b);
void copyBufferToGPU(); void copyBufferToGPU();
PycronImage* loadImage(std::string path);
void updateVMVars(pkpy::VM* vm); void updateVMVars(pkpy::VM* vm);
void loadPalette(std::string path); void loadPalette(std::string path);
@ -76,7 +77,7 @@ public:
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(const 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);
void Img(PycronImage* img, int x, int y);
int GetPixel(int x, int y); int GetPixel(int x, int y);

View File

@ -0,0 +1,8 @@
//
// Created by Bobby Lucero on 5/22/24.
//
#include "PycronImage.h"
PycronImage::PycronImage(int width, int height) : width(width), height(height), data(width * height) {
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <vector>
struct PycronImage {
int width;
int height;
std::vector<int8_t> data;
PycronImage(int width, int height);
};

View File

@ -32,7 +32,7 @@ Pycron::Pycron() {
m_graphics->loadPalette("resources/thecosmos.hex"); m_graphics->loadPalette("resources/thecosmos.hex");
m_graphics->bindMethods(m_vm); m_graphics->bindMethods(m_vm);
m_graphics->updateVMVars(m_vm); m_graphics->updateVMVars(m_vm);
m_stateManager = new StateManager(this); m_stateManager = new StateManager(this, m_graphics);

View File

@ -8,7 +8,7 @@ protected:
State(){} State(){}
public: public:
virtual ~State() = default; virtual ~State() = default;
virtual void Draw(Graphics* graphics) = 0; virtual void Draw() = 0;
virtual void OnEnter() = 0; virtual void OnEnter() = 0;
virtual void OnExit() = 0; virtual void OnExit() = 0;
virtual void onKeyPressed(int key) = 0; virtual void onKeyPressed(int key) = 0;

View File

@ -4,9 +4,9 @@
#include "StateManager.h" #include "StateManager.h"
StateManager::StateManager(Pycron *pycron) : m_pycron(pycron){ StateManager::StateManager(Pycron *pycron, Graphics *graphics) : m_pycron(pycron){
m_gameState = new GameState(m_pycron->m_vm); m_gameState = new GameState(m_pycron->m_vm, graphics);
m_editorState = new EditorState(m_pycron->m_vm); m_editorState = new EditorState(m_pycron->m_vm, graphics);
m_currentState = nullptr; m_currentState = nullptr;
RequestStateChange(GAME); RequestStateChange(GAME);
} }
@ -14,6 +14,8 @@ StateManager::StateManager(Pycron *pycron) : m_pycron(pycron){
StateManager::~StateManager() { StateManager::~StateManager() {
m_currentState = nullptr; m_currentState = nullptr;
delete m_gameState; delete m_gameState;
delete m_editorState;
delete m_graphics;
} }
@ -40,7 +42,7 @@ void StateManager::RequestStateChange(StateManager::StateType state) {
} }
} }
void StateManager::Draw(Graphics *graphics) { void StateManager::Draw() {
if(IsKeyPressed(KEY_ENTER)){ if(IsKeyPressed(KEY_ENTER)){
if(m_currentState == m_gameState){ if(m_currentState == m_gameState){
@ -56,11 +58,11 @@ void StateManager::Draw(Graphics *graphics) {
m_pycron->m_graphics->Text(m_gameState->m_previousError, 2, 2, 59); m_pycron->m_graphics->Text(m_gameState->m_previousError, 2, 2, 59);
} }
else{ else{
m_currentState->Draw(graphics); m_currentState->Draw();
} }
} }
else{ else{
m_currentState->Draw(graphics); m_currentState->Draw();
} }
} }
} }

View File

@ -22,10 +22,11 @@ private:
Pycron* m_pycron; Pycron* m_pycron;
GameState* m_gameState; GameState* m_gameState;
EditorState* m_editorState; EditorState* m_editorState;
Graphics* m_graphics;
public: public:
explicit StateManager(Pycron* pycron); explicit StateManager(Pycron* pycron, Graphics* graphics);
~StateManager(); ~StateManager();
void RequestStateChange(StateType state); void RequestStateChange(StateType state);
@ -34,7 +35,7 @@ public:
void RequestRunGame(); void RequestRunGame();
void RequestStopGame(); void RequestStopGame();
void Draw(Graphics* graphics); void Draw();
}; };

View File

@ -3,21 +3,28 @@
// //
#include "EditorState.h" #include "EditorState.h"
#include "../Graphics/PycronImage.h"
EditorState::EditorState(pkpy::VM *vm) : m_vm(vm){ EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphics(graphics){
test = m_graphics->loadImage("resources/plane2.png");
} }
void EditorState::Draw(Graphics *graphics) { EditorState::~EditorState() {
graphics->Clear(1); delete test;
}
void EditorState::Draw() {
m_graphics->Clear(1);
std::string text = "Editor State"; std::string text = "Editor State";
graphics->Text(text, graphics->m_screenWidth / 2 - (text.size() / 2 * 6), graphics->m_screenHeight / 2 - (7 / 2), 5); m_graphics->Text(text, m_graphics->m_screenWidth / 2 - (text.size() / 2 * 6), m_graphics->m_screenHeight / 2 - (7 / 2), 5);
for (int y = 0; y < 128; ++y) { for (int y = 0; y < 128; ++y) {
for (int x = 0; x < 128; ++x) { for (int x = 0; x < 128; ++x) {
int c = x; int c = x;
graphics->Pixel(x, y, graphics->rgbToID(x * 2, y * 2, graphics->mouseX())); m_graphics->Pixel(x, y, m_graphics->rgbToID(x * 2, y * 2, m_graphics->mouseX()));
} }
} }
std::cout << test->width << "\n";
m_graphics->Img(test, m_graphics->mouseX() - (test->height / 2), m_graphics->mouseY() - (test->width / 2));
} }
void EditorState::OnEnter() { void EditorState::OnEnter() {

View File

@ -1,18 +1,23 @@
#pragma once #pragma once
#include "../State.h" #include "../State.h"
class PycronImage;
class EditorState : public State{ class EditorState : public State{
public: public:
EditorState(pkpy::VM* vm); EditorState(pkpy::VM* vm, Graphics* graphics);
~EditorState();
void Draw(Graphics* graphics) override; void Draw() override;
void OnEnter() override; void OnEnter() override;
void OnExit() override; void OnExit() override;
void onKeyPressed(int key) override; void onKeyPressed(int key) override;
private: private:
pkpy::VM* m_vm; pkpy::VM* m_vm;
PycronImage* test;
Graphics* m_graphics;
}; };

View File

@ -8,12 +8,12 @@
#include <filesystem> #include <filesystem>
#include "../Pycron.h" #include "../Pycron.h"
GameState::GameState(pkpy::VM* vm) :m_vm(vm){ GameState::GameState(pkpy::VM* vm, Graphics* graphics) :m_vm(vm), m_graphics(graphics){
m_updateFunction = nullptr; m_updateFunction = nullptr;
m_previousError = ""; m_previousError = "";
} }
void GameState::Draw(Graphics *graphics) { void GameState::Draw() {
try{ try{
if(m_updateFunction != nullptr){ if(m_updateFunction != nullptr){
m_vm->call(m_updateFunction); m_vm->call(m_updateFunction);

View File

@ -9,9 +9,9 @@ public:
std::string m_previousError; std::string m_previousError;
bool m_errorThrown = false; bool m_errorThrown = false;
GameState(pkpy::VM* vm); GameState(pkpy::VM* vm, Graphics* graphics);
void Draw(Graphics* graphics) override; void Draw() override;
void OnEnter() override; void OnEnter() override;
void OnExit() override; void OnExit() override;
void onKeyPressed(int key) override; void onKeyPressed(int key) override;
@ -20,7 +20,7 @@ private:
pkpy::VM* m_vm; pkpy::VM* m_vm;
pkpy::PyObject* m_updateFunction; pkpy::PyObject* m_updateFunction;
Graphics* m_graphics;
std::unordered_map<std::string, std::string> readPythonFiles(const std::string& dir); std::unordered_map<std::string, std::string> readPythonFiles(const std::string& dir);
void loadPythonModules(std::unordered_map<std::string, std::string>& fileContents); void loadPythonModules(std::unordered_map<std::string, std::string>& fileContents);