bool PicPxIsEdge(const Pic *pic, const Vec2i pos, const bool isPixel) { const GraphicsDevice *g = &gGraphicsDevice; const bool isTopOrBottomEdge = pos.y == -1 || pos.y == pic->size.y; const bool isLeftOrRightEdge = pos.x == -1 || pos.x == pic->size.x; const bool isLeft = pos.x > 0 && !isTopOrBottomEdge && PixelToColor(g, *(pic->Data + pos.x - 1 + pos.y * pic->size.x)).a; const bool isRight = pos.x < pic->size.x - 1 && !isTopOrBottomEdge && PixelToColor(g, *(pic->Data + pos.x + 1 + pos.y * pic->size.x)).a; const bool isAbove = pos.y > 0 && !isLeftOrRightEdge && PixelToColor(g, *(pic->Data + pos.x + (pos.y - 1) * pic->size.x)).a; const bool isBelow = pos.y < pic->size.y - 1 && !isLeftOrRightEdge && PixelToColor(g, *(pic->Data + pos.x + (pos.y + 1) * pic->size.x)).a; if (isPixel) { return !(isLeft && isRight && isAbove && isBelow); } else { return isLeft || isRight || isAbove || isBelow; } }
static void DrawGuideImage( DrawBuffer *b, SDL_Surface *guideImage, Uint8 alpha) { SDL_LockSurface(guideImage); // Scale based on ratio between map size and guide image size, // so that the guide image stretches to the map size double xScale = (double)guideImage->w / (gMap.Size.x * TILE_WIDTH); double yScale = (double)guideImage->h / (gMap.Size.y * TILE_HEIGHT); for (int j = 0; j < b->g->cachedConfig.Res.y; j++) { int y = (int)round((j + b->yTop) * yScale); for (int i = 0; i < b->g->cachedConfig.Res.x; i++) { int x = (int)round((i + b->xTop) * xScale); if (x >= 0 && x < guideImage->w && y >= 0 && y < guideImage->h) { int imgIndex = y * guideImage->w + x; Uint32 p = ((Uint32 *)guideImage->pixels)[imgIndex]; color_t c = PixelToColor(b->g, p); c.a = alpha; Draw_Point(i, j, c); } } } SDL_UnlockSurface(guideImage); }
void PicTrim(Pic *pic, const bool xTrim, const bool yTrim) { // Scan all pixels looking for the min/max of x and y Vec2i min = pic->size; Vec2i max = Vec2iZero(); for (Vec2i pos = Vec2iZero(); pos.y < pic->size.y; pos.y++) { for (pos.x = 0; pos.x < pic->size.x; pos.x++) { const Uint32 pixel = *(pic->Data + pos.x + pos.y * pic->size.x); if (PixelToColor(&gGraphicsDevice, pixel).a > 0) { min.x = MIN(min.x, pos.x); min.y = MIN(min.y, pos.y); max.x = MAX(max.x, pos.x); max.y = MAX(max.y, pos.y); } } } // If no opaque pixels found, don't trim Vec2i newSize = pic->size; Vec2i offset = Vec2iZero(); if (min.x < max.x && min.y < max.y) { if (xTrim) { newSize.x = max.x - min.x + 1; offset.x = min.x; } if (yTrim) { newSize.y = max.y - min.y + 1; offset.y = min.y; } } // Trim by copying pixels Uint32 *newData; CMALLOC(newData, newSize.x * newSize.y * sizeof *newData); for (Vec2i pos = Vec2iZero(); pos.y < newSize.y; pos.y++) { for (pos.x = 0; pos.x < newSize.x; pos.x++) { Uint32 *target = newData + pos.x + pos.y * newSize.x; const int srcIdx = pos.x + offset.x + (pos.y + offset.y) * pic->size.x; *target = *(pic->Data + srcIdx); } } // Replace the old data CFREE(pic->Data); pic->Data = newData; pic->size = newSize; pic->offset = Vec2iZero(); }
bool TMXLoader::Private::processMap(XMLElement &m) { if ((XML_SUCCESS != m.QueryIntAttribute("width", &map_size.width)) || (XML_SUCCESS != m.QueryIntAttribute("height", &map_size.height)) || (XML_SUCCESS != m.QueryIntAttribute("tilewidth", &tile_size.width)) || (XML_SUCCESS != m.QueryIntAttribute("tileheight", &tile_size.height))) { MMWARNING("Map element is missing one or more required attributes."); return(false); } /* default scale */ scale.set(1.f, 1.f); /* process properties */ XMLElement *l_properties = m.FirstChildElement(TMXPROPERTIES_NODE); XMLElement *l_property = l_properties ? l_properties->FirstChildElement(TMXPROPERTIES_PROPERTY_NODE) : 0; if (l_property) do { const char *l_pname = l_property->Attribute("name"); if (!l_pname) continue; /* scale property */ if (0 == MMSTRCASECMP(l_pname, "scale")) { const char *l_value = l_property->Attribute("value"); if (!l_value) { MMWARNING("Skipping incomplete scale property."); continue; } if (0 == MMSTRCASECMP(l_value, "screen")) { const Math::Size2f &l_vsize = Graphics::Viewport::Size(); const Math::Size2i &l_wsize = Graphics::Viewport::WindowSize(); /* * calculate pixels per viewport coordinate ratio * scale ratio = vSize (vcoord)) / wSize (pixels) */ scale = l_vsize / l_wsize.cast<float>(); continue; } else if (2 == sscanf(l_value, "%fx%f", &scale.width, &scale.height)) continue; else if (1 == sscanf(l_value, "%f", &scale.width)) { scale.height = scale.width; continue; } MMERROR("Invalid scale value encountered."); continue; } /* * Parse scene background color */ else if (0 == MMSTRCASECMP(l_pname, "bgcolor")) { const char *l_value = l_property->Attribute("value"); if (!l_value) { MMWARNING("Skipping incomplete background color property."); continue; } /* * Valid formats: #RRGGBB, RRGGBB. */ uint16_t l_pxl[3]; if ((sscanf(l_value, "#%2hx%2hx%2hx", &l_pxl[0], &l_pxl[1], &l_pxl[2]) != 3) && (sscanf(l_value, "%2hx%2hx%2hx", &l_pxl[0], &l_pxl[1], &l_pxl[2]) != 3)) { MMWARNING("Skipping invalid background color value."); continue; } /* set background color */ Game::SceneBase &l_scene_base = static_cast<Game::SceneBase &>(scene); l_scene_base.setBackground(PixelToColor(l_pxl)); continue; } } while ((l_property = l_property->NextSiblingElement(TMXPROPERTIES_PROPERTY_NODE))); MMINFO("Map scale size (" << scale.width << "x" << scale.height << ")"); /* calculate half-relative map size (used to offset coordinates) */ hrmap_size.width = scale.width * static_cast<float>(map_size.width * tile_size.width); hrmap_size.height = scale.height * static_cast<float>(map_size.height * tile_size.height); return(true); }