c++ - Strange behaviour updating sprite position -
c++ - Strange behaviour updating sprite position -
i'm coding simple roguelike game in c++ using sdl library, , have problems moving character on screen. each time frame needs rendered, update position of sprite using update() function, nil if player standing still. issue motion command, , starting animation, utilize step() function called 1 time per each player motion 1 tile another. upon receiving "up" command, game behaves fine , character moves smoothly in 1 sec new position. however, when "down" command given, moves @ half speed, , after 1 sec has passed, instantly "teleported" final position, sudden flicker. code motion identical, fact in 1 case delta motion summed y position, in other case subtracted. maybe fact position integer , delta double causing problems? sum , subract behave differently (maybe different rounding)? here relevant code (sorry length):
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 not wall, set animation m_status = walking_up; m_ydelta = m_currmap->tileheight(); // sprite have move tile m_yvel = m_currmap->tileheight() / 1000.0f; // in 1 sec 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; // ms passed since lastly update switch(m_status) { case walking_up: m_ypos -= m_yvel * m_animtimer; // update position m_ydelta -= m_yvel * m_animtimer; // update 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; // , stop } else m_animtimer = sdl_getticks(); // else update timer } edit: removed variables , left elapsed time, speed , final position. moves without flickering, downwards , right movements visibly slower , left ones. still wonder why...
edit 2: ok, figured out why happening. supposed in first place, there different rounding double integer when comes sum , subtraction. if perform cast this:
m_xpos += (int)(m_xvel * m_animtimer); the animation speed same, , problem solved.
consider following:
#include <iostream> void main() { int = 1, b = 1; += 0.1f; b -= 0.1f; std::cout << << std::endl; std::cout << b << std::endl; } during implicit conversion of float int when , b assigned, past decimal point truncated , not rounded. result of programme is:
1 0 you've said m_ypos integer , m_yvel double. consider happens in player::update if result of m_yvel * m_animtimer less 1. in up case, result sprite moves downwards 1 pixel, in down case, sprite won't move @ all, because if add together less 1 integer, nil happen. seek storing positions doubles , converting them integers when need pass them drawing functions.
a trick can ensure rounding instead of truncation during conversion add together 0.5 floating point value during assignment integer.
for example:
double d1 = 1.2; double d2 = 1.6; int x = d1 + 0.5; int y = d2 + 0.5; in case, x become 1, while y become 2.
c++ sdl
Comments
Post a Comment