Logic Question

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
ntitan
Posts: 21
Joined: Tue Mar 22, 2005 2:44 pm

Logic Question

Post by ntitan »

Can someone help me out here.

I knew I was doing this wrong when I did it, but I dont know any other way.

I've placed all my logic to control player movement within the loop:

Code: Select all

while(device->run())
  {
  }
As a result depending on the FPS, my player goes faster or slower.

What can I do to make my player move consistently regardless of FPS?

I'm using the getCollisionResultPosition function to move my player, I.E.

Code: Select all


vector3df playerpos = LocalPlayer->node->getPosition();

/* Modifying position +- speed */

triangle3df triout;
bool outFalling;
playerpos = colman->getCollisionResultPosition(WorldSelector,  
  playerpos,  
  vector3df(28.0f,28.0f,28.0f),   // dimensions
  velocity,  
  triout,  
  outFalling,  
  0.0005f,  //sliding speed
  vector3df(0.0f, 0.0f, 0.0f)  // gravity
 );

LocalPlayer->node->setPosition(playerpos);

jox
Bug Slayer
Posts: 726
Joined: Thu Apr 22, 2004 6:55 pm
Location: Germany

Post by jox »

Maybe this helps:

Tutorial : Timing And Movement Part 1
http://irrlicht.sourceforge.net/phpBB2/ ... php?p=7342
It is like it is. And because it is like it is, things are like they are.
ntitan
Posts: 21
Joined: Tue Mar 22, 2005 2:44 pm

Post by ntitan »

Doh, there's a tutorial on it?

Thanks Jox!
ntitan
Posts: 21
Joined: Tue Mar 22, 2005 2:44 pm

Post by ntitan »

OK, another question.

I've tried to implement a simple version of what is shown in the tutorial, I had to change it since the one there didnt seem to work right for me.

So here's the code I made:

Code: Select all

int m_DeltaTime; 
int m_LastDeltaTime; 
int m_TimeFactor; 

void updatetime() 
	{ 
	m_DeltaTime = device->getTimer()->getTime(); 
	m_TimeFactor = (m_DeltaTime-m_LastDeltaTime); 
	m_LastDeltaTime = m_DeltaTime;
	}

Then I take m_TimeFactor and multiply it with my speed var.
"This works great!" My speed stays consistent relative to the frame rate,
HOWEVER as a result the camera which has a parent to the moving object is now really jerky.

Is this normal? Do I need to implement some kind of code to try and smooth the movement of the camera?

Or did I write this time function wrong?

Thanks again,
Nihal
Fraza
Posts: 113
Joined: Sat Feb 26, 2005 11:28 am
Location: Leeds

Post by Fraza »

I haven't read much into this, but if you're looking for smoothness, shouldn't you be using floating points?
SARIN
Posts: 139
Joined: Fri Oct 29, 2004 3:53 am

Post by SARIN »

or, instead of putting in all that stuff, just times all movement by the time since the last frame.
Fraza
Posts: 113
Joined: Sat Feb 26, 2005 11:28 am
Location: Leeds

Post by Fraza »

That's what that stuff in the loop does... isn't it?
ntitan
Posts: 21
Joined: Tue Mar 22, 2005 2:44 pm

Post by ntitan »

Right, that function just calculates the time since it was last called (which would be once per frame). Then I use the result (m_TimeFactor) to multiply times the speed.

But as a result I get occasional strange flicker/twitching of my screen.
I used int's because the time functions dont return floats, but converting them to floats doesnt seem to help either.

As the game runs m_TimeFactor tends to vary between 6 - 3. Not a major difference in movement speed.
ntitan
Posts: 21
Joined: Tue Mar 22, 2005 2:44 pm

Post by ntitan »

OK, I think I've figured out a solution that is atleast asthetically good. I'm not sure how its going to mess with my multiplayer updates.

Basically I just mandated that my time differenence variable 'm_TimeFactor' does not change by more then a small increment per frame.

It seems the problem was that sporadically the frame rate was jumping up and down, causing a flickering effect.

Here's the code I added. Guess I'll have to see what happens in multiplayer when I get there...

Code: Select all

float m_DeltaTime; 
float m_LastDeltaTime; 
float m_TimeFactor; 
float m_LastTimeFactor; 

