#include static inline Uint32 _surf_pixel (SDL_Surface *surface, int x, int y) { int bpp = SDL_BYTESPERPIXEL (surface->format); Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp; switch (bpp) { case 1: return *p; case 2: return *(Uint16 *) p; case 3: if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { return p[0] << 16 | p[1] << 8 | p[2]; } else { return p[0] | p[1] << 8 | p[2] << 16; } case 4: return *(Uint32 *) p; default: return 0; // shouldn't happen } } World * World_load_from_file (const char *path) { World *self = g_new0 (World, 1); self->buildings = g_array_new (FALSE, FALSE, sizeof (Building *)); SDL_Surface *surf = IMG_Load (path); if (!surf) { g_warning ("Failed to load map from path %s (returning NULL): %s", path, SDL_GetError ()); return NULL; } self->width = surf->w; self->height = surf->h; self->tiles = g_array_sized_new (FALSE, FALSE, sizeof (MapTile *), surf->w * surf->h); SDL_LockSurface (surf); const SDL_PixelFormatDetails *details = SDL_GetPixelFormatDetails (surf->format); for (int y = 0; y < surf->h; ++y) { for (int x = 0; x < surf->w; ++x) { MapTile *mt = g_new0 (MapTile, 1); mt->x = x; mt->y = y; Uint32 pixel = _surf_pixel (surf, x, y); Uint8 r, g, b, a; /* NULL is a palette, only used in indexed images. */ SDL_GetRGBA (pixel, details, NULL, &r, &g, &b, &a); /* Improved color ranges (handles light blue water better) */ if (b > 120 && (b > g || b > r)) { /* Water: medium-to-light blues */ mt->terrain_type = TERRAIN_WATER; } else if (g > 140 && g >= r && g >= b) { /* Green-dominant = flat/grassland */ mt->terrain_type = TERRAIN_FLAT; } else { /* Otherwise: hills/mountains */ mt->terrain_type = TERRAIN_HILL; } /* Thanks, ChatGPT! */ g_array_append_val (self->tiles, mt); } } SDL_UnlockSurface (surf); SDL_DestroySurface (surf); return self; }