在这个文件夹创建:include\dialogue_portraits.h
#ifndef GUARD_DIALOGUE_PORTRAITS_H
#define GUARD_DIALOGUE_PORTRAITS_H

#include "global.h"

// 头像位置定义
#define PORTRAIT_LEFT_X         2   // 左侧头像位置
#define PORTRAIT_RIGHT_X        21  // 右侧头像位置
#define PORTRAIT_Y              7   // 对话框上方位置

// 头像状态枚举
enum PortraitState {
    PORTRAIT_STATE_NONE = 0,
    PORTRAIT_STATE_SHOWING,
    PORTRAIT_STATE_VISIBLE,
    PORTRAIT_STATE_HIDING
};

// 头像结构体
struct DialoguePortrait {
    u8 spriteId;           // 精灵ID
    u8 state;              // 当前状态
    u8 currentFrame;       // 当前帧
    u8 timer;              // 动画计时器
    u16 paletteTag;        // 调色板标签
    u16 gfxTag;            // 图形标签
};

// 函数声明
void InitDialoguePortraitSystem(void);
void CleanupDialoguePortraitSystem(void);
bool8 ShowDialoguePortrait(u8 portraitId, u8 side, u16 gfxTag, u16 paletteTag);
bool8 ShowDialoguePortraitWithFlip(u8 portraitId, u8 side, u16 gfxTag, u16 paletteTag, bool8 hFlip, bool8 vFlip);
void HideDialoguePortrait(u8 side);
void UpdateDialoguePortraits(void);
bool8 ArePortraitsActive(void);
void SetDialoguePortraitFlip(u8 side, bool8 hFlip, bool8 vFlip);

#endif // GUARD_DIALOGUE_PORTRAITS_H
在这个文件夹创建:src\dialogue_portraits.c
#include "global.h"
#include "dialogue_portraits.h"
#include "window.h"
#include "menu.h"
#include "sprite.h"
#include "malloc.h"
#include "task.h"
#include "text_window.h"
#include "constants/trainers.h"
#include "data.h"
#include "decompress.h"
#include "constants/songs.h"
#include "portrait_data.h"

// 自定义头像ID范围定义
#define CUSTOM_PORTRAIT_ID_START  1000
#define CUSTOM_PORTRAIT_ID_END    1999

// 头像系统全局变量
static EWRAM_DATA struct DialoguePortrait sPortraits[2] = {0};
static EWRAM_DATA bool8 sPortraitSystemInitialized = FALSE;

// 自定义头像资源声明
extern const u8 gHeadPortrait_001_Gfx[];
extern const u16 gHeadPortrait_001_Pal[];
extern const u8 gHeadPortrait_002_Gfx[];
extern const u16 gHeadPortrait_002_Pal[];

// 加载自定义头像资源
static bool8 LoadCustomPortrait(u16 portraitId, u16 *gfxTag, u16 *paletteTag)
{
    u16 localId = portraitId - CUSTOM_PORTRAIT_ID_START + 1;

    // 根据ID加载对应的自定义头像资源
    const u8 *gfxData = NULL;
    const u16 *palData = NULL;

    switch (localId) {
        case 1:
            gfxData = gHeadPortrait_001_Gfx;
            palData = gHeadPortrait_001_Pal;
            break;
        case 2:
            gfxData = gHeadPortrait_002_Gfx;
            palData = gHeadPortrait_002_Pal;
            break;
        default:
            return FALSE;  // 不支持的自定义头像ID
    }

    if (!gfxData || !palData)
        return FALSE;

    // 加载自定义头像图形
    struct CompressedSpriteSheet spriteSheet = {
        .data = (const void *)gfxData,
        .size = 0x800,  // 64x64像素,4bpp
        .tag = portraitId + 0x3000  // 使用0x3000系列标签避免与训练师冲突
    };
    LoadCompressedSpriteSheet(&spriteSheet);

    // 加载自定义头像调色板
    struct SpritePalette spritePalette = {
        .data = (const void *)palData,
        .tag = portraitId + 0x4000  // 使用0x4000系列标签
    };
    LoadSpritePalette(&spritePalette);

    *gfxTag = portraitId + 0x3000;
    *paletteTag = portraitId + 0x4000;

    return TRUE;
}

