C++ C++/SDL:淡出已具有每像素alpha信息的曲面

C++ C++/SDL:淡出已具有每像素alpha信息的曲面,c++,sdl,alpha,fading,C++,Sdl,Alpha,Fading,假设我们有一个32位的PNG文件,它是以半透明的方式绘制的,具有某种幽灵/无形的字符。它不是在每个地方都一样透明,所以我们需要在加载到曲面时获得每像素的alpha信息 对于淡入/淡出,设置整个曲面的alpha值是一个好方法;但在这种情况下不是这样,因为曲面已经具有每像素信息,而SDL不会将这两者结合起来 什么是一个有效的解决方法(而不是要求艺术家为角色提供一些很棒的淡入/淡出动画)?我认为实现所需效果的最简单方法是首先加载包含角色精灵的源曲面,然后,对于重影的每个实例,创建曲面的工作副本。您需要

假设我们有一个32位的PNG文件,它是以半透明的方式绘制的,具有某种幽灵/无形的字符。它不是在每个地方都一样透明,所以我们需要在加载到曲面时获得每像素的alpha信息

对于淡入/淡出,设置整个曲面的alpha值是一个好方法;但在这种情况下不是这样,因为曲面已经具有每像素信息,而SDL不会将这两者结合起来


什么是一个有效的解决方法(而不是要求艺术家为角色提供一些很棒的淡入/淡出动画)?

我认为实现所需效果的最简单方法是首先加载包含角色精灵的
曲面,然后,对于重影的每个实例,创建曲面的
工作副本。您需要做的是,每当实例的alpha值发生变化时,
SDL_BlitSurface
()将您的
源代码
复制到您的
工作
副本中,然后应用透明度(您可能应该将其保持为介于0和1之间的浮点值),然后在每个像素的alpha通道上应用透明度

在32位曲面的情况下,假设您最初加载
并分配
工作
SDL_曲面
s,您可能可以按照以下方式执行操作:

SDL_BlitSurface(source, NULL, working, NULL);
if(SDL_MUSTLOCK(working)) 
{
    if(SDL_LockSurface(working) < 0) 
    {
        return -1;
    }
}

Uint8 * pixels = (Uint8 *)working->pixels;
pitch_padding = (working->pitch - (4 * working->w));
pixels += 3; // Big Endian will have an offset of 0, otherwise it's 3 (R, G and B)
for(unsigned int row = 0; row < working->h; ++row) 
{
    for(unsigned int col = 0; col < working->w; ++col) 
    {
        *pixels = (Uint8)(*pixels * character_transparency); // Could be optimized but probably not worth it
        pixels += 4;
    }
    pixels += pitch_padding;
}

if(SDL_MUSTLOCK(working)) 
{
    SDL_UnlockSurface(working);
}
SDL_BlitSurface(源、空、工作、空);
如果(SDL_必须锁定(工作))
{
如果(SDL_锁面(工作)<0)
{
返回-1;
}
}
Uint8*像素=(Uint8*)工作->像素;
螺距_填充=(工作->螺距-(4*工作->w));
像素+=3;//Big-Endian的偏移量为0,否则为3(R、G和B)
对于(无符号整数行=0;行<工作->h;++行)
{
for(无符号整数列=0;列<工作->w;++col)
{
*像素=(Uint8)(*像素*字符透明度);//可以优化,但可能不值得
像素+=4;
}
像素+=基音填充;
}
如果(SDL_必须锁定(工作))
{
SDL_解锁表面(工作);
}

这段代码的灵感来自于
SDL\u gfx
(),但是如果你只是这么做,我就不会为此而费心去链接库了。

看起来很棒!我一有时间就试试这个。很好,谢谢!我还将4s替换为working->format->BytePerPixel,并使用SDL_字节顺序检查endianness。