我在 SDL 中显示精灵时遇到问题
I have an issue to display sprites in SDL
我正在使用 SDL 开发平台游戏,但我有一个错误,我不知道如何修复它。
我读了一张看起来像这样的地图:
0=sprites/background.jpeg
1=sprites/dirt.jpeg
2
sprites/ww_left.png
sprites/ww_right.png
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
我通过简单地 blitting 我的图片来显示 1 和 2,我通过从我的图片中取出一个像素来显示 0。
这些是我的显示功能:
https://github.com/vladydan/Darien_Reborn/blob/master/srcs/aff_map.c
我的问题是背景覆盖了我的角色精灵。
这是我开始时的显示,看起来不错:
这就是我移动太多时会发生的情况:
如果我继续向右移动,显示会再次正常,但总有那么一刻我的 sprite 会被覆盖。
我知道它是从哪里来的,但我不知道如何修复它,你有什么想法吗?
推测:当您直接访问像素时,如在函数 aff_background
中,您必须锁定表面,尤其是在硬件模式下。
检查这是否是您的问题(并非 100% 确定)的一种简单方法是使用 SDL_SWSURFACE
标志调用 SDL_SetVideoMode
。甚至更好地检查 SDL_MUSTLOCK
.
一般来说,比起原始像素写入,更喜欢 blitting 子图像。有可能 blit 排队甚至异步完成,并且像素写入会中断绘制顺序。
祝你好运。
编辑: 在阅读了其他答案并进一步检查您的代码后,这里有一个 hack 应该会给您想要的结果,
while (++i != 16)
{
pos.x = 0;
j = -1;
while (++j != 15)
{
if (game->map.map[i][j] == 1)
SDL_BlitSurface(game->map.sprites[1], NULL, game->sdl.screen,
&pos);
else if ((game->map.map[i][j] == 0 || game->map.map[i][j] == 2))
aff_background(game, pos);
if (game->map.map[i][j] == 2)
// record sprite starting position from map entry.
sprite_start_pos = pos;
pos.x += 100;
}
pos.y += 52;
}
// write sprite image after everything else.
aff_sprite(game, sprite_start_pos);
SDL_Flip(game->sdl.screen);
while (++i != 16)
{
pos.x = 0;
j = -1;
while (++j != 15)
{
if (game->map.map[i][j] == 1)
SDL_BlitSurface(game->map.sprites[1], NULL, game->sdl.screen,
&pos);
else if ((game->map.map[i][j] == 0 || game->map.map[i][j] == 2))
aff_background(game, pos);
if (game->map.map[i][j] == 2)
aff_sprite(game, pos);
pos.x += 100;
}
pos.y += 52;
}
SDL_Flip(game->sdl.screen);
return (0);
}
看起来你只是在以某种逻辑控制的顺序任意渲染。我认为最好的办法是按照你给我们的索引降序渲染,一层一层地渲染,第一层作为背景。
您可能还想尝试使用 SDL_Texture
以及使用硬件加速,这也可能解决您的渲染问题。也可能是渲染模式的问题
我正在使用 SDL 开发平台游戏,但我有一个错误,我不知道如何修复它。
我读了一张看起来像这样的地图:
0=sprites/background.jpeg
1=sprites/dirt.jpeg
2
sprites/ww_left.png
sprites/ww_right.png
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
我通过简单地 blitting 我的图片来显示 1 和 2,我通过从我的图片中取出一个像素来显示 0。
这些是我的显示功能: https://github.com/vladydan/Darien_Reborn/blob/master/srcs/aff_map.c
我的问题是背景覆盖了我的角色精灵。
这是我开始时的显示,看起来不错:
这就是我移动太多时会发生的情况:
如果我继续向右移动,显示会再次正常,但总有那么一刻我的 sprite 会被覆盖。 我知道它是从哪里来的,但我不知道如何修复它,你有什么想法吗?
推测:当您直接访问像素时,如在函数 aff_background
中,您必须锁定表面,尤其是在硬件模式下。
检查这是否是您的问题(并非 100% 确定)的一种简单方法是使用 SDL_SWSURFACE
标志调用 SDL_SetVideoMode
。甚至更好地检查 SDL_MUSTLOCK
.
一般来说,比起原始像素写入,更喜欢 blitting 子图像。有可能 blit 排队甚至异步完成,并且像素写入会中断绘制顺序。
祝你好运。
编辑: 在阅读了其他答案并进一步检查您的代码后,这里有一个 hack 应该会给您想要的结果,
while (++i != 16)
{
pos.x = 0;
j = -1;
while (++j != 15)
{
if (game->map.map[i][j] == 1)
SDL_BlitSurface(game->map.sprites[1], NULL, game->sdl.screen,
&pos);
else if ((game->map.map[i][j] == 0 || game->map.map[i][j] == 2))
aff_background(game, pos);
if (game->map.map[i][j] == 2)
// record sprite starting position from map entry.
sprite_start_pos = pos;
pos.x += 100;
}
pos.y += 52;
}
// write sprite image after everything else.
aff_sprite(game, sprite_start_pos);
SDL_Flip(game->sdl.screen);
while (++i != 16)
{
pos.x = 0;
j = -1;
while (++j != 15)
{
if (game->map.map[i][j] == 1)
SDL_BlitSurface(game->map.sprites[1], NULL, game->sdl.screen,
&pos);
else if ((game->map.map[i][j] == 0 || game->map.map[i][j] == 2))
aff_background(game, pos);
if (game->map.map[i][j] == 2)
aff_sprite(game, pos);
pos.x += 100;
}
pos.y += 52;
}
SDL_Flip(game->sdl.screen);
return (0);
}
看起来你只是在以某种逻辑控制的顺序任意渲染。我认为最好的办法是按照你给我们的索引降序渲染,一层一层地渲染,第一层作为背景。
您可能还想尝试使用 SDL_Texture
以及使用硬件加速,这也可能解决您的渲染问题。也可能是渲染模式的问题