// 初始化头像系统
void InitDialoguePortraitSystem(void)
{
    // 如果已经初始化,先清理
    if (sPortraitSystemInitialized) {
        CleanupDialoguePortraitSystem();
    }

    // 初始化头像数据
    memset(sPortraits, 0, sizeof(sPortraits));

    // 初始化资源标签为无效值
    for (int i = 0; i < 2; i++) {
        sPortraits[i].spriteId = 0xFF;
        sPortraits[i].gfxTag = 0xFFFF;
        sPortraits[i].paletteTag = 0xFFFF;
    }

    sPortraitSystemInitialized = TRUE;
}

// 清理头像系统
void CleanupDialoguePortraitSystem(void)
{
    if (!sPortraitSystemInitialized)
        return;

    // 销毁精灵
    if (sPortraits[0].spriteId != 0xFF && sPortraits[0].spriteId < MAX_SPRITES) {
        DestroySprite(&gSprites[sPortraits[0].spriteId]);
    }
    if (sPortraits[1].spriteId != 0xFF && sPortraits[1].spriteId < MAX_SPRITES) {
        DestroySprite(&gSprites[sPortraits[1].spriteId]);
    }

    memset(sPortraits, 0, sizeof(sPortraits));
    sPortraitSystemInitialized = FALSE;
}

// 显示头像
bool8 ShowDialoguePortrait(u8 portraitId, u8 side, u16 gfxTag, u16 paletteTag)
{
    if (!sPortraitSystemInitialized || side > 1)
        return FALSE;

    struct DialoguePortrait *portrait = &sPortraits[side];

    // 如果已经有头像显示,先隐藏并清理
    if (portrait->state != PORTRAIT_STATE_NONE) {
        HideDialoguePortrait(side);
    }

    // 加载头像图形资源
    if (gfxTag >= CUSTOM_PORTRAIT_ID_START && gfxTag <= CUSTOM_PORTRAIT_ID_END) {
        // 使用自定义头像
        if (!LoadCustomPortrait(gfxTag, &portrait->gfxTag, &portrait->paletteTag)) {
            return FALSE;
        }
    } else if (gfxTag < TRAINER_PIC_COUNT) {
        // 使用系统预定义的训练师图像
        const struct TrainerSprite *trainerSprite = &gTrainerSprites[gfxTag];

        // 加载图像数据
        struct CompressedSpriteSheet spriteSheet = {
            .data = trainerSprite->frontPic.data,
            .size = trainerSprite->frontPic.size,
            .tag = gfxTag + 0x1000  // 使用唯一标签避免冲突
        };
        LoadCompressedSpriteSheet(&spriteSheet);

        // 加载调色板数据
        struct SpritePalette spritePalette = {
            .data = trainerSprite->palette.data,
            .tag = gfxTag + 0x2000  // 使用唯一标签避免冲突
        };
        LoadSpritePalette(&spritePalette);

        // 更新标签以便后续使用
        portrait->gfxTag = gfxTag + 0x1000;
        portrait->paletteTag = gfxTag + 0x2000;
    } else {
        // 对于无效的ID,直接返回失败
        return FALSE;
    }

    // 创建精灵来显示头像
    struct SpriteTemplate spriteTemplate = {
        .tileTag = portrait->gfxTag,
        .paletteTag = portrait->paletteTag,
        .oam = &(const struct OamData){
            .y = 0,
            .affineMode = ST_OAM_AFFINE_OFF,
            .objMode = ST_OAM_OBJ_NORMAL,
            .bpp = ST_OAM_4BPP,
            .shape = SPRITE_SHAPE(64x64),
            .x = 0,
            .size = SPRITE_SIZE(64x64),
            .tileNum = 0,
            .priority = 1,
            .paletteNum = 0,
        },
        .anims = gDummySpriteAnimTable,
        .images = NULL,
        .affineAnims = gDummySpriteAffineAnimTable,
        .callback = SpriteCallbackDummy
    };

    // 计算精灵位置
    u16 x, y;
    if (side == 0) { // 左侧
        x = PORTRAIT_LEFT_X * 8 + 32;  // 窗口中心位置
    } else { // 右侧
        x = PORTRAIT_RIGHT_X * 8 + 32;
    }
    y = PORTRAIT_Y * 8 + 32;

    portrait->spriteId = CreateSprite(&spriteTemplate, x, y, 0);
    if (portrait->spriteId == MAX_SPRITES) {
        // 创建精灵失败,清理资源
        FreeSpritePaletteByTag(portrait->paletteTag);
        FreeSpriteTilesByTag(portrait->gfxTag);
        portrait->gfxTag = 0xFFFF;
        portrait->paletteTag = 0xFFFF;
        return FALSE;
    }

    // 设置精灵属性
    struct Sprite *sprite = &gSprites[portrait->spriteId];
    sprite->oam.priority = 1;  // 在对话框之上
    sprite->subpriority = 4;

    // 设置状态
    portrait->state = PORTRAIT_STATE_SHOWING;
    portrait->currentFrame = 0;
    portrait->timer = 0;

    return TRUE;
}

