640 lines
22 KiB
C++
640 lines
22 KiB
C++
#include "jdraw.h"
|
|
#include <SDL2/SDL.h>
|
|
#include "gif.c"
|
|
#include "jfile.h"
|
|
#include <vector>
|
|
|
|
namespace draw
|
|
{
|
|
// La idea de esta unitat es usar "superficies", que no son mes que arrays de bytes, per a anar pintant.
|
|
// El resultat final s'ha de pintar en algun moment a la superficie "screen" (o siga, especificar nullptr en setDestination)
|
|
// Aleshores, en "render" el contingut de screen se volca a la textura SDL que crearem,
|
|
// i eixa textura se pintarà a pantalla com se sol fer amb SDL. Ho anirem veient en el codi.
|
|
|
|
SDL_Window *sdl_window = nullptr; // La finestra de SDL
|
|
SDL_Renderer *sdl_renderer = nullptr; // El renderer de SDL
|
|
SDL_Texture *sdl_texture = nullptr; // La textura de SDL a la que pintarem la nostra superficie "screen" i que despres volcarem a pantalla
|
|
|
|
static int screen_zoom = 1;
|
|
static bool screen_fullscreen = false;
|
|
static int screen_width = 320;
|
|
static int screen_height = 240;
|
|
std::string screen_title = "";
|
|
|
|
surface *screen = nullptr; // La superficie screen, que representa la pantalla. Se crea i destrueix internament
|
|
surface *destination = nullptr; // Punter a la actual superficie de destí
|
|
surface *source = nullptr; // Punter a la actual superficie d'oritge
|
|
surface *pushedSource = nullptr; // Punter a la superficie d'oritge que s'ha pushat
|
|
|
|
uint32_t palette[256]; // La paleta de colors
|
|
uint8_t color_indices[256]; // Indices dels colors per defecte
|
|
uint8_t sel_color = 0; // Color seleccionat per defecte
|
|
uint8_t transparent = 0; // El color transparent
|
|
|
|
surface *textsurf = nullptr; // Surface on guardar el gif amb la font
|
|
surface *textsurf2 = nullptr; // Surface on guardar el gif amb la font gran
|
|
|
|
SDL_Rect viewport;
|
|
|
|
surface* managed[50];
|
|
int num_managed = 0;
|
|
|
|
namespace stencil
|
|
{
|
|
static bool enabled = false;
|
|
static uint8_t value = 0;
|
|
static surface *stencil = nullptr;
|
|
|
|
void init()
|
|
{
|
|
if (stencil) freeSurface(stencil);
|
|
stencil = createSurface(screen->w, screen->h);
|
|
}
|
|
|
|
void enable() { enabled = true; }
|
|
void disable() { enabled = false; }
|
|
|
|
void clear(const uint8_t val)
|
|
{
|
|
if (!enabled || !stencil) return;
|
|
memset(stencil->pixels, val, stencil->w*stencil->h);
|
|
}
|
|
|
|
void set(const uint8_t val)
|
|
{
|
|
if (!enabled || !stencil) return;
|
|
value = val;
|
|
}
|
|
|
|
const uint8_t query(const int x, const int y)
|
|
{
|
|
if (!stencil) return 0;
|
|
return stencil->pixels[x+y*stencil->w];
|
|
}
|
|
}
|
|
|
|
// Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla
|
|
void init(const std::string &titol, const uint16_t width, const uint16_t height, const int zoom, const bool fullscreen)
|
|
{
|
|
screen_title = titol;
|
|
screen_fullscreen = fullscreen;
|
|
screen_zoom = zoom;
|
|
screen_width = width;
|
|
screen_height = height;
|
|
|
|
// [TODO] Incloure gestió de pantalla completa
|
|
|
|
// Inicialització de les estructures de SDL
|
|
sdl_window = SDL_CreateWindow(screen_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width * screen_zoom, screen_height * screen_zoom, screen_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_SHOWN);
|
|
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
|
|
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);
|
|
|
|
// Establim el tamany "logic", indepndent del tamany de finestra
|
|
SDL_RenderSetLogicalSize(sdl_renderer, width, height);
|
|
|
|
// Creem la superficie "screen" i la establim com a superficie destinació
|
|
screen = createSurface(width, height);
|
|
setDestination(screen);
|
|
sel_color = transparent = 0;
|
|
for (int i=0;i<256;++i) color_indices[i] = i;
|
|
|
|
int size;
|
|
char *buffer = file::getFileBuffer("gifs.txt", size, true);
|
|
char *p = buffer;
|
|
char *n = buffer;
|
|
while (*n!=0) {
|
|
while (*n!='\n') n++;
|
|
*n=0;
|
|
loadSurface(p);
|
|
p=++n;
|
|
}
|
|
free(buffer);
|
|
|
|
textsurf = getSurface("font.gif");
|
|
textsurf2 = getSurface("font2.gif");
|
|
}
|
|
|
|
// Finalització del sistema
|
|
void quit()
|
|
{
|
|
for (int i=0; i<num_managed; ++i) if (managed[i]) freeSurface(managed[i]);
|
|
//if (textsurf) freeSurface(textsurf);
|
|
//if (textsurf2) freeSurface(textsurf2);
|
|
|
|
// Si la superficie "screen" existia, alliberem la seua memòria
|
|
if (screen != nullptr)
|
|
{
|
|
freeSurface(screen);
|
|
}
|
|
|
|
// Destruim tot el relacionat amb SDL
|
|
SDL_DestroyTexture(sdl_texture);
|
|
SDL_DestroyRenderer(sdl_renderer);
|
|
SDL_DestroyWindow(sdl_window);
|
|
|
|
// Fiquem tots els punters a nullptr, per si de cas no estem eixint del programa
|
|
// i anem a tornar a inicialitzar el sistema
|
|
sdl_window = nullptr;
|
|
sdl_renderer = nullptr;
|
|
sdl_texture = nullptr;
|
|
screen = destination = source = nullptr;
|
|
}
|
|
|
|
void reinit()
|
|
{
|
|
// Destruim tot el relacionat amb SDL
|
|
SDL_DestroyTexture(sdl_texture);
|
|
SDL_DestroyRenderer(sdl_renderer);
|
|
SDL_DestroyWindow(sdl_window);
|
|
|
|
const int zoom = screen_fullscreen ? 1 : screen_zoom;
|
|
sdl_window = SDL_CreateWindow(screen_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width * zoom, screen_height * zoom, screen_fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:SDL_WINDOW_SHOWN);
|
|
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
|
|
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height);
|
|
|
|
// Establim el tamany "logic", indepndent del tamany de finestra
|
|
SDL_RenderSetLogicalSize(sdl_renderer, screen_width, screen_height);
|
|
}
|
|
|
|
void setZoom(const int value)
|
|
{
|
|
if (value < 1) return;
|
|
|
|
SDL_DisplayMode dm;
|
|
SDL_GetCurrentDisplayMode(0, &dm);
|
|
|
|
if (screen_width*value > dm.w) return;
|
|
if (screen_height*value > dm.h) return;
|
|
|
|
screen_zoom = value;
|
|
reinit();
|
|
}
|
|
|
|
void incZoom()
|
|
{
|
|
setZoom(screen_zoom+1);
|
|
}
|
|
|
|
void decZoom()
|
|
{
|
|
setZoom(screen_zoom-1);
|
|
}
|
|
|
|
void toggleFullscreen()
|
|
{
|
|
screen_fullscreen = !screen_fullscreen;
|
|
reinit();
|
|
}
|
|
|
|
void setFullscreen(const bool value)
|
|
{
|
|
if (screen_fullscreen == value) return;
|
|
screen_fullscreen = value;
|
|
reinit();
|
|
}
|
|
|
|
const bool getFullscreen()
|
|
{
|
|
return screen_fullscreen;
|
|
}
|
|
|
|
const int getZoom()
|
|
{
|
|
return screen_zoom;
|
|
}
|
|
|
|
// Crea una superficie i torna un punter a ella
|
|
surface *createSurface(const uint16_t w, const uint16_t h)
|
|
{
|
|
// Primer reservem memòria per a la estructura "surface"
|
|
surface *surf = (surface *)malloc(sizeof(surface));
|
|
|
|
// Després reservem memòria per als pixels
|
|
surf->pixels = (uint8_t *)malloc(w * h);
|
|
|
|
// I apuntem el ample i alt de la superficie
|
|
surf->w = w;
|
|
surf->h = h;
|
|
|
|
// Es una surface nova, no ve de arxiu ni tindrà varies referències
|
|
surf->filename = nullptr;
|
|
|
|
// ...i tornem la superficie creada, clar
|
|
return surf;
|
|
}
|
|
|
|
// Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella
|
|
void loadSurface(const std::string &filename)
|
|
{
|
|
// Agafem un buffer de bytes de l'arxiu especificat
|
|
// getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
|
|
int size;
|
|
uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size);
|
|
|
|
// Si ens ha tornat nullptr, es que no l'ha trobat, tornem nosaltres també nullptr ja que no s'ha pogut crear la superficie
|
|
if (buffer == nullptr)
|
|
{
|
|
printf("ERROR: GIF no trobat: '%s'\n", filename.c_str());
|
|
exit(1);
|
|
}
|
|
|
|
// Primer reservem memòria per a la estructura "surface"
|
|
surface *surf = (surface *)malloc(sizeof(surface));
|
|
|
|
// Després li passem el buffer de bytes a la funció de carregar un GIF.
|
|
// El resultat es un array de bytes, els pixels en sí. Ja havem reservat
|
|
// la memòria necessaria en "LoadGif", així que no tenim que fer-ho ara,
|
|
// però, ojo, sí que tindrem que alliberar-la.
|
|
surf->pixels = LoadGif(buffer, &surf->w, &surf->h);
|
|
|
|
// Com ja no ens fa falta, alliberem la memòria del buffer del arxiu
|
|
free(buffer);
|
|
|
|
// Especifiquem el nom de l'arxiu del que vé i el guardem a la llista
|
|
surf->filename = (char*)malloc(filename.length()+1);
|
|
strcpy(surf->filename, filename.c_str());
|
|
managed[num_managed++] = surf;
|
|
}
|
|
|
|
void reloadSurface(surface *surf)
|
|
{
|
|
free(surf->pixels);
|
|
int size;
|
|
uint8_t *buffer = (uint8_t *)file::getFileBuffer(surf->filename, size);
|
|
surf->pixels = LoadGif(buffer, &surf->w, &surf->h);
|
|
free(buffer);
|
|
}
|
|
|
|
void reloadAll()
|
|
{
|
|
for (int i=0; i<num_managed; ++i) reloadSurface(managed[i]);
|
|
}
|
|
|
|
surface *getSurface(const std::string &filename)
|
|
{
|
|
for(int i=0; i<num_managed; ++i)
|
|
{
|
|
// Si ja existia, pujem el nombre de referències i tornem eixa surface, i au
|
|
if (strcmp(managed[i]->filename, filename.c_str())==0)
|
|
{
|
|
return managed[i];
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// Allibera la memòria d'una superficie, els seus pixels inclosos
|
|
void freeSurface(surface *surf)
|
|
{
|
|
// Si la superficie existeix...
|
|
if (surf != nullptr)
|
|
{
|
|
// Si el array de pixels existeix, l'alliberem
|
|
if (surf->pixels != nullptr)
|
|
{
|
|
free(surf->pixels);
|
|
}
|
|
|
|
// Si el nom de l'arxiu existeix, l'alliberem
|
|
if (surf->filename != nullptr)
|
|
{
|
|
free(surf->filename);
|
|
}
|
|
|
|
free(surf);
|
|
}
|
|
}
|
|
|
|
// Estableix una superficie com a superficie que rebrà les funcions de pintat (especificar nullptr per a pintar a pantalla)
|
|
void setDestination(surface *surf)
|
|
{
|
|
// Si han especificat nullptr, fiquem "screen" com a destinació
|
|
destination = surf == nullptr ? screen : surf;
|
|
resetViewport();
|
|
}
|
|
|
|
// Estableix una superficie com a superficie de la que s'agafaràn els gràfics per a pintar
|
|
void setSource(surface *surf)
|
|
{
|
|
// Si han especificat nullptr, fiquem "screen" com a font
|
|
source = surf == nullptr ? screen : surf;
|
|
}
|
|
|
|
void pushSource()
|
|
{
|
|
pushedSource = source;
|
|
}
|
|
|
|
void popSource()
|
|
{
|
|
source = pushedSource;
|
|
}
|
|
|
|
void setViewport(const int x, const int y, const int w, const int h)
|
|
{
|
|
viewport.x = x<0 ? 0 : x>=destination->w ? 0 : x;
|
|
viewport.y = y<0 ? 0 : y>=destination->h ? 0 : y;
|
|
viewport.w = w+viewport.x<destination->w ? w : destination->w-viewport.x;
|
|
viewport.h = h+viewport.y<destination->h ? h : destination->h-viewport.y;
|
|
}
|
|
|
|
void resetViewport()
|
|
{
|
|
viewport.x = viewport.y = 0;
|
|
viewport.w = destination->w;
|
|
viewport.h = destination->h;
|
|
}
|
|
|
|
const int getLocalX(const int x)
|
|
{
|
|
return x - viewport.x;
|
|
}
|
|
|
|
const int getLocalY(const int y)
|
|
{
|
|
return y - viewport.y;
|
|
}
|
|
|
|
// Estableix la paleta del sistema carregant-la d'un GIF
|
|
void loadPalette(const std::string &filename)
|
|
{
|
|
// Agafem un buffer de bytes de l'arxiu especificat
|
|
// getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
|
|
int size;
|
|
uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size);
|
|
|
|
// Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta
|
|
// Van a ser 256 entrades de 32 bits, cada entrada es un color, amb el format 0xAARRGGBB
|
|
uint32_t *pal = LoadPalette(buffer);
|
|
|
|
// Copiem eixe array al nostre array de la paleta de sistema. Ara ja tenim la paleta carregada.
|
|
memcpy(palette, pal, 1024); // 32 bits per entrada == 4 bytes x 256 entrades == 1024
|
|
|
|
// Alliberem el array que ens habia tornat LoadPalette()
|
|
free(pal);
|
|
|
|
// I també el buffer del arxiu
|
|
free(buffer);
|
|
}
|
|
|
|
void setPaletteColor(const uint8_t index, const uint8_t r, const uint8_t g, const uint8_t b)
|
|
{
|
|
palette[index] = (r<<16) + (g<<8) + b;
|
|
}
|
|
|
|
// Esborra la superficie "destination" amb el color especificat
|
|
void cls(const uint8_t color)
|
|
{
|
|
// El tamany es width x height bytes
|
|
const int size = destination->w * destination->h;
|
|
|
|
// Omplim la memòria dels pixels de la superficie de destinació amb "color"
|
|
memset(destination->pixels, color_indices[color], size);
|
|
}
|
|
|
|
//Estableix el color especificat com a transparent
|
|
void setTrans(const uint8_t color)
|
|
{
|
|
transparent = color;
|
|
}
|
|
|
|
// Funció interna per a pintar un pixel d'una superficie sense eixir-se'n de la memòria i petar el mame
|
|
void pset(surface *surface, const int x, const int y, const uint8_t color)
|
|
{
|
|
// Si el color es transparent, eixim, ni ens molestem en mirar res més
|
|
if (color == transparent) return;
|
|
|
|
// Si està fora de la surface, directament passem
|
|
if (x < 0 || y < 0 || x >= surface->w || y >= surface->h)
|
|
return;
|
|
|
|
// Si pintem a "destination", mirem que estiga dins del "viewport" i sinó fora
|
|
if (surface == destination) {
|
|
if (x+viewport.x >= 0 && y+viewport.y >= 0 && x < viewport.w && y < viewport.h)
|
|
{
|
|
surface->pixels[(viewport.x+x) + (y+viewport.y) * surface->w] = color_indices[color];
|
|
if (stencil::stencil && stencil::enabled) stencil::stencil->pixels[(viewport.x+x) + (y+viewport.y) * stencil::stencil->w] = stencil::value;
|
|
}
|
|
} else {
|
|
// Si no es destinations, pintem i au
|
|
surface->pixels[x + y * surface->w] = color_indices[color];
|
|
}
|
|
}
|
|
|
|
// Funció interna per a llegir un pixel d'una superficie sense eixir-se'n de la memòria i petar el mame
|
|
const uint8_t pget(surface *surface, const int x, const int y)
|
|
{
|
|
// Si està fora de la surface, directament passem
|
|
if (x < 0 || y < 0 || x >= surface->w || y >= surface->h)
|
|
return 0;
|
|
|
|
// Si estem llegint de "destination", mirar que estigam llegint dins del viewport
|
|
if (surface == destination) {
|
|
if (x+viewport.x >= 0 && y+viewport.y >= 0 && x < viewport.w && y < viewport.h)
|
|
return surface->pixels[(viewport.x + x) + (viewport.y + y) * surface->w];
|
|
} else {
|
|
// Si no es "destination",
|
|
return surface->pixels[x + y * surface->w];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Pinta un troç de la superficie "source" en la superficie "destination".
|
|
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int flip, int dw, int dh)
|
|
{
|
|
// Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
|
|
if (source == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (dw==0) dw = w;
|
|
if (dh==0) dh = h;
|
|
|
|
// En principi, el quadrat de l'oritge començarà en (sx,sy) i avançarem 1 pixel en positiu tant en x com en y
|
|
float sdx = float(w)/float(dw);
|
|
float sdy = float(h)/float(dh);
|
|
float ssx = sx;
|
|
float ssy = sy;
|
|
|
|
// Però si s'ha especificat que fem flip en horitzontal...
|
|
if (flip & DRAW_FLIP_HORIZONTAL)
|
|
{
|
|
sdx = -sdx; // Avançarem 1 pixel en negatiu
|
|
ssx = sx + w - 1; // I començarem al final, o siga, sumarem a sx el ample
|
|
}
|
|
|
|
// De igual forma per al flip en vertical, per a la y
|
|
if (flip & DRAW_FLIP_VERTICAL)
|
|
{
|
|
sdy = -sdy;
|
|
ssy = sy + h - 1;
|
|
}
|
|
|
|
// guardem la coordenada d'oritge en x per a restablir-la a cada linea
|
|
int csx = ssx;
|
|
|
|
// Anem linea per linea. Les variables dels dos bucles for controlen les coordenades en la destinació, que sempre van avant.
|
|
for (int y = dy; y < dy + dh; ++y)
|
|
{
|
|
ssx = csx; // fiquem la coordenada de l'oritge al principi
|
|
|
|
// en cada linea, anem pixel a pixel
|
|
for (int x = dx; x < dx + dw; ++x)
|
|
{
|
|
pset(destination, x, y, pget(source, ssx, ssy)); // Agafem pixel de l'oritge i el fiquem en la destinació
|
|
ssx += sdx; // avancem (o retrocedim) la coordenada x de l'oritge
|
|
}
|
|
ssy += sdy; // avancem (o retrocedim) la coordenada y de l'oritge
|
|
}
|
|
}
|
|
|
|
void swapcol(const Uint8 c1, const Uint8 c2)
|
|
{
|
|
color_indices[c1] = c2;
|
|
}
|
|
|
|
void restorecol(const Uint8 c)
|
|
{
|
|
color_indices[c] = c;
|
|
}
|
|
|
|
void color(const Uint8 col)
|
|
{
|
|
sel_color = col;
|
|
}
|
|
|
|
void isoline(int x, int y, const int dx, const int dy, const int len)
|
|
{
|
|
for (int i=0; i<len; ++i)
|
|
{
|
|
pset(destination, x,y, sel_color);
|
|
x+=dx;
|
|
pset(destination, x,y, sel_color);
|
|
x+=dx; y+=dy;
|
|
}
|
|
}
|
|
|
|
void hline(const int x, const int y, const int w)
|
|
{
|
|
for (int i=x;i<x+w;++i) pset(destination, i, y, sel_color);
|
|
}
|
|
|
|
void vline(const int x, const int y, const int h)
|
|
{
|
|
for (int i=y;i<y+h;++i) pset(destination, x, i, sel_color);
|
|
}
|
|
|
|
void fillrect(const int x, const int y, const int w, const int h)
|
|
{
|
|
for (int j=y;j<y+h;++j) for (int i=x;i<x+w;++i) pset(destination, i, j, sel_color);
|
|
}
|
|
|
|
void rect(const int x, const int y, const int w, const int h)
|
|
{
|
|
hline(x,y,w);
|
|
hline(x,y+h-1,w);
|
|
vline(x,y,h);
|
|
vline(x+w-1,y,h);
|
|
}
|
|
|
|
void pset(const int x, const int y, const uint8_t color)
|
|
{
|
|
pset(destination, x, y, color);
|
|
}
|
|
|
|
void print(const char* text, const int x, const int y, const Uint8 color, const Uint8 borde)
|
|
{
|
|
surface* tmp = source;
|
|
source = textsurf;
|
|
swapcol(1, color);
|
|
const int len = strlen(text);
|
|
for (int i=0;i<len;++i)
|
|
{
|
|
char chr = text[i];
|
|
if (borde!=0)
|
|
{
|
|
swapcol(1, borde);
|
|
draw(-1+x+i*4, y-1, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(x+i*4, y-1, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(1+x+i*4, y-1, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(-1+x+i*4, y, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(1+x+i*4, y, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(-1+x+i*4, y+1, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(x+i*4, y+1, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
draw(1+x+i*4, y+1, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
swapcol(1, color);
|
|
}
|
|
draw(x+i*4, y, 4, 6, (chr&15)*4, (chr>>4)*6);
|
|
}
|
|
source = tmp;
|
|
}
|
|
|
|
void print2(const char* text, const int x, const int y, const Uint8 color, const int zoom)
|
|
{
|
|
surface* tmp = source;
|
|
source = textsurf2;
|
|
swapcol(1, color);
|
|
const int len = strlen(text);
|
|
for (int i=0;i<len;++i)
|
|
{
|
|
char chr = text[i]-32;
|
|
draw((x+(i*(zoom&FONT_ZOOM_HORIZONTAL?2:1)))*8, y*8, 8, 8, (chr&15)*8, (chr>>4)*8, DRAW_FLIP_NONE,zoom&FONT_ZOOM_HORIZONTAL?16:8, zoom&FONT_ZOOM_VERTICAL?16:8);
|
|
}
|
|
source = tmp;
|
|
}
|
|
|
|
void print2(const int num, const int positions, const int x, const int y, const uint8_t color, const int zoom)
|
|
{
|
|
const char empty = positions < 0 ? '0' : ' ';
|
|
const int pos = positions < 0 ? -positions : positions;
|
|
char buffer[pos+1];
|
|
int digit = pos-1;
|
|
int value = num<0 ? -num : num;
|
|
while (digit>=0)
|
|
{
|
|
if (digit==0 && num<0) {
|
|
buffer[digit] = '-';
|
|
} else {
|
|
buffer[digit] = (value%10)==0 && digit<pos-1 ? empty : (value%10)+48;
|
|
value = value/10;
|
|
}
|
|
digit--;
|
|
}
|
|
buffer[pos]=0;
|
|
print2(buffer, x, y, color, zoom);
|
|
}
|
|
|
|
// Refresca la pantalla
|
|
void render()
|
|
{
|
|
|
|
Uint32 *sdl_pixels; // Punter al array de pixels que enstornarà SDL_LockTexture
|
|
int sdl_pitch; // Ací estarà guardat el pitch de la textura, com es de 32 bits, no m'afecta
|
|
const uint32_t size = screen->w * screen->h; // tamany de la superficie
|
|
|
|
// Bloquejem la textura SDL i agafem els seus pixels (son enters de 32 bits amb format 0xAARRGGBB)
|
|
//int result =
|
|
SDL_LockTexture(sdl_texture, NULL, (void **)&sdl_pixels, &sdl_pitch);
|
|
|
|
// Cada pixel de la superficie "screen" es un enter de 8 bits que representa un index en la paleta de colors
|
|
// Per tant, per a pintar en la textura SDL, pillem el color de la paleta que correspon al index en "screen"
|
|
// i el enviem a la textura SDL
|
|
for (uint32_t i = 0; i < size; ++i)
|
|
{
|
|
sdl_pixels[i] = palette[screen->pixels[i]];
|
|
}
|
|
|
|
// Desbloquejem la textura
|
|
SDL_UnlockTexture(sdl_texture);
|
|
|
|
// Pintem la textura a pantalla
|
|
SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
|
|
|
|
// I ho presentem
|
|
SDL_RenderPresent(sdl_renderer);
|
|
}
|
|
|
|
}
|