[GBA教程]实现静态CG图显示

[GBA教程]实现静态CG图显示

在src/scrcmd.c 文件末尾添加 ShowCG 相关的函数和数据结构。

#define PLAY_CG             (0)
#define PLAY_MESSAGE        (1)
#define WAIT_BUTTON         (2)
#define PLAY_FADE           (3)
#define PLAY_END            (4)
#define PAUSE_TIME          (5)

static const struct BgTemplate sBgTemplates[] =
{
    {
        .bg = 0,
        .charBaseIndex = 3,
        .mapBaseIndex = 31,
        .screenSize = 0,
        .paletteMode = 0,
        .priority = 0,
        .baseTile = 0
    },
    {
        .bg = 2,
        .charBaseIndex = 0,
        .mapBaseIndex = 29,
        .screenSize = 0,
        .paletteMode = 1,
        .priority = 3,
        .baseTile = 0
    },
};

static const struct WindowTemplate sWindowTemplates[] =
{
    {
        .bg = 0,
        .tilemapLeft = 3,
        .tilemapTop = 15,
        .width = 24,
        .height = 4,
        .paletteNum = 15,
        .baseBlock = 0x010
    },
    DUMMY_WIN_TEMPLATE,
};

//tilemap单独提供下载,放在对应文件夹即可
//添加CG图
static const u8 sDefaultCG_TileMap[] = INCBIN_U8("graphics/cg/raw.bin.lz");
static const u8 sCGA1_Tiles[] = INCBIN_U8("graphics/cg/CG1.8bpp.lz");
static const u8 sCGA1_Pal[] = INCBIN_U8("graphics/cg/CG1.gbapal");
static const u8 sCGA2_Tiles[] = INCBIN_U8("graphics/cg/CG2.8bpp.lz");
static const u8 sCGA2_Pal[] = INCBIN_U8("graphics/cg/CG2.gbapal");

//CG图编号
static const u8* sCGTable[][10] =
{
    [0] = {sCG1_Tiles, sCG1_Pal},
    [1] = {sCG2_Tiles, sCG2_Pal},
};

static const u8 sText_Color[] = {0, 1, 2};

//对话表编号
static const u8* sCGMessage[] =
{
    [0] = COMPOUND_STRING("?:如果时间能永远\n停留在这个时刻就好了。\p洛汐:是啊。"),
    [1] = COMPOUND_STRING("洛汐:你知道启明星吗?\n就是在太阳升起前,\l最后那颗最亮的星星。\p?:当然知道啊。"),
};

//CG表编号
static const u8 sCGAnimList[][60] =
{
    [0] = {
        PLAY_CG, 0,         // 播放CG
        PLAY_MESSAGE, 0,    // 播放对话
        WAIT_BUTTON, 0,     // 等待按钮
        PLAY_CG, 1,         // 播放cg
        PLAY_MESSAGE, 1,    // 播放对话
        WAIT_BUTTON, 0,     // 等待按钮
        PLAY_END            // 结束
    },
};

static void VblankCB_ShowCG(void)
{
    LoadOam();
    ProcessSpriteCopyRequests();
    TransferPlttBuffer();
}

static void CB2_ShowCGWait(void)
{
    RunTasks();
    DoScheduledBgTilemapCopiesToVram();
    UpdatePaletteFade();
}

static void CB2_ShowCG(void)
{
    SetVBlankCallback(NULL);

    SetGpuReg(REG_OFFSET_DISPCNT, 0);
    SetGpuReg(REG_OFFSET_BG3CNT, 0);
    SetGpuReg(REG_OFFSET_BG2CNT, 0);
    SetGpuReg(REG_OFFSET_BG1CNT, 0);
    SetGpuReg(REG_OFFSET_BG0CNT, 0);

    ChangeBgX(0, 0, BG_COORD_SET);
    ChangeBgY(0, 0, BG_COORD_SET);
    ChangeBgX(1, 0, BG_COORD_SET);
    ChangeBgY(1, 0, BG_COORD_SET);
    ChangeBgX(2, 0, BG_COORD_SET);
    ChangeBgY(2, 0, BG_COORD_SET);
    ChangeBgX(3, 0, BG_COORD_SET);
    ChangeBgY(3, 0, BG_COORD_SET);

    DmaFill16(3, 0, VRAM, VRAM_SIZE);
    DmaFill32(3, 0, OAM, OAM_SIZE);
    DmaFill16(3, 0, PLTT, PLTT_SIZE);

    u8 cgindex = sCGAnimList[gSpecialVar_0x8004][1];

    LZ77UnCompVram((void*)sDefaultCG_TileMap, (void *)(BG_SCREEN_ADDR(29)));
    LZ77UnCompVram((void*)sCGTable[cgindex][0], (void *)(BG_CHAR_ADDR(0)));

    ResetBgsAndClearDma3BusyFlags(0);
    InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));

    ScanlineEffect_Stop();
    ResetTasks();
    ResetSpriteData();
    ResetPaletteFade();
    FreeAllSpritePalettes();
    ResetAllPicSprites();

    InitWindows(sWindowTemplates);
    DeactivateAllTextPrinters();

    LoadPalette((void*)sCGTable[cgindex][1], BG_PLTT_ID(0), 15 * 32);
    LoadPalette(GetOverworldTextboxPalettePtr(), BG_PLTT_ID(15), PLTT_SIZE_4BPP);
    BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, 0);

    EnableInterrupts(DISPSTAT_VBLANK);
    SetVBlankCallback(VblankCB_ShowCG);
    SetMainCallback2(CB2_ShowCGWait);
    u8 taskID = CreateTask(Task_ReadCMD, 0);
    gTasks[taskID].data[0] = 2;

    SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR);
    SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ);
    SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(10, 230));
    SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(115, 155));
    SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP | DISPCNT_WIN0_ON);
    SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_DARKEN);
    SetGpuReg(REG_OFFSET_BLDY, 7);

    ShowBg(0);
    ShowBg(2);
}

