KILEYI

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

sdlpal精灵素材内存截取并保存到硬盘

github地址

https://github.com/sdlpal/sdlpal

 

简单阅读了一下源码,虽然项目用到了stb_image.h,但是我们还需要stb_image_write.h来写文件,所以还得再搞一下

https://github.com/nothings/stb

 

打开项目文件

sdlpal\win32\sdlpal.sln

确保先能编译,并正确运行,我以DOS仙剑为例测试的

首先,关闭一些启动动画

打开 main.c 文件

//PAL_TrademarkScreen();
//PAL_SplashScreen();

 

项目中加入stb_image_write.h的include路径

打开 palette.c 文件,头部加入

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

加入全局变量和控制变量

复制代码
SDL_Color pe_palette[256];
int pe_palette_ready = 0;

static int bOnce_day = 0;
static int bOnce_night = 0;

static int bRec_day = 0;
static int bRec_night = 0;

static int pe_id = 0;
复制代码

在下面的 PAL_GetPalette 函数中找到 palette 部分代码,修改如下

复制代码
for (i = 0; i < 256; i++)
   {
      palette[i].r = buf[(fNight ? 256 * 3 : 0) + i * 3] << 2;
      palette[i].g = buf[(fNight ? 256 * 3 : 0) + i * 3 + 1] << 2;
      palette[i].b = buf[(fNight ? 256 * 3 : 0) + i * 3 + 2] << 2;

      if (iPaletteNum == 0)
      {
          if (pe_id == 1)
          {
              pe_palette[i].r = palette[i].r;
              pe_palette[i].g = palette[i].g;
              pe_palette[i].b = palette[i].b;
          }
          
      }
#if 0
      palette[i].r += (255 - palette[i].r) / 5;
      palette[i].g += (255 - palette[i].g) / 5;
      palette[i].b += (255 - palette[i].b) / 5;
#endif
   }
   
   if (iPaletteNum == 0)
   {
       if (!fNight)
       {
           if (bRec_day)
           {
               if (pe_id == 1)
               {
                   if (!bOnce_day)
                   {
                       bOnce_day = 1;

                       char* peOutFile = "pat_0_day.png";

                       int bRet = access(peOutFile, 0);
                       //0为存在
                       if (bRet != 0)
                       {
                           int w = 256;
                           int h = 1;
                           int n = 4;
                           unsigned char* data = malloc(w * h * n);

                           if (data != 0)
                           {
                               for (int i = 0; i < 256; i++)
                               {
                                   data[i * 4 + 0] = palette[i].r;
                                   data[i * 4 + 1] = palette[i].g;
                                   data[i * 4 + 2] = palette[i].b;
                                   data[i * 4 + 3] = 255;
                               }
                               stbi_write_png(peOutFile, w, h, n, data, w * n);

                               free(data);
                           }
                       }
                   }
               }
           }
           
           if (pe_id == 1)
           {
               pe_palette_ready = 1;
           }

           pe_id++;
       }
       //night palette
       else
       {
           if (bRec_night)
           {
               if (!bOnce_night)
               {
                   bOnce_night = 1;

                   char* peOutFile = "pat_0_night.png";

                   int bRet = access(peOutFile, 0);
                   if (bRet != 0)
                   {
                       int w = 256;
                       int h = 1;
                       int n = 4;
                       unsigned char* data = malloc(w * h * n);

                       if (data != 0)
                       {
                           for (int i = 0; i < 256; i++)
                           {
                               data[i * 4 + 0] = palette[i].r;
                               data[i * 4 + 1] = palette[i].g;
                               data[i * 4 + 2] = palette[i].b;
                               data[i * 4 + 3] = 255;
                           }
                           stbi_write_png(peOutFile, w, h, n, data, w * n);

                           free(data);
                       }
                   }
               }
           }
       }
   }
复制代码

调试运行,读档进入游戏后,在bOnce_day和bOnce_night处下断点,变量设为1,即可dump两个调色板

