Пример #1
0
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;
	}
}
Пример #2
0
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);
}
Пример #3
0
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();
}
Пример #4
0
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);
}