Flood Fill, Replace, Minimap border, Undo/Redo, bugs...

This commit is contained in:
2016-05-23 19:01:14 +02:00
parent a4d5bb8ee2
commit 349e2235f9

109
main.cpp
View File

@@ -17,6 +17,9 @@
struct Mouse { struct Mouse {
int x, y; int x, y;
bool buttons[3]; bool buttons[3];
bool mouse_down[3];
bool mouse_up[3];
bool mouse_old[3];
}; };
typedef bool(*LoopFun)(void); typedef bool(*LoopFun)(void);
@@ -56,14 +59,24 @@ unsigned char* map = nullptr;
int map_x = 0; int map_x = 0;
int map_y = 0; int map_y = 0;
#define UNDO_MAX 16
unsigned char* undo = nullptr;
int undo_pointer = 0;
int undo_min = 0;
int undo_max = 0;
int tile_sel = 0; int tile_sel = 0;
int tile_back = 0; int tile_back = 0;
const char* GetPath(const char* filename) { const char* GetPath(const char* filename) {
#ifdef __APPLE__
static char fullpath[400]; static char fullpath[400];
strcpy(fullpath, path); strcpy(fullpath, path);
strcat(fullpath, filename); strcat(fullpath, filename);
return fullpath; return fullpath;
#else
return filename;
#endif
} }
int StrToInt(const char* str) { int StrToInt(const char* str) {
@@ -76,6 +89,35 @@ int StrToInt(const char* str) {
return val; return val;
} }
#define UndoInc(var) (var = (var+1)%UNDO_MAX)
#define UndoDec(var) (var = (var-1+UNDO_MAX)%UNDO_MAX)
void Undo_Create() {
unsigned char* dest = undo + (map_width*map_height*undo_pointer);
memcpy(dest, map, map_width*map_height);
}
void Undo_Restore() {
unsigned char* src = undo + (map_width*map_height*undo_pointer);
memcpy(map, src, map_width*map_height);
}
void Undo_Op() {
UndoInc(undo_pointer);
Undo_Create();
undo_max = undo_pointer;
if (undo_pointer == undo_min) UndoInc(undo_min);
}
void Undo_Undo() {
if (undo_pointer != undo_min) {
Undo_Restore();
UndoDec(undo_pointer);
}
}
void Undo_Redo() {
if (undo_pointer != undo_max) {
UndoInc(undo_pointer);
Undo_Restore();
}
}
void LoadConfig() { void LoadConfig() {
FILE* f = fopen(GetPath("config.ini"), "r"); FILE* f = fopen(GetPath("config.ini"), "r");
if (!f) { error = 1; return; } if (!f) { error = 1; return; }
@@ -113,7 +155,7 @@ void Init() {
LoadConfig(); LoadConfig();
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_EVERYTHING);
sdlWindow = SDL_CreateWindow("Mappy v0.1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width*zoom, screen_height*zoom, SDL_WINDOW_SHOWN); sdlWindow = SDL_CreateWindow("Mappy v0.3", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_width*zoom, screen_height*zoom, SDL_WINDOW_SHOWN);
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_PRESENTVSYNC); sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_BLEND);
SDL_RenderSetLogicalSize(sdlRenderer, screen_width, screen_height); SDL_RenderSetLogicalSize(sdlRenderer, screen_width, screen_height);
@@ -164,6 +206,7 @@ void Init() {
f = fopen(GetPath(map_filename), "rb"); f = fopen(GetPath(map_filename), "rb");
map = (unsigned char*)malloc(map_width*map_height); map = (unsigned char*)malloc(map_width*map_height);
undo = (unsigned char*)malloc(map_width*map_height*UNDO_MAX);
if (f) { if (f) {
int old_map_width = 0, old_map_height = 0; int old_map_width = 0, old_map_height = 0;
fread(&old_map_width, 1, 1, f); fread(&old_map_width, 1, 1, f);
@@ -270,6 +313,14 @@ bool Update() {
mouse.x /= zoom; mouse.x /= zoom;
mouse.y /= zoom; mouse.y /= zoom;
mouse.mouse_down[0] = mouse.mouse_down[1] = mouse.mouse_down[2] = mouse.mouse_up[0] = mouse.mouse_up[1] = mouse.mouse_up[2] = false;
if ((buttons & 1) == 1) { if (!mouse.mouse_old[0]) mouse.mouse_down[0] = true; } else { if (mouse.mouse_old[0]) mouse.mouse_up[0] = true; }
if ((buttons & 2) == 2) { if (!mouse.mouse_old[1]) mouse.mouse_down[1] = true; } else { if (mouse.mouse_old[1]) mouse.mouse_up[1] = true; }
if ((buttons & 4) == 4) { if (!mouse.mouse_old[2]) mouse.mouse_down[2] = true; } else { if (mouse.mouse_old[2]) mouse.mouse_up[2] = true; }
mouse.mouse_old[0] = (buttons & 1) == 1;
mouse.mouse_old[1] = (buttons & 2) == 2;
mouse.mouse_old[2] = (buttons & 4) == 4;
if (buttons == 0) ignoreMouse = false; if (buttons == 0) ignoreMouse = false;
if (buttons != 0 && !ignoreMouse) { if (buttons != 0 && !ignoreMouse) {
@@ -343,6 +394,44 @@ void DoTilePal() {
if (keyJustPressed == SDL_SCANCODE_Q) state = STATE_TILEMAP; if (keyJustPressed == SDL_SCANCODE_Q) state = STATE_TILEMAP;
} }
void floodfill_r(const int x, const int y, const int tile) {
const int width_in_tiles = screen_width / tile_width;
const int height_in_tiles = screen_height / tile_height;
if ( (keyboard[SDL_SCANCODE_LCTRL] ) || ( (x >= map_x && y >= map_y && x < (map_x + width_in_tiles) && y < (map_y + height_in_tiles)) ) ) {
if (map[x + y * map_width] == tile) {
map[x + y * map_width] = tile_sel;
floodfill_r(x + 1, y, tile);
floodfill_r(x - 1, y, tile);
floodfill_r(x, y + 1, tile);
floodfill_r(x, y - 1, tile);
}
}
}
void FloodFill() {
const int x = map_x + (mouse.x / tile_width);
const int y = map_y + (mouse.y / tile_height);
const int tile = map[x + y * map_width];
if (tile != tile_sel) floodfill_r(x, y, tile);
}
void ReplaceTile() {
const int x = map_x + (mouse.x / tile_width);
const int y = map_y + (mouse.y / tile_height);
const int tile = map[x + y * map_width];
const bool all_map = keyboard[SDL_SCANCODE_LCTRL];
const int xi = all_map ? 0 : map_x;
const int yi = all_map ? 0 : map_y;
const int w = all_map ? map_width : xi+(screen_width / tile_width);
const int h = all_map ? map_height : yi+(screen_height / tile_height);
for (int yy = yi; yy < h; yy++) {
for (int xx = xi; xx < w; xx++) {
if (map[xx + yy * map_width] == tile) map[xx + yy * map_width] = tile_sel;
}
}
}
void DoTileMap() { void DoTileMap() {
static bool menu = false; static bool menu = false;
@@ -362,7 +451,8 @@ void DoTileMap() {
DrawRect(cur_x*tile_width - 1, cur_y*tile_height - 1, tile_width + 2, tile_height + 2, 255, 255, 255, 128); DrawRect(cur_x*tile_width - 1, cur_y*tile_height - 1, tile_width + 2, tile_height + 2, 255, 255, 255, 128);
if (keyJustPressed == SDL_SCANCODE_TAB) { if (keyJustPressed == SDL_SCANCODE_TAB) {
menu = true; return; } menu = true; return;
}
if (keyJustPressed == SDL_SCANCODE_Q) state = STATE_TILEPAL; if (keyJustPressed == SDL_SCANCODE_Q) state = STATE_TILEPAL;
if (keyJustPressed == SDL_SCANCODE_E) { state = STATE_MINIMAP; UpdateMiniMap(); } if (keyJustPressed == SDL_SCANCODE_E) { state = STATE_MINIMAP; UpdateMiniMap(); }
if (keyJustPressed == SDL_SCANCODE_X) { int temp = tile_back; tile_back = tile_sel; tile_sel = temp; } if (keyJustPressed == SDL_SCANCODE_X) { int temp = tile_back; tile_back = tile_sel; tile_sel = temp; }
@@ -370,10 +460,19 @@ void DoTileMap() {
if (keyJustPressed == SDL_SCANCODE_LEFT || keyJustPressed == SDL_SCANCODE_A) if (map_x > 0) map_x -= width_in_tiles; if (keyJustPressed == SDL_SCANCODE_LEFT || keyJustPressed == SDL_SCANCODE_A) if (map_x > 0) map_x -= width_in_tiles;
if (keyJustPressed == SDL_SCANCODE_DOWN || keyJustPressed == SDL_SCANCODE_S) if (map_y < map_height - height_in_tiles) map_y += height_in_tiles; if (keyJustPressed == SDL_SCANCODE_DOWN || keyJustPressed == SDL_SCANCODE_S) if (map_y < map_height - height_in_tiles) map_y += height_in_tiles;
if (keyJustPressed == SDL_SCANCODE_UP || keyJustPressed == SDL_SCANCODE_W) if (map_y > 0) map_y -= height_in_tiles; if (keyJustPressed == SDL_SCANCODE_UP || keyJustPressed == SDL_SCANCODE_W) if (map_y > 0) map_y -= height_in_tiles;
if (keyJustPressed == SDL_SCANCODE_F) { Undo_Op(); FloodFill(); }
if (keyJustPressed == SDL_SCANCODE_R) { Undo_Op(); ReplaceTile(); }
if (mouse.mouse_down[MOUSE_BUTTON_LEFT] || mouse.mouse_down[MOUSE_BUTTON_RIGHT]) { Undo_Op(); }
if (mouse.buttons[MOUSE_BUTTON_RIGHT]) { map[(map_x + cur_x) + (map_y + cur_y)*map_width] = tile_back; } if (mouse.buttons[MOUSE_BUTTON_RIGHT]) { map[(map_x + cur_x) + (map_y + cur_y)*map_width] = tile_back; }
if (mouse.buttons[MOUSE_BUTTON_LEFT]) { map[(map_x + cur_x) + (map_y + cur_y)*map_width] = tile_sel; } if (mouse.buttons[MOUSE_BUTTON_LEFT]) { map[(map_x + cur_x) + (map_y + cur_y)*map_width] = tile_sel; }
if (mouse.buttons[MOUSE_BUTTON_MIDDLE]) { tile_sel = map[(map_x + cur_x) + (map_y + cur_y)*map_width]; } if (mouse.buttons[MOUSE_BUTTON_MIDDLE]) { tile_sel = map[(map_x + cur_x) + (map_y + cur_y)*map_width]; }
} else {
if (keyJustPressed == SDL_SCANCODE_Z && keyboard[SDL_SCANCODE_LCTRL]) { Undo_Undo(); }
if (keyJustPressed == SDL_SCANCODE_Y && keyboard[SDL_SCANCODE_LCTRL]) { Undo_Redo(); }
if (keyJustPressed == SDL_SCANCODE_Z && keyboard[SDL_SCANCODE_LCTRL] && keyboard[SDL_SCANCODE_LSHIFT]) { Undo_Redo(); }
}
else {
if (keyJustPressed == SDL_SCANCODE_TAB) { menu = false; return; } if (keyJustPressed == SDL_SCANCODE_TAB) { menu = false; return; }
FillRect(0, 0, screen_width, screen_height, 0, 0, 0, 192); FillRect(0, 0, screen_width, screen_height, 0, 0, 0, 192);
if (Button(6, 6, "Save")) { if (Button(6, 6, "Save")) {
@@ -385,6 +484,7 @@ void DoTileMap() {
menu = false; ignoreMouse = true; menu = false; ignoreMouse = true;
} }
if (Button(6, 24, "Clear")) { if (Button(6, 24, "Clear")) {
Undo_Op();
for (int y = 0; y < height_in_tiles; y++) { for (int y = 0; y < height_in_tiles; y++) {
for (int x = 0; x < width_in_tiles; x++) { for (int x = 0; x < width_in_tiles; x++) {
map[(map_x + x) + (map_y + y) * map_width] = tile_back; map[(map_x + x) + (map_y + y) * map_width] = tile_back;
@@ -393,6 +493,7 @@ void DoTileMap() {
menu = false; ignoreMouse = true; menu = false; ignoreMouse = true;
} }
if (Button(6, 42, "Border")) { if (Button(6, 42, "Border")) {
Undo_Op();
for (int y = 0; y < height_in_tiles; y++) { for (int y = 0; y < height_in_tiles; y++) {
map[(map_x) + (map_y + y) * map_width] = tile_sel; map[(map_x) + (map_y + y) * map_width] = tile_sel;
map[(map_x + width_in_tiles - 1) + (map_y + y) * map_width] = tile_sel; map[(map_x + width_in_tiles - 1) + (map_y + y) * map_width] = tile_sel;
@@ -409,6 +510,7 @@ void DoTileMap() {
#define mod(x, y) (((x % y)+y)%y) #define mod(x, y) (((x % y)+y)%y)
void ShiftMap(int sx, int sy) { void ShiftMap(int sx, int sy) {
Undo_Op();
int test = mod(-1, 240); int test = mod(-1, 240);
sx *= (screen_width/tile_width); sx *= (screen_width/tile_width);
sy *= (screen_height / tile_height); sy *= (screen_height / tile_height);
@@ -447,6 +549,7 @@ void DoMiniMap() {
const int screen_height_in_tiles = screen_height / tile_height; const int screen_height_in_tiles = screen_height / tile_height;
DrawRect((ox + map_x) - 1, (oy + map_y) - 1, screen_width_in_tiles + 2, screen_height_in_tiles + 2, 255, 255, 255); DrawRect((ox + map_x) - 1, (oy + map_y) - 1, screen_width_in_tiles + 2, screen_height_in_tiles + 2, 255, 255, 255);
//DrawRect(ox + (tile_sel % tiles_per_row)*tile_width - 1, oy + (tile_sel / tiles_per_row)*tile_height - 1, tile_width + 2, tile_height + 2, 255, 255, 255); //DrawRect(ox + (tile_sel % tiles_per_row)*tile_width - 1, oy + (tile_sel / tiles_per_row)*tile_height - 1, tile_width + 2, tile_height + 2, 255, 255, 255);
DrawRect(ox - 1, oy - 1, map_width + 2, map_height + 2, 255, 0, 0);
if (mouse.buttons[MOUSE_BUTTON_LEFT]) { if (mouse.buttons[MOUSE_BUTTON_LEFT]) {
map_x = int((mouse.x-ox) / screen_width_in_tiles) * screen_width_in_tiles; map_x = int((mouse.x-ox) / screen_width_in_tiles) * screen_width_in_tiles;
map_y = int((mouse.y - oy) / screen_height_in_tiles) * screen_height_in_tiles; map_y = int((mouse.y - oy) / screen_height_in_tiles) * screen_height_in_tiles;