白天

 

夜晚

然后打开 palcommon.c 文件

参考 PAL_RLEBlitToSurfaceWithShadow 函数,写一个类似的函数,起名叫 PE_RLEBlitToSurface,内容如下,其实就是简化版,低依赖版本

复制代码
INT
PE_RLEBlitToSurface(
    LPCBITMAPRLE      lpBitmapRLE,
    LPCBYTE lpDstSurface,
    int surfaceWidth,
    int surfaceHeight
)
{
    UINT          i, j, k, sx;
    INT           x, y;
    UINT          uiLen = 0;
    UINT          uiWidth = 0;
    UINT          uiHeight = 0;
    UINT          uiSrcX = 0;
    BYTE          T;
    INT           dx = 0;
    INT           dy = 0;
    LPBYTE        p;

    //
    // Check for NULL pointer.
    //
    if (lpBitmapRLE == NULL || lpDstSurface == NULL)
    {
        return -1;
    }

    //
    // Skip the 0x00000002 in the file header.
    //
    if (lpBitmapRLE[0] == 0x02 && lpBitmapRLE[1] == 0x00 &&
        lpBitmapRLE[2] == 0x00 && lpBitmapRLE[3] == 0x00)
    {
        lpBitmapRLE += 4;
    }

    //
    // Get the width and height of the bitmap.
    //
    uiWidth = lpBitmapRLE[0] | (lpBitmapRLE[1] << 8);
    uiHeight = lpBitmapRLE[2] | (lpBitmapRLE[3] << 8);

    //
    // Check whether bitmap intersects the surface.
    //
    if (uiWidth + dx <= 0 || dx >= surfaceWidth ||
        uiHeight + dy <= 0 || dy >= surfaceHeight)
    {
        goto end;
    }

    //
    // Calculate the total length of the bitmap.
    // The bitmap is 8-bpp, each pixel will use 1 byte.
    //
    uiLen = uiWidth * uiHeight;

    //
    // Start decoding and blitting the bitmap.
    //
    lpBitmapRLE += 4;
    for (i = 0; i < uiLen;)
    {
        T = *lpBitmapRLE++;
        if ((T & 0x80) && T <= 0x80 + uiWidth)
        {
            i += T - 0x80;
            uiSrcX += T - 0x80;
            if (uiSrcX >= uiWidth)
            {
                uiSrcX -= uiWidth;
                dy++;
            }
        }
        else
        {
            //
            // Prepare coordinates.
            //
            j = 0;
            sx = uiSrcX;
            x = dx + uiSrcX;
            y = dy;

            //
            // Skip the points which are out of the surface.
            //
            if (y < 0)
            {
                j += -y * uiWidth;
                y = 0;
            }
            else if (y >= surfaceHeight)
            {
                goto end; // No more pixels needed, break out
            }

            while (j < T)
            {
                //
                // Skip the points which are out of the surface.
                //
                if (x < 0)
                {
                    j += -x;
                    if (j >= T) break;
                    sx += -x;
                    x = 0;
                }
                else if (x >= surfaceWidth)
                {
                    j += uiWidth - sx;
                    x -= sx;
                    sx = 0;
                    y++;
                    if (y >= surfaceHeight)
                    {
                        goto end; // No more pixels needed, break out
                    }
                    continue;
                }

                //
                // Put the pixels in row onto the surface
                //
                k = T - j;
                if (surfaceWidth - x < k) k = surfaceWidth - x;
                if (uiWidth - sx < k) k = uiWidth - sx;
                sx += k;
                p = lpDstSurface + y * surfaceWidth;
                //if (bShadow)
                //{
                //    j += k;
                //    for (; k != 0; k--)
                //    {
                //        p[x] = PAL_CalcShadowColor(p[x]);
                //        x++;
                //    }
                //}
                //else
                {
                    for (; k != 0; k--)
                    {
                        p[x] = lpBitmapRLE[j];
                        j++;
                        x++;
                    }
                }

                if (sx >= uiWidth)
                {
                    sx -= uiWidth;
                    x -= uiWidth;
                    y++;
                    if (y >= surfaceHeight)
                    {
                        goto end; // No more pixels needed, break out
                    }
                }
            }
            lpBitmapRLE += T;
            i += T;
            uiSrcX += T;
            while (uiSrcX >= uiWidth)
            {
                uiSrcX -= uiWidth;
                dy++;
            }
        }
    }

end:
    //
    // Success
    //
    return 0;
}
复制代码

