#include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" #include "font.h" #include "gif.c" #include #define STATE_TILEMAP 0 #define STATE_TILEPAL 1 #define STATE_MINIMAP 2 #define MOUSE_BUTTON_LEFT 0 #define MOUSE_BUTTON_MIDDLE 1 #define MOUSE_BUTTON_RIGHT 2 #ifdef __APPLE__ #define CTRL SDL_SCANCODE_LGUI #else #define CTRL SDL_SCANCODE_LCTRL #endif struct Mouse { int x, y; bool buttons[3]; bool mouse_down[3]; bool mouse_up[3]; bool mouse_old[3]; }; typedef bool(*LoopFun)(void); SDL_Window* sdlWindow = NULL; SDL_Renderer* sdlRenderer = NULL; SDL_Texture* sdlFontTexture = NULL; SDL_Texture* sdlTilesTexture = NULL; SDL_Texture* sdlMinimapTexture = NULL; SDL_Event sdlEvent; SDL_Scancode keyJustPressed = SDL_SCANCODE_UNKNOWN; const Uint8* keyboard = nullptr; Uint32* minitiles = nullptr; bool ignoreMouse = false; bool anyKey = false; LoopFun loop; Mouse mouse; int error = 0; int dialog = 0; int state = STATE_TILEMAP; int tile_width = 16; int tile_height = 16; int map_width = 240; int map_height = 240; int screen_width = 256; int screen_height = 192; int zoom = 2; char tiles_filename[100] = { 0 }; char map_filename[100] = { 0 }; int tilemap_width = 0; int tilemap_height = 0; char path[400] = {0}; 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; int sprites = 208; 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) { int val = 0; int size = strlen(str); for (int i = 0; i < size; i++) { if (str[i] < 48 || str[i] > 57) return 0; val = val * 10 + (str[i] - 48); } return val; } #define UndoInc(var) (var = (var+1)%UNDO_MAX) #define UndoDec(var) (var = (var-1+UNDO_MAX)%UNDO_MAX) void Undo_Create(const bool actor) { unsigned char* dest = undo + ((map_width*map_height+1)*undo_pointer); *dest = actor ? 1 : 0; dest++; unsigned char* src = actor ? map + (map_width*map_height) : map; memcpy(dest, src, map_width*map_height); } void Undo_Restore() { unsigned char* src = undo + ((map_width*map_height+1)*undo_pointer); const bool actor = (*src == 1); src++; unsigned char* dest = actor ? map + (map_width*map_height) : map; memcpy(dest, src, map_width*map_height); } void Undo_Op(const bool actor = false) { UndoInc(undo_pointer); Undo_Create(actor); 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; } char key[50]; char val[255]; while (!feof(f)) { fscanf(f, "%s = %s", key, val); if (strcmp(key, "tile_width") == 0) { tile_width = StrToInt(val); } else if (strcmp(key, "tile_height") == 0) { tile_height = StrToInt(val); } else if (strcmp(key, "map_width") == 0) { map_width = StrToInt(val); } else if (strcmp(key, "map_height") == 0) { map_height = StrToInt(val); } else if (strcmp(key, "screen_width") == 0) { screen_width = StrToInt(val); } else if (strcmp(key, "screen_height") == 0) { screen_height = StrToInt(val); } else if (strcmp(key, "zoom") == 0) { zoom = StrToInt(val); } else if (strcmp(key, "tiles") == 0) { strcpy(tiles_filename, val); } else if (strcmp(key, "map") == 0) { strcpy(map_filename, val); } else if (strcmp(key, "sprites") == 0) { sprites = StrToInt(val); } } fclose(f); } void UpdateMiniMap() { const int tmtw = (tilemap_width / tile_width); Uint32* pixels = (Uint32*)malloc(map_width * map_height*sizeof(Uint32)); for (int y = 0; y < map_height; y++) { for (int x = 0; x < map_width; x++) { const Uint8 tile = map[x + y*map_width]; pixels[x + y*map_width] = minitiles[(tile % tmtw) + (tile / tmtw)*tmtw]; } } SDL_UpdateTexture(sdlMinimapTexture, NULL, pixels, map_width * sizeof(Uint32)); free(pixels); } const bool IsGIF(const char* filename) { const int filename_size = strlen(filename); if ((filename[filename_size-3]=='g') && (filename[filename_size-2]=='i') && (filename[filename_size-1]=='f') || (filename[filename_size-3]=='G') && (filename[filename_size-2]=='I') && (filename[filename_size-1]=='F')) return true; return false; } void Init() { LoadConfig(); SDL_Init(SDL_INIT_EVERYTHING); 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); unsigned short w, h; unsigned char* buffer = LoadGif(font, &w, &h); sdlFontTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h); Uint32* pixels = (Uint32*)malloc(w*h*sizeof(Uint32)); for (int i = 0; i < w*h; i++) { pixels[i] = buffer[i] == 0 ? 0x00000000 : 0xffffffff; } SDL_UpdateTexture(sdlFontTexture, NULL, pixels, w * sizeof(Uint32)); SDL_SetTextureBlendMode(sdlFontTexture, SDL_BLENDMODE_BLEND); free(buffer); free(pixels); int c; FILE* f = fopen(GetPath(tiles_filename), "rb"); if (!f) { error = 2; return; } if (IsGIF(tiles_filename)) { fseek(f, 0, SEEK_END); const long fsize = ftell(f); fseek(f, 0, SEEK_SET); /* same as rewind(f); */ char *string = (char*)malloc(fsize + 1); fread(string, 1, fsize, f); string[fsize] = 0; unsigned short w, h; buffer = LoadGif((unsigned char*)string, &w, &h); tilemap_width = w; tilemap_height = h; Uint8* palette = LoadPalette((unsigned char*)string); Uint32 pal[256]; for (int i=0;i<256;++i) { pal[i] = 0xFF000000 + (palette[(i*3)]) + (palette[(i*3)+1] << 8) + (palette[(i*3)+2] << 16); } free(palette); free(string); if (buffer == NULL) { error = 2; return; } sdlTilesTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, tilemap_width, tilemap_height); Uint32* pixels = (Uint32*)malloc(w*h*sizeof(Uint32)); for (int i = 0; i < w*h; i++) { pixels[i] = pal[buffer[i]]; } SDL_UpdateTexture(sdlTilesTexture, NULL, pixels, w * sizeof(Uint32)); SDL_SetTextureBlendMode(sdlTilesTexture, SDL_BLENDMODE_BLEND); free(buffer); buffer = (Uint8*)malloc(w*h*sizeof(Uint32)); memcpy(buffer, pixels, w*h*sizeof(Uint32)); free(pixels); } else { buffer = stbi_load_from_file(f, &tilemap_width, &tilemap_height, &c, 4); sdlTilesTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, tilemap_width, tilemap_height); SDL_UpdateTexture(sdlTilesTexture, NULL, buffer, tilemap_width * sizeof(Uint32)); SDL_SetTextureBlendMode(sdlTilesTexture, SDL_BLENDMODE_BLEND); } fclose(f); const int tmtw = (tilemap_width / tile_width); const int tmth = (tilemap_height / tile_height); minitiles = (Uint32*)malloc(tmtw * tmth*sizeof(Uint32)); for (int tmy = 0; tmy < tmth; tmy++) { for (int tmx = 0; tmx < tmth; tmx++) { const int bx = tmx*tile_width; const int by = tmy*tile_height; int r = 0, g = 0, b = 0; for (int ty = 0; ty < tile_width; ty++) { for (int tx = 0; tx < tile_height; tx++) { const Uint32 offset = (bx + tx) * 4 + (by + ty)*(tilemap_width * 4); r += buffer[offset]; g += buffer[offset+1]; b += buffer[offset+2]; } } r /= (tile_width*tile_height); g /= (tile_width*tile_height); b /= (tile_width*tile_height); minitiles[tmx + tmy*tmtw] = 0xFF000000 + b + (g << 8) + (r << 16); } } if (IsGIF(tiles_filename)) { free(buffer); } else { stbi_image_free(buffer); } f = fopen(GetPath(map_filename), "rb"); map = (unsigned char*)calloc(map_width*map_height*2, 1); undo = (unsigned char*)malloc((map_width*map_height*UNDO_MAX)+UNDO_MAX); if (f) { int old_map_width = 0, old_map_height = 0; fread(&old_map_width, 1, 1, f); fread(&old_map_height, 1, 1, f); if (old_map_width == map_width && old_map_height == map_height) { fread(map, map_width*map_height*2, 1, f); } else { unsigned char* old_map = (unsigned char*)malloc(old_map_width*old_map_height); fread(old_map, old_map_width*old_map_height*2, 1, f); for (int y = 0; y < map_height; y++) { for (int x = 0; x < map_width; x++) { map[x + y*map_width] = 0; map[(x + y*map_width)+(map_width*map_height)] = 0; if (old_map_width > x && old_map_height > y && (x + y*map_width) < (old_map_width*old_map_height)) { map[x + y*map_width] = old_map[x + y*(old_map_width)]; map[(x + y*map_width)+(map_width*map_height)] = old_map[(x + y*(old_map_width))+(old_map_width*old_map_height)]; } } } dialog = 2; } fclose(f); } else { f = fopen(GetPath(map_filename), "wb"); if (!f) { error = 3; return; } fwrite(&map_width, 1, 1, f); fwrite(&map_height, 1, 1, f); fwrite(map, map_width*map_height*2, 1, f); fclose(f); dialog = 1; } sdlMinimapTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, map_width, map_height); UpdateMiniMap(); keyboard = SDL_GetKeyboardState(nullptr); //SDL_Surface* bmp = SDL_LoadBMP("assets.bmp"); //texture = SDL_CreateTextureFromSurface(renderer, bmp); //SDL_FreeSurface(bmp); } void Quit() { SDL_DestroyTexture(sdlFontTexture); SDL_DestroyRenderer(sdlRenderer); SDL_DestroyWindow(sdlWindow); SDL_Quit(); } void Flip() { SDL_RenderPresent(sdlRenderer); } void Clear() { SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255); SDL_RenderClear(sdlRenderer); } void Draw(SDL_Texture* texture, int x, int y, int sx, int sy, int w, int h) { SDL_Rect src, dst; src.x = sx; src.y = sy; dst.x = x; dst.y = y; src.w = dst.w = w; src.h = dst.h = h; SDL_RenderCopy(sdlRenderer, texture, &src, &dst); } void FillRect(int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255) { SDL_Rect src; src.x = x; src.y = y; src.w = w; src.h = h; SDL_SetRenderDrawColor(sdlRenderer, r, g, b, a); SDL_RenderFillRect(sdlRenderer, &src); } void DrawRect(int x, int y, int w, int h, Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255) { SDL_Rect src; src.x = x; src.y = y; src.w = w; src.h = h; SDL_SetRenderDrawColor(sdlRenderer, r, g, b, a); SDL_RenderDrawRect(sdlRenderer, &src); } void Print(int x, int y, const char* text) { int str_size = strlen(text); for (int i = 0; i < str_size; i++) { char chr = text[i] - 32; Draw(sdlFontTexture, x + (i * 6), y, (chr & 0x0f) * 6, (chr >> 4) * 6, 6, 6); } } bool Button(int x, int y, const char* text) { bool inside = (mouse.x >= x) && (mouse.y >= y) && (mouse.x < x + 55) && (mouse.y < y + 12); if (inside) { FillRect(x, y, 55, 13, 128, 64, 64, 255); } else { FillRect(x, y, 55, 13, 255, 64, 64, 255); } Print(x+4, y+4, text); return inside && mouse.buttons[0]; } bool Update() { anyKey = false; keyJustPressed = SDL_SCANCODE_UNKNOWN; while (SDL_PollEvent(&sdlEvent)) { if (sdlEvent.type == SDL_QUIT) {return true; break; } else if (sdlEvent.type == SDL_KEYDOWN) { anyKey = true; keyJustPressed = sdlEvent.key.keysym.scancode; if (sdlEvent.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { return true; } } } Uint32 buttons = SDL_GetMouseState(&mouse.x, &mouse.y); 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) { mouse.buttons[0] = (buttons & 1) == 1; mouse.buttons[1] = (buttons & 2) == 2; mouse.buttons[2] = (buttons & 4) == 4; } else { mouse.buttons[0] = mouse.buttons[1] = mouse.buttons[2] = false; } return false; } void PrintFatalError(const char* errorMsg) { int size = strlen(errorMsg); Print((screen_width - (size*6)) / 2, (screen_height - 6) / 2, errorMsg); } void ShowError() { switch (error) { case 1: PrintFatalError("config.ini not found"); break; case 2: PrintFatalError("tiles file not found"); break; case 3: PrintFatalError("cannot create map file"); break; } } void ShowDialog() { int size = 0; switch (dialog) { case 1: size = strlen("Map file not found"); Print((screen_width - (size * 6)) / 2, (screen_height - 6) / 2, "Map file not found"); size = strlen("A new one has been created"); Print((screen_width - (size * 6)) / 2, ((screen_height - 6) / 2)+6, "A new one has been created"); if (Button((screen_width - 55) / 2, screen_height - 40, "Ok")) { dialog = 0; ignoreMouse = true; } break; case 2: size = strlen("Map has been resized"); Print((screen_width - (size * 6)) / 2, (screen_height - 6) / 2, "Map has been resized"); size = strlen("using config.ini info"); Print((screen_width - (size * 6)) / 2, ((screen_height - 6) / 2) + 6, "using config.ini info"); if (Button((screen_width - 55) / 2, screen_height - 40, "Ok")) { dialog = 0; ignoreMouse = true; } break; //case 3: PrintFatalError("No s'ha trobat l'arxiu de mapa"); break; } } void DoTilePal() { int ox = 0, oy = 0; if (tilemap_width <= screen_width) { ox = (screen_width - tilemap_width) / 2; } else { const int max_offset = tilemap_width - screen_width; const float mouse_ratio = float(mouse.x) / float(screen_width); ox = -(mouse_ratio * max_offset); } if (tilemap_height <= screen_height) { oy = (screen_height - tilemap_height) / 2; } else { const int max_offset = tilemap_height - screen_height; const float mouse_ratio = float(mouse.y) / float(screen_height); oy = -(mouse_ratio * max_offset); } Draw(sdlTilesTexture, ox, oy, 0, 0, tilemap_width, tilemap_height); int tiles_per_row = tilemap_width / tile_width; DrawRect(ox + (tile_back % tiles_per_row)*tile_width - 1, oy + (tile_back / tiles_per_row)*tile_height - 1, tile_width + 2, tile_height + 2, 255, 64, 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); if (mouse.buttons[2]) { tile_back = ((mouse.x - ox) / tile_width) + ((mouse.y - oy) / tile_height) * tiles_per_row; state = STATE_TILEMAP; ignoreMouse = true; } if (mouse.buttons[0]) { tile_sel = ((mouse.x - ox) / tile_width) + ((mouse.y - oy) / tile_height) * tiles_per_row; state = STATE_TILEMAP; ignoreMouse = true; } 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[CTRL] ) || ( (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[CTRL]; 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; const int width_in_tiles = screen_width / tile_width; const int height_in_tiles = screen_height / tile_height; const int pal_width_in_tiles = tilemap_width / tile_width; for (int y = 0; y < height_in_tiles; y++) { for (int x = 0; x < width_in_tiles; x++) { unsigned char tile = map[(map_x + x) + (map_y + y) * map_width]; Draw(sdlTilesTexture, x*tile_width, y*tile_height, (tile % pal_width_in_tiles)*tile_width, (tile / pal_width_in_tiles)*tile_height, tile_width, tile_height); if (!keyboard[SDL_SCANCODE_LSHIFT]) { unsigned char sprite = map[((map_x + x) + (map_y + y) * map_width) + (map_width*map_height)]; if (sprite != 0) Draw(sdlTilesTexture, x*tile_width, y*tile_height, (sprite % pal_width_in_tiles)*tile_width, (sprite / pal_width_in_tiles)*tile_height, tile_width, tile_height); } } } if (!menu) { const int cur_x = mouse.x / tile_width; const int cur_y = mouse.y / tile_height; 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; } 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; } if (keyJustPressed == SDL_SCANCODE_RIGHT || keyJustPressed == SDL_SCANCODE_D) if (map_x < map_width - width_in_tiles) 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_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(); } static int scroll_x = 0; static int scroll_y = 0; static int old_map_x = 0; static int old_map_y = 0; if (mouse.mouse_down[MOUSE_BUTTON_LEFT] || mouse.mouse_down[MOUSE_BUTTON_RIGHT]) { Undo_Op(); } if (mouse.mouse_down[MOUSE_BUTTON_LEFT]) { old_map_x = map_x; old_map_y = map_y; scroll_x = cur_x; scroll_y = cur_y; } if (mouse.buttons[MOUSE_BUTTON_RIGHT]) { if (tile_back < sprites) map[(map_x + cur_x) + (map_y + cur_y)*map_width] = tile_back; } if (mouse.buttons[MOUSE_BUTTON_LEFT]) { if (keyboard[SDL_SCANCODE_SPACE]) { map_x = old_map_x - (cur_x - scroll_x); map_y = old_map_y - (cur_y - scroll_y); } else { const int pos = (map_x + cur_x) + (map_y + cur_y)*map_width; if (tile_sel >= sprites) { ignoreMouse = true; if (map[pos + (map_width*map_height)] == 0) { map[pos + (map_width*map_height)] = tile_sel; } else { map[pos + (map_width*map_height)] = 0; } } else { map[pos] = tile_sel; } } } if (mouse.buttons[MOUSE_BUTTON_MIDDLE]) { tile_sel = map[(map_x + cur_x) + (map_y + cur_y)*map_width]; } if (keyJustPressed == SDL_SCANCODE_Z && keyboard[CTRL]) { Undo_Undo(); } if (keyJustPressed == SDL_SCANCODE_Y && keyboard[CTRL]) { Undo_Redo(); } if (keyJustPressed == SDL_SCANCODE_Z && keyboard[CTRL] && 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")) { FILE* f = fopen(GetPath(map_filename), "wb"); fwrite(&map_width, 1, 1, f); fwrite(&map_height, 1, 1, f); fwrite(map, map_width*map_height*2, 1, f); fclose(f); 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; } } 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; } for (int x = 0; x < width_in_tiles; x++) { map[(map_x + x) + (map_y) * map_width] = tile_sel; map[(map_x + x) + (map_y + height_in_tiles - 1) * map_width] = tile_sel; } menu = false; ignoreMouse = true; } } } #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); unsigned char* new_map = (unsigned char*)malloc(map_width*map_height); for (int y = 0; y < map_height; y++) { for (int x = 0; x < map_width; x++) { new_map[x + y*map_width] = map[mod(x+sx, map_width) + mod(y+sy, map_height)*map_width]; } } free(map); map = new_map; UpdateMiniMap(); } void DoMiniMap() { int ox = 0, oy = 0; if (map_width <= screen_width) { ox = (screen_width - map_width) / 2; } else { const int max_offset = map_width - screen_width; const float mouse_ratio = float(mouse.x) / float(screen_width); ox = -(mouse_ratio * max_offset); } if (map_height <= screen_height) { oy = (screen_height - map_height) / 2; } else { const int max_offset = map_height - screen_height; const float mouse_ratio = float(mouse.y) / float(screen_height); oy = -(mouse_ratio * max_offset); } Draw(sdlMinimapTexture, ox, oy, 0, 0, map_width, map_height); const int screen_width_in_tiles = screen_width / tile_width; 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; state = STATE_TILEMAP; ignoreMouse = true; } if (keyJustPressed == SDL_SCANCODE_E) state = STATE_TILEMAP; if (keyboard[CTRL]) { if (keyJustPressed == SDL_SCANCODE_A) ShiftMap(1, 0); if (keyJustPressed == SDL_SCANCODE_D) ShiftMap(-1, 0); if (keyJustPressed == SDL_SCANCODE_W) ShiftMap(0, 1); if (keyJustPressed == SDL_SCANCODE_S) ShiftMap(0, -1); } } int main(int argc, char* argv[]) { /*const int len = strlen(argv[0])-30; memcpy(path, argv[0], len); path[len] = '\0';*/ Init(); while (!Update()) { Clear(); if (error == 0) { if (dialog == 0) { switch (state) { case STATE_TILEMAP: DoTileMap(); break; case STATE_TILEPAL: DoTilePal(); break; case STATE_MINIMAP: DoMiniMap(); break; }; /*char num[5]; sprintf(num, "%d", mouse.x); Print(100, 100, num); sprintf(num, ",%d", mouse.y); Print(118, 100, num); if (Button(2, 2, "New")) { strcpy(state, "New pressed"); } if (Button(2, 12, "Open")) { strcpy(state, "open pressed"); } if (Button(2, 22, "Save")) { strcpy(state, "save pressed"); } if (Button(2, 32, "Save As")) { strcpy(state, "Save As pressed"); } FillRect(0, 183, 256, 9, 128, 128, 128, 255); Print(2, 185, state);*/ } else { ShowDialog(); } } else { ShowError(); } Flip(); } Quit(); return 0; }