diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f4d93d..99ed260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,5 +47,6 @@ if(EMSCRIPTEN) endif() file(COPY ${CMAKE_SOURCE_DIR}/resources DESTINATION ${CMAKE_BINARY_DIR}) +file(COPY ${CMAKE_SOURCE_DIR}/python DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/python/main.py b/python/main.py new file mode 100644 index 0000000..e1e557f --- /dev/null +++ b/python/main.py @@ -0,0 +1,17 @@ + +i = 0 +def update(): + global i + i += 1 + clear(43) + x = sin(i * 0.071234) * 50 + 100 + y = sin(i * 0.0236) * 20 + 80 + circle(x + sin(i * 0.05) * 30, y + cos(i * 0.05) * 30, 5, 15) + circle(x + sin(i * 0.05) * 30, y + cos(i * 0.05) * 30, 3, 11) + circle(x + -sin(i * 0.05) * 30, y + -cos(i * 0.05) * 30, 5, 17) + circle(x + -sin(i * 0.05) * 30, y + -cos(i * 0.05) * 30, 3, 19) + + + +clear(44) +circle(20,30, 5, 17) diff --git a/src/Graphics/Graphics.cpp b/src/Graphics/Graphics.cpp index 3a8c87f..80aff05 100644 --- a/src/Graphics/Graphics.cpp +++ b/src/Graphics/Graphics.cpp @@ -6,6 +6,9 @@ #include "Graphics.h" #include "../Utilities.h" +std::vector Graphics::palette; + + Graphics::Graphics(int screenWidth, int screenHeight, int startupScale) : screenWidth(screenWidth), screenHeight(screenHeight){ startupScreenWidth = screenWidth * startupScale; startupScreenHeight = screenHeight * startupScale; @@ -16,11 +19,19 @@ Graphics::Graphics(int screenWidth, int screenHeight, int startupScale) : screen InitWindow(startupScreenWidth, startupScreenHeight, "test"); SetTargetFPS(60); virtualScreen = LoadRenderTexture(screenWidth, screenHeight); + virtualScreenLocalBounds = {0.0f, 0.0f, (float)virtualScreen.texture.width, -(float)virtualScreen.texture.height }; + updateFunction = nullptr; calculateScreenPositionInWindow(); + + std::cout << origin.x << " : " << origin.y << std::endl; + std::cout << virtualScreenLocalBounds.width << " : " << virtualScreenLocalBounds.height << std::endl; + std::cout << virtualScreenWindowBounds.width << " : " << virtualScreenWindowBounds.height << std::endl; + + } -void Graphics::draw() { +void Graphics::draw(pkpy::VM* vm) { windowShouldClose = WindowShouldClose(); @@ -32,18 +43,12 @@ void Graphics::draw() { BeginTextureMode(virtualScreen); ////////// - ClearBackground(palette[1]); - DrawText(("Hello World " + std::to_string(GetFPS()) + " FPS").c_str(), 5, 5, 5, RAYWHITE); - - DrawRectangle(3, 19, 33, 33, BLACK); - - for (int i = 0; i < 8; ++i) { - for (int j = 0; j < 8; ++j) { - DrawRectangle(4 + i * 4, 20 + j * 4, 3, 3, palette[i + j * 8]); - } + try{ + if(updateFunction != nullptr) + vm->call(updateFunction); + } catch(pkpy::Exception e){ + std::cout << e.summary() << std::endl; } - - DrawCircleLines(mouseX(), mouseY(),3, palette[18]); ////////// EndTextureMode(); @@ -52,7 +57,7 @@ void Graphics::draw() { void Graphics::renderVirtualScreen() { BeginDrawing(); - ClearBackground(palette[0]); + //ClearBackground(palette[16]); DrawTexturePro(virtualScreen.texture, virtualScreenLocalBounds, virtualScreenWindowBounds, origin, 0.0f, WHITE); EndDrawing(); } @@ -114,6 +119,48 @@ void Graphics::toggleFullScreen() { calculateScreenPositionInWindow(); } +void Graphics::bindMethods(pkpy::VM *vm) { + vm->bind(vm->builtins, "clear(color: int)", reinterpret_cast(Clear)); + vm->bind(vm->builtins, "pixel(x: int, y: int, color: int)", reinterpret_cast(Pixel)); + vm->bind(vm->builtins, "circle(x: int, y: int, radius: float, color: int)", reinterpret_cast(Circle)); +} + +void Graphics::Clear(pkpy::VM* vm, pkpy::ArgsView args) { + int paletteIndex = pkpy::py_cast(vm, args[0]); + if(paletteIndex < 0 || paletteIndex >= palette.size()) paletteIndex = 0; + ClearBackground(palette[paletteIndex]); +} + +void Graphics::Pixel(pkpy::VM* vm, pkpy::ArgsView args) { + int x = pkpy::py_cast(vm, args[0]); + int y = pkpy::py_cast(vm, args[1]); + int paletteIndex = pkpy::py_cast(vm, args[2]); + DrawPixel(x, y, palette[paletteIndex]); +} + +void Graphics::Circle(pkpy::VM* vm, pkpy::ArgsView args) { + float x = pkpy::py_cast(vm, args[0]); + float y = pkpy::py_cast(vm, args[1]); + float radius = pkpy::py_cast(vm, args[2]); + int paletteIndex = pkpy::py_cast(vm, args[3]); + DrawCircle(x, y, radius, palette[paletteIndex]); +} + +void Graphics::searchForDrawFunc(pkpy::VM* vm) { + updateFunction = vm->eval("update"); + if(updateFunction == nullptr){ + std::cout << "Can't find update function" << std::endl; + } +} + +void Graphics::beginDraw() { + BeginTextureMode(virtualScreen); +} + +void Graphics::endDraw() { + EndTextureMode(); +} + diff --git a/src/Graphics/Graphics.h b/src/Graphics/Graphics.h index ece4ffe..16b3bdd 100644 --- a/src/Graphics/Graphics.h +++ b/src/Graphics/Graphics.h @@ -1,5 +1,6 @@ #pragma once #include "raylib.h" +#include "pocketpy/vm.h" #include #include @@ -18,7 +19,6 @@ private: Rectangle virtualScreenLocalBounds; // virtual screen bounds RenderTexture2D virtualScreen; // actual pixel screen - std::vector palette; private: void renderVirtualScreen(); @@ -31,15 +31,32 @@ public: bool windowShouldClose; + static std::vector palette; + + pkpy::PyObject* updateFunction; + + public: Graphics(int screenWidth, int screenHeight, int startupScale); - void draw(); + void draw(pkpy::VM* vm); + + void beginDraw(); + void endDraw(); void loadPalette(std::string path); int mouseX(); int mouseY(); void toggleFullScreen(); + void bindMethods(pkpy::VM* vm); + + void searchForDrawFunc(pkpy::VM* vm); + + + static void Clear(pkpy::VM* vm, pkpy::ArgsView args); + static void Pixel(pkpy::VM* vm, pkpy::ArgsView args); + static void Circle(pkpy::VM* vm, pkpy::ArgsView args); + }; diff --git a/src/Pycron.cpp b/src/Pycron.cpp index dfe1086..0f440d2 100644 --- a/src/Pycron.cpp +++ b/src/Pycron.cpp @@ -1,10 +1,27 @@ // // Created by Bobby Lucero on 4/20/24. // +#include +#include +#include +#include #include "Pycron.h" #include "Utilities.h" #include "Graphics/Graphics.h" + +std::string loadFileToString(const std::string& filename) { + std::ifstream file(filename); // Open the file + std::stringstream buffer; // String stream to hold file content + if (file.is_open()) { // Check if file is open + buffer << file.rdbuf(); // Read the entire file into the buffer + file.close(); // Close the file + } else { + std::cerr << "Unable to open file: " << filename << std::endl; + } + return buffer.str(); // Return the content string +} + Pycron::Pycron() { SetTraceLogLevel(LOG_ERROR); @@ -13,14 +30,21 @@ Pycron::Pycron() { vm = new pkpy::VM(); + bindMethods(vm); + + graphics->bindMethods(vm); + + std::string python = loadFileToString("../python/main.py"); + + graphics->beginDraw(); try { - pkpy::CodeObject_ code = vm->compile("return 'test'", "main.py", pkpy::EXEC_MODE, false); - pkpy::PyObject* obj = vm->_exec(code, vm->_main); - - auto& str = pkpy::py_cast(vm, obj); + pkpy::CodeObject_ code = vm->compile(python, "main.py", pkpy::EXEC_MODE, false); + vm->_exec(code, vm->_main); + graphics->searchForDrawFunc(vm); }catch (pkpy::Exception e) { - + std::cout << e.summary() << std::endl; } + graphics->endDraw(); } @@ -37,6 +61,38 @@ void Pycron::StartGameLoop() { if (IsKeyPressed(KEY_F)) { graphics->toggleFullScreen(); } - graphics->draw(); + graphics->draw(vm); } -} \ No newline at end of file +} + +void Pycron::bindMethods(pkpy::VM *vm) { + vm->bind(vm->builtins, "rnd(min: int, max: int) -> int", reinterpret_cast(getRandomNumber)); + vm->bind(vm->builtins, "sin(num: float) -> float", reinterpret_cast(getSin)); + vm->bind(vm->builtins, "cos(num: float) -> float", reinterpret_cast(getCos)); +} + + +pkpy::PyObject* Pycron::getRandomNumber(pkpy::VM* vm, pkpy::ArgsView args) { + int min = pkpy::py_cast(vm, args[0]); + int max = pkpy::py_cast(vm, args[1]); + // Seed the random number generator with a random device + std::random_device rd; + std::mt19937 gen(rd()); + + // Define a uniform distribution for the range [min, max] + std::uniform_int_distribution distribution(min, max); + + // Generate a random number within the specified range + return pkpy::py_var(vm, distribution(gen)); +} + +pkpy::PyObject* Pycron::getSin(pkpy::VM* vm, pkpy::ArgsView args) { + auto num = pkpy::py_cast(vm, args[0]); + return pkpy::py_var(vm, sin(num)); +} + +pkpy::PyObject* Pycron::getCos(pkpy::VM* vm, pkpy::ArgsView args) { + auto num = pkpy::py_cast(vm, args[0]); + return pkpy::py_var(vm, cos(num)); +} + diff --git a/src/Pycron.h b/src/Pycron.h index be367bd..4247132 100644 --- a/src/Pycron.h +++ b/src/Pycron.h @@ -17,6 +17,11 @@ public: ~Pycron(); void StartGameLoop(); + void bindMethods(pkpy::VM* vm); + + static pkpy::PyObject* getRandomNumber(pkpy::VM* vm, pkpy::ArgsView args); + static pkpy::PyObject* getSin(pkpy::VM* vm, pkpy::ArgsView args); + static pkpy::PyObject* getCos(pkpy::VM* vm, pkpy::ArgsView args); };