记得 palcommon.h 中声明一下

INT
PE_RLEBlitToSurface(
    LPCBITMAPRLE      lpBitmapRLE,
    LPCBYTE lpDstSurface,
    int surfaceWidth,
    int surfaceHeight
);

写好之后,我们就有把单张精灵写入指定内存的能力了

 

精灵素材一般在两个位置,一是地图精灵,二是战斗精灵

我们先来dump地图精灵

打开 scene.c 文件

头部引入全局变量和控制变量

extern SDL_Color pe_palette[256];
extern int pe_palette_ready;

static int bLockRec2 = 0;
static int bLockRec3 = 0;
static int bLockRec4 = 0;

extern 的两个变量是之前 palette.c 中定义的

向下找到注释

//
// Put all the sprites to be drawn into our array.
//

//
// Players
//

这是地图模式下,玩家渲染的代码

修改如下

复制代码
for (i = 0; i <= (short)gpGlobals->wMaxPartyMemberIndex + gpGlobals->nFollower; i++)
{
    LPCBITMAPRLE lpBitmap =
        PAL_SpriteGetFrame(PAL_GetPlayerSprite((BYTE)i), gpGlobals->rgParty[i].wFrame);

    if (lpBitmap == NULL)
    {
        continue;
    }

    //BOOKMARK            保存地图模式 玩家精灵
    if (pe_palette_ready)
    {
        if (bLockRec3)
        {
            LPSPRITE curSpr = PAL_GetPlayerSprite((BYTE)i);
            int imagecount = (curSpr[0] | (curSpr[1] << 8));

            for (int k = 0; k < imagecount; k++)
            {
                LPCBITMAPRLE curBitmap = PAL_SpriteGetFrame(PAL_GetPlayerSprite((BYTE)i), k);

                LPBYTE p_p = curBitmap;

                int w = p_p[0] | (p_p[1] << 8);
                int h = p_p[2] | (p_p[3] << 8);

                if (w > 1024 || h > 1024)
                {
                    continue;
                }

                int len = w * h;

                unsigned char* pe_surface = malloc(len);

                PE_RLEBlitToSurface(curBitmap, pe_surface, w, h);

                LPBYTE p_now = pe_surface;

                LPBYTE pixel = p_now;

                char peOutFile[256] = {0};
                char tmp[256] = { 0 };

                char* startStr = "player";
                char* cont = "__";
                char* ext = ".png";

                strcat(peOutFile, startStr);
                strcat(peOutFile, cont);

                itoa(i, tmp, 10);
                strcat(peOutFile, tmp);
                strcat(peOutFile, cont);

                itoa(k, tmp, 10);
                strcat(peOutFile, tmp);
                strcat(peOutFile, ext);

                //player__i__k.png

                int bRet = access(peOutFile, 0);
                //0为存在
                if (bRet != 0)
                {
                    int n = 4;
                    unsigned char* data = malloc(w * h * n);

                    if (data != 0)
                    {
                        for (int j = 0; j < len; j++)
                        {
                            BYTE cur = pixel[j];
                            data[j * 4 + 0] = pe_palette[cur].r;
                            data[j * 4 + 1] = pe_palette[cur].g;
                            data[j * 4 + 2] = pe_palette[cur].b;
                            data[j * 4 + 3] = 255;
                        }
                        stbi_write_png(peOutFile, w, h, n, data, w * n);

                        free(pe_surface);
                        free(data);
                    }
                }
            }
        }
    }

    //
    // Add it to our array
    //
    PAL_AddSpriteToDraw(lpBitmap,
        gpGlobals->rgParty[i].x - PAL_RLEGetWidth(lpBitmap) / 2,
        gpGlobals->rgParty[i].y + gpGlobals->wLayer + 10,
        gpGlobals->wLayer + 6);

    //
    // Calculate covering tiles on the map
    //
    PAL_CalcCoverTiles(&g_rgSpriteToDraw[g_nSpriteToDraw - 1]);
}
复制代码

