GBA开发问题:精灵无法正常显示在背景之上
GBA精灵显示异常问题排查与修复
问题根源分析
你的代码存在三个核心问题,导致精灵显示异常:
ATTR2重复赋值与优先级错误:
obj_set_attr已经完成了精灵属性的初始化,但后续又通过character->attr2 = ATTR2_BUILD(tid, pb, 2);覆盖了属性值。GBA的显示优先级规则是数值越小,层级越靠前,BG0的默认优先级为0,而你设置的精灵优先级为2,这会导致精灵被背景完全遮挡;同时重复赋值会干扰obj_set_attr的其他正确配置。循环中重复修改REG_DISPCNT:
在updateMain的循环里每次都重新设置显示控制寄存器,还额外开启了BG1,但你并未初始化BG1对应的显存块(CBB/SBB),这会导致显存读取非法数据,引发闪烁或异常色块。精灵尺寸与Tile资源不匹配:
64x64的8BPP精灵需要占用64个连续的8x8 Tile(64/8=8,8×8=64个Tile),每个8BPP Tile占64字节,总大小为4096字节。如果characterTiles的长度不足,会读取到显存中未初始化的垃圾数据,表现为粉色方块。
修复后的代码
int main () { initMain(); while(1) { vid_vsync(); key_poll(); updateMain(); } return 0; } void initMain() { // 背景初始化 memcpy(pal_bg_mem, backgroundPal, backgroundPalLen); memcpy(&tile_mem[0][0], backgroundTiles, backgroundTilesLen); memcpy(&se_mem[30][0], backgroundMap, backgroundMapLen); // 精灵初始化 memcpy(pal_obj_mem, characterPal, characterPalLen); // 确保characterTiles长度至少为4096字节(64个8BPP Tile) memcpy(&tile_mem[4][0], characterTiles, characterTilesLen); oam_init(obj_buffer, 128); REG_BG0CNT = BG_CBB(0) | BG_SBB(30) | BG_8BPP | BG_REG_32x32; // 仅在初始化时设置一次显示控制寄存器,无需开启未使用的BG1 REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_OBJ | DCNT_OBJ_1D; } void updateMain() { int x = 96, y = 96; u32 tid = 0, pb = 0; // 设置精灵优先级为0,确保在BG0上方显示 u32 priority = 0; OBJ_ATTR *character = &obj_buffer[0]; // 统一通过obj_set_attr设置所有属性,避免重复赋值冲突 obj_set_attr(character, ATTR0_SQUARE, // 方形精灵 ATTR1_SIZE_64, // 64x64像素尺寸 ATTR2_BUILD(tid, pb, priority)); // 优先级设为0 obj_set_pos(character, x, y); oam_copy(oam_mem, obj_buffer, 1); // 移除循环中对REG_DISPCNT的冗余修改 }
额外检查点
- 确认
characterPal的索引0不是粉色(GBA精灵的透明色为调色板索引0,若该索引为粉色,透明区域会显示粉色)。 - 验证
characterTiles的实际长度是否符合64x64精灵的需求(至少4096字节)。
内容的提问来源于stack exchange,提问作者CatBusStop
相关产品推荐
相关产品推荐