// 显示头像(带翻转参数)
bool8 ShowDialoguePortraitWithFlip(u8 portraitId, u8 side, u16 gfxTag, u16 paletteTag, bool8 hFlip, bool8 vFlip)
{
    if (!ShowDialoguePortrait(portraitId, side, gfxTag, paletteTag))
        return FALSE;

    // 设置翻转状态
    SetDialoguePortraitFlip(side, hFlip, vFlip);

    return TRUE;
}

// 隐藏头像
void HideDialoguePortrait(u8 side)
{
    if (!sPortraitSystemInitialized || side > 1)
        return;

    struct DialoguePortrait *portrait = &sPortraits[side];

    if (portrait->state == PORTRAIT_STATE_NONE)
        return;

    // 销毁精灵
    if (portrait->spriteId != 0xFF && portrait->spriteId < MAX_SPRITES) {
        DestroySprite(&gSprites[portrait->spriteId]);
        portrait->spriteId = 0xFF;
    }

    // 释放资源
    if (portrait->gfxTag != 0xFFFF) {
        FreeSpritePaletteByTag(portrait->paletteTag);
        FreeSpriteTilesByTag(portrait->gfxTag);
    }

    // 重置所有状态和标签
    portrait->state = PORTRAIT_STATE_NONE;
    portrait->currentFrame = 0;
    portrait->timer = 0;
    portrait->gfxTag = 0xFFFF;
    portrait->paletteTag = 0xFFFF;
}

// 更新头像
void UpdateDialoguePortraits(void)
{
    if (!sPortraitSystemInitialized)
        return;

    for (int i = 0; i < 2; i++) {
        struct DialoguePortrait *portrait = &sPortraits[i];

        switch (portrait->state) {
            case PORTRAIT_STATE_SHOWING:
                portrait->timer++;
                if (portrait->timer > 10) {  // 显示动画持续10帧
                    portrait->state = PORTRAIT_STATE_VISIBLE;
                }
                break;

            case PORTRAIT_STATE_VISIBLE:
                // 可以在这里添加呼吸动画等效果
                portrait->timer++;
                if (portrait->timer > 60) {  // 每秒更新一次
                    portrait->timer = 0;
                    portrait->currentFrame = (portrait->currentFrame + 1) % 2;
                }
                break;

            case PORTRAIT_STATE_HIDING:
                portrait->timer++;
                if (portrait->timer > 10) {  // 隐藏动画持续10帧
                    portrait->state = PORTRAIT_STATE_NONE;
                }
                break;

            default:
                break;
        }
    }
}

// 设置头像翻转
void SetDialoguePortraitFlip(u8 side, bool8 hFlip, bool8 vFlip)
{
    if (!sPortraitSystemInitialized || side > 1)
        return;

    struct DialoguePortrait *portrait = &sPortraits[side];

    // 检查是否有有效的精灵
    if (portrait->spriteId == 0xFF || portrait->spriteId >= MAX_SPRITES)
        return;

    // 检查精灵是否处于活动状态
    if (portrait->state == PORTRAIT_STATE_NONE)
        return;

    struct Sprite *sprite = &gSprites[portrait->spriteId];

    // 设置精灵的翻转属性
    sprite->hFlip = hFlip;
    sprite->vFlip = vFlip;

    // 直接设置OAM翻转位,不使用异或操作
    sprite->oam.matrixNum &= 0x7;  // 清除翻转位
    if (hFlip)
        sprite->oam.matrixNum |= (1 << 3);  // 设置水平翻转位
    if (vFlip)
        sprite->oam.matrixNum |= (1 << 4);  // 设置垂直翻转位
}

