我正在用C++編寫一個簡單的roguelike遊戲,使用SDL庫,我在屏幕上移動我的角色時遇到了一些問題。每次渲染框架時,我都會使用update()函數更新精靈的位置,如果玩家靜止不動,它將不會執行任何操作。爲了發出移動命令,從而開始動畫,我使用step()函數,每個玩家從一個貼片到另一個貼片移動一次。在收到「向上」命令後,遊戲表現良好,角色在一秒鐘內平穩移動到新位置。然而,當發出「下行」命令時,他以大約一半的速度移動,顯然在一秒鐘後,他立即被「傳送」到最終位置,突然閃爍。運動的代碼基本上是相同的,但事實上,在一種情況下,三角形運動被加總到y位置,而在另一種情況下,則被減去。也許事實上,位置是一個整數,三角洲是一個雙倍是導致問題? 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:好吧,我想出了爲什麼會發生這種情況。正如我首先想到的那樣,當涉及到加法和減法時,從雙倍到整數的舍入是不同的。如果我這樣表演:
m_xPos += (int)(m_xVel * m_animTimer);
動畫速度是一樣的,問題就解決了。
可能是錯的,但在'Player :: update'中,在'WALKING_DOWN'情況下,它們不應該使用'+ ='而不是' - ='嗎?我只是猜測'WALKING_DOWN'應該與'WALKING_UP'完全相反。不知道這是否與你的問題有關。 – 2012-01-15 21:18:00
@KenWayneVanderLinde m_yDelta變量存儲要走過的剩餘像素以達到該位置,因此在這兩種情況下都應該遞減。 – 2012-01-15 21:20:00
「m_yPos」,「m_yVel」和「m_animTimer」的類型是什麼?而且,我認爲應該總是更新'm_animTimer',否則在下次調用'update'時會得到假值。 – 2012-01-15 21:26:32