bLockRec3 下断点开启,就可以得到地图模式下,玩家移动图了

然后找到下面的注释

//
// Event Objects (Monsters/NPCs/others)
//

就可以得到玩家外的角色,比如电脑NPC版的赵灵儿

复制代码
for (i = gpGlobals->g.rgScene[gpGlobals->wNumScene - 1].wEventObjectIndex;
    i < gpGlobals->g.rgScene[gpGlobals->wNumScene].wEventObjectIndex; i++)
{
    LPCBITMAPRLE     lpFrame;
    LPCSPRITE        lpSprite;

    LPEVENTOBJECT    lpEvtObj = &(gpGlobals->g.lprgEventObject[i]);

    int              iFrame;

    if (lpEvtObj->sState == kObjStateHidden || lpEvtObj->sVanishTime > 0 ||
        lpEvtObj->sState < 0)
    {
        continue;
    }

    //
    // Get the sprite
    //
    lpSprite = PAL_GetEventObjectSprite((WORD)i + 1);
    if (lpSprite == NULL)
    {
        continue;
    }

    iFrame = lpEvtObj->wCurrentFrameNum;
    if (lpEvtObj->nSpriteFrames == 3)
    {
        //
        // walking character
        //
        if (iFrame == 2)
        {
        iFrame = 0;
        }

        if (iFrame == 3)
        {
        iFrame = 2;
        }
    }

    lpFrame = PAL_SpriteGetFrame(lpSprite,
        lpEvtObj->wDirection * lpEvtObj->nSpriteFrames + iFrame);

    if (lpFrame == NULL)
    {
        continue;
    }

    //
    // Calculate the coordinate and check if outside the screen
    //
    x = (SHORT)lpEvtObj->x - PAL_X(gpGlobals->viewport);
    x -= PAL_RLEGetWidth(lpFrame) / 2;

    if (x >= 320 || x < -(int)PAL_RLEGetWidth(lpFrame))
    {
        //
        // outside the screen; skip it
        //
        continue;
    }

    y = (SHORT)lpEvtObj->y - PAL_Y(gpGlobals->viewport);
    y += lpEvtObj->sLayer * 8 + 9;

    vy = y - PAL_RLEGetHeight(lpFrame) - lpEvtObj->sLayer * 8 + 2;
    if (vy >= 200 || vy < -(int)PAL_RLEGetHeight(lpFrame))
    {
        //
        // outside the screen; skip it
        //
        continue;
    }

    //
    // Add it into the array
    //
    PAL_AddSpriteToDraw(lpFrame, x, y, lpEvtObj->sLayer * 8 + 2);

    //
    // Calculate covering map tiles
    //
    PAL_CalcCoverTiles(&g_rgSpriteToDraw[g_nSpriteToDraw - 1]);



    //BOOKMARK            保存地图模式 Monsters/NPCs/others
    if (pe_palette_ready)
    {
        if (bLockRec4)
        {
            LPCBITMAPRLE curBitmap = lpFrame;
            LPBYTE p_p = curBitmap;

            int w = p_p[0] | (p_p[1] << 8);
            int h = p_p[2] | (p_p[3] << 8);

            if (w > 1024 || h > 1024)
            {
                continue;
            }

            int len = w * h;

            unsigned char* pe_surface = malloc(len);

            PE_RLEBlitToSurface(curBitmap, pe_surface, w, h);

            LPBYTE p_now = pe_surface;

            LPBYTE pixel = p_now;



            char peOutFile[256] = { 0 };
            char tmp[256] = { 0 };

            char* cont = "__";
            char* ext = ".png";

            itoa(i, peOutFile, 10);
            strcat(peOutFile, cont);

            itoa(lpEvtObj->wDirection, tmp, 10);
            strcat(peOutFile, tmp);
            strcat(peOutFile, cont);

            itoa(lpEvtObj->nSpriteFrames, tmp, 10);
            strcat(peOutFile, tmp);
            strcat(peOutFile, cont);

            itoa(iFrame, tmp, 10);
            strcat(peOutFile, tmp);
            strcat(peOutFile, ext);

            //i__wDirection__nSpriteFrames__iFrame.png

            int bRet = access(peOutFile, 0);
            //0为存在
            if (bRet != 0)
            {
                int n = 4;
                unsigned char* data = malloc(w * h * n);

                if (data != 0)
                {
                    for (int j = 0; j < len; j++)
                    {
                        BYTE cur = pixel[j];
                        data[j * 4 + 0] = pe_palette[cur].r;
                        data[j * 4 + 1] = pe_palette[cur].g;
                        data[j * 4 + 2] = pe_palette[cur].b;
                        data[j * 4 + 3] = 255;
                    }
                    stbi_write_png(peOutFile, w, h, n, data, w * n);

                    free(pe_surface);
                    free(data);
                }
            }
        }
    }
}
复制代码