// 检查是否有头像活动
bool8 ArePortraitsActive(void)
{
    if (!sPortraitSystemInitialized)
        return FALSE;

    return (sPortraits[0].state != PORTRAIT_STATE_NONE || 
            sPortraits[1].state != PORTRAIT_STATE_NONE);
}
在这个文件夹创建:src\portrait_data.c
#include "global.h"

// 自定义头像资源定义
// 这些将由工具链从graphics/head/文件夹中的PNG和PAL文件自动生成

// 头像001 - 玩家头像
const u8 gHeadPortrait_001_Gfx[] = INCBIN_U8("graphics/head/head_001.4bpp.smol");
const u16 gHeadPortrait_001_Pal[] = INCBIN_U16("graphics/head/head_001.gbapal");

// 头像002 - 预留给其他角色
const u8 gHeadPortrait_002_Gfx[] = INCBIN_U8("graphics/head/head_002.4bpp.smol");
const u16 gHeadPortrait_002_Pal[] = INCBIN_U16("graphics/head/head_002.gbapal");
修改这个文件:src\field_message_box.c
#include "global.h"
#include "menu.h"
#include "string_util.h"
#include "task.h"
#include "text.h"
#include "match_call.h"
#include "field_message_box.h"
#include "text_window.h"
#include "script.h"
#include "dialogue_portraits.h"  //新增代码
void InitFieldMessageBox(void)
{
    sFieldMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN;
    gTextFlags.canABSpeedUpPrint = FALSE;
    gTextFlags.useAlternateDownArrow = FALSE;
    gTextFlags.autoScroll = FALSE;
    gTextFlags.forceMidTextSpeed = FALSE;
    InitDialoguePortraitSystem();   //新增代码
}
#define tState data[0]

static void Task_DrawFieldMessage(u8 taskId)
{
    struct Task *task = &gTasks[taskId];

    switch (task->tState)
    {
        case 0:
            if (gMsgIsSignPost)
                LoadSignPostWindowFrameGfx();
            else
                LoadMessageBoxAndBorderGfx();
            task->tState++;
            break;
        case 1:
           DrawDialogueFrame(0, TRUE);
           task->tState++;
           break;
        case 2:
            UpdateDialoguePortraits();   //新增代码
            if (RunTextPrintersAndIsPrinter0Active() != TRUE)
            {
                sFieldMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN;
                DestroyTask(taskId);
            }
    }
}
void HideFieldMessageBox(void)
{
    DestroyTask_DrawFieldMessage();
    ClearDialogWindowAndFrame(0, TRUE);
    CleanupDialoguePortraitSystem();  //新增代码
    sFieldMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN;
}
这个文件添加代码:data\specials.inc
    def_special Special_ShowDialoguePortrait
    def_special Special_HideDialoguePortrait
    def_special Special_UpdateDialoguePortraits
    def_special Special_InitDialoguePortraitSystem
    def_special Special_ShowDialoguePortrait
    def_special Special_ShowDialoguePortraitWithFlip
    def_special Special_HideDialoguePortrait
    def_special Special_UpdateDialoguePortraits
    def_special Special_CleanupDialoguePortraitSystem
    def_special Special_SetDialoguePortraitFlip

这个文件新增代码:src\field_specials.c
#include "dialogue_portraits.h"   //新增代码

// 头像系统special函数实现
void Special_InitDialoguePortraitSystem(void)
{
    InitDialoguePortraitSystem();
}

void Special_ShowDialoguePortrait(void)
{
    u8 side = gSpecialVar_0x8004;      // 0=左侧,1=右侧
    u8 portraitId = gSpecialVar_0x8005; // 头像ID
    u16 gfxTag = gSpecialVar_0x8006;    // 图形标签
    u16 paletteTag = gSpecialVar_0x8007; // 调色板标签

    ShowDialoguePortrait(portraitId, side, gfxTag, paletteTag);
}

void Special_ShowDialoguePortraitWithFlip(void)
{
    u8 side = gSpecialVar_0x8004;      // 0=左侧,1=右侧
    u8 portraitId = gSpecialVar_0x8005; // 头像ID
    u16 gfxTag = gSpecialVar_0x8006;    // 图形标签
    u16 paletteTag = gSpecialVar_0x8007; // 调色板标签
    bool8 hFlip = gSpecialVar_0x8008;   // 水平翻转
    bool8 vFlip = gSpecialVar_0x8009;   // 垂直翻转

    ShowDialoguePortraitWithFlip(portraitId, side, gfxTag, paletteTag, hFlip, vFlip);
}

