Added buffer, reimplemented some drawing functions on cpu
This commit is contained in:
parent
b53fc267cb
commit
9e48025846
@ -5,6 +5,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "../Utilities.h"
|
#include "../Utilities.h"
|
||||||
|
#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){
|
||||||
@ -16,10 +17,19 @@ Graphics::Graphics(int screenWidth, int screenHeight, int startupScale) : m_scre
|
|||||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||||
InitWindow(m_startupScreenWidth, m_startupScreenHeight, "test");
|
InitWindow(m_startupScreenWidth, m_startupScreenHeight, "test");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
m_virtualScreen = LoadRenderTexture(screenWidth, screenHeight);
|
m_virtualScreen = LoadRenderTexture(screenWidth, screenHeight);
|
||||||
m_origin = {0,0};
|
m_origin = {0,0};
|
||||||
m_virtualScreenLocalBounds = {0.0f, 0.0f, (float)m_virtualScreen.texture.width, -(float)m_virtualScreen.texture.height };
|
m_virtualScreenLocalBounds = {0.0f, 0.0f, (float)m_virtualScreen.texture.width, (float)m_virtualScreen.texture.height };
|
||||||
m_virtualScreenWindowBounds = {0.0f, 0.0f, (float)m_windowWidth, (float)m_windowHeight};
|
m_virtualScreenWindowBounds = {0.0f, 0.0f, (float)m_windowWidth, (float)m_windowHeight};
|
||||||
|
|
||||||
|
m_virtualScreenImageBuffer = GenImageColor(m_screenWidth, m_screenHeight, BLACK);
|
||||||
|
m_virtualScreenColorBuffer = {};
|
||||||
|
|
||||||
|
for (int i = 0; i < screenWidth * screenHeight; ++i) {
|
||||||
|
m_virtualScreenColorBuffer.push_back(GetRandomValue(0, 5));
|
||||||
|
}
|
||||||
|
|
||||||
calculateScreenPositionInWindow();
|
calculateScreenPositionInWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,18 +43,26 @@ void Graphics::draw(StateManager* stateManager) {
|
|||||||
calculateScreenPositionInWindow();
|
calculateScreenPositionInWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
BeginTextureMode(m_virtualScreen);
|
|
||||||
stateManager->Draw(this);
|
stateManager->Draw(this);
|
||||||
|
copyBufferToGPU();
|
||||||
EndTextureMode();
|
|
||||||
|
|
||||||
renderVirtualScreen();
|
renderVirtualScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::copyBufferToGPU() {
|
||||||
|
Color* pixel_data = LoadImageColors(m_virtualScreenImageBuffer);
|
||||||
|
for (int i = 0; i < m_screenWidth * m_screenHeight; ++i) {
|
||||||
|
pixel_data[i] = GetColor(m_paletteByID[m_virtualScreenColorBuffer[i]]);
|
||||||
|
}
|
||||||
|
UpdateTexture(m_virtualScreen.texture, pixel_data);
|
||||||
|
UnloadImageColors(pixel_data);
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::renderVirtualScreen() {
|
void Graphics::renderVirtualScreen() {
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(BLACK);
|
ClearBackground(BLACK);
|
||||||
DrawTexturePro(m_virtualScreen.texture, m_virtualScreenLocalBounds, m_virtualScreenWindowBounds, m_origin, 0.0f, WHITE);
|
DrawTexturePro(m_virtualScreen.texture, m_virtualScreenLocalBounds, m_virtualScreenWindowBounds, m_origin, 0.0f, WHITE);
|
||||||
|
DrawText(std::to_string(GetFPS()).c_str(), 10, 10, 30, YELLOW);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,32 +182,131 @@ void Graphics::bindMethods(pkpy::VM *vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Clear(int paletteIndex) {
|
void Graphics::Clear(int paletteIndex) {
|
||||||
if(paletteIndex < 0 || paletteIndex >= m_paletteByID.size()) paletteIndex = 0;
|
for (int y = 0; y < m_screenHeight; ++y) {
|
||||||
ClearBackground(GetColor(m_paletteByID[paletteIndex]));
|
for (int x = 0; x < m_screenWidth; ++x) {
|
||||||
|
Pixel(x, y, paletteIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Pixel(int x, int y, int paletteIndex) {
|
void Graphics::Pixel(int x, int y, int paletteIndex) {
|
||||||
DrawPixel(x, y, GetColor(m_paletteByID[paletteIndex]));
|
paletteIndex = Clamp(paletteIndex, 0, m_paletteByID.size() - 1);
|
||||||
|
if(x < 0 || y < 0 || x >= m_screenWidth || y >= m_screenHeight) return;
|
||||||
|
|
||||||
|
m_virtualScreenColorBuffer[y * m_screenWidth + x] = paletteIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Circle(int x, int y, int radius, int paletteIndex) {
|
void Graphics::Circle(int x, int y, int radius, int paletteIndex) {
|
||||||
DrawCircle(x, y, radius, GetColor(m_paletteByID[paletteIndex]));
|
Ellipse(x, y, radius, radius, paletteIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::Ellipse(int x, int y, int w, int h, int paletteIndex){
|
||||||
|
|
||||||
|
int x0 = x - w;
|
||||||
|
int y0 = y - h;
|
||||||
|
int x1 = x + w;
|
||||||
|
int y1 = y + h;
|
||||||
|
|
||||||
|
if(x0 > x1 || y0 > y1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int a = abs(x1 - x0), b = abs(y1 - y0), b1 = b & 1;
|
||||||
|
int dx = 4 * (1 - a) * b * b, dy = 4 * (b1 + 1) * a * a;
|
||||||
|
int err = dx + dy + b1 * a * a, e2;
|
||||||
|
|
||||||
|
if (x0 > x1) { x0 = x1; x1 += a; }
|
||||||
|
if (y0 > y1) y0 = y1;
|
||||||
|
y0 += (b + 1) / 2; y1 = y0 - b1;
|
||||||
|
a *= 8 * a; b1 = 8 * b * b;
|
||||||
|
|
||||||
|
int prevY = y0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Pixel( x1, y0, paletteIndex);
|
||||||
|
Pixel( x0, y0, paletteIndex);
|
||||||
|
Pixel( x0, y1, paletteIndex);
|
||||||
|
Pixel( x1, y1, paletteIndex);
|
||||||
|
if(y0 != prevY && (y0 - y) != h){
|
||||||
|
h_line(x1, y0, x - (x1 - x) + 1, paletteIndex);
|
||||||
|
h_line(x1, y - (y0 - y), x - (x1 - x) + 1, paletteIndex);
|
||||||
|
}
|
||||||
|
prevY = y0;
|
||||||
|
e2 = 2 * err;
|
||||||
|
if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
|
||||||
|
if (e2 >= dx || 2 * err > dy) { x0++; x1--; err += dx += b1; } /* x step */
|
||||||
|
} while (x0 <= x1);
|
||||||
|
|
||||||
|
while (y0-y1 < b)
|
||||||
|
{ /* too early stop of flat ellipses a=1 */
|
||||||
|
Pixel( x0 - 1, y0, paletteIndex); /* -> finish tip of ellipse */
|
||||||
|
Pixel( x1 + 1, y0++, paletteIndex);
|
||||||
|
Pixel( x0 - 1, y1, paletteIndex);
|
||||||
|
Pixel( x1 + 1, y1--, paletteIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h_line(x - w, y, x + w, paletteIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::EllipseBorder(int x, int y, int w, int h, int paletteIndex){
|
||||||
|
|
||||||
|
int x0 = x - w;
|
||||||
|
int y0 = y - h;
|
||||||
|
int x1 = x + w;
|
||||||
|
int y1 = y + h;
|
||||||
|
|
||||||
|
if(x0 > x1 || y0 > y1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int a = abs(x1 - x0), b = abs(y1 - y0), b1 = b & 1;
|
||||||
|
int dx = 4 * (1 - a) * b * b, dy = 4 * (b1 + 1) * a * a;
|
||||||
|
int err = dx + dy + b1 * a * a, e2;
|
||||||
|
|
||||||
|
if (x0 > x1) { x0 = x1; x1 += a; }
|
||||||
|
if (y0 > y1) y0 = y1;
|
||||||
|
y0 += (b + 1) / 2; y1 = y0 - b1;
|
||||||
|
a *= 8 * a; b1 = 8 * b * b;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Pixel( x1, y0, paletteIndex);
|
||||||
|
Pixel( x0, y0, paletteIndex);
|
||||||
|
Pixel( x0, y1, paletteIndex);
|
||||||
|
Pixel( x1, y1, paletteIndex);
|
||||||
|
|
||||||
|
e2 = 2 * err;
|
||||||
|
if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
|
||||||
|
if (e2 >= dx || 2 * err > dy) { x0++; x1--; err += dx += b1; } /* x step */
|
||||||
|
} while (x0 <= x1);
|
||||||
|
|
||||||
|
while (y0-y1 < b)
|
||||||
|
{ /* too early stop of flat ellipses a=1 */
|
||||||
|
Pixel( x0 - 1, y0, paletteIndex); /* -> finish tip of ellipse */
|
||||||
|
Pixel( x1 + 1, y0++, paletteIndex);
|
||||||
|
Pixel( x0 - 1, y1, paletteIndex);
|
||||||
|
Pixel( x1 + 1, y1--, paletteIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Graphics::Rect(int x, int y, int width, int height, int paletteIndex) {
|
void Graphics::Rect(int x, int y, int width, int height, int paletteIndex) {
|
||||||
DrawRectangle(x, y, width, height, GetColor(m_paletteByID[paletteIndex]));
|
for (int i = 0; i < height; ++i) {
|
||||||
|
h_line(x, y + i, x + width - 1, paletteIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::RectBorder(int x, int y, int width, int height, int paletteIndex) {
|
||||||
|
h_line(x, y, x + width - 1, paletteIndex);
|
||||||
|
h_line(x, y + height - 1, x + width - 1, paletteIndex);
|
||||||
|
v_line(x, 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(std::string s, int x, int y, int paletteIndex) {
|
||||||
DrawText(s.c_str(), x, y, 5, GetColor(m_paletteByID[paletteIndex]));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::beginDraw() {
|
|
||||||
BeginTextureMode(m_virtualScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::endDraw() {
|
|
||||||
EndTextureMode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::updateVMVars(pkpy::VM* vm) {
|
void Graphics::updateVMVars(pkpy::VM* vm) {
|
||||||
@ -199,6 +316,35 @@ void Graphics::updateVMVars(pkpy::VM* vm) {
|
|||||||
vm->builtins->attr().set("height", pkpy::py_var(vm, m_screenHeight));
|
vm->builtins->attr().set("height", pkpy::py_var(vm, m_screenHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::h_line(int x1, int y, int x2, int paletteIndex) {
|
||||||
|
if(y < 0 || y >= m_screenHeight) return;
|
||||||
|
int startX = x1;
|
||||||
|
int endX = x2;
|
||||||
|
if(x1 > x2){
|
||||||
|
startX = x2;
|
||||||
|
endX = x1;
|
||||||
|
}
|
||||||
|
for (int i = startX; i <= endX; ++i) {
|
||||||
|
Pixel(i, y, paletteIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::v_line(int x, int y1, int y2, int paletteIndex) {
|
||||||
|
if(x < 0 || x >= m_screenWidth) return;
|
||||||
|
int startY = y1;
|
||||||
|
int endY = y2;
|
||||||
|
if(y1 > y2){
|
||||||
|
startY = y2;
|
||||||
|
endY = y1;
|
||||||
|
}
|
||||||
|
for (int i = startY; i <= endY; ++i) {
|
||||||
|
Pixel(x, i, paletteIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
class StateManager;
|
class StateManager;
|
||||||
|
|
||||||
@ -21,13 +22,18 @@ private:
|
|||||||
Rectangle m_virtualScreenWindowBounds; // size of rect texture on window
|
Rectangle m_virtualScreenWindowBounds; // size of rect texture on window
|
||||||
Vector2 m_origin; // position of rect texture on window
|
Vector2 m_origin; // position of rect texture on window
|
||||||
Rectangle m_virtualScreenLocalBounds; // virtual screen bounds
|
Rectangle m_virtualScreenLocalBounds; // virtual screen bounds
|
||||||
RenderTexture2D m_virtualScreen; // actual pixel screen
|
RenderTexture2D m_virtualScreen;
|
||||||
|
std::vector<uint8_t> m_virtualScreenColorBuffer;
|
||||||
|
Image m_virtualScreenImageBuffer;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderVirtualScreen();
|
void renderVirtualScreen();
|
||||||
void calculateScreenPositionInWindow();
|
void calculateScreenPositionInWindow();
|
||||||
|
|
||||||
|
void h_line(int x1, int y, int x2, int paletteIndex);
|
||||||
|
void v_line(int x, int y1, int y2, int paletteIndex);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// virtual screen
|
// virtual screen
|
||||||
int m_screenWidth = 0;
|
int m_screenWidth = 0;
|
||||||
@ -46,8 +52,7 @@ public:
|
|||||||
|
|
||||||
void draw(StateManager* stateManager);
|
void draw(StateManager* stateManager);
|
||||||
|
|
||||||
void beginDraw();
|
void copyBufferToGPU();
|
||||||
void endDraw();
|
|
||||||
|
|
||||||
void updateVMVars(pkpy::VM* vm);
|
void updateVMVars(pkpy::VM* vm);
|
||||||
|
|
||||||
@ -61,7 +66,10 @@ public:
|
|||||||
void Clear(int paletteIndex);
|
void Clear(int paletteIndex);
|
||||||
void Pixel(int x, int y, int paletteIndex);
|
void Pixel(int x, int y, int paletteIndex);
|
||||||
void Circle(int x, int y, int radius, int paletteIndex);
|
void Circle(int x, int y, int radius, int paletteIndex);
|
||||||
|
void Ellipse(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 Text(std::string s, int x, int y, int paletteIndex);
|
void Text(std::string s, int x, int y, int paletteIndex);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,14 +20,11 @@ void StateManager::RequestStateChange(StateManager::StateType state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(m_currentState){
|
if(m_currentState){
|
||||||
// Game state needs ability to draw during code loading
|
|
||||||
if(m_currentState == m_gameState){
|
if(m_currentState == m_gameState){
|
||||||
m_pycron->m_graphics->beginDraw();
|
|
||||||
m_currentState->OnEnter();
|
m_currentState->OnEnter();
|
||||||
if(m_gameState->m_errorThrown){
|
if(m_gameState->m_errorThrown){
|
||||||
m_pycron->m_graphics->Text(m_gameState->m_previousError, 2, 2, 59);
|
m_pycron->m_graphics->Text(m_gameState->m_previousError, 2, 2, 59);
|
||||||
}
|
}
|
||||||
m_pycron->m_graphics->endDraw();
|
|
||||||
}else{
|
}else{
|
||||||
m_currentState->OnEnter();
|
m_currentState->OnEnter();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user