🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

cross platform

Started by
37 comments, last by icecubeflower 15 years, 8 months ago
Quote:
Under your current system, lets say your guy moves 1px every 1ms. However, the LCD only refreshes at 60hz. That means that by the time the LCD decides to refresh, your guy will have moved about 17 pixels, but it doesn't look choppy. Right?


I guess that proves you were right the whole time. My eyes never were getting 1000fps. So if my guy ever moved 1024 pixels in one second and it didn't look choppy, it wasn't because I was seeing a frame for every pixel moved. He was actually moving about 17 pixels per frame as far as my eyes were concerned the entire time. Yeah I think I get it now.
Advertisement
These are two very diffent things, right?
Quote:
unsigned int deltaTick = SDL_GetTicks()-primo.elticko;
for( unsigned int i=0; i<deltaTick; ++i )
{
//update everything
}
primo.elticko += deltaTick;

and
Quote:
float position_x = 10;//pixels
float speed = 0.1f;//pixels per second
float delta_time = 1/16.0f;//1/16th of a second
position_x += speed * delta_time;

int pixel_pos_x = (int)position_x;

//update function
unsigned int deltaTick = SDL_GetTicks()-primo.elticko;
float delta_time = deltaTick / 1000.0f

//update everything using delta_time as a multiplier for speeds

primo.elticko += deltaTick;


I forsee a problem with the bottom way. My program checks for collision detection every cycle. With the bottom way suppose the draw function takes up some extra time. That makes my guys move further in the next cycle. So they're essentially warping from one point to another. It's possible guys will walk through each other because they skipped the moment in time where they existed at the same spot.

I guess I was going to run into this problem anyway when I added really fast stuff like arrows or bullets. Is the solution just to make better collision detection that looks at the paths the guys took and checks for collision at each skipped cycle so it behaves just like it would if nothing ever made updates happen less frequently?
There could be a problem with the top way too, except it's hard to say since you don't show the details. But yes, no matter how you do this, you're essentially sampling an object's position at discrete moments in time, and therefore - if you want to do things properly - need to account for the moments in between those samples. However, for a typical SDL game, this is probably overkill. I'd recommend setting some limits so that this doesn't occur.
So... I pretty much have to do it the top way then? The top way behaves the same no matter the speed of the computer. The bottom way increases the distance between sampled points as the computer gets slower.
If your collision detection system can't cope with large movements, then yes, a lot of games actually run the update function using a fixed delta-time value - so if 16ms has passed you could run update 16 times using a delta-time of 1ms (which is essentially what the top way is doing).