接下来看看战斗部分 battle.c

头部引入全局变量和控制变量

extern SDL_Color pe_palette[256];
extern int pe_palette_ready;

static int bLockRec5 = 0;
static int bLockRec6 = 0;
static int bLockRec7 = 0;

找到下面的注释,dump敌人战斗精灵

//
// Draw the enemies
//

复制代码
for (j = g_Battle.wMaxEnemyIndex; j >= 0; j--)
{
    i = enemyDrawSeq[j];
    pos = g_Battle.rgEnemy[i].pos;

    if (g_Battle.rgEnemy[i].rgwStatus[kStatusConfused] > 0 &&
        g_Battle.rgEnemy[i].rgwStatus[kStatusSleep] == 0 &&
        g_Battle.rgEnemy[i].rgwStatus[kStatusParalyzed] == 0)
    {
        //
        // Enemy is confused
        //
        pos = PAL_XY(PAL_X(pos) + RandomLong(-1, 1), PAL_Y(pos));
    }

    pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)) / 2,
        PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame)));

    if (g_Battle.rgEnemy[i].wObjectID != 0)
    {
        if (g_Battle.rgEnemy[i].iColorShift)
        {
        PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
            g_Battle.lpSceneBuf, pos, g_Battle.rgEnemy[i].iColorShift);
        }
        else
        {
        PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame),
            g_Battle.lpSceneBuf, pos);

        //BOOKMARK          保存战斗模式 敌人
        if (pe_palette_ready)
        {
            if (bLockRec5)
            {
                LPCBITMAPRLE curBitmap = PAL_SpriteGetFrame(g_Battle.rgEnemy[i].lpSprite, g_Battle.rgEnemy[i].wCurrentFrame);
                LPBYTE p_p = curBitmap;

                int w = p_p[0] | (p_p[1] << 8);
                int h = p_p[2] | (p_p[3] << 8);

                if (w > 1024 || h > 1024)
                {
                    continue;
                }

                int len = w * h;

                unsigned char* pe_surface = malloc(len);

                PE_RLEBlitToSurface(curBitmap, pe_surface, w, h);

                LPBYTE p_now = pe_surface;

                LPBYTE pixel = p_now;



                char peOutFile[256] = { 0 };
                char tmp[256] = { 0 };

                char* cont = "__";
                char* ext = ".png";

                itoa(i, peOutFile, 10);
                strcat(peOutFile, cont);

                itoa(g_Battle.rgEnemy[i].wCurrentFrame, tmp, 10);
                strcat(peOutFile, tmp);
                strcat(peOutFile, ext);

                //i__wCurrentFrame.png
                int bRet = access(peOutFile, 0);
                //0为存在
                if (bRet != 0)
                {
                    int n = 4;
                    unsigned char* data = malloc(w * h * n);

                    if (data != 0)
                    {
                        for (int k = 0; k < len; k++)
                        {
                            BYTE cur = pixel[k];
                            data[k * 4 + 0] = pe_palette[cur].r;
                            data[k * 4 + 1] = pe_palette[cur].g;
                            data[k * 4 + 2] = pe_palette[cur].b;
                            data[k * 4 + 3] = 255;
                        }
                        stbi_write_png(peOutFile, w, h, n, data, w * n);

                        free(pe_surface);
                        free(data);
                    }
                }
            }
        }
        }
    }
}
复制代码