void Special_HideDialoguePortrait(void)
{
    u8 side = gSpecialVar_0x8004; // 0=左侧,1=右侧
    HideDialoguePortrait(side);
}

void Special_UpdateDialoguePortraits(void)
{
    UpdateDialoguePortraits();
}

void Special_CleanupDialoguePortraitSystem(void)
{
    CleanupDialoguePortraitSystem();
}

void Special_SetDialoguePortraitFlip(void)
{
    u8 side = gSpecialVar_0x8004;  // 0=左侧,1=右侧
    bool8 hFlip = gSpecialVar_0x8005; // 水平翻转
    bool8 vFlip = gSpecialVar_0x8006; // 垂直翻转

    SetDialoguePortraitFlip(side, hFlip, vFlip);
}
新增文件:include\portrait_data.h
#ifndef GUARD_PORTRAIT_DATA_H
#define GUARD_PORTRAIT_DATA_H

// 自定义头像资源声明
// 这些将由工具链从graphics/head/文件夹中的PNG和PAL文件生成

extern const u8 gHeadPortrait_001_Gfx[];
extern const u16 gHeadPortrait_001_Pal[];
extern const u8 gHeadPortrait_002_Gfx[];
extern const u16 gHeadPortrait_002_Pal[];

#endif // GUARD_PORTRAIT_DATA_H
文件新增代码:include\constants\field_specials.h
// 头像系统Special函数常量
#define SPECIAL_INIT_DIALOGUE_PORTRAIT_SYSTEM    0x200
#define SPECIAL_SHOW_DIALOGUE_PORTRAIT           0x201
#define SPECIAL_HIDE_DIALOGUE_PORTRAIT           0x202
#define SPECIAL_UPDATE_DIALOGUE_PORTRAITS        0x203
#define SPECIAL_CLEANUP_DIALOGUE_PORTRAIT_SYSTEM  0x204
文件新增代码:graphics_file_rules.mk
### Custom Trainer Portraits ###
# Define custom graphics directory
CUSTOMGFXDIR := graphics/head

# Convert PNG to 4bpp format for trainer portraits
$(CUSTOMGFXDIR)/head_001.4bpp: %.4bpp: %.png
    $(GFX) $< $@ -num_tiles 64 -Wnum_tiles

# Convert 4bpp to compressed .4bpp.smol format
$(CUSTOMGFXDIR)/head_001.4bpp.smol: %.4bpp.smol: %.4bpp
    $(SMOL) -w $< $@

# Extract palette from PNG and convert to GBAPAL format
$(CUSTOMGFXDIR)/head_001.gbapal: %.gbapal: %.png
    $(GFX) $< $@ -palette

脚本测试示例:


Text_PortraitFlipIntro:
    .string "这是头像翻转功能演示。\n我们将展示各种翻转效果。$"

Text_PortraitNormal:
    .string "这是正常方向的头像。$"

Text_PortraitHFlip:
    .string "这是水平翻转的头像。\n头像现在面向左边。$"

Text_PortraitVFlip:
    .string "这是垂直翻转的头像。\n头像现在上下颠倒。$"

Text_PortraitBothFlip:
    .string "这是同时水平和垂直翻转的头像。\n相当于180度旋转。$"

Text_PortraitRestored:
    .string "恢复正常方向的头像。$"

Text_DualPortraitIntro:
    .string "现在演示双人对话中的翻转效果。$"

Text_LeftCharacterNormal:
    .string "左边角色:你好!我是面向右边的。$"

Text_RightCharacterFlipped:
    .string "右边角色:你好!我现在面向左边。$"

Text_BothFacingForward:
    .string "两个角色都面向前方了!$"

Text_DynamicFlipIntro:
    .string "演示动态翻转效果,模拟角色转头。$"

Text_FacingRight:
    .string "面向右边...$"

Text_FacingLeft:
    .string "面向左边...$"

Text_FacingRightAgain:
    .string "又面向右边了!$"

Text_DemoComplete:
    .string "头像翻转功能演示完成!$"

