gpt4 book ai didi

c++ - 更新 Sprite 位置的奇怪行为

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:38:46 26 4
gpt4 key购买 nike

我正在使用 SDL 库用 C++ 编写一个简单的 roguelike 游戏,但在屏幕上移动我的角色时遇到了一些问题。每次需要渲染一帧时,我都会使用 update() 函数更新 Sprite 的位置,如果玩家静止不动,该函数不会执行任何操作。为了发出移动命令,从而启动动画,我使用了 step() 函数,每个玩家从一个图 block 移动到另一个图 block 时只调用一次。收到“向上”命令后,游戏运行良好,角色在一秒钟内平稳移动到新位置。不过,当“向下”的命令下达后,他的移动速度会减半,而且显然在一秒过去后,瞬间就被“传送”到了最终的位置,身形骤然一闪。运动的代码基本上是相同的,但事实上,在一种情况下增量运动被加到 y 位置,在另一种情况下被减去。也许位置是整数而增量是 double 的事实引起了问题? sum 和 subract 的行为是否不同(可能不同的舍入)?这是相关代码(抱歉,长度):

void Player::step(Player::Direction dir)
{
if(m_status != STANDING) // no animation while standing
return;

switch(dir)
{
case UP:
if(m_currMap->tileAt(m_xPos, m_yPos - m_currMap->tileHeight())->m_type == Tile::FLOOR)
{
// if next tile is not a wall, set up animation
m_status = WALKING_UP;
m_yDelta = m_currMap->tileHeight(); // sprite have to move by a tile
m_yVel = m_currMap->tileHeight() / 1000.0f; // in one second
m_yNext = m_yPos - m_currMap->tileHeight(); // store final destination
}
break;
case DOWN:
if(m_currMap->tileAt(m_xPos, m_yPos + m_currMap->tileHeight())->m_type == Tile::FLOOR)
{
m_status = WALKING_DOWN;
m_yDelta = m_currMap->tileHeight();
m_yVel = m_currMap->tileHeight() / 1000.0f;
m_yNext = m_yPos + m_currMap->tileHeight();
}
break;

//...

default:
break;
}

m_animTimer = SDL_GetTicks();
}

void Player::update()
{
m_animTimer = SDL_GetTicks() - m_animTimer; // get the ms passed since last update

switch(m_status)
{
case WALKING_UP:
m_yPos -= m_yVel * m_animTimer; // update position
m_yDelta -= m_yVel * m_animTimer; // update the remaining space
break;
case WALKING_DOWN:
m_yPos += m_yVel * m_animTimer;
m_yDelta -= m_yVel * m_animTimer;
break;

//...

default:
break;
}

if(m_xDelta <= 0 && m_yDelta <= 0) // if i'm done moving
{
m_xPos = m_xNext; // adjust position
m_yPos = m_yNext;
m_status = STANDING; // and stop
}
else
m_animTimer = SDL_GetTicks(); // else update timer
}

编辑:我删除了一些变量,只留下耗时、速度和最终位置。现在它移动没有闪烁,但向下和向右的移动明显比向上和向左的移动慢。仍然想知道为什么...

编辑 2: 好吧,我明白了为什么会这样。正如我首先假设的那样,当涉及到加法和减法时,从 double 到整数的舍入是不同的。如果我执行这样的转换:

m_xPos += (int)(m_xVel * m_animTimer);

动画速度一样,问题解决。

最佳答案

考虑以下几点:

#include <iostream>

void main()
{
int a = 1, b = 1;
a += 0.1f;
b -= 0.1f;

std::cout << a << std::endl;
std::cout << b << std::endl;
}

在分配 a 和 b 时将 float 隐式转换为 int 期间,小数点后的所有内容都将被截断而不是舍入。该程序的结果是:

1
0

您说过 m_yPos 是一个整数,而 m_yVel 是一个 double 。考虑如果 m_yVel * m_animTimer 的结果小于 1,Player::update 会发生什么。在 UP 的情况下,结果将是你的 sprite 向下移动一个像素,但在 DOWN 的情况下,你的 sprite 根本不会移动,因为如果你将小于 1 的值加到一个整数上,什么也不会发生。尝试将您的位置存储为 double ,并且仅在需要将它们传递给绘图函数时才将它们转换为整数。

确保在转换期间舍入而不是截断的一个技巧是在分配给整数期间始终将浮点值加 0.5。

例如:

double d1 = 1.2;
double d2 = 1.6;
int x = d1 + 0.5;
int y = d2 + 0.5;

在这种情况下,x 将变为 1,而 y 将变为 2。

关于c++ - 更新 Sprite 位置的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8873420/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com