- No se, molts canvis i coses
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
libs = -lSDL3 -lGL
|
||||
libs = -lSDL3
|
||||
cppflags = -g
|
||||
executable = dilemmaker
|
||||
sourcepath = source source/japi
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
#include "enemies.h"
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace enemies
|
||||
{
|
||||
std::unordered_map<std::string, enemy_t> enemies;
|
||||
|
||||
inline void trim(std::string& s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
||||
}
|
||||
|
||||
void processKeyValue(const std::string& enemy_name, const std::string& section, const std::string& key, const std::string& value)
|
||||
{
|
||||
enemy_t& enemy = enemies[enemy_name];
|
||||
|
||||
if (section == "global") {
|
||||
if (key == "tileSetFile") {
|
||||
enemy.tileSetFile = images::getImage("enemies/"+value);
|
||||
} else if (key == "frame_width") {
|
||||
enemy.frame_width = std::stoi(value);
|
||||
} else if (key == "frame_height") {
|
||||
enemy.frame_height = std::stoi(value);
|
||||
}
|
||||
} else if (section == "animation") {
|
||||
if (key == "name") {
|
||||
enemy.animations.back().name = value;
|
||||
printf("animacio '%s' frames: ", value.c_str());
|
||||
} else if (key == "loop") {
|
||||
enemy.animations.back().loop = std::stoi(value);
|
||||
} else if (key == "speed") {
|
||||
enemy.animations.back().speed = std::stof(value);
|
||||
} else if (key == "frames") {
|
||||
std::stringstream ss(value);
|
||||
std::string frame;
|
||||
while (std::getline(ss, frame, ',')) {
|
||||
if (!frame.empty()) {
|
||||
enemy.animations.back().frames.emplace_back(std::stoi(frame));
|
||||
printf("%s,", frame.c_str());
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loadEnemy(fs::path filename)
|
||||
{
|
||||
std::string enemy_name = filename.stem().string();
|
||||
|
||||
std::ifstream file(filename);
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open file.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string current_section = "global";
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
//std::cout << "'" << line << "'\n";
|
||||
// Trim and clean line, ignore empty lines and comments
|
||||
trim(line);
|
||||
if (line.empty() || line[0] == '#') continue;
|
||||
|
||||
// Remove inline comments
|
||||
/*std::size_t comment_pos = line.find('#');
|
||||
if (comment_pos != std::string::npos) {
|
||||
line = line.substr(0, comment_pos);
|
||||
trim(line);
|
||||
}*/
|
||||
|
||||
// Check if entering or exiting a section
|
||||
if (line[0] == '[')
|
||||
{
|
||||
std::size_t closing_pos = line.find(']');
|
||||
if (closing_pos != std::string::npos && closing_pos > 1)
|
||||
{
|
||||
std::string section = line.substr(1,closing_pos-1);
|
||||
if (section[0] == '/') {
|
||||
current_section = "global";
|
||||
} else {
|
||||
current_section = section;
|
||||
if (section == "animation") enemies[enemy_name].animations.emplace_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get and process key/value
|
||||
std::size_t eq_pos = line.find('=');
|
||||
if (eq_pos != std::string::npos) {
|
||||
std::string key = line.substr(0, eq_pos);
|
||||
std::string value = line.substr(eq_pos + 1);
|
||||
trim(key);
|
||||
trim(value);
|
||||
processKeyValue(enemy_name, current_section, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
// Get all enemies
|
||||
fs::path target_dir = "./data/enemies";
|
||||
std::vector<fs::path> enemy_files;
|
||||
|
||||
try {
|
||||
for (const auto& entry : fs::directory_iterator(target_dir)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".ani") {
|
||||
enemy_files.push_back(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& path : enemy_files) {
|
||||
std::cout << "Processing " << path.filename() << '\n';
|
||||
loadEnemy(path);
|
||||
}
|
||||
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
std::cerr << "Filesystem error: " << e.what() << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enemy_t &get(std::string name)
|
||||
{
|
||||
return enemies[name];
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
#include "images.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace enemies
|
||||
{
|
||||
struct animation_t
|
||||
{
|
||||
std::string name {""};
|
||||
float speed {0.0f};
|
||||
uint8_t loop {0};
|
||||
std::vector<uint8_t> frames;
|
||||
};
|
||||
|
||||
struct enemy_t
|
||||
{
|
||||
draw::surface *tileSetFile {nullptr};
|
||||
uint8_t frame_width {0};
|
||||
uint8_t frame_height {0};
|
||||
std::vector<animation_t> animations;
|
||||
};
|
||||
|
||||
void load();
|
||||
enemy_t &get(std::string name);
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#include "images.h"
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace images
|
||||
{
|
||||
std::map<std::string, draw::surface*> images;
|
||||
|
||||
draw::surface *getImage(std::string filename)
|
||||
{
|
||||
auto item = images.find(filename);
|
||||
if (item != images.end()) return item->second;
|
||||
|
||||
draw::surface *image = draw::loadSurface(filename.c_str());
|
||||
images[filename] = image;
|
||||
return image;
|
||||
}
|
||||
|
||||
int loadPalette(std::string filename)
|
||||
{
|
||||
uint32_t palette[16];
|
||||
|
||||
FILE *file = fopen(filename.c_str(), "r");
|
||||
if (!file) return -1;
|
||||
|
||||
char header[32];
|
||||
int version, count;
|
||||
|
||||
// Read and validate header
|
||||
if (!fgets(header, sizeof(header), file) || strncmp(header, "JASC-PAL", 8) != 0) {
|
||||
fclose(file);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (fscanf(file, "%d\n%d\n", &version, &count) != 2 || count != 16) {
|
||||
fclose(file);
|
||||
return -3;
|
||||
}
|
||||
|
||||
// Read 16 RGB triplets
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
int r, g, b;
|
||||
if (fscanf(file, "%d %d %d\n", &r, &g, &b) != 3) {
|
||||
fclose(file);
|
||||
return -4;
|
||||
}
|
||||
palette[i] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
draw::setPalette(palette, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "japi/draw.h"
|
||||
#include <string>
|
||||
|
||||
namespace images
|
||||
{
|
||||
draw::surface *getImage(std::string filename);
|
||||
int loadPalette(std::string filename);
|
||||
}
|
||||
@@ -2,88 +2,16 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include "gif.h"
|
||||
#include "file.h"
|
||||
//#include "shader.h"
|
||||
|
||||
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
|
||||
//SDL_Texture *sdl_shadertex {nullptr}; // La textura de SDL per al shader
|
||||
SDL_Texture *sdl_source {nullptr};
|
||||
|
||||
static int screen_zoom = 1;
|
||||
static bool screen_fullscreen = false;
|
||||
static bool screen_cursor = true;
|
||||
static char* screen_shader = nullptr;
|
||||
static bool shader_enabled = false;
|
||||
static float window_ratio = 1;
|
||||
static int canvas_width;
|
||||
static int canvas_height;
|
||||
static int desktop_width;
|
||||
static int desktop_height;
|
||||
static int window_width;
|
||||
static int window_height;
|
||||
static int offset_x = 0;
|
||||
static int offset_y = 0;
|
||||
char window_title[256];
|
||||
|
||||
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 *pushed_source {nullptr}; // Punter a la superficie d'oritge que s'ha pushat
|
||||
|
||||
uint32_t palette[256]; // La paleta de colors
|
||||
uint32_t aux_palette[256]; // La paleta de colors, para els fadein
|
||||
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
|
||||
|
||||
SDL_Rect viewport;
|
||||
|
||||
bool fading_out = false;
|
||||
bool fading_in = false;
|
||||
|
||||
void createDisplay()
|
||||
void init(const char *titol, const uint16_t width, const uint16_t height)
|
||||
{
|
||||
// Ajustem el zoom i el ratio, per si tenen valors locs
|
||||
if (screen_zoom <= 0) screen_zoom = 1;
|
||||
if (window_ratio <= 0) window_ratio = 1;
|
||||
|
||||
// Ajustem el tamany de la finestra, segons el zoom i el ratio
|
||||
window_width = canvas_width*screen_zoom;
|
||||
window_height = window_ratio != 1 ? int(float(canvas_width)*window_ratio*float(screen_zoom)) : canvas_height*screen_zoom;
|
||||
|
||||
// Mentres no càpiga en la pantalla, reduïm el zoom
|
||||
while (window_width > desktop_width || window_height > desktop_height) {
|
||||
screen_zoom--;
|
||||
window_width = canvas_width*screen_zoom;
|
||||
window_height = window_ratio != 1 ? int(float(canvas_width)*window_ratio*float(screen_zoom)) : canvas_height*screen_zoom;
|
||||
}
|
||||
|
||||
if (screen_fullscreen) {
|
||||
if (desktop_width * window_ratio > desktop_height) {
|
||||
offset_y = 0;
|
||||
window_height = desktop_height;
|
||||
window_width = desktop_height/window_ratio;
|
||||
offset_x = (desktop_width - window_width)/2;
|
||||
} else {
|
||||
offset_x = 0;
|
||||
window_width = desktop_width;
|
||||
window_height = desktop_width*window_ratio;
|
||||
offset_y = (desktop_height - window_height)/2;
|
||||
}
|
||||
} else {
|
||||
offset_x = offset_y = 0;
|
||||
}
|
||||
|
||||
sdl_window = SDL_CreateWindow(window_title, window_width, window_height, SDL_WINDOW_OPENGL|(screen_fullscreen?SDL_WINDOW_FULLSCREEN:0));
|
||||
sdl_window = SDL_CreateWindow(titol, width, height, SDL_WINDOW_RESIZABLE);
|
||||
if (!sdl_window) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize window!\n");
|
||||
exit(1);
|
||||
@@ -94,432 +22,123 @@ namespace draw
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize renderer!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor();
|
||||
|
||||
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, canvas_width, canvas_height);
|
||||
SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST);
|
||||
if (!sdl_texture) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize texture!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// sdl_shadertex = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, window_width, window_height);
|
||||
// SDL_SetTextureScaleMode(sdl_shadertex, SDL_SCALEMODE_NEAREST);
|
||||
|
||||
// loadShader();
|
||||
//SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
void destroyDisplay()
|
||||
{
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
SDL_DestroyRenderer(sdl_renderer);
|
||||
SDL_DestroyWindow(sdl_window);
|
||||
}
|
||||
|
||||
// Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla
|
||||
void init(const char *titol, const uint16_t width, const uint16_t height, const int zoom, const bool fullscreen, const float ratio)
|
||||
{
|
||||
screen_zoom = file::getConfigValueInteger("zoom", zoom);
|
||||
screen_fullscreen = file::getConfigValueBool("fullscreen", fullscreen);
|
||||
window_ratio = ratio;
|
||||
canvas_width = width;
|
||||
canvas_height = height;
|
||||
strcpy(window_title, titol);
|
||||
|
||||
const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay());
|
||||
if (!dm)
|
||||
{
|
||||
SDL_Log("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
desktop_width = dm->w;
|
||||
desktop_height = dm->h;
|
||||
|
||||
createDisplay();
|
||||
// Inicialització de les estructures de SDL
|
||||
/*
|
||||
sdl_window = SDL_CreateWindow(titol, width * zoom, height * zoom, 0);
|
||||
if (!sdl_window) {
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize window!\n");
|
||||
exit(1);
|
||||
}
|
||||
sdl_renderer = SDL_CreateRenderer(sdl_window, NULL);
|
||||
if (!sdl_renderer) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize renderer!\n");
|
||||
exit(1);
|
||||
}
|
||||
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST);
|
||||
if (!sdl_texture) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize texture!\n");
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
// Creem la superficie "screen" i la establim com a superficie destinació
|
||||
screen = createSurface(width, height);
|
||||
destination = screen;
|
||||
viewport.x = viewport.y = 0;
|
||||
viewport.w = width;
|
||||
viewport.h = height;
|
||||
sel_color = transparent = 0;
|
||||
for (int i=0;i<256;++i) color_indices[i] = i;
|
||||
|
||||
//SDL_HideCursor();
|
||||
//textsurf = loadSurface("font.gif");
|
||||
}
|
||||
|
||||
// Finalització del sistema
|
||||
void quit()
|
||||
{
|
||||
//if (textsurf) freeSurface(textsurf);
|
||||
SDL_DestroyRenderer(sdl_renderer);
|
||||
SDL_DestroyWindow(sdl_window);
|
||||
|
||||
// Si la superficie "screen" existia, alliberem la seua memòria
|
||||
if (screen != nullptr)
|
||||
{
|
||||
freeSurface(screen);
|
||||
}
|
||||
|
||||
// Destruim tot el relacionat amb SDL
|
||||
destroyDisplay();
|
||||
|
||||
// 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 setZoom(const int value) {
|
||||
screen_zoom = value;
|
||||
destroyDisplay();
|
||||
createDisplay();
|
||||
file::setConfigValueInteger("zoom", screen_zoom);
|
||||
}
|
||||
|
||||
const int getZoom()
|
||||
SDL_Texture *createSurface(const uint16_t w, const uint16_t h)
|
||||
{
|
||||
return screen_zoom;
|
||||
return SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
}
|
||||
|
||||
const float getScaleX()
|
||||
SDL_Texture *loadSurface(const char *filename, const int transparent)
|
||||
{
|
||||
return float(window_width) / float(canvas_width);
|
||||
}
|
||||
int size;
|
||||
uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size);
|
||||
if (buffer == nullptr) return nullptr;
|
||||
|
||||
const float getScaleY()
|
||||
{
|
||||
return float(window_height) / float(canvas_height);
|
||||
}
|
||||
uint16_t w, h;
|
||||
uint8_t *pixels = LoadGif(buffer, &w, &h);
|
||||
|
||||
const int getOffsetX()
|
||||
{
|
||||
return offset_x;
|
||||
}
|
||||
int paletteSize;
|
||||
uint32_t *pal = LoadPalette(buffer, &paletteSize);
|
||||
|
||||
const int getOffsetY()
|
||||
{
|
||||
return offset_y;
|
||||
}
|
||||
SDL_Texture *surf = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h);
|
||||
SDL_SetTextureBlendMode(surf, SDL_BLENDMODE_BLEND);
|
||||
|
||||
bool getFullscreen() {
|
||||
return screen_fullscreen;
|
||||
}
|
||||
Uint32 *sdl_pixels;
|
||||
int sdl_pitch;
|
||||
|
||||
void setFullscreen(const bool value) {
|
||||
screen_fullscreen=value;
|
||||
destroyDisplay();
|
||||
createDisplay();
|
||||
file::setConfigValueBool("fullscreen", screen_fullscreen);
|
||||
}
|
||||
SDL_LockTexture(surf, NULL, (void **)&sdl_pixels, &sdl_pitch);
|
||||
for (uint32_t i = 0; i < w*h; ++i) sdl_pixels[i] = transparent==pixels[i] ? 0x00000000 : pal[pixels[i]] | 0xff000000;
|
||||
SDL_UnlockTexture(surf);
|
||||
|
||||
void hideCursor()
|
||||
{
|
||||
screen_cursor = false;
|
||||
SDL_HideCursor();
|
||||
}
|
||||
free(pal);
|
||||
free(pixels);
|
||||
free(buffer);
|
||||
|
||||
void showCursor()
|
||||
{
|
||||
screen_cursor = true;
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// ...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
|
||||
surface *loadSurface(const char *filename, const bool loadPalette)
|
||||
void freeSurface(SDL_Texture *surf)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Si li havem dit que carregue també la paleta...
|
||||
if (loadPalette)
|
||||
{
|
||||
// Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta
|
||||
// Van a ser com a molt 256 entrades de 32 bits (pero no sempre), cada entrada es un color, amb el format 0xAARRGGBB
|
||||
int paletteSize;
|
||||
uint32_t *pal = LoadPalette(buffer, &paletteSize);
|
||||
|
||||
// Copiem eixe array al nostre array de la paleta de sistema. Ara ja tenim la paleta carregada.
|
||||
for (int i=0;i<256;++i) {
|
||||
palette[i] = i<paletteSize ? pal[i] : 0;
|
||||
}
|
||||
//memset(palette, 0, 1024); // Fiquem tot a 0, que la paleta potser no es de 256 i quedaria basura
|
||||
//memcpy(palette, pal, paletteSize*4); // 32 bits per entrada == 4 bytes x 'paletteSize' entrades
|
||||
|
||||
// Alliberem el array que ens habia tornat LoadPalette()
|
||||
free(pal);
|
||||
}
|
||||
|
||||
// Com ja no ens fa falta, alliberem la memòria del buffer del arxiu
|
||||
free(buffer);
|
||||
|
||||
// I finalment tornem la superficie
|
||||
return surf;
|
||||
SDL_DestroyTexture(surf);
|
||||
}
|
||||
|
||||
// Allibera la memòria d'una superficie, els seus pixels inclosos
|
||||
void freeSurface(surface *surf)
|
||||
void setDestination(SDL_Texture *surf)
|
||||
{
|
||||
// Si la superficie existeix...
|
||||
if (surf != nullptr)
|
||||
{
|
||||
// Si el array de pixels existeix, l'alliberem
|
||||
if (surf->pixels != nullptr)
|
||||
{
|
||||
free(surf->pixels);
|
||||
}
|
||||
|
||||
// ... alliberem la superficie
|
||||
free(surf);
|
||||
}
|
||||
SDL_SetRenderTarget(sdl_renderer, surf);
|
||||
}
|
||||
|
||||
// Estableix una superficie com a superficie que rebrà les funcions de pintat (especificar nullptr per a pintar a pantalla)
|
||||
void setDestination(surface *surf)
|
||||
void setSource(SDL_Texture *surf)
|
||||
{
|
||||
// Si han especificat nullptr, fiquem "screen" com a destinació
|
||||
destination = surf == nullptr ? screen : surf;
|
||||
resetViewport();
|
||||
sdl_source = surf;
|
||||
}
|
||||
|
||||
// Estableix una superficie com a superficie de la que s'agafaràn els gràfics per a pintar
|
||||
void setSource(surface *surf)
|
||||
|
||||
void setClip(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
// Si han especificat nullptr, fiquem "screen" com a font
|
||||
source = surf == nullptr ? screen : surf;
|
||||
SDL_Rect rect {x, y, w, h};
|
||||
SDL_SetRenderClipRect(sdl_renderer, &rect);
|
||||
}
|
||||
|
||||
void pushSource()
|
||||
void resetClip()
|
||||
{
|
||||
pushed_source = source;
|
||||
SDL_SetRenderClipRect(sdl_renderer, nullptr);
|
||||
}
|
||||
|
||||
void popSource()
|
||||
SDL_Point getWindowSize()
|
||||
{
|
||||
source = pushed_source;
|
||||
}
|
||||
|
||||
void setViewport(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
viewport.x = x>0?x:0;
|
||||
viewport.y = y>0?y:0;
|
||||
viewport.w = w+x<destination->w?w:destination->w;
|
||||
viewport.h = h+y<destination->h?h:destination->h;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Carrega la paleta d'un GIF i la torna en un array de uint32_t
|
||||
uint32_t *loadPalette(const char *filename, int *paletteSize)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// I també el buffer del arxiu
|
||||
free(buffer);
|
||||
|
||||
if (paletteSize) *paletteSize = size;
|
||||
return pal;
|
||||
}
|
||||
|
||||
// Estableix la paleta del sistema, o part de ella, des d'un array especificat
|
||||
void setPalette(const uint32_t *pal, const int len, const int pos)
|
||||
{
|
||||
for (int i=0; i<len; ++i)
|
||||
{
|
||||
palette[i+pos] = pal[i];
|
||||
}
|
||||
}
|
||||
|
||||
//Recupera la paleta del sistema, o part de ella, a un array
|
||||
uint32_t *getPalette()
|
||||
{
|
||||
uint32_t *p = (uint32_t*)malloc(256*sizeof(uint32_t));
|
||||
for (int i=0; i<256; ++i) p[i] = palette[i];
|
||||
SDL_Point p;
|
||||
SDL_GetWindowSize(sdl_window, &p.x, &p.y);
|
||||
return p;
|
||||
}
|
||||
|
||||
// Estableix una entrada de la paleta del sistema
|
||||
void setPaletteEntry(const uint8_t index, const uint8_t r, const uint8_t g, const uint8_t b)
|
||||
void setColor(const uint32_t col)
|
||||
{
|
||||
palette[index] = (r << 16) + (g << 8) + b;
|
||||
SDL_SetRenderDrawColor(sdl_renderer, (col>>16)&0xff, (col>>8)&0xff, (col)&0xff, (col>>24)&0xff);
|
||||
}
|
||||
|
||||
// Esborra la superficie "destination" amb el color especificat
|
||||
void cls(const uint8_t color)
|
||||
void cls(const uint32_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, size);
|
||||
setColor(color);
|
||||
SDL_RenderClear(sdl_renderer);
|
||||
}
|
||||
|
||||
//Estableix el color especificat com a transparent
|
||||
void setTrans(const uint8_t color)
|
||||
void line(const int x1, const int y1, const int x2, const int y2)
|
||||
{
|
||||
transparent = color;
|
||||
SDL_RenderLine(sdl_renderer, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
// 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)
|
||||
void fillrect(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
// Si el color es transparent, eixim, ni ens molestem en mirar res més
|
||||
if (color == transparent) 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];
|
||||
} else {
|
||||
// Si no es destinations, mirem que estiga dins de la surface, i sinó fora!
|
||||
if (x >= 0 && y >= 0 && x < surface->w && y < surface->h)
|
||||
surface->pixels[x + y * surface->w] = color_indices[color];
|
||||
}
|
||||
SDL_FRect rect {float(x), float(y), float(w),float(h)};
|
||||
SDL_RenderFillRect(sdl_renderer, &rect);
|
||||
}
|
||||
|
||||
// Funció interna per a llegir un pixel d'una superficie eixir-se'n de la memòria i petar el mame
|
||||
const uint8_t pget(surface *surface, const int x, const int y)
|
||||
void rect(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
// 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", si la coordenada està dins del rang que abarca la superficie,
|
||||
if (x >= 0 && y >= 0 && x < surface->w && y < surface->h)
|
||||
return surface->pixels[x + y * surface->w];
|
||||
}
|
||||
|
||||
return 0;
|
||||
SDL_FRect rect {float(x), float(y), float(w),float(h)};
|
||||
SDL_RenderRect(sdl_renderer, &rect);
|
||||
}
|
||||
|
||||
void putPixel(const int x, const int y, const uint8_t color)
|
||||
void draw(const SDL_Rect source, const SDL_Rect dest, const SDL_FlipMode flip)
|
||||
{
|
||||
pset(screen, x, y, color);
|
||||
}
|
||||
|
||||
// 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 draw::flip flip)
|
||||
{
|
||||
// Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
|
||||
if (source == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
int sdx = 1, sdy = 1, ssx = sx, ssy = sy;
|
||||
|
||||
// Però si s'ha especificat que fem flip en horitzontal...
|
||||
if (flip & draw::flip::horizontal)
|
||||
{
|
||||
sdx = -1; // 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 = -1;
|
||||
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 + h; ++y)
|
||||
{
|
||||
ssx = csx; // fiquem la coordenada de l'oritge al principi
|
||||
|
||||
// en cada linea, anem pixel a pixel
|
||||
for (int x = dx; x < dx + w; ++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
|
||||
}
|
||||
if (!sdl_source) return;
|
||||
SDL_FRect src {float(source.x), float(source.y), float(source.w),float(source.h)};
|
||||
SDL_FRect dst {float(dest.x), float(dest.y), float(dest.w),float(dest.h)};
|
||||
SDL_RenderTextureRotated(sdl_renderer, sdl_source, &src, &dst, 0.0, nullptr, flip);
|
||||
}
|
||||
|
||||
/*
|
||||
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int zoom)
|
||||
{
|
||||
// Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
|
||||
@@ -549,137 +168,16 @@ namespace draw
|
||||
}
|
||||
|
||||
// Carrega la superficie especificada en "source" i la pinta tota en la superficie "destination", posició (0,0).
|
||||
void draw(draw::surface* surf)
|
||||
void draw(SDL_Texture* surf)
|
||||
{
|
||||
setSource(surf);
|
||||
draw();
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
bool decPalEntry(const uint8_t index, const uint8_t val)
|
||||
{
|
||||
const uint32_t entry = palette[index];
|
||||
uint8_t r = (entry >> 16) & 0xff;
|
||||
uint8_t g = (entry >> 8) & 0xff;
|
||||
uint8_t b = entry & 0xff;
|
||||
|
||||
r = r>=val ? r-val : 0;
|
||||
g = g>=val ? g-val : 0;
|
||||
b = b>=val ? b-val : 0;
|
||||
palette[index] = (r << 16) + (g << 8) + b;
|
||||
|
||||
return palette[index] != 0;
|
||||
}
|
||||
|
||||
bool incPalEntry(const uint8_t index, const uint8_t val)
|
||||
{
|
||||
const uint32_t entry = palette[index];
|
||||
uint8_t r = (entry >> 16) & 0xff;
|
||||
uint8_t g = (entry >> 8) & 0xff;
|
||||
uint8_t b = entry & 0xff;
|
||||
|
||||
const uint32_t dest_entry = aux_palette[index];
|
||||
const uint8_t dr = (dest_entry >> 16) & 0xff;
|
||||
const uint8_t dg = (dest_entry >> 8) & 0xff;
|
||||
const uint8_t db = dest_entry & 0xff;
|
||||
|
||||
r = (r+val > dr) ? dr : r+val;
|
||||
g = (g+val > dg) ? dg : g+val;
|
||||
b = (b+val > db) ? db : b+val;
|
||||
palette[index] = (r << 16) + (g << 8) + b;
|
||||
|
||||
return palette[index] != aux_palette[index];
|
||||
}
|
||||
|
||||
void fadein()
|
||||
{
|
||||
if (!fading_in) {
|
||||
for (int i=0;i<256;++i) {
|
||||
aux_palette[i] = palette[i];
|
||||
palette[i] = 0;
|
||||
}
|
||||
}
|
||||
fading_in = false;
|
||||
for (int i=0; i<256; ++i) if (incPalEntry(i, 8)) fading_in = true;
|
||||
}
|
||||
|
||||
void fadeout()
|
||||
{
|
||||
fading_out = false;
|
||||
for (int i=0; i<256; ++i) if (decPalEntry(i, 8)) fading_out = true;
|
||||
}
|
||||
|
||||
bool isfading()
|
||||
{
|
||||
return fading_in || fading_out;
|
||||
}
|
||||
*/
|
||||
|
||||
// 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
|
||||
|
||||
if (fading_in) fadein();
|
||||
if (fading_out) fadeout();
|
||||
|
||||
// Bloquejem la textura SDL i agafem els seus pixels (son enters de 32 bits amb format 0xAARRGGBB)
|
||||
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]] | 0xff000000;
|
||||
}
|
||||
|
||||
// Desbloquejem la textura
|
||||
SDL_UnlockTexture(sdl_texture);
|
||||
|
||||
SDL_SetRenderTarget(sdl_renderer, nullptr);
|
||||
// Pintem la textura a pantalla
|
||||
SDL_RenderTexture(sdl_renderer, sdl_texture, NULL, NULL);
|
||||
|
||||
// I ho presentem
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,158 +1,36 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
//#define DRAW_FLIP_NONE 0
|
||||
//#define DRAW_FLIP_HORIZONTAL 1
|
||||
//#define DRAW_FLIP_VERTICAL 2
|
||||
//#define DRAW_FLIP_BOTH 3
|
||||
|
||||
// Unitat per a la gestió dels recursos gràfics i dibuixat en pantalla
|
||||
namespace draw
|
||||
{
|
||||
enum flip { none, horizontal, vertical, both };
|
||||
|
||||
// Estructura per a mantindre una superficie de pintat, la "pantalla virtual" de tota la vida
|
||||
struct surface
|
||||
{
|
||||
uint16_t w; // Ample de la superficie
|
||||
uint16_t h; // Alt de la superficie
|
||||
uint8_t *pixels; // pixels de la superficie
|
||||
};
|
||||
|
||||
/// @brief Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla.
|
||||
/// @brief La finestra serà width*zoom x height*zoom de gran.
|
||||
/// @param titol es el text que apareixerà en la finestra
|
||||
/// @param width es el ample de la finestra "virtual"
|
||||
/// @param height es el alt de la finestra "virtual"
|
||||
/// @param zoom es com de grans son els pixels.
|
||||
void init(const char *titol, const uint16_t width, const uint16_t height, const int zoom, const bool fullscreen=false, const float ratio=1.0);
|
||||
|
||||
/// @brief Finalització del sistema (tancar coses de SDL, superficies fixes, etc...)
|
||||
void init(const char *titol, const uint16_t width, const uint16_t height);
|
||||
void quit();
|
||||
|
||||
void setZoom(const int value);
|
||||
const int getZoom();
|
||||
const float getScaleX();
|
||||
const float getScaleY();
|
||||
const int getOffsetX();
|
||||
const int getOffsetY();
|
||||
SDL_Texture *createSurface(const uint16_t w, const uint16_t h);
|
||||
SDL_Texture *loadSurface(const char* filename, const int transparent = -1);
|
||||
void freeSurface(SDL_Texture *surf);
|
||||
void setDestination(SDL_Texture *surf);
|
||||
void setSource(SDL_Texture *surf);
|
||||
|
||||
bool getFullscreen();
|
||||
void setFullscreen(const bool value);
|
||||
void setClip(const int x, const int y, const int w, const int h);
|
||||
void resetClip();
|
||||
|
||||
void hideCursor();
|
||||
void showCursor();
|
||||
SDL_Point getWindowSize();
|
||||
|
||||
/// @brief Crea una superficie i torna un punter a ella
|
||||
/// @param w ample de la superficie
|
||||
/// @param h alt de la superficie
|
||||
/// @return un punter a una nova superficie
|
||||
surface *createSurface(const uint16_t w, const uint16_t h);
|
||||
|
||||
/// @brief Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella
|
||||
/// @param filename nom de l'arxiu GIF d'on carregar la superficie
|
||||
/// @param loadPalette si es true també se carrega la paleta del GIF
|
||||
/// @return un punter a una nova superficie
|
||||
surface *loadSurface(const char* filename, const bool loadPalette = false);
|
||||
|
||||
/// @brief Allibera la memòria d'una superficie, els seus pixels inclosos
|
||||
/// @param surf punter a la superficie a alliberar
|
||||
void freeSurface(surface *surf);
|
||||
|
||||
/// @brief Estableix una superficie com a superficie que rebrà les funcions de pintat (especificar nullptr per a pintar a pantalla)
|
||||
/// @param surf punter a la superficie a establir com a destinació
|
||||
void setDestination(surface *surf);
|
||||
|
||||
/// @brief Estableix una superficie com a superficie de la que s'agafaràn els gràfics per a pintar
|
||||
/// @param surf punter a la superficie a establir com a oritge
|
||||
void setSource(surface *surf);
|
||||
|
||||
void pushSource();
|
||||
void popSource();
|
||||
|
||||
void setViewport(const int x, const int y, const int w, const int h);
|
||||
void resetViewport();
|
||||
|
||||
const int getLocalX(const int x);
|
||||
const int getLocalY(const int y);
|
||||
|
||||
/// @brief Carrega la paleta d'un GIF i la torna en un array de uint32_t
|
||||
/// @param filename nom de l'arxiu GIF d'on carregar la paleta
|
||||
/// @param paletteSize si no es NULL ens torna el tamany de la paleta carregada
|
||||
uint32_t *loadPalette(const char *filename, int *paletteSize = nullptr);
|
||||
|
||||
/// @brief Estableix la paleta del sistema, o part de ella, des d'un array especificat
|
||||
/// @param pal un array de uint32_t
|
||||
/// @param len quantes entrades volem trasladar a la paleta de sistema (no superar el tamany de 'pal'!)
|
||||
/// @param pos des de quina posició de la paleta de sistema comencem a copiar
|
||||
void setPalette(const uint32_t *pal, const int len, const int pos=0);
|
||||
|
||||
/// @brief Recupera la paleta del sistema, o part de ella, a un array
|
||||
/// @return un array de uint32_t
|
||||
uint32_t *getPalette();
|
||||
|
||||
/// @brief Estableix una entrada de la paleta del sistema
|
||||
/// @param index l'index de l'entrada de la paleta
|
||||
/// @param r la component roja de l'entrada de la paleta
|
||||
/// @param g la component verda de l'entrada de la paleta
|
||||
/// @param b la component blava de l'entrada de la paleta
|
||||
void setPaletteEntry(const uint8_t index, const uint8_t r, const uint8_t g, const uint8_t b);
|
||||
|
||||
/// @brief Esborra la superficie "destination" amb el color especificat
|
||||
/// @param color color a usar per a borrar la superficie de destinació
|
||||
void cls(const uint8_t color);
|
||||
|
||||
/// @brief Estableix el color especificat com a transparent
|
||||
/// @param color color a usar com a transparent
|
||||
void setTrans(const uint8_t color);
|
||||
|
||||
void putPixel(const int x, const int y, const uint8_t color);
|
||||
|
||||
/// @brief Pinta un troç de la superficie "source" en la superficie "destination".
|
||||
/// @param dx coordenada x de la destinació
|
||||
/// @param dy coordenada y de la destinació
|
||||
/// @param w ample del quadrat a pintar
|
||||
/// @param h alt del quadrat a pintar
|
||||
/// @param sx coordenada x de l'oritge
|
||||
/// @param sy coordenada y de l'oritge
|
||||
/// @param flip si s'ha de fer flip en hortizontal o vertical (o ambdos)
|
||||
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const draw::flip flip = draw::flip::none);
|
||||
|
||||
/// @brief Pinta un troç de la superficie "source" en la superficie "destination", amb zoom.
|
||||
/// @param dx coordenada x de la destinació
|
||||
/// @param dy coordenada y de la destinació
|
||||
/// @param w ample del quadrat d'oritge a pintar
|
||||
/// @param h alt del quadrat d'oritge a pintar
|
||||
/// @param sx coordenada x de l'oritge
|
||||
/// @param sy coordenada y de l'oritge
|
||||
/// @param zoom zoom a aplicar al pintar
|
||||
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int zoom);
|
||||
|
||||
/// @brief Pinta tota la superficie "source" en la superficie "destination", posició (x,y).
|
||||
/// @param x coordenada x de la destinació
|
||||
/// @param y coordenada y de la destinació
|
||||
void draw(const int x, const int y);
|
||||
|
||||
/// @brief Pinta tota la superficie "source" en la superficie "destination", posició (0,0).
|
||||
void draw();
|
||||
|
||||
/// @brief Carrega la superficie especificada en "source" i la pinta tota en la superficie "destination", posició (0,0).
|
||||
void draw(draw::surface* surf);
|
||||
|
||||
void swapcol(const uint8_t c1, const uint8_t c2);
|
||||
void restorecol(const uint8_t c);
|
||||
void color(const uint8_t col);
|
||||
void hline(const int x, const int y, const int w);
|
||||
void vline(const int x, const int y, const int h);
|
||||
void setColor(const uint32_t col);
|
||||
void cls(const uint32_t color);
|
||||
void line(const int x1, const int y1, const int x2, const int y2);
|
||||
void fillrect(const int x, const int y, const int w, const int h);
|
||||
void rect(const int x, const int y, const int w, const int h);
|
||||
|
||||
void fadein();
|
||||
void fadeout();
|
||||
bool isfading();
|
||||
void draw(const SDL_Rect source, const SDL_Rect dest, const SDL_FlipMode flip = SDL_FLIP_NONE);
|
||||
//void draw(const int x, const int y);
|
||||
//void draw();
|
||||
//void draw(SDL_Texture* surf);
|
||||
|
||||
|
||||
//void print(const char* text, const int x, const int y, const uint8_t color, const uint8_t borde);
|
||||
|
||||
/// @brief Refresca la pantalla
|
||||
void render();
|
||||
}
|
||||
|
||||
73
source/japi/font.cpp
Normal file
73
source/japi/font.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "font.h"
|
||||
#include "draw.h"
|
||||
#include "file.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace font
|
||||
{
|
||||
SDL_Texture *surf {nullptr};
|
||||
char spaces[127];
|
||||
int pos = 30;
|
||||
int chars_per_line = 0;
|
||||
|
||||
void load(const char* filename)
|
||||
{
|
||||
char font_filename[256];
|
||||
strcpy(font_filename, filename);
|
||||
strcat(font_filename, ".txt");
|
||||
|
||||
int filesize;
|
||||
char *buffer = file::getFileBuffer(font_filename, filesize, true);
|
||||
char *p = buffer;
|
||||
|
||||
pos = 30;
|
||||
bool eof = false;
|
||||
while (true) {
|
||||
if (*p=='#') while (*p!=0 && *p!=10) p++;
|
||||
if (*p==0) break;
|
||||
p++;
|
||||
spaces[pos++] = (*p)-48;
|
||||
if (pos==127) break;
|
||||
p++;
|
||||
if (*p==0) break;
|
||||
p++;
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
char gif_filename[256];
|
||||
strcpy(gif_filename, filename);
|
||||
strcat(gif_filename, ".gif");
|
||||
surf = draw::loadSurface(gif_filename, 0);
|
||||
}
|
||||
|
||||
void printChar(const char c, int x, int y)
|
||||
{
|
||||
const int w = spaces[30];
|
||||
const int h = spaces[31];
|
||||
const int chars_per_line = (surf->w/w);
|
||||
const int sx = ((c-32) % chars_per_line)*8;
|
||||
const int sy = ((c-32) / chars_per_line)*8;
|
||||
//printf("char %i, sx:%i, sy:%i\n", c, sx, sy);
|
||||
draw::draw({sx, sy, spaces[c], h}, {x, y, spaces[c], h});
|
||||
}
|
||||
|
||||
void print(const char* text, int x, int y)
|
||||
{
|
||||
draw::setSource(surf);
|
||||
while(*text) {
|
||||
printChar(*text, x, y);
|
||||
x += spaces[*text]+1;
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
const int len(const char *text)
|
||||
{
|
||||
int l = 0;
|
||||
while (*text) {
|
||||
l += spaces[*text]+1;
|
||||
text++;
|
||||
}
|
||||
return l-1;
|
||||
}
|
||||
}
|
||||
8
source/japi/font.h
Normal file
8
source/japi/font.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
namespace font
|
||||
{
|
||||
void load(const char* filename);
|
||||
void print(const char* text, int x, int y);
|
||||
const int len(const char *text);
|
||||
}
|
||||
@@ -84,19 +84,19 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (e.type==SDL_EVENT_KEY_UP)
|
||||
{
|
||||
switch (e.key.scancode) {
|
||||
case SDL_SCANCODE_F1:
|
||||
draw::setZoom(draw::getZoom()-1);
|
||||
break;
|
||||
case SDL_SCANCODE_F2:
|
||||
draw::setZoom(draw::getZoom()+1);
|
||||
break;
|
||||
case SDL_SCANCODE_F3:
|
||||
draw::setFullscreen(!draw::getFullscreen());
|
||||
break;
|
||||
default:
|
||||
// switch (e.key.scancode) {
|
||||
// case SDL_SCANCODE_F1:
|
||||
// draw::setZoom(draw::getZoom()-1);
|
||||
// break;
|
||||
// case SDL_SCANCODE_F2:
|
||||
// draw::setZoom(draw::getZoom()+1);
|
||||
// break;
|
||||
// case SDL_SCANCODE_F3:
|
||||
// draw::setFullscreen(!draw::getFullscreen());
|
||||
// break;
|
||||
// default:
|
||||
input::updateKeypressed(e.key.scancode);
|
||||
}
|
||||
// }
|
||||
}
|
||||
if (e.type==SDL_EVENT_MOUSE_BUTTON_UP)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "input.h"
|
||||
#include <SDL3/SDL.h>
|
||||
#include "draw.h"
|
||||
|
||||
namespace input
|
||||
{
|
||||
@@ -79,7 +78,7 @@ namespace input
|
||||
{
|
||||
float x;
|
||||
SDL_GetMouseState(&x, NULL);
|
||||
return (x-draw::getOffsetX())/draw::getScaleX();
|
||||
return x;
|
||||
}
|
||||
|
||||
// Torna la posició Y actual del ratolí
|
||||
@@ -87,7 +86,7 @@ namespace input
|
||||
{
|
||||
float y;
|
||||
SDL_GetMouseState(NULL, &y);
|
||||
return (y-draw::getOffsetY())/draw::getScaleY();
|
||||
return y;
|
||||
}
|
||||
|
||||
// Determina si el botó del ratolí especificat està sent polsada ara mateix
|
||||
@@ -103,6 +102,11 @@ namespace input
|
||||
return btnClicked == btn;
|
||||
}
|
||||
|
||||
void mouseDiscard()
|
||||
{
|
||||
btnClicked = 0;
|
||||
}
|
||||
|
||||
// Obté el valor actual de la rodeta del ratolí
|
||||
const int mouseWheel()
|
||||
{
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace input
|
||||
/// @return true si està polsat, false si no
|
||||
const bool mouseClk(const int btn);
|
||||
|
||||
void mouseDiscard();
|
||||
|
||||
/// @brief Obté el valor actual de la rodeta del ratolí
|
||||
/// @return 0 si no es mou, positiu si roda cap amunt, negatiu si roda cap avall
|
||||
const int mouseWheel();
|
||||
|
||||
@@ -1,31 +1,45 @@
|
||||
#include "rooms.h"
|
||||
#include "enemies.h"
|
||||
#include "japi/draw.h"
|
||||
#include "japi/game.h"
|
||||
#include "images.h"
|
||||
#include "japi/font.h"
|
||||
#include "menu.h"
|
||||
|
||||
bool loop();
|
||||
|
||||
void game::init()
|
||||
{
|
||||
draw::init("DILEMMAKER v0.1", 320, 240, 2, false);
|
||||
draw::init("DILEMMAKER v0.1", 800, 600);
|
||||
game::setState(loop);
|
||||
enemies::load();
|
||||
rooms::load();
|
||||
images::loadPalette("./data/palette/zx-spectrum.pal");
|
||||
font::load("font/8bithud");
|
||||
}
|
||||
|
||||
bool loop()
|
||||
{
|
||||
draw::cls(4);
|
||||
draw::setTrans(255);
|
||||
//rooms::drawFullMap();
|
||||
|
||||
rooms::draw();
|
||||
draw::color(COLOR_BRIGHT_BLACK);
|
||||
/*for (int i=0; i<=32; ++i) draw::vline(64+i*16, 48, 256);
|
||||
for (int i=0; i<=16; ++i) draw::hline(64, 48+i*16, 512);
|
||||
*/
|
||||
draw::cls(0x00000000);
|
||||
|
||||
menu::start();
|
||||
if (menu::option("FILE")) {
|
||||
menu::popup::start();
|
||||
menu::popup::end();
|
||||
}
|
||||
if (menu::option("EDIT")) {
|
||||
menu::popup::start();
|
||||
menu::popup::end();
|
||||
}
|
||||
if (menu::option("SELECTION")) {
|
||||
menu::popup::start();
|
||||
menu::popup::end();
|
||||
}
|
||||
if (menu::option("VIEW")) {
|
||||
menu::popup::start();
|
||||
menu::popup::end();
|
||||
}
|
||||
|
||||
/*x1 += 6; x2 = x1 + font::len("FILE")+6;
|
||||
font::print("FILE", x1, 5); x1=x2;
|
||||
|
||||
font::print("EDIT", x, 5); x+= font::len("EDIT")+12;
|
||||
font::print("SELECTION", x, 5); x+= font::len("SELECTION")+12;
|
||||
font::print("VIEW", x, 5); x+= font::len("VIEW")+12;*/
|
||||
draw::render();
|
||||
return true;
|
||||
}
|
||||
|
||||
68
source/menu.cpp
Normal file
68
source/menu.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "menu.h"
|
||||
#include "japi/input.h"
|
||||
#include "japi/draw.h"
|
||||
#include "japi/font.h"
|
||||
|
||||
namespace menu
|
||||
{
|
||||
int x1, x2, m;
|
||||
int menu_shown = -1;
|
||||
|
||||
void start()
|
||||
{
|
||||
draw::setColor(0xff3c3c3c);
|
||||
draw::fillrect(0,0,draw::getWindowSize().x,24);
|
||||
x1=0; x2=0; m=-1;
|
||||
}
|
||||
|
||||
bool option(const char* label)
|
||||
{
|
||||
m++;
|
||||
x1 = x2 + 8; x2 = x1 + font::len(label)+8;
|
||||
int mx = input::mouseX();
|
||||
int my = input::mouseY();
|
||||
if (mx>=x1 && my>=0 && mx<x2 && my<24) {
|
||||
draw::setColor(0xff464646);
|
||||
draw::fillrect(x1-8, 0, x2-x1+8, 24);
|
||||
if (input::mouseClk(input::mouse::button::left)) {
|
||||
input::mouseDiscard();
|
||||
menu_shown = (menu_shown == m) ? -1 : m;
|
||||
} else {
|
||||
if (menu_shown != -1) menu_shown = m;
|
||||
}
|
||||
}
|
||||
font::print(label, x1, 9);
|
||||
|
||||
return menu_shown==m;
|
||||
}
|
||||
|
||||
namespace popup
|
||||
{
|
||||
void start()
|
||||
{
|
||||
draw::setColor(0xff3c3c3c);
|
||||
draw::fillrect(x1-8,24,200,200);
|
||||
|
||||
int mx = input::mouseX();
|
||||
int my = input::mouseY();
|
||||
if (mx>=x1-8 && my>=24 && mx<x1-8+200 && my<24+200) {
|
||||
if (input::mouseClk(input::mouse::button::left)) {
|
||||
input::mouseDiscard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool option(const char* label)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void end()
|
||||
{
|
||||
if (input::mouseClk(input::mouse::button::left)) {
|
||||
menu_shown = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
14
source/menu.h
Normal file
14
source/menu.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace menu
|
||||
{
|
||||
void start();
|
||||
bool option(const char* label);
|
||||
|
||||
namespace popup
|
||||
{
|
||||
void start();
|
||||
bool option(const char* label);
|
||||
void end();
|
||||
}
|
||||
}
|
||||
387
source/rooms.cpp
387
source/rooms.cpp
@@ -1,387 +0,0 @@
|
||||
#include "rooms.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
#include <map>
|
||||
#include "images.h"
|
||||
#include "enemies.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace rooms
|
||||
{
|
||||
int num_total_rooms = 0;
|
||||
std::string current_room = "";
|
||||
std::map<std::string, room_t> rooms;
|
||||
int full_map_x = 0, full_map_y = 0;
|
||||
draw::surface *map_surface {nullptr};
|
||||
|
||||
static const char *paletteMap[] = {
|
||||
"black", "bright_black", "blue", "bright_blue",
|
||||
"red", "bright_red", "magenta", "bright_magenta",
|
||||
"green", "bright_green", "cyan", "bright_cyan",
|
||||
"yellow", "bright_yellow", "white", "bright_white"
|
||||
};
|
||||
const uint8_t colorToNum(std::string value)
|
||||
{
|
||||
for (int i=0; i<16; ++i) if (value == paletteMap[i]) return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void trim(std::string& s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
||||
}
|
||||
|
||||
void processKeyValue(const std::string& room_name, const std::string& section, const std::string& key, const std::string& value)
|
||||
{
|
||||
room_t& room = rooms[room_name];
|
||||
|
||||
if (section == "global") {
|
||||
if (key == "name") {
|
||||
room.name = value;
|
||||
} else if (key == "bgColor") {
|
||||
room.bgColor = colorToNum(value);
|
||||
} else if (key == "border") {
|
||||
room.border = colorToNum(value);
|
||||
//} else if (key == "tileMapFile") {
|
||||
// room.tileMapFile = value;
|
||||
} else if (key == "tileSetFile") {
|
||||
room.tileSetFile = images::getImage("tilesets/"+value);
|
||||
} else if (key == "roomUp") {
|
||||
room.roomUp = value.substr(0, value.find_last_of('.'));;
|
||||
} else if (key == "roomDown") {
|
||||
room.roomDown = value.substr(0, value.find_last_of('.'));;
|
||||
} else if (key == "roomLeft") {
|
||||
room.roomLeft = value.substr(0, value.find_last_of('.'));;
|
||||
} else if (key == "roomRight") {
|
||||
room.roomRight = value.substr(0, value.find_last_of('.'));;
|
||||
} else if (key == "itemColor1") {
|
||||
room.itemColor1 = colorToNum(value);
|
||||
} else if (key == "itemColor2") {
|
||||
room.itemColor2 = colorToNum(value);
|
||||
}
|
||||
} else if (section == "enemy") {
|
||||
if (key == "animation") {
|
||||
room.enemies.back().animation = value.substr(0, value.find_last_of('.'));
|
||||
} else if (key == "x") {
|
||||
room.enemies.back().x = std::stoi(value);
|
||||
} else if (key == "y") {
|
||||
room.enemies.back().y = std::stoi(value);
|
||||
} else if (key == "vx") {
|
||||
room.enemies.back().vx = std::stof(value);
|
||||
} else if (key == "vy") {
|
||||
room.enemies.back().vy = std::stof(value);
|
||||
} else if (key == "x1") {
|
||||
room.enemies.back().x1 = std::stoi(value);
|
||||
} else if (key == "y1") {
|
||||
room.enemies.back().y1 = std::stoi(value);
|
||||
} else if (key == "x2") {
|
||||
room.enemies.back().x2 = std::stoi(value);
|
||||
} else if (key == "y2") {
|
||||
room.enemies.back().y2 = std::stoi(value);
|
||||
} else if (key == "color") {
|
||||
room.enemies.back().color = colorToNum(value);
|
||||
} else if (key == "flip") {
|
||||
room.enemies.back().flip = value=="true" ? true : false;
|
||||
} else if (key == "mirror") {
|
||||
room.enemies.back().mirror = value=="true" ? true : false;
|
||||
}
|
||||
} else if (section == "item") {
|
||||
if (key == "tile") {
|
||||
room.items.back().tile = std::stoi(value);
|
||||
} else if (key == "x") {
|
||||
room.items.back().x = std::stoi(value);
|
||||
} else if (key == "y") {
|
||||
room.items.back().y = std::stoi(value);
|
||||
} else if (key == "counter") {
|
||||
room.items.back().counter = std::stof(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadRoom(fs::path filename)
|
||||
{
|
||||
std::string room_name = filename.stem().string();
|
||||
|
||||
std::ifstream file(filename);
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open file.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string current_section = "global";
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
//std::cout << "'" << line << "'\n";
|
||||
// Trim and clean line, ignore empty lines and comments
|
||||
trim(line);
|
||||
if (line.empty() || line[0] == '#') continue;
|
||||
|
||||
// Remove inline comments
|
||||
/*std::size_t comment_pos = line.find('#');
|
||||
if (comment_pos != std::string::npos) {
|
||||
line = line.substr(0, comment_pos);
|
||||
trim(line);
|
||||
}*/
|
||||
|
||||
// Check if entering or exiting a section
|
||||
if (line[0] == '[')
|
||||
{
|
||||
std::size_t closing_pos = line.find(']');
|
||||
if (closing_pos != std::string::npos && closing_pos > 1)
|
||||
{
|
||||
std::string section = line.substr(1,closing_pos-1);
|
||||
if (section[0] == '/') {
|
||||
current_section = "global";
|
||||
} else {
|
||||
current_section = section;
|
||||
if (section == "enemy") rooms[room_name].enemies.emplace_back();
|
||||
else if (section == "item") rooms[room_name] .items.emplace_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get and process key/value
|
||||
std::size_t eq_pos = line.find('=');
|
||||
if (eq_pos != std::string::npos) {
|
||||
std::string key = line.substr(0, eq_pos);
|
||||
std::string value = line.substr(eq_pos + 1);
|
||||
trim(key);
|
||||
trim(value);
|
||||
processKeyValue(room_name, current_section, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadTiles(fs::path filename)
|
||||
{
|
||||
filename.replace_extension(".tmx");
|
||||
std::string room_name = filename.stem().string();
|
||||
std::string line;
|
||||
bool inData = false;
|
||||
int row = 0, col = 0;
|
||||
|
||||
std::ifstream file(filename);
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open file.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
room_t& room = rooms[room_name];
|
||||
|
||||
while (std::getline(file, line)) {
|
||||
if (!inData) {
|
||||
if (line.find("<data encoding=\"csv\">") != std::string::npos) inData = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.find("</data>") != std::string::npos) break;
|
||||
|
||||
std::stringstream ss(line);
|
||||
std::string value;
|
||||
while (std::getline(ss, value, ',')) {
|
||||
if (!value.empty()) {
|
||||
room.tiles[col][row] = std::stoi(value);
|
||||
++col;
|
||||
if (col == 32) {
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generateThumbnail(fs::path filename)
|
||||
{
|
||||
std::string room_name = filename.stem().string();
|
||||
room_t &room = rooms[room_name];
|
||||
|
||||
// Primer generem un pixel per a cada tile del gif de tiles
|
||||
draw::surface *tiles = room.tileSetFile;
|
||||
uint8_t pixels[tiles->w/8][tiles->h/8];
|
||||
for (int ty=0; ty<tiles->h/8; ty++) {
|
||||
for (int tx=0; tx<tiles->w/8; tx++) {
|
||||
uint8_t count[16] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
for (int y=0;y<8;++y)
|
||||
for (int x=0;x<8;x++) {
|
||||
count[tiles->pixels[(x+tx*8)+(y+ty*8)*tiles->w]]++;
|
||||
}
|
||||
uint8_t max_count=0;
|
||||
uint8_t max_index=0;
|
||||
for (int i=0; i<16; ++i) if (count[i] > max_count) {max_count=count[i]; max_index=i;}
|
||||
pixels[tx][ty] = max_index;
|
||||
}
|
||||
}
|
||||
|
||||
room.thumbnail = draw::createSurface(32,16);
|
||||
for (int y=0; y<16; ++y) {
|
||||
for (int x=0; x<32; ++x) {
|
||||
uint16_t tile = room.tiles[x][y];
|
||||
if (tile>0) {
|
||||
tile--;
|
||||
room.thumbnail->pixels[x+y*32] = pixels[tile%24][tile/24];
|
||||
} else {
|
||||
room.thumbnail->pixels[x+y*32] = room.bgColor!=0 ? room.bgColor : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, bool> visited;
|
||||
|
||||
void detectFullMapOffset(std::string room_name, int x, int y)
|
||||
{
|
||||
if (visited.find(room_name)!= visited.end()) return;
|
||||
printf("Visiting '%s'...\n", room_name.c_str());
|
||||
visited[room_name] = true;
|
||||
|
||||
if (full_map_x < x) full_map_x = x;
|
||||
if (full_map_y < y) full_map_y = y;
|
||||
|
||||
room_t &room = rooms[room_name];
|
||||
room.map_x = x;
|
||||
room.map_y = y;
|
||||
if (room.roomUp != "0") detectFullMapOffset(room.roomUp, x, y+1);
|
||||
if (room.roomLeft != "0") detectFullMapOffset(room.roomLeft, x+1, y);
|
||||
if (room.roomDown != "0") detectFullMapOffset(room.roomDown, x, y-1);
|
||||
if (room.roomRight != "0") detectFullMapOffset(room.roomRight, x-1, y);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
// Get all room files
|
||||
fs::path target_dir = "./data/room";
|
||||
std::vector<fs::path> room_files;
|
||||
|
||||
try {
|
||||
for (const auto& entry : fs::directory_iterator(target_dir)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".room") {
|
||||
room_files.push_back(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(room_files.begin(), room_files.end());
|
||||
|
||||
for (const auto& path : room_files) {
|
||||
std::cout << "Processing " << path.filename() << '\n';
|
||||
loadRoom(path);
|
||||
loadTiles(path);
|
||||
generateThumbnail(path);
|
||||
}
|
||||
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
std::cerr << "Filesystem error: " << e.what() << '\n';
|
||||
}
|
||||
|
||||
visited.clear();
|
||||
detectFullMapOffset("01", 0, 0);
|
||||
full_map_x++;
|
||||
full_map_y++;
|
||||
|
||||
if (map_surface) draw::freeSurface(map_surface);
|
||||
map_surface = draw::createSurface(256,128);
|
||||
|
||||
/*for (auto &item : rooms)
|
||||
{
|
||||
room_t &room = item.second;
|
||||
std::cout << room.name << std::endl;
|
||||
|
||||
for (int y=0; y<16; ++y) {
|
||||
for (int x=0; x<32; ++x)
|
||||
std::cout << std::to_string(room.tiles[x][y]) << ",";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}*/
|
||||
/*room_t &room = rooms["01"];
|
||||
for (int y=0; y<16; ++y) {
|
||||
for (int x=0; x<32; ++x)
|
||||
std::cout << std::to_string(room.tiles[x][y]) << ",";
|
||||
std::cout << std::endl;
|
||||
}*/
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
room_t &room = rooms["01"];
|
||||
|
||||
draw::setTrans(16);
|
||||
draw::setDestination(map_surface);
|
||||
draw::resetViewport();
|
||||
draw::setSource(room.tileSetFile);
|
||||
draw::cls(room.bgColor);
|
||||
|
||||
for (int y=0; y<16; ++y) {
|
||||
for (int x=0; x<32; ++x) {
|
||||
uint16_t tile = room.tiles[x][y];
|
||||
if (tile>0) {
|
||||
tile--;
|
||||
draw::draw(x*8, y*8, 8, 8, (tile%24)*8, (tile/24)*8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw::setTrans(0);
|
||||
for (auto enemy : room.enemies)
|
||||
{
|
||||
enemies::enemy_t &anim = enemies::get(enemy.animation);
|
||||
draw::setSource(anim.tileSetFile);
|
||||
const int tile = anim.animations[0].frames[0];
|
||||
draw::swapcol(1, enemy.color);
|
||||
draw::draw(enemy.x*8, enemy.y*8, anim.frame_width, anim.frame_height, tile*anim.frame_width, 0);
|
||||
draw::restorecol(1);
|
||||
}
|
||||
|
||||
draw::setTrans(16);
|
||||
draw::setDestination(nullptr);
|
||||
draw::setSource(map_surface);
|
||||
draw::cls(COLOR_BRIGHT_BLACK);
|
||||
//draw::color(room.border);
|
||||
//draw::fillrect(48, 32, 512+32, 256+32);
|
||||
//draw::setViewport(64, 48, 512, 256);
|
||||
draw::setViewport(32, 24, 256, 128);
|
||||
draw::draw(0, 0);
|
||||
draw::resetViewport();
|
||||
|
||||
//draw::setSource(room.thumbnail);
|
||||
//draw::draw();
|
||||
}
|
||||
|
||||
uint8_t blinking = 0;
|
||||
void drawFullMap()
|
||||
{
|
||||
blinking = (blinking+1)%16;
|
||||
for (auto &item : rooms)
|
||||
{
|
||||
auto room = item.second;
|
||||
int x = ((full_map_x-room.map_x)*38)-1;
|
||||
int y = ((full_map_y-room.map_y)*22)-1;
|
||||
draw::resetViewport();
|
||||
|
||||
if (item.first == "01") {
|
||||
draw::color(blinking);
|
||||
draw::rect(x-1, y-1, 36, 20);
|
||||
draw::color(COLOR_BLACK);
|
||||
draw::rect(x, y, 34, 18);
|
||||
} else {
|
||||
draw::color(COLOR_WHITE);
|
||||
draw::rect(x+1, y+1, 34, 18);
|
||||
draw::color(COLOR_BLACK);
|
||||
draw::rect(x, y, 34, 18);
|
||||
}
|
||||
draw::setSource(room.thumbnail);
|
||||
draw::draw(x+1, y+1, 32, 16, 0, 0);
|
||||
|
||||
if (room.roomUp != "0") draw::fillrect(x+15, y-4, 4, 4);
|
||||
if (room.roomLeft != "0") draw::fillrect(x-4, y+7, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "japi/draw.h"
|
||||
|
||||
#define COLOR_BLACK 0
|
||||
#define COLOR_BRIGHT_BLACK 1
|
||||
#define COLOR_BLUE 2
|
||||
#define COLOR_BRIGHT_BLUE 3
|
||||
#define COLOR_RED 4
|
||||
#define COLOR_BRIGHT_RED 5
|
||||
#define COLOR_MAGENTA 6
|
||||
#define COLOR_BRIGHT_MAGENTA 7
|
||||
#define COLOR_GREEN 8
|
||||
#define COLOR_BRIGHT_GREEN 9
|
||||
#define COLOR_CYAN 10
|
||||
#define COLOR_BRIGHT_CYAN 11
|
||||
#define COLOR_YELLOW 12
|
||||
#define COLOR_BRIGHT_YELLOW 13
|
||||
#define COLOR_WHITE 14
|
||||
#define COLOR_BRIGHT_WHITE 15
|
||||
|
||||
namespace rooms
|
||||
{
|
||||
struct enemy_t
|
||||
{
|
||||
std::string animation {""};
|
||||
uint8_t x {0};
|
||||
uint8_t y {0};
|
||||
float vx {0.0f};
|
||||
float vy {0.0f};
|
||||
uint8_t x1 {0};
|
||||
uint8_t y1 {0};
|
||||
uint8_t x2 {0};
|
||||
uint8_t y2 {0};
|
||||
uint8_t color {COLOR_WHITE};
|
||||
bool flip {false};
|
||||
bool mirror {false};
|
||||
};
|
||||
|
||||
struct item_t
|
||||
{
|
||||
uint8_t tile {0};
|
||||
uint8_t x {0};
|
||||
uint8_t y {0};
|
||||
float counter {0.0f};
|
||||
};
|
||||
|
||||
struct room_t
|
||||
{
|
||||
std::string name {""};
|
||||
uint8_t bgColor {COLOR_BLACK};
|
||||
uint8_t border {COLOR_BLACK};
|
||||
draw::surface *tileSetFile {nullptr};
|
||||
std::string roomUp {0};
|
||||
std::string roomDown {0};
|
||||
std::string roomLeft {0};
|
||||
std::string roomRight {0};
|
||||
uint8_t itemColor1 {0};
|
||||
uint8_t itemColor2 {0};
|
||||
std::vector<enemy_t> enemies;
|
||||
std::vector<item_t> items;
|
||||
uint16_t tiles[32][16];
|
||||
draw::surface *thumbnail {nullptr};
|
||||
int map_x {0};
|
||||
int map_y {0};
|
||||
};
|
||||
|
||||
void load();
|
||||
void draw();
|
||||
void drawFullMap();
|
||||
}
|
||||
Reference in New Issue
Block a user