// 示例1:基本头像显示和翻转
EventScript_PortraitFlipBasic::
    lock
    faceplayer
    
    // 初始化头像系统
    special Special_InitDialoguePortraitSystem
    
    msgbox Text_PortraitFlipIntro, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 显示左侧头像(使用自定义头像ID)
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // 头像ID 0 (未使用)
    setvar VAR_0x8006, 1000   // 自定义头像ID: head_001.png
    setvar VAR_0x8007, 0      // 调色板标签 (未使用)
    special Special_ShowDialoguePortrait
    
    msgbox Text_PortraitNormal, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 水平翻转头像
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 1      // hFlip=TRUE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_PortraitHFlip, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 垂直翻转头像
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // hFlip=FALSE
    setvar VAR_0x8006, 1      // vFlip=TRUE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_PortraitVFlip, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 同时水平和垂直翻转
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 1      // hFlip=TRUE
    setvar VAR_0x8006, 1      // vFlip=TRUE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_PortraitBothFlip, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 恢复正常方向
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // hFlip=FALSE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_PortraitRestored, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 隐藏头像
    setvar VAR_0x8004, 0      // 左侧
    special Special_HideDialoguePortrait
    
    // 清理头像系统
    special Special_CleanupDialoguePortraitSystem
    
    release
    end

// 示例2:双人对话中的翻转效果
EventScript_PortraitFlipDual::
    lock
    faceplayer
    
    // 初始化头像系统
    special Special_InitDialoguePortraitSystem
    
    msgbox Text_DualPortraitIntro, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 显示两个头像
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // 头像ID 0
    setvar VAR_0x8006, 1001     // 训练师ID: Brendan
    setvar VAR_0x8007, 0      // 调色板标签
    special Special_ShowDialoguePortrait
    
    setvar VAR_0x8004, 1      // 右侧
    setvar VAR_0x8005, 1      // 头像ID 1
    setvar VAR_0x8006, 1000     // 训练师ID: May
    setvar VAR_0x8007, 0      // 调色板标签
    special Special_ShowDialoguePortrait
    
    // 左侧角色说话(正常面向右边)
    msgbox Text_LeftCharacterNormal, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 右侧角色说话(水平翻转面向左边)
    setvar VAR_0x8004, 1      // 右侧
    setvar VAR_0x8005, 1      // hFlip=TRUE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_RightCharacterFlipped, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 两个角色都面向前方
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // hFlip=FALSE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    setvar VAR_0x8004, 1      // 右侧
    setvar VAR_0x8005, 0      // hFlip=FALSE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_BothFacingForward, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 隐藏头像
    setvar VAR_0x8004, 0      // 左侧
    special Special_HideDialoguePortrait
    
    setvar VAR_0x8004, 1      // 右侧
    special Special_HideDialoguePortrait
    
    // 清理头像系统
    special Special_CleanupDialoguePortraitSystem
    
    release
    end

// 示例3:动态翻转效果(模拟角色转头)
EventScript_PortraitFlipDynamic::
    lock
    faceplayer
    
    // 初始化头像系统
    special Special_InitDialoguePortraitSystem
    
    msgbox Text_DynamicFlipIntro, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 显示头像
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // 头像ID 0
    setvar VAR_0x8006, 1000   // 自定义头像ID
    setvar VAR_0x8007, 0      // 调色板标签
    special Special_ShowDialoguePortrait
    
    // 正常方向(面向右边)
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // hFlip=FALSE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_FacingRight, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    delay 30
    
    // 水平翻转(面向左边)
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 1      // hFlip=TRUE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_FacingLeft, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    delay 30
    
    // 再次翻转回来
    setvar VAR_0x8004, 0      // 左侧
    setvar VAR_0x8005, 0      // hFlip=FALSE
    setvar VAR_0x8006, 0      // vFlip=FALSE
    special Special_SetDialoguePortraitFlip
    
    msgbox Text_FacingRightAgain, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    // 隐藏头像
    setvar VAR_0x8004, 0      // 左侧
    special Special_HideDialoguePortrait
    
    // 清理头像系统
    special Special_CleanupDialoguePortraitSystem
    
    msgbox Text_DemoComplete, MSGBOX_DEFAULT
    waitmessage
    waitbuttonpress
    
    release
    end
最后修改:2025 年 11 月 17 日
如果觉得我的文章对你有用,请随意赞赏