static void Task_ChangeCG(u8 taskId)
{
    if (!gPaletteFade.active)
    {
        LZ77UnCompVram((void*)sDefaultCG_TileMap, (void *)(BG_SCREEN_ADDR(29)));
        LZ77UnCompVram((void*)sCGTable[gTasks[taskId].data[1]][0], (void *)(BG_CHAR_ADDR(0)));
        LoadPalette((void*)sCGTable[gTasks[taskId].data[1]][1], BG_PLTT_ID(0), 15 * 32);
        BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, 0);
        gTasks[taskId].func = Task_ReadCMD;
    }
}

static void Task_PlayMessage(u8 taskId)
{
    if (RunTextPrintersAndIsPrinter0Active())
        return;

    if (JOY_NEW(A_BUTTON | B_BUTTON))
    {
        SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_NONE);
        HideBg(0);
        FillWindowPixelBuffer(0, PIXEL_FILL(0));
        PutWindowTilemap(0);
        CopyWindowToVram(0, COPYWIN_FULL);
        gTasks[taskId].func = Task_ReadCMD;
    }
}

static void Task_WaitFadeAndButton(u8 taskId)
{
    if (JOY_NEW(A_BUTTON | B_BUTTON))
    {
        gTasks[taskId].func = Task_ReadCMD;
    }
}

static void Task_ReadCMD(u8 taskId)
{
    if (gPaletteFade.active)
        return;

    u8 animID = sCGAnimList[gSpecialVar_0x8004][gTasks[taskId].data[0]++];
    u8 animParam = sCGAnimList[gSpecialVar_0x8004][gTasks[taskId].data[0]++];

    if (animID == PLAY_END)
    {
        DestroyTask(taskId);
        SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
    }
    else
    {
        if (animID == PLAY_CG)
        {
            BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, 0);
            gTasks[taskId].data[1] = animParam;
            gTasks[taskId].func = Task_ChangeCG;
        }
        else if (animID == PAUSE_TIME)
        {
            gTasks[taskId].func = TaskDummy;
        }
        else if (animID == WAIT_BUTTON)
        {
            gTasks[taskId].func = Task_WaitFadeAndButton;
        }
        else
        {
            FillWindowPixelBuffer(0, PIXEL_FILL(0));
            AddTextPrinterParameterized4(0, FONT_NORMAL, 0, 0, 0, 0, sText_Color, GetPlayerTextSpeedDelay(), sCGMessage[animParam]);
            PutWindowTilemap(0);
            CopyWindowToVram(0, COPYWIN_FULL);
            ScheduleBgCopyTilemapToVram(0);
            SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_DARKEN);
            ShowBg(0);
            gTasks[taskId].func = Task_PlayMessage;
        }
    }
}

void ShowCG(void)
{
    SetMainCallback2(CB2_ShowCG);
}

在 src/scrcmd.c 文件顶部添加函数声明

static void Task_ReadCMD(u8 taskId);

在 src/scrcmd.c 文件中添加头文件的包含

#include "bg.h"
#include "scanline_effect.h"
#include "trainer_pokemon_sprites.h"

在 data/specials.inc 文件中注册 ShowCG 特殊函数,以便脚本可以调用它。

def_special ShowCG

在graphics文件夹创建cg文件夹,将你的cg图放进去即可

脚本示例:

setvar 0x8004 3  //CG表编号
special ShowCG
waitstate
 

raw.bin

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容