SDL在闪电战中,失去透明度并变黑

SDL on blit, loses transparency and turns black

本文关键字:透明度 失去 闪电战 SDL      更新时间:2023-10-16

几个星期以来,我和朋友们一直在做一个项目。确切地说是一场比赛。我们遇到了一个巨大的问题,这个问题破坏了游戏。玩家应该是透明的部分是黑色的。

MergeSurfaces函数是blit。Rect本身被写入SDL_Rect,blit被执行

void MergeSurfaces(SDL_Surface *From, SDL_Surface *To, int FromX, int FromY, int FromWidth, int FromLenght, int ToX, int ToY){


            SDL_Rect srcRect;    
            srcRect.x = FromX;    
            srcRect.y = FromY;
            srcRect.w = FromWidth;   
            srcRect.h = FromLenght;
            SDL_Rect dstRect;    
            dstRect.x = ToX;    
            dstRect.y = ToY;    
            SDL_BlitSurface(From, &srcRect, To, &dstRect);
        }

这就是玩家成型功能。

//------------------------------------------------------------------------------------------
//----MAIN LOAD FUNCTION
//------------------------------------------------------------------------------------------    
    void LoadPlayerGraphics(SDL_Surface* BodyID[], int PlayerHeight, int PlayerWidth, long EquipmentID[], int MovementAmountX, int MovementAmountY){
        SDL_Surface* Image;
        SDL_Surface* EquipmentColorization;
        std::string FileName;
        int ID;

        Clean(BodyID,MovementAmountX*MovementAmountY,PlayerWidth,PlayerHeight);

        for(int i = -1; i < 8; i++){
            ID = 0;
            //here we put a small exception to firstly load the player. And only then dress Him
            if(i == -1){
                FileName = "resource/images/Player/WhiteMaleBody.png";
                goto playerbody;
            }
            if(EquipmentID[i] != 0){
                GetFileNameByID(EquipmentID[i],FileName);
            playerbody:
                Image = IMG_Load(FileName.c_str());
                if(Image == NULL){
                    exit(1);
                }
                //Needed for equipment coloring. At this point we will put RGB masks in order to color the armor by it's type
                EquipmentColorization = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, MovementAmountX*PlayerWidth, MovementAmountY*PlayerHeight, 32, 0, 0, 0, 0);

                GraphicsFunctions.MergeSurfaces(Image,EquipmentColorization,0,0,MovementAmountX*PlayerWidth,MovementAmountY*PlayerHeight,0,0);
                for(int i = 0; i < MovementAmountY; i++){
                    for(int j = 0; j < MovementAmountX; j++){
                        ID++;   
                        //We put the graphics on and on on top. So we dress the frames. BodyID[ID] are frames by motion ID. We just fill this up.
                        GraphicsFunctions.MergeSurfaces(    EquipmentColorization,BodyID[ID],
                                                            (j * PlayerWidth),
                                                            (i * PlayerHeight),
                                                            PlayerWidth,PlayerHeight,
                                                            0,0);
                        if(BodyID[i] == NULL){
                            exit(2);
                        }
                    }
                }
            }
        }
    }

Clean函数,如果你想知道它的作用。我还没有解放这里的表面。由于我是在程序结束时完成的,到目前为止,这已经加载了一次。所以基本上,它只是为了创建这些表面,以便填充它们。

void Clean(SDL_Surface* TheSurface[], int MovementAmount, int PlayerWidth, int PlayerHeight){
        GraphicsFunctions.Setrgba();
        for(int i = 0; i <= MovementAmount; i++){
            TheSurface[i] = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, PlayerWidth, PlayerHeight, 32, 0, 0, 0, 0);
        }
    }

接下来是"框架"部分,或者使角色看起来正在移动。它在其他地方叫,所以我可以很容易地控制速度。

void Variate(SDL_Surface* Graphical_Output){
        GraphicsFunctions.MergeSurfaces(BodyID[MovementVariationID[MovementID][Variation]], Graphical_Output, 0, 0, PlayerWidth, PlayerHeight, 0, 0);
        Variation++;
        if(Variation == MovementVariationIn[MovementID]){
            Variation = 0;
        }
    }

这是主线程控件。主系统线程,Blits和Flips到您在这里看到的表面。

//------------------------------------------------------------------------------------------
//----MAIN Thread Function (As Thread Repeat to infinity LOL)
//------------------------------------------------------------------------------------------
    int Player_Main(void *unused){
        GraphicsFunctions.Setrgba();
        PlayerGraphics = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, 1024, 768, 32, GraphicsFunctions.r, GraphicsFunctions.g, GraphicsFunctions.b, GraphicsFunctions.a);
        while(!EndProgram){
            PlayerMovementGraphics::Variate(PlayerGraphics);
            SDL_Delay(200);
        }
        return 0;
    }

当然,这里还需要改进。但自从我几周前开始研究SDL以来。我还有很多东西要学。这基本上就是目前图形的全部内容。因此,也许你可以检测到为什么玩家本身在应该透明的地方是黑色的。

您编写:

SDL_CreateRGBSurface( SDL_HWSURFACE | SDL_SRCALPHA,
                      PlayerWidth, PlayerHeight, 
                      32, 0, 0, 0, 0 );

来自文件:

对RGB遮罩使用零将根据深度设置默认值。然而,对Amask使用零会导致Amask为0。

如果你想要阿尔法通道,你需要明确指定你的掩码:

SDL_CreateRGBSurface( SDL_HWSURFACE | SDL_SRCALPHA,
                      PlayerWidth, PlayerHeight, 32,
                      0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF );