iDevGames Forums
Question about Timer - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: Question about Timer (/thread-3115.html)



Question about Timer - bonanza - Aug 6, 2007 11:49 PM

Hi, i'am working on a Editor, and i like to move all Objects Timebased, here a snippet of my code:
Code:
/* Create an update timer */
    timer = [NSTimer scheduledTimerWithTimeInterval: (0.001f) target: self
                                           selector: @selector(heartbeat) userInfo: nil
                                            repeats: YES];


- (void) drawRect: (NSRect) rect
{        
    start = [NSDate timeIntervalSinceReferenceDate];
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glLoadIdentity();
    
    [_camera animate:deltaTime];
    
    glFlush();                                            
    [[self openGLContext] flushBuffer];    
    
    end = [NSDate timeIntervalSinceReferenceDate];
    deltaTime = end-start;
}

move my objects:
Code:
object.position+=velocity*deltaTime;

Is this the right way??


Question about Timer - Nevada - Aug 7, 2007 03:34 AM

Your move objects code is correct, but I didn't think you could just subtract pointer values like that. I believe you can cut some overhead by just doing this:

Code:
NSDate *clockTime = [[[NSDate alloc] initWithTimeIntervalSinceNow:0] retain];
double last = (double)[clockTime timeIntervalSinceNow];

void renderCode {
    deltaT = (double)[clockTime timeIntervalSinceNow] - (double)last;
    last = (double)[clockTime timeIntervalSinceNow];
}

or something similar suiting your needs. I'm also assuming you have some kind of setNeedsDisplay or display call somewhere in the heartbeat selector.


Question about Timer - OneSadCookie - Aug 7, 2007 03:51 AM

They're NSTimeIntervals, not pointers.

Also, you definitely don't want to create an NSDate object like that, and if you did, you definitely wouldn't want to overretain it Rasp

I haven't thought whether the OP's code is OK or not, but yours is definitely not good Rasp


Question about Timer - Nevada - Aug 7, 2007 06:02 AM

Bleh, I thought he was saying:

start = [NSDate dateWithIntervalSinceReferenceDate];

Wacko Ignore me... That's what happens when you read too quickly (especially at 6:00AM).

Anyway, what's wrong with having one static NSDate object? Does alloc:init automatically retain? I know if I use a convenience method the runtime complains because there is no auto-release pool available during static initialization. I sidestepped all of this and and just made a Clock class (more portable).


Question about Timer - ThemsAllTook - Aug 7, 2007 06:07 AM

That's one way to do it. Here's an article that demonstrates another way, and points out a few pitfalls of the variable interval approach: http://www.sacredsoftware.net/tutorials/Animation/TimeBasedAnimation.xhtml


Question about Timer - Nevada - Aug 7, 2007 06:12 AM

Oh, I see the problem now. Your deltaTime is only measuring how long it takes for you to render, not how long it has been since render was called (what you want). Rearrange it as follows:

Code:
start = [NSDate timeIntervalSinceReferenceDate];
deltaTime = end-start;
end = start;

animate(deltaTime);

deltaTime is computed before end is set so it will be using the end set in the previous loop. You'll want to make sure that end is initialized to some value close (preferably equal to) start the first time around or you'll be sending an invalid deltaTime to your animate routine (which could throw your animations into an unexpected state before anything even starts).


Question about Timer - bonanza - Aug 7, 2007 06:56 AM

Nevada Wrote:Oh, I see the problem now. Your deltaTime is only measuring how long it takes for you to render, not how long it has been since render was called (what you want). Rearrange it as follows:

Code:
start = [NSDate timeIntervalSinceReferenceDate];
deltaTime = end-start;
end = start;

animate(deltaTime);

deltaTime is computed before end is set so it will be using the end set in the previous loop. You'll want to make sure that end is initialized to some value close (preferably equal to) start the first time around or you'll be sending an invalid deltaTime to your animate routine (which could throw your animations into an unexpected state before anything even starts).

Ah, thanks thats what i'am looking for ;-).

one more question :-)
i'am working on a simple particlesystem, in this i like to fade particle over a time here a snippet:
Code:
-(void)initParticles:(int)i
{
    float theta = (float) ((rand() % 360) - 180) * 180 / PI;
    
    p[i].velocity.x = _velocity.x+ (cos(theta)*1.5f);
    p[i].velocity.y = _velocity.y+ ((float)(rand() % 4095) * 0.000025f * _velocity.y);
    p[i].velocity.z = _velocity.z+ (sin(theta)*1.5f);
    
    p[i].gravity = _gravity;
    p[i].position = _position;
    p[i].lifeTime = getRandomMinMax(1.0f,_lifeTime);
    p[i].timeAlive = 0.0f;
    p[i].size = _size;
    p[i].color = _pvRandomIVector(makeVector(0.0f, 0.0f, 0.0f), makeVector(1.0f, 1.0f, 1.0f) );
}

-(void)update:(float)timeDelta
{
    int i;
    
    for (i=0; i<NUMPARTICLES; i++)
    {
        p[i].timeAlive+=timeDelta;
        
        p[i].velocity.x += p[i].gravity.x*timeDelta;
        p[i].velocity.y += p[i].gravity.y*timeDelta;
        p[i].velocity.z += p[i].gravity.z*timeDelta;
            
        p[i].position.x+=p[i].velocity.x*timeDelta;
        p[i].position.y+=p[i].velocity.y*timeDelta;
        p[i].position.z+=p[i].velocity.z*timeDelta;
            
        if (p[i].position.y < 0.0f)
            p[i].velocity.y = -0.6 * p[i].velocity.y + ((rand() % 255) / 255.0f);

        if(p[i].timeAlive >= p[i].lifeTime)
        {
            [self initParticles:i];
        }
    }
}

-(void)render
{
    glBindTexture(GL_TEXTURE_2D, _texture);
    
    glEnable(GL_BLEND);            
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    
    glEnable(GL_POINT_SPRITE);
    glPointSize( _size);
    glBegin(GL_POINTS);
    
    int i;
    for (i=0; i<NUMPARTICLES; i++)
    {        
        glVertex3f(p[i].position.x, p[i].position.y, p[i].position.z);
        glColor4d(p[i].color.x, p[i].color.y, p[i].color.z, 1- (p[i].timeAlive / p[i].lifeTime) );
    }
    glEnd();
    glDisable(GL_BLEND);
    glDisable(GL_POINT_SPRITE);
}
the problem is, some particle don't fade as expected, the are blinking and change the color since they are fade out. (difficult to explain, sorry for my bad english).
i cant find whats going wrong here.
when i using only one particle the system works as expected, more than one the system sucks, anyone know whats wrong??

thanks


Question about Timer - ThemsAllTook - Aug 7, 2007 07:17 AM

Not sure if it's your only problem, but if you want that call to glColor4d to affect the current particle you're drawing instead of the next one, you'll want to put it before the glVertex3f call.


Question about Timer - bonanza - Aug 7, 2007 07:25 AM

ThemsAllTook Wrote:Not sure if it's your only problem, but if you want that call to glColor4d to affect the current particle you're drawing instead of the next one, you'll want to put it before the glVertex3f call.

damn Mad its so simple, thank you.
what you mean, with "only problem", you see more ???


Question about Timer - ThemsAllTook - Aug 7, 2007 10:22 AM

All I mean is that I was only skimming, so although that was the only problem I noticed, I might have found more if I read the code more closely. Since it fixed your bug, though, maybe I wouldn't. Smile