#include #include "area.h" #include "layer.h" #include "viewport.h" #include "resources/map.h" #include "logging.h" static void blit_map_layers(struct map *, struct area *); static void blit_map_layer(struct map *, enum map_layer_id, struct area *, enum area_layer_id); struct area * area_new(struct map *map) { struct area *a; a = malloc(sizeof(*a)); if (a == NULL) { return NULL; } blit_map_layers(map, a); return a; } static void blit_map_layers(struct map *map, struct area *area) { area->map_layers[AREA_LAYER_BOT] = SDL_CreateRGBSurface( SDL_HWSURFACE | SDL_SRCCOLORKEY, map->width * map->tilewidth, map->height * map->tileheight, 32, 0, 0, 0, 0); blit_map_layer(map, MAP_LAYER_GROUND, area, AREA_LAYER_BOT); blit_map_layer(map, MAP_LAYER_OBJ_LOW, area, AREA_LAYER_BOT); area->map_layers[AREA_LAYER_MID] = SDL_CreateRGBSurface( SDL_HWSURFACE | SDL_SRCCOLORKEY, map->width * map->tilewidth, map->height * map->tileheight, 32, 0, 0, 0, 0); blit_map_layer(map, MAP_LAYER_OBJ_MID, area, AREA_LAYER_MID); area->map_layers[AREA_LAYER_TOP] = SDL_CreateRGBSurface( SDL_HWSURFACE | SDL_SRCCOLORKEY, map->width * map->tilewidth, map->height * map->tileheight, 32, 0, 0, 0, 0); blit_map_layer(map, MAP_LAYER_OBJ_HIGH, area, AREA_LAYER_TOP); } static void blit_map_layer(struct map *map, enum map_layer_id map_layer, struct area *area, enum area_layer_id area_layer) { int i; Uint32 gid; int tile_found; struct map_tileset *mts; Uint32 mts_lastgid; SDL_Rect tilerect, layerrect; SDL_SetColorKey(area->map_layers[area_layer], SDL_SRCCOLORKEY, 0); for (i = 0; i < map->width * map->height; ++i) { gid = map->layers[map_layer].tiles[i]; if (gid == 0) { continue; } tile_found = 0; for (mts = map->tilesets_head; mts != NULL; mts = mts->next) { mts_lastgid = mts->firstgid + mts->tileset->width * mts->tileset->height; if (gid >= mts->firstgid && gid < mts_lastgid) { gid -= mts->firstgid; tilerect.x = gid % mts->tileset->width; tilerect.y = gid / mts->tileset->width; tilerect.w = mts->tileset->tilewidth; tilerect.h = mts->tileset->tileheight; tilerect.x *= tilerect.w; tilerect.y *= tilerect.h; layerrect.x = i % map->width; layerrect.y = i / map->width; layerrect.w = mts->tileset->tilewidth; layerrect.h = mts->tileset->tileheight; layerrect.x *= layerrect.w; layerrect.y *= layerrect.h; #if 0 debug("Blitting %dx%d tile at (%d,%d) " "onto layer at (%d,%d)...", tilerect.w, tilerect.h, tilerect.x, tilerect.y, layerrect.x, layerrect.y); #endif SDL_BlitSurface(mts->tileset->image->image, &tilerect, area->map_layers[area_layer], &layerrect); tile_found = 1; break; } } if (!tile_found) { warn("Tile with gid 0x%8.8x not found", gid); } } } void render_area_to_viewport(struct area *area, struct viewport *vp) { SDL_Rect srcrect; SDL_Rect dstrect; srcrect.x = vp->x; srcrect.y = vp->y; srcrect.w = vp->w; srcrect.h = vp->h; dstrect.x = 0; dstrect.y = 0; dstrect.w = vp->w; dstrect.h = vp->h; render_area_to_surface(area, &srcrect, vp->screen, &dstrect); } void render_area_to_surface(struct area *area, SDL_Rect *arearect, SDL_Surface *surface, SDL_Rect *surfacerect) { SDL_Rect srcrect, dstrect; /* For demo */ SDL_Rect tmprect; memcpy(&srcrect, arearect, sizeof(srcrect)); memcpy(&dstrect, surfacerect, sizeof(dstrect)); /* Fast fill with black to avoid artifacts in off-map pixels. */ /* NB: This is gray, at least temporarily. */ SDL_FillRect(surface, &dstrect, SDL_MapRGB(surface->format, 63, 63, 63)); /* For demo */ tmprect.x = dstrect.x + 120 - 8; tmprect.y = dstrect.y + 80 - 12; tmprect.w = 16; tmprect.h = 20; /* Avoid fun glitches due to negative coordinates in source * rectangles. */ if (srcrect.x < 0) { srcrect.x = 0; dstrect.x = surfacerect->x - arearect->x; } if (srcrect.y < 0) { srcrect.y = 0; dstrect.y = surfacerect->y - arearect->y; } #if 0 debug("Rendering %dx%d area rect at (%d,%d) " "onto %dx%d surface rect at (%d,%d)...", srcrect.w, srcrect.h, srcrect.x, srcrect.y, dstrect.w, dstrect.h, dstrect.x, dstrect.y); #endif /* Blit bottom layer. */ SDL_BlitSurface(area->map_layers[AREA_LAYER_BOT], &srcrect, surface, &dstrect); /* return;*/ /* TODO: Blit low sprites. */ /* For demo */ SDL_FillRect(surface, &tmprect, SDL_MapRGB(surface->format, 31, 31, 127)); /* Blit middle layer. */ SDL_BlitSurface(area->map_layers[AREA_LAYER_MID], &srcrect, surface, &dstrect); /* TODO: Blit high sprites. */ /* Blit top layer. */ SDL_BlitSurface(area->map_layers[AREA_LAYER_TOP], &srcrect, surface, &dstrect); }