void updatetime() 
	{ 
	m_DeltaTime = device->getTimer()->getTime(); 
	m_TimeFactor = (m_DeltaTime-m_LastDeltaTime)*0.01f;

	if(m_TimeFactor > m_LastTimeFactor+0.01f) m_TimeFactor = m_LastTimeFactor + 0.01f;
	if(m_TimeFactor < m_LastTimeFactor-0.01f) m_TimeFactor = m_LastTimeFactor - 0.01f;

	m_LastDeltaTime = m_DeltaTime;
	m_LastTimeFactor = m_TimeFactor;
	}

Fraza
Posts: 113
Joined: Sat Feb 26, 2005 11:28 am
Location: Leeds

Post by Fraza »

I don't know exactly what you are trying to achieve with the following

Code: Select all

   if(m_TimeFactor > m_LastTimeFactor+0.01f) m_TimeFactor = m_LastTimeFactor + 0.01f;
   if(m_TimeFactor < m_LastTimeFactor-0.01f) m_TimeFactor = m_LastTimeFactor - 0.01f;
It looks as though it is designed to soften the blow of jumpiness, but it loses the movement rate consistencey, which is not a good way to go on an MPG.

Maybe you could enlighten me. Also, by using floats I meant for values that have the possibility of being floats. Persumably when you divide m_TimeFactor by 100 this is for scaling movement?

anyway, I would have thought the code would look something like that, I haven't seen the tutorial so I don't know what kind of stuff it covers.

Code: Select all

//include etc

//Globals
//constants
const float MOVE_RATE_MOD = whatever float gives the best result
//variables
int iLastTime;

//function prototypes
float getMoveRateModifier();

int main()
{
    //initialisation code
    iLastTime = device -> getTime();
    float fThisMoveDist;
    while(device -> run())
    {
        fThisMoveDist = MOVE_RATE_MOD * getMoveRateModifier();
        //use fThisMoveDist
        //perhaps a timedelay in here would help to keep down the jumpiness?
    }
}

float getMoveRateModifier()
{
    int iTime = device -> getTime();
    float fResult = (iTime - iLastTime) / 100; //I think this is what you'd want
    iLastTime = iTime;
    return fResult;
}
I haven't thought much about that code or compiled it, so there are probably a few mistakes (especially seeing as I only started C++ 2 months ago!). But that hopefully gives you the basic gist of my train of thought, also, where I used fThisMoveDist is where I assumed you should be using a float.

Hopefully this can be of some use :D

Edit:

Actually, having thought about it, you may want something like this...

Code: Select all

//include etc

//Globals
//constants
const float MOVE_RATE_MOD = whatever float gives the best result
const int TIME_TO_ELLAPSE = whichever time you want to ellapse between frames (in the same units as the device -> getTime() function is in.
//variables
int iLastTime;

//function prototypes
float getMoveRateModifier();
bool getIsNextFrame();

int main()
{
    //initialisation code
    iLastTime = device -> getTime();
    float fThisMoveDist;
    bool bDoneFrame = false;
    while(device -> run())
    {
        if(!bDoneFrame)
        {
            //begin and end scene go in this if statement
            fThisMoveDist = MOVE_RATE_MOD * getMoveRateModifier();
            //use fThisMoveDist
            bDoneFrame = true;
        }
        else
            if(getIsNextFrame)
                bDoneFrame = false;
    }
}

//function definitions
float getMoveRateModifier()
{
    int iTime = device -> getTime();
    float fResult = (iTime - iLastTime) / 100; //I think this is what you'd want
    iLastTime = iTime;
    return fResult;
}

bool getIsNextFrame()
{
    int iTime = device -> getTime();
    if((iTime - iLastTime) >= TIME_TO_ELLAPSE)
        return true;
    return false;
}
This code will delay the next frame from being drawn until the system is ready, this will guarntee a consistent FPS on high perormance machines. The minimum FPS you should be going for is 24 FPS, so if you organise your game to run at 24FPS+ consistently using this method on a min spec machine the ga,e will work fine on other computers too. A below minimum spec computer will however have the problems you describe about jumpy movement (but they shouldn't really be running the game!).

Nocode has been comiled, if you have any problems implementing it (if you decide to do so) then just post here.
Post Reply