gpt4 book ai didi

c++ - SDL-绘制 'negative'圆圈( war 迷雾)

转载 作者:可可西里 更新时间:2023-11-01 18:04:04 32 4
gpt4 key购买 nike

我有800x600正方形要绘制到屏幕上。我想在其中“剪切”圆圈(其中alpha值为0)。基本上,我是在 map 上绘制整个矩形,因此我在绘制的这些“圆圈”中可以看到 map ,否则会看到灰色正方形

最佳答案

因此,我认为您正在尝试向其中一款游戏添加 war 迷雾?

几周前,我为本地大学制作了一个小型演示,以展示A *寻路功能,因此我认为我可以为您增加 war 迷雾。结果如下:

初始 map

首先,从完整的 map 开始,这是完全可见的



然后,我添加了一个覆盖整个屏幕的表面(请注意,我的 map 比屏幕小,因此在这种情况下,我只是在屏幕上添加了 war 迷雾,但是如果您要滚动,请确保它覆盖了每个 map 像素1:1)

mFogOfWar = SDL_CreateRGBSurface(SDL_HWSURFACE, in_Width, in_Height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_Rect screenRect = {0, 0, in_Width, in_Height};
SDL_FillRect(mFogOfWar, &screenRect, 0xFF202020);

然后,您需要绘制它...我在绘制游戏对象之后并且在绘制UI之前添加了此调用
DrawSurface(mFogOfWar, 0, 0);

在哪里
void RenderingManager::DrawSurface(SDL_Surface* in_Surface, int in_X, int in_Y)
{
SDL_Rect Dest = { in_X, in_Y, 0, 0 };
SDL_BlitSurface(in_Surface, NULL, mScreen, &Dest);
}

这应该给您以下结果:

“打洞表面”

然后,我创建了一个如下所示的32位 .png(棋盘显示alpha)

渲染主角时,我添加了此调用:
gRenderingManager.RemoveFogOfWar(int(mX) + SPRITE_X_OFFSET, int(mY) + SPRITE_Y_OFFSET);

偏移仅用于使子画面与子画面居中,基本上,我要传递给 RemoveFogOfWar的内容是我的子画面的中心。

移除 war 迷雾

现在是 war 迷雾的肉。我做了两个版本,一个版本永久删除了 war 迷雾,另一个版本重置了 war 迷雾。我的 war 迷雾重置依赖于 punch表面具有将alpha重置为 0的轮廓,并且我的角色每帧移动的像素少于轮廓包含的像素,否则我将 Rect保留在应用打洞的位置,在重新绘制新的打洞器之前,我会重新填充它。

由于找不到与SDL的“乘积”混合,因此我决定编写一个简单的函数,该函数在打洞表面上进行迭代并在 war 迷雾的表面上更新Alpha。最重要的部分是确保您留在曲面的边界内,因此它占用了大部分代码...可能会有一些裁剪功能,但是我没有打扰检查:
void RenderingManager::RemoveFogOfWar(int in_X, int in_Y)
{
const int halfWidth = mFogOfWarPunch->w / 2;
const int halfHeight = mFogOfWarPunch->h / 2;

SDL_Rect sourceRect = { 0, 0, mFogOfWarPunch->w, mFogOfWarPunch->h };
SDL_Rect destRect = { in_X - halfWidth, in_Y - halfHeight, mFogOfWarPunch->w, mFogOfWarPunch->h };

// Make sure our rects stays within bounds
if(destRect.x < 0)
{
sourceRect.x -= destRect.x; // remove the pixels outside of the surface
sourceRect.w -= sourceRect.x; // shrink to the surface, not to offset fog
destRect.x = 0;
destRect.w -= sourceRect.x; // shrink the width to stay within bounds
}
if(destRect.y < 0)
{
sourceRect.y -= destRect.y; // remove the pixels outside
sourceRect.h -= sourceRect.y; // shrink to the surface, not to offset fog
destRect.y = 0;
destRect.h -= sourceRect.y; // shrink the height to stay within bounds
}

int xDistanceFromEdge = (destRect.x + destRect.w) - mFogOfWar->w;
if(xDistanceFromEdge > 0) // we're busting
{
sourceRect.w -= xDistanceFromEdge;
destRect.w -= xDistanceFromEdge;
}
int yDistanceFromEdge = (destRect.y + destRect.h) - mFogOfWar->h;
if(yDistanceFromEdge > 0) // we're busting
{
sourceRect.h -= yDistanceFromEdge;
destRect.h -= yDistanceFromEdge;
}

SDL_LockSurface(mFogOfWar);

Uint32* destPixels = (Uint32*)mFogOfWar->pixels;
Uint32* srcPixels = (Uint32*)mFogOfWarPunch->pixels;

static bool keepFogRemoved = false;

for(int x = 0; x < destRect.w; ++x)
{
for(int y = 0; y < destRect.h; ++y)
{
Uint32* destPixel = destPixels + (y + destRect.y) * mFogOfWar->w + destRect.x + x;
Uint32* srcPixel = srcPixels + (y + sourceRect.y) * mFogOfWarPunch->w + sourceRect.x + x;

unsigned char* destAlpha = (unsigned char*)destPixel + 3; // fetch alpha channel
unsigned char* srcAlpha = (unsigned char*)srcPixel + 3; // fetch alpha channel
if(keepFogRemoved == true && *srcAlpha > 0)
{
continue; // skip this pixel
}

*destAlpha = *srcAlpha;
}
}

SDL_UnlockSurface(mFogOfWar);
}

即使角色移动后,它也使用 keepFogRemoved = false给了我

而这与 keepFogRemoved = true
验证

重要的部分实际上是确保不要在像素缓冲区之外进行写操作,因此请注意带有负偏移量或可能使您脱离宽度或高度的偏移量。为了验证我的代码,我在单击鼠标时尝试了对 RemoveFogOfWar的简单调用,并尝试了拐角和边缘,以确保我没有出现“一举两得”的问题
case SDL_MOUSEBUTTONDOWN:
{
if(Event.button.button == SDL_BUTTON_LEFT)
{
gRenderingManager.RemoveFogOfWar(Event.button.x, Event.button.y);
}
break;
}

注释

显然,“打洞”不需要32位纹理,但这是我想到的最清晰的方法来向您展示如何进行操作。可以使用每个像素低至1位(打开/关闭)来完成此操作。您还可以添加一些渐变,然后更改
if(keepFogRemoved == true && *srcAlpha > 0)
{
continue; // skip this pixel
}


if(*srcAlpha > *destAlpha)
{
continue;
}

要保持这样的平滑混合:

3状态的 war 迷雾

我以为我应该添加这个...我添加了一种创建三态 war 迷雾的方法: visibleseenfogged

为此,我只需保留上次“打洞” war 迷雾的位置的 SDL_Rect,如果alpha值低于某个值,则将其限制在该值。

因此,只需添加
for(int x = 0; x < mLastFogOfWarPunchPosition.w; ++x)
{
for(int y = 0; y < mLastFogOfWarPunchPosition.h; ++y)
{
Uint32* destPixel = destPixels + (y + mLastFogOfWarPunchPosition.y) * mFogOfWar->w + mLastFogOfWarPunchPosition.x + x;
unsigned char* destAlpha = (unsigned char*)destPixel + 3;

if(*destAlpha < 0x60)
{
*destAlpha = 0x60;
}
}
}
mLastFogOfWarPunchPosition = destRect;

就在“扑朔迷离” war 迷雾的循环之前,我得到的 war 迷雾类似于您在《星际争霸》等游戏中可能遇到的情况:

现在,由于“看到的” war 迷雾是半透明的,因此您将需要调整渲染方法以正确地裁剪将在雾中出现的“敌人”,因此您看不到它们,但仍然可以看到地形。

希望这可以帮助!

关于c++ - SDL-绘制 'negative'圆圈( war 迷雾),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13654753/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com