找到下面的注释,dump玩家召唤神和玩家,战斗精灵

//
// Draw the summoned god
//

复制代码
if (g_Battle.lpSummonSprite != NULL)
{
    //
    // Draw the summoned god
    //
    pos = PAL_XY(PAL_X(g_Battle.posSummon) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame)) / 2,
        PAL_Y(g_Battle.posSummon) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame)));

    PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame),
        g_Battle.lpSceneBuf, pos);

    //BOOKMARK          保存战斗模式 召唤神
    if (pe_palette_ready)
    {
        if (bLockRec7)
        {
            LPCBITMAPRLE curBitmap = PAL_SpriteGetFrame(g_Battle.lpSummonSprite, g_Battle.iSummonFrame);
            LPBYTE p_p = curBitmap;

            int w = p_p[0] | (p_p[1] << 8);
            int h = p_p[2] | (p_p[3] << 8);

            if (w < 1024 && h < 1024)
            {
                int len = w * h;

                unsigned char* pe_surface = malloc(len);

                PE_RLEBlitToSurface(curBitmap, pe_surface, w, h);

                LPBYTE p_now = pe_surface;

                LPBYTE pixel = p_now;



                char peOutFile[256] = { 0 };
                char tmp[256] = { 0 };

                char* startStr = "god";
                char* cont = "__";
                char* ext = ".png";

                strcat(peOutFile, startStr);
                strcat(peOutFile, cont);

                itoa(g_Battle.iSummonFrame, tmp, 10);
                strcat(peOutFile, tmp);
                strcat(peOutFile, ext);

                //god__i__wCurrentFrame.png
                int bRet = access(peOutFile, 0);
                //0为存在
                if (bRet != 0)
                {
                    int n = 4;
                    unsigned char* data = malloc(w * h * n);

                    if (data != 0)
                    {
                        for (int k = 0; k < len; k++)
                        {
                            BYTE cur = pixel[k];
                            data[k * 4 + 0] = pe_palette[cur].r;
                            data[k * 4 + 1] = pe_palette[cur].g;
                            data[k * 4 + 2] = pe_palette[cur].b;
                            data[k * 4 + 3] = 255;
                        }
                        stbi_write_png(peOutFile, w, h, n, data, w * n);

                        free(pe_surface);
                        free(data);
                    }
                }
            }
        }
    }
}
else
{
    //
    // Draw the players
    //
    for (i = gpGlobals->wMaxPartyMemberIndex; i >= 0; i--)
    {
        pos = g_Battle.rgPlayer[i].pos;

        if (gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusConfused] != 0 &&
        gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusSleep] == 0 &&
        gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusParalyzed] == 0 &&
        gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0)
        {
        //
        // Player is confused
        //
        continue;
        }

        pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2,
        PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)));

        if (g_Battle.rgPlayer[i].iColorShift != 0)
        {
        PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
            g_Battle.lpSceneBuf, pos, g_Battle.rgPlayer[i].iColorShift);
        }
        else if (g_Battle.iHidingTime == 0)
        {
        PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
            g_Battle.lpSceneBuf, pos);

        //BOOKMARK          保存战斗模式 玩家
        if (pe_palette_ready)
        {
            if (bLockRec6)
            {
                LPCBITMAPRLE curBitmap = PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame);
                LPBYTE p_p = curBitmap;

                int w = p_p[0] | (p_p[1] << 8);
                int h = p_p[2] | (p_p[3] << 8);

                if (w > 1024 || h > 1024)
                {
                    continue;
                }

                int len = w * h;

                unsigned char* pe_surface = malloc(len);

                PE_RLEBlitToSurface(curBitmap, pe_surface, w, h);

                LPBYTE p_now = pe_surface;

                LPBYTE pixel = p_now;


                    
                char peOutFile[256] = { 0 };
                char tmp[256] = { 0 };

                char* startStr = "player";
                char* cont = "__";
                char* ext = ".png";

                strcat(peOutFile, startStr);
                strcat(peOutFile, cont);

                itoa(i, tmp, 10);
                strcat(peOutFile, tmp);
                strcat(peOutFile, cont);

                itoa(g_Battle.rgPlayer[i].wCurrentFrame, tmp, 10);
                strcat(peOutFile, tmp);
                strcat(peOutFile, ext);

                //player__i__wCurrentFrame.png
                int bRet = access(peOutFile, 0);
                //0为存在
                if (bRet != 0)
                {
                    int n = 4;
                    unsigned char* data = malloc(w * h * n);

                    if (data != 0)
                    {
                        for (int k = 0; k < len; k++)
                        {
                            BYTE cur = pixel[k];
                            data[k * 4 + 0] = pe_palette[cur].r;
                            data[k * 4 + 1] = pe_palette[cur].g;
                            data[k * 4 + 2] = pe_palette[cur].b;
                            data[k * 4 + 3] = 255;
                        }
                        stbi_write_png(peOutFile, w, h, n, data, w * n);

                        free(pe_surface);
                        free(data);
                    }
                }
            }
        }
        }
    }

    //
    // Confused players should be drawn on top of normal players
    //
    for (i = gpGlobals->wMaxPartyMemberIndex; i >= 0; i--)
    {
        if (gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusConfused] != 0 &&
        gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusSleep] == 0 &&
        gpGlobals->rgPlayerStatus[gpGlobals->rgParty[i].wPlayerRole][kStatusParalyzed] == 0 &&
        gpGlobals->g.PlayerRoles.rgwHP[gpGlobals->rgParty[i].wPlayerRole] > 0)
        {
        //
        // Player is confused
        //
        int xd = PAL_X(g_Battle.rgPlayer[i].pos), yd = PAL_Y(g_Battle.rgPlayer[i].pos);
        if(!PAL_IsPlayerDying(gpGlobals->rgParty[i].wPlayerRole))
            yd += RandomLong(-1, 1);
        pos = PAL_XY(xd, yd);
        pos = PAL_XY(PAL_X(pos) - PAL_RLEGetWidth(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)) / 2,
            PAL_Y(pos) - PAL_RLEGetHeight(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame)));

        if (g_Battle.rgPlayer[i].iColorShift != 0)
        {
            PAL_RLEBlitWithColorShift(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                g_Battle.lpSceneBuf, pos, g_Battle.rgPlayer[i].iColorShift);
        }
        else if (g_Battle.iHidingTime == 0)
        {
            PAL_RLEBlitToSurface(PAL_SpriteGetFrame(g_Battle.rgPlayer[i].lpSprite, g_Battle.rgPlayer[i].wCurrentFrame),
                g_Battle.lpSceneBuf, pos);
        }
        }
    }
}
复制代码

 

posted on   KILEYI  阅读(189)  评论(0编辑  收藏  举报

点击右上角即可分享
微信分享提示