Flood Fill, Replace, Minimap border, Undo/Redo, bugs...
This commit is contained in:
109
main.cpp
109
main.cpp
@@ -17,6 +17,9 @@
|
||||
struct Mouse {
|
||||
int x, y;
|
||||
bool buttons[3];
|
||||
bool mouse_down[3];
|
||||
bool mouse_up[3];
|
||||
bool mouse_old[3];
|
||||
};
|
||||
|
||||
typedef bool(*LoopFun)(void);
|
||||
@@ -56,14 +59,24 @@ unsigned char* map = nullptr;
|
||||
int map_x = 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_back = 0;
|
||||
|
||||
const char* GetPath(const char* filename) {
|
||||
#ifdef __APPLE__
|
||||
static char fullpath[400];
|
||||
strcpy(fullpath, path);
|
||||
strcat(fullpath, filename);
|
||||
return fullpath;
|
||||
#else
|
||||
return filename;
|
||||
#endif
|
||||
}
|
||||
|
||||
int StrToInt(const char* str) {
|
||||
@@ -76,6 +89,35 @@ int StrToInt(const char* str) {
|
||||
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() {
|
||||
FILE* f = fopen(GetPath("config.ini"), "r");
|
||||
if (!f) { error = 1; return; }
|
||||
@@ -113,7 +155,7 @@ void Init() {
|
||||
LoadConfig();
|
||||
|
||||
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);
|
||||
SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderSetLogicalSize(sdlRenderer, screen_width, screen_height);
|
||||
@@ -164,6 +206,7 @@ void Init() {
|
||||
|
||||
f = fopen(GetPath(map_filename), "rb");
|
||||
map = (unsigned char*)malloc(map_width*map_height);
|
||||
undo = (unsigned char*)malloc(map_width*map_height*UNDO_MAX);
|
||||
if (f) {
|
||||
int old_map_width = 0, old_map_height = 0;
|
||||
fread(&old_map_width, 1, 1, f);
|
||||
@@ -270,6 +313,14 @@ bool Update() {
|
||||
mouse.x /= 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) {
|
||||
@@ -343,6 +394,44 @@ void DoTilePal() {
|
||||
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() {
|
||||
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);
|
||||
|
||||
if (keyJustPressed == SDL_SCANCODE_TAB) {
|
||||
menu = true; return; }
|
||||
menu = true; return;
|
||||
}
|
||||
if (keyJustPressed == SDL_SCANCODE_Q) state = STATE_TILEPAL;
|
||||
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; }
|
||||
@@ -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_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_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_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]; }
|
||||
} 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; }
|
||||
FillRect(0, 0, screen_width, screen_height, 0, 0, 0, 192);
|
||||
if (Button(6, 6, "Save")) {
|
||||
@@ -385,6 +484,7 @@ void DoTileMap() {
|
||||
menu = false; ignoreMouse = true;
|
||||
}
|
||||
if (Button(6, 24, "Clear")) {
|
||||
Undo_Op();
|
||||
for (int y = 0; y < height_in_tiles; y++) {
|
||||
for (int x = 0; x < width_in_tiles; x++) {
|
||||
map[(map_x + x) + (map_y + y) * map_width] = tile_back;
|
||||
@@ -393,6 +493,7 @@ void DoTileMap() {
|
||||
menu = false; ignoreMouse = true;
|
||||
}
|
||||
if (Button(6, 42, "Border")) {
|
||||
Undo_Op();
|
||||
for (int y = 0; y < height_in_tiles; y++) {
|
||||
map[(map_x) + (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)
|
||||
|
||||
void ShiftMap(int sx, int sy) {
|
||||
Undo_Op();
|
||||
int test = mod(-1, 240);
|
||||
sx *= (screen_width/tile_width);
|
||||
sy *= (screen_height / tile_height);
|
||||
@@ -447,6 +549,7 @@ void DoMiniMap() {
|
||||
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 + (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]) {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user