hello every body : a problem in the issue of Player movement.
I have a Player character in empty scene moves from point A to B and returns to A in constant speed , At first hour of game running it was OKAY , After three Hours the movement became slow and slow , thank beforehand
Game.h
D3DXMATRIX Player_Matrix ; //main player matrix .
D3DXVECTOR3 PlayerPos; //main player position .
D3DXVECTOR3 PlayerLook; //main player Look at position .
Game.cpp
//Initialize()
D3DXMatrixIdentity(&Player_Matrix);
PlayerPos = D3DXVECTOR3(10.0f,0.0f,10.0f);
PlayerLook = D3DXVECTOR3(0.0f,0.0f,1.0f);
.
//MovePlayer()
//declarations
static float angle = D3DXToRadian(0);
float Speed = 70.0f ;
PlayerPos += ( PlayerLook * ( Speed * (m_timeDelta)) );
if(PlayerPos.x >= 320) // 320:(B)
{
angle = D3DXToRadian(180);
}
if(PlayerPos.x <= 0) // 0:(A)
{
angle = D3DXToRadian(180);
}
//Setting up player matrixes
D3DXMATRIX TransMat , RotMat , TempMat , ;
D3DXMatrixIdentity(&TempMat);
D3DXMatrixIdentity(&RotMat);
D3DXMatrixIdentity(&TransMat);
//Setup Rotation matrix .
D3DXMatrixRotationY(&RotMat,angle);
angle = 0.0f ;
//Attach PlayerLook Vector to rotation matrix
D3DXVec3TransformCoord(&PlayerLook,&PlayerLook,&RotMat);
//gathering rotation matrix with player matrix
D3DXMatrixMultiply(&Player_Matrix,&Player_Matrix,&RotMat);
//transmat is an empty matrix to collect new player position
D3DXMatrixTranslation(&TransMat, PlayerPos.x,PlayerPos.y, PlayerPos.z);
//multiply new position matrix with main player matrix
D3DXMatrixMultiply(&TempMat,&Player_Matrix,&TransMat);
d3ddev->SetTransform(D3DTS_WORLD,&TempMat);
Main_Player->Render();
I would look into how you're calculating m_timeDelta. Perhaps your methodology is allowing floating point error to build up.
Here's an article on the subject: https://randomascii.wordpress.com/2012/02/13/dont-store-that-in-a-float/
I'm with Tom Forsyth, and think that 64-bit integer is the best storage type for absolute times (http://home.comcast.net/~tom_forsyth/blog.wiki.html#[[A%20matter%20of%20precision]]), but double will work fine too.
PlayerLook seems suspicious.
It is being iteratively rotated every frame, with floating point errors it's possible it might gradually be shrinking, probably only on the frames where the rotation changes.
You could confirm by looking at its value in the debugger after several hours of running, or you could eliminate it as a possibility if you renormalize it every frame and see if the slowdown disappears.
I've just found both the problem and its solution :
As I've explained before that all the App works fine , the problem is : the movement (just x++,y++,z++) gets slow and slow after a period of time . First I thought that it's a memory leak but the animation and delta time works fine .here, tried to find the reasonable problem that causes this .
I got the release of the App to other PC , after periods of time the App works fine , at that moment I saw the FPS won't reach 60.0 frame per sec , after search in MS DirectX SDK inside DXUT I found a struct which control FPS , there a Doc that speaks about GPU and the acceleration , they advice to control FPS and its limitation , Here is the Code :
//-----------------------------------------------------------------------------
// Name: LockFrameRate()
// Desc: Limit The frame Rate to specified
//-----------------------------------------------------------------------------
bool LockFrameRate(int frame_rate , float SecPerCnt )
{
static __int64 StartTime = 0 ;
__int64 CurTime = 0 ;
QueryPerformanceCounter((LARGE_INTEGER*)&CurTime);
float CurrentSecond = (float)((CurTime - StartTime )* SecPerCnt ) ;
// Get the elapsed time by subtracting the current time from the last time
// If the desired frame rate amount of seconds has passed -- return true (ie Blit())
if( CurrentSecond > (1.0f / frame_rate) )
{
// Reset the last time
StartTime = CurTime;
return true;
}
return false;
}
// int WINAPI WinMain(....)
//***************************
// Initialize Timing Preformance . *
//***************************
//Store Counts per second
__int64 CountPerSec = 0 ;
//Gets how many counts does the CPU do per second
QueryPerformanceFrequency((LARGE_INTEGER*)&CountPerSec);
//Gets second per count to preform it with different typs of CPUs
float SecondPerCount = 1.0f / CountPerSec ;
//Initial Previous Time
__int64 PrevTime = 0 ;
QueryPerformanceCounter((LARGE_INTEGER*)&PrevTime);
while(msg.message != WM_QUIT) // while not quit message , go on
{
if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(LockFrameRate(60 , SecondPerCount)) // If it is time to draw, do so , I selected 60 fps to limit
{
//Capture Current Time
__int64 CurTime = 0 ;
QueryPerformanceCounter((LARGE_INTEGER*)&CurTime);
//Calculate Delta Time
float DeltaTime =(float) ((CurTime - PrevTime) * SecondPerCount) ;
//Engine loop
Engine->Engine_Run(DeltaTime , SecondPerCount );
//After Frame Ends set Pervious Time to Current Time
PrevTime = CurTime ;
}
//else
//Sleep(1); // Give the OS a little bit of time to process other things
}
I commented Sleep(1) because I know scientifically it's just a burden on the CPU but I put it for Scientific confidence , that's between App and other there is a idle proc that waits for each other this is in nowadays computer technologies .
if you want to try it you can feel some screen stops happens these are unwanted
.
thank you Stack Over Flow .
. thank you guys .
Related
I am trying to write simple loop with fixed delta time used for physics and interpolation before rendering the state. I am using Gaffer on games tutorial on fixed timesteps and I tried to understand it and make it work.
float timeStep = 0.01;
float alpha = 1.0;
while (isOpen()) {
processInput();
deltaTime = clock.restart(); // get elapsed time
if (deltaTime > 0.25) { deltaTime = 0.25; } // drop frame guard
accumulator += deltaTime;
while (accumulator >= timeStep) {
// spritePosBefore = sprite.getPosition();
accumulator -= timeStep;
// sprite.move(velocity * timeStep, 0);
// spritePosAfter = sprite.getPosition();
}
if (accumulator > timeStep) { alpha = accumulator / timeStep; } else { alpha = 1.0; }
// sprite.setPosition(Vector2f(spritePosBefore * (1 - alpha) + spritePosAfter * alpha));
clear();
draw(sprite);
display();
}
Now, everything looks good. I have fixed timestep for physics, draw whenever I can after physics are updated and interpolate between two positions. It should work flawless but I can still see sprite stuttering or even going back by one pixel once in a while. Why does it happen? Is there any problem with my code? I spent last two days trying to understand game loop which would ensure me flawless motions but it seems like it doesn't work as I thought it will. Any idea what could be improved?
You should remove the if statement and always calculate alpha; the if statement will never be executed as the condition is always false after the while loop is exited!
After the loop the accumulator will be between 0 and timeStep so you just end up drawing the latest position instead of interpolating.
I don't think the way you do it is necessarily wrong but it looks a bit overcomplicated. I don't understand exactly what you're trying to do so I'm just going to share the way I implement a "fixed time step" in my SFML applications.
The following is the simplest way and will be "good enough" for most applications. It's not the most precise though (the can be a little error between the measured time and the real time) :
sf::Clock clock;
sf::Event event;
while (window_.isOpen()) {
while (window_.pollEvent(event)) {}
if (clock.getElapsedTime().asSeconds() > FLT_FIXED_TIME_STEP) {
clock.restart();
update(FLT_FIXED_TIME_STEP);
}
render();
}
And if you really need precision, you can add a float variable that will act as a "buffer" :
sf::Clock clock;
sf::Event event;
float timeBeforeNextStep = 0.f; // "buffer"
float timeDilation = 1.f; // Useful if you want to slow or speed up time ( <1 for slowmo, >1 for speedup)
while (window_.isOpen()) {
while (window_.pollEvent(event)) {}
timeBeforeNextStep -= clock.restart().asSeconds() * timeDilation;
if (timeBeforeNextStep < FLT_FIXED_TIME_STEP) {
timeBeforeNextStep += FLT_FIXED_TIME_STEP; // '+=', not '=' to make sure we don't lose any time.
update(FLT_FIXED_TIME_STEP);
// Rendering every time you update is not always the best solution, especially if you have a very small time step.
render();
}
}
You might want to use another buffer for rendering (if you want to run at exactly 60 FPS for example).
I am using SFML making a 2D platformer. I read so many timestep articles but they don't work well for me. I am implementing it like 2500 FPS timestep, on my desktop pc it's amazingly smooth, on my laptop it's getting 300 FPS(I check with Fraps), it's not that smooth at laptop but still playable.
Here are the code snippets:
sf::Clock clock;
const sf::Time TimePerFrame = sf::seconds(1.f/2500.f);
sf::Time TimeSinceLastUpdate = sf::Time::Zero;
sf::Time elapsedTime;
These are variables and here is the game loop,
while(!quit){
elapsedTime = clock.restart();
TimeSinceLastUpdate += elapsedTime;
while (TimeSinceLastUpdate > TimePerFrame){
TimeSinceLastUpdate -= TimePerFrame;
Player::instance()->handleAll();
}
Player::instance()->render();
}
In the Player.h, I've got movement constants,
const float GRAVITY = 0.35 /2500.0f; // Uses += every frame
const float JUMP_SPEED = -400.0f/2500.0f; //SPACE -> movementSpeed.y = JUMP_SPEED;
//When character is touching to ground
const float LAND_ACCEL = 0.075 /2500.0f; // These are using +=
const float LAND_DECEL = 1.5 /2500.0f;
const float LAND_FRICTION = 0.5 /2500.0f;
const float LAND_STARTING_SPEED = 0.075; // This uses =, instead of +=
In the handleAll function of Player class, there is
cImage.move(movementSpeed);
checkCollision();
And lastly, checkCollision function, simply checks if character's master bounding box intersects the object's rectangle from each side, sets the speed x or y to 0, then fixes the overlapping by setting character position to the edge.
//Collision
if(masterBB().intersects(objectsIntersecting[i]->GetAABB())){
//HORIZONTAL
if(leftBB().intersects(objectsIntersecting[i]->GetAABB())){
if(movementSpeed.x < 0)
movementSpeed.x = 0;
cImage.setPosition(objectsIntersecting[i]->GetAABB().left + objectsIntersecting[i]->GetAABB().width + leftBB().width , cImage.getPosition().y);
}
else if(rightBB().intersects(objectsIntersecting[i]->GetAABB())){
if(movementSpeed.x > 0)
movementSpeed.x = 0;
cImage.setPosition(objectsIntersecting[i]->GetAABB().left - rightBB().width , cImage.getPosition().y);
}
//VERTICAL
if(movementSpeed.y < 0 && topBB().intersects(objectsIntersecting[i]->GetAABB())){
movementSpeed.y = 0;
cImage.setPosition(cImage.getPosition().x , objectsIntersecting[i]->GetAABB().top + objectsIntersecting[i]->GetAABB().height + masterBB().height/2);
}
if(movementSpeed.y > 0 && bottomBB().intersects(objectsIntersecting[i]->GetAABB())){
movementSpeed.y = 0;
cImage.setPosition(cImage.getPosition().x , objectsIntersecting[i]->GetAABB().top - masterBB().height/2);
//and some state updates
}
}
I tried to use 60 FPS Timestep like million times but all speed variables become so slow, I can't simply do like *2500.0f / 60.0f to all constants, It doesn't feel same. If I get close constants, It feels "ok" but then when the collision happens, character's position is getting setted all the time and it flys out of the map because of the big lap on the object caused by high speed constants applied every frame I guess...
I need to add, Normally, the book I took the timestep code uses
cImage.move(movementSpeed*TimePerFrame.asSeconds());
but as you saw, I just put /2500.0f to every constant and I don't use it.
So, is 1/2500 seconds per frame good? If not, how can I change all of these to 1/60.0f?
You're doing it wrong.
Your monitor most likely has a refresh rate of 60 Hz (= 60 FPS), thus trying to render an image at 2500 FPS is a huge waste of resources. If the only reason for choosing 2500 FPS is that your movement doesn't work the same, haven't you ever thought about, that the problem then might be with the movement code?
At best you'd implement a fixed timestep (famous article), that way your physics can run at whatever rate you want (2500 "FPS" would still be crazy, so don't do it) and is independent from your rendering rate. So even if you get some varying FPS, it won't influence your physics.
So I have been playing around with DirectX11 lately and I'm still pretty new at it. I'm trying to move something right now with the translation and this is what I've got. I've been reading Frank D Luna's book on DirectX11 and he provides a gameTimer class but I really am not sure how to use delta time. This is the small snippet of code I was working with. Obviously this won't work because whenever I'm not pressing the key the time is still increasing and it's total time.
// Button down event.
if (GetAsyncKeyState('W') & 0x8000)
{
XMMATRIX carTranslate;
// Every quarter second incremete it
static float t_base = 0.0f;
if( (mTimer.TotalTime() - t_base) >= 0.25f )
t_base += 0.25f;
carPos.x = mTimer.TotalTime();
carPos.y = 1.0f;
carPos.z = 0.0f;
carTranslate = XMMatrixTranslation(carPos.x, carPos.y, carPos.z);
XMStoreFloat4x4(&mCarWorld, XMMatrixMultiply(carScale, carTranslate));
}
Usually we constantly render frames (redrawing screen) in a while loop (so called "main loop"). To "move" an object we just draw it in another position than it was in previous frame.
To move objects consistently, you need to know a time between frames. We call it "delta time" (dt). So, between frames, time increases by dt. Given velocity (speed) of object (v), we can calculate displacement as dx = dt * v. Then, to get current position, we just add dx to previous position: x += dx.
Note, that is a bad idea to calculate delta just inside your update or rendering code. Avoiding spreading out this functionality, we usually localize this calculations in timer/clock class.
Here is a simplified example:
// somewhere in timer class
// `Time` and `Duration` are some time units
class Timer {
Time m_previousTime;
Duration m_delta;
public:
Duration getDelta() const { return m_delta; }
void tick() {
m_delta = currentTime() - m_previousTime; // just subtract
m_previousTime = currentTime; // `current` becomes `previous` for next frame
}
};
// main loop
while(rendering) {
Timer.tick();
Frame(m_Timer.getDelta());
}
void Frame(Duration dt) {
if(keyPressed) {
object.position += dt * object.velocity;
}
}
You can now even make your object to move with acceleration (throttle, gravity, etc.):
object.velocity += dt * object.acceleration;
object.position += dt * object.velocity;
Hope you got the idea!
Happy coding!
I'm trying to define a time step for the physics simulation in a PhysX application, such that the physics will run at the same speed on all machines. I wish for the physics to update at 60FPS, so each update should have a delta time of 1/60th of a second.
My application must use GLUT. Currently, my loop is set up as follows.
Idle Function:
void GLUTGame::Idle()
{
newElapsedTime = glutGet(GLUT_ELAPSED_TIME);
deltaTime = newElapsedTime - lastElapsedTime;
lastElapsedTime = newElapsedTime;
glutPostRedisplay();
}
The frame rate does not really matter in this case - it's only the speed at which my physics update that actually matters.
My render function contains the following:
void GLUTGame::Render()
{
// Rendering Code
simTimer += deltaTime;
if (simTimer > m_fps)
{
m_scene->UpdatePhys(m_fps);
simTimer = 0;
}
}
Where:
Fl32 m_fps = 1.f/60.f
However, this results in some very slow updates, due to the fact that deltaTime appears to equal 0 on most loops (which shouldn't actually be possible...) I've tried moving my deltaTime calculations to the bottom of my rendering function, as I thought that maybe the idle callback was called too often, but this did not solve the issue. Any ideas what I'm doing wrong here?
From the OpenGL website, we find that glutGet(GLUT_ELAPSED_TIME) returns the number of passed milliseconds as an int. So, if you call your void GLUTGame::Idle() method about 2000 times per second, then the time passed after one such call is about 1000 * 1/2000 = 0.5 ms. Thus more than 2000 calls per second to void GLUTGame::Idle() results in glutGet(GLUT_ELAPSED_TIME) returning 0 due to integer rounding.
Likely you're adding very small numbers to larger ones and you get rounding errors.
Try this:
void GLUTGame::Idle()
{
newElapsedTime = glutGet(GLUT_ELAPSED_TIME);
timeDelta = newElapsedTime - lastElapsedTime;
if (timeDelta < m_fps) return;
lastElapsedTime = newElapsedTime;
glutPostRedisplay();
}
You can do something similar in the other method if you want to.
I don't now anything about GLUT or PhysX, but here's how to have something execute at the same rate (using integers) no matter how fast the game runs:
if (currentTime - lastUpdateTime > msPerUpdate)
{
DWORD msPassed = currentTime - lastUpdateTime;
int updatesPassed = msPassed / msPerUpdate;
for (int i=0; i<updatesPassed; i++)
UpdatePhysX(); //or whatever function you use
lastUpdateTime = currentTime - msPassed + (updatesPassed * msPerUpdate);
}
Where currentTime is updated to timeGetTime every run through the game loop, lastUpdateTime is the last time PhysX updated, and msPerUpdate is the amount of milliseconds you assign to each update - 16 or 17 ms for 60fps
If you want to support floating-point update factors (which is recommended for a physics application), then define float timeMultiplier and update it every frame like so: timeMultiplier = (float)frameRate / desiredFrameRate; - where frameRate is self-explanatory and desiredFramerate is 60.0f if you want the physics updating at 60 fps. To do this, you have to update UpdatePhysX as taking a float parameter that it multiplies all update factors by.
I have a program in which I am drawing images on the screen. The draw function here is called per frame inside in which I have all my drawing code.
I have written an image sequencer that return the respective image from an index of images.
void draw()
{
sequence.getFrameForTime(getCurrentElapsedTime()).draw(0,0); //get current time returns time in float and startson application start
}
On key press, I have start the sequences from the first image [0] and then go on further. So, everytime I press a key, it has to start from [0] unlike the above code where it basically uses the currentTime%numImages to get the frame (which is not the start 0 position of image).
I was thinking to write a timer of own that basically can be triggered everytime I press the key so that the time always starts from 0. But before doing that, I wanted to ask if anybody had better/easier implementation ideas for this?
EDIT
Why I didn't use just a counter?
I have framerate adjustments in my ImageSequence as well.
Image getFrameAtPercent(float rate)
{
float totalTime = sequence.size() / frameRate;
float percent = time / totalTime;
return setFrameAtPercent(percent);
}
int getFrameIndexAtPercent(float percent){
if (percent < 0.0 || percent > 1.0) percent -= floor(percent);
return MIN((int)(percent*sequence.size()), sequence.size()-1);
}
void draw()
{
sequence.getFrameForTime(counter++).draw(0,0);
}
void OnKeyPress(){ counter = 0; }
Is there a reason this wont suffice?
What you should do is increase a "currentFrame" as a float and convert it to an int to index your frame:
void draw()
{
currentFrame += deltaTime * framesPerSecond; // delta time being the time between the current frame and your last frame
if(currentFrame >= numImages)
currentFrame -= numImages;
sequence.getFrameAt((int)currentFrame).draw(0,0);
}
void OnKeyPress() { currentFrame = 0; }
This should gracefully handle machines with different framerates and even changes of framerates on a single machine.
Also, you won't be skipping part of a frame when you loop over as the remainder of the substraction is kept.