However, the alternative (which admittedly is more work) is to improve the collision detection so that it can cope with large movements ;)
I can't get smooth scrolling, I can't figure out why. I have a resolution of 1024x768. One unit is HORZ or 1024 (I use HORZ and VERT sporadically, I'm in the middle of getting rid of my magic numbers.)

So my hero's speed is 0.5f or half a unit per second or 512 pixels. Whatever you want to call it.

When my update function is like this, scrolling is super smooth. I cut a lot of stuff out before I posted here, I just leave what matters.
void tickmaster(Uint8 *keys, MapBox **icemap, MapBox **lastmap, BasicBox &primo, Iceint &iceblock, WeatherBox &nature, AudioBox *boombox){   Uint32 history;  //how much time has passed since last update   history=SDL_GetTicks()-primo.elticko;   if(history>=1)  //monitor is only 60fps probably so why bother updating more   {      //primo.elticko=SDL_GetTicks();      primo.elticko+=history;      switch(primo.istate)  //another switch(istate) to execute every cycle      {      case 1:         input(keys, icemap, lastmap, primo, iceblock, history);      }   }}

See, I say when history is >= 1. It updates every millisecond if it can. But if my monitor is only 60hrtz then updating every millisecond cannot explain the smooth scrolling. If my monitor is 60fps and my guy moves 512 pixels per second, then my map is scrolling about 16 pixels per FRAME. Period. I'm never seeing my map scroll a pixel per frame.

So I tried all the advice above. My update function is like this now:
void tickmaster(Uint8 *keys, MapBox **icemap, MapBox **lastmap, BasicBox &primo, Iceint &iceblock, WeatherBox &nature, AudioBox *boombox){   Uint32 history;  //how much time has passed since last update   history=SDL_GetTicks()-primo.elticko;   if(history>=16)  //monitor is only 60fps probably so why bother updating more   {      //primo.elticko=SDL_GetTicks();      primo.elticko+=history;      switch(primo.istate)  //another switch(istate) to execute every cycle      {      case 1:         input(keys, icemap, lastmap, primo, iceblock, history);      }   }}

I figure updating every 16 milliseconds about matches a standard framerate.

My input() funtion called above is like this: (again I'm cutting most of it out)
//blah blah blahelse if(THIS IS THE ONE THAT'S GETTING EXECUTED FOR MOVING TO THE RIGHT){   primo.hero.Gizmove(1,history,(*icemap)->mapgrid);   setfx(*icemap,primo);}//blah blah blah


Gizmove goes like this:
switch(idirection){case 1:  //right   fhor+=fspeed*(float(history)/1000.0f)*float(HORZ);}

fhor is inside the hero's struct. It's a float. fspeed is in his struct. It's 0.5f. history is passed from the update function, it's the milliseconds since the last update. HORZ is 1024

I'm not using tiles, my maps are hand drawn. I say a map has irow rows and icol columns. If icol==3 then the map is 3 screens wide. So I use a floats called fx and fy to scroll around on the map depending on where the hero is. If his X coordinate is under 512 then fx==0 because the map should be scrolled all the way to the left. If his x coordinate is icol*1024-512 or greater then fx==1024*(icol-1) (in other words, scrolled as far to the right as possible)

So that setfx function above, it's like this:
void setfx(MapBox *icemap,BasicBox &primo){   //primo.fxstore=primo.fx;   if(primo.hero.fhor<=512.0f)      primo.fx=0.0f;   else if(primo.hero.fhor<icemap->mapgrid.icol*HORZ-(HORZ/2))      primo.fx=primo.hero.fhor-512.0f;   else      primo.fx=float(icemap->mapgrid.icol-1)*1024.0f;}


Then when I draw my map I go like this:
  /*glPushMatrix();  glTranslatef(-primo.fx,-primo.fy,0.0f);  glBegin(GL_POLYGON);     glTexCoord2f(0,1);	glVertex3f(0,768*icemap->mapgrid.irow,0.0);     glTexCoord2f(1,1);	glVertex3f(1024*icemap->mapgrid.icol,768*icemap->mapgrid.irow,0.0);     glTexCoord2f(1,0);	glVertex3f(1024*icemap->mapgrid.icol,0,0.0);     glTexCoord2f(0,0);	glVertex3f(0,0,0.0);  glEnd();  glPopMatrix();*/glBegin(GL_POLYGON);     glTexCoord2f(primo.fx/(float(icemap->mapgrid.icol)*1024.0f),(primo.fy+768.0f)/(float(icemap->mapgrid.irow)*768.0f));     glVertex3f(0.0f,768.0f,0.0f);  //bottom leftglTexCoord2f((primo.fx+1024.0f)/(float(icemap->mapgrid.icol)*1024.0f),(primo.fy+768.0f)/(float(icemap->mapgrid.irow)*768.0f));     glVertex3f(1024.0f,768.0f,0.0f);  //bottom rightglTexCoord2f((primo.fx+1024.0f)/(float(icemap->mapgrid.icol)*1024.0f),primo.fy/(float(icemap->mapgrid.irow)*768.0f));     glVertex3f(1024.0f,0.0f,0.0f);  //top rightglTexCoord2f(primo.fx/(float(icemap->mapgrid.icol)*1024.0f),primo.fy/(float(icemap->mapgrid.irow)*768.0f));     glVertex3f(0.0f,0.0f,0.0f);  //top left  glEnd();


Generally I do it the bottom way, I just grab a rectangle out of my map and only draw on the screen. I tried it the top way just now for the hell of it to see if it made any difference but it didn't. The top way draws the entire map and srolls to the correct place. I don't know a lot about OpenGL, I assume the bottom way is faster and the top way draws stuff you'll never see. But whatever that's not the issue.

Whenever I make 16ms go by between updates the map scrolling is choppy. It's like it jerks across the srceen. But that doesn't make sense because if my monitor is 60 hrtz then when I had 1ms between updates I wasn't seeing every update. The map was scrolling the same amount per frame. So I'm doing something wrong but I don't know what.

Hey also when it's choppy it looks like the screen got sliced horizontally 4 or 5 times and the slices don't line up. I can't see exactly what's happening but it looks like one slice is pushed to the right and the next to the left or something like that. ...I don't know what's going on. I can guess maybe the screen isn't drawn all the way and then it starts drawing a new frame? I don't know.

[Edited by - icecubeflower on September 28, 2008 4:58:43 PM]
Quote: Original post by icecubeflower
Hey also when it's choppy it looks like the screen got sliced horizontally 4 or 5 times and the slices don't line up. I can't see exactly what's happening but it looks like one slice is pushed to the right and the next to the left or something like that. ...I don't know what's going on. I can guess maybe the screen isn't drawn all the way and then it starts drawing a new frame? I don't know.

This sounds like tearing, and is usually fixed by ensuring V-Sync is turned on in your graphics card settings.

Okay, I'll try to figure out how to do that. (this is on Linux)

But I've played 3D quake like games and stuff on here before and never saw tearing. Isn't there a way for me to write my program so that tearing will not happen no matter if the user has V-Sync enabled or not? ...I mean I actually tried to simulate V-Sync by doing something like this at the end of my draw() function:

inum=SDL_GetTicks();
while(SDL_GetTicks()-inum<17)
{
//waste cycles
}

And it didn't help at all. If my problem is tearing then it was still tearing.
Quote: Original post by icecubeflower
Okay, I'll try to figure out how to do that. (this is on Linux)

But I've played 3D quake like games and stuff on here before and never saw tearing. Isn't there a way for me to write my program so that tearing will not happen no matter if the user has V-Sync enabled or not?
Vsync is typically enabled programatically, rather than by the user.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Oh. Well that's good. Alright I know what to try next.

Man making your own game is a hell of a crash course.

This topic is closed to new replies.

Advertisement