Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a thread that uses TimeUnit.MILLISECONDS.sleep(5);

Problem is when I load my app on a faster phone say with a snapdragon, it runs at lightning speed.

Is there a way to control this speed so processor speed is not an attributing factor?

Thanks!

share|improve this question
add comment

3 Answers 3

up vote -3 down vote accepted

He'res the class I wrote for this purpose. Use it by first calling start() and then sleepRequiredTime() in your gameloop. call getTimeSinceLastSleep() for elapsed time.

runsPrSecondHint will dictate your wanted FPS. I'm not sure this solution is perfect though, so any input from others is welcome.

package com.ngame.spacegame.utils;

public class ThreadSleepManager {

private int m_runsPrSecondHint;
private float m_maxAllowedSleepTime;
private boolean m_running;

private long m_startTime = 0;
private long m_lastSleepTime = 0;

private int[] m_lastRuntimes;
private int m_runtimeToWriteToIndex = 0;
private int m_averageSleepTime = 0;
private int m_timeSinceLastSleep = 0;

private static final int AVERAGE_POOL = 10;

public ThreadSleepManager( int runsPrSecondHint ) {
    m_runsPrSecondHint = runsPrSecondHint;

    m_maxAllowedSleepTime = 1000.0f / m_runsPrSecondHint;
    initLastRuntimes();
}

private void initLastRuntimes() {
    m_lastRuntimes = new int[AVERAGE_POOL];
    for ( int i : m_lastRuntimes ) {
        m_lastRuntimes[ i ] = (int)m_maxAllowedSleepTime; 
    }
}

public int getTimeSinceLastSleep() {
    return m_timeSinceLastSleep;
}

public int getAverageSleepTime() {
    return m_averageSleepTime;
}

public void start() {
    m_startTime = System.currentTimeMillis();
    m_lastSleepTime = m_startTime;
}

/**
 * Sleeps an optimal amount of time for trying 
 * to have the current thread calling run at m_runsPrSecondHint
 */
public void sleepRequiredTime() {
    assert( m_running == true );
    long currentTime = System.currentTimeMillis();
    m_timeSinceLastSleep = (int) (currentTime - m_lastSleepTime);

    // Update data used for average sleep time calculation
    m_lastRuntimes[ m_runtimeToWriteToIndex ] = m_timeSinceLastSleep;
    m_runtimeToWriteToIndex = ( m_runtimeToWriteToIndex + 1 ) % AVERAGE_POOL;

    // Sleep long enough for the average time since last sleep to stay as close as
    // possible to m_maxAllowedSleepTime
    m_averageSleepTime = calcAverageTimeSinceLastSleep();

    int timeToSleep = (int) (m_maxAllowedSleepTime - m_averageSleepTime);
    if( timeToSleep > 0 ) {
        try {
            Thread.sleep( timeToSleep );
        }
        catch( InterruptedException e ) {

        }
    }

    m_lastSleepTime = currentTime;
}

private int calcAverageTimeSinceLastSleep() {
    int sum_sleep_time = 0;

    for ( int runtime : m_lastRuntimes ) {
        sum_sleep_time += runtime; 
    }

    return sum_sleep_time / m_lastRuntimes.length;
}

}

share|improve this answer
    
That being said, I would probably fix my time step if I were you. Even though this code here tries to find a smart amount of time to sleep based on the average calculation times of previous frames, it seems to stutter now and again. You should accept fix your timestep as answer instead =) –  Nailer Oct 15 '10 at 8:37
add comment

You need to Fix Your Timestep!

http://gafferongames.com/game-physics/fix-your-timestep/

share|improve this answer
2  
Favorite just for this link. Pesky black box physics. –  David Young Oct 14 '10 at 18:55
    
The OP should not be using a fixed sleep time when the rest of the processing can take an unknown amount of time. –  dash-tom-bang Oct 14 '10 at 19:11
    
Please read the article fully then. He addresses this issue when he talks about "The Spiral of Death". –  AttackingHobo Oct 14 '10 at 19:19
    
yes, so I was commenting that the simple takeaway for the OP is that ... Fixed timestep is the One True Path, even if GoG takes a lot of words to get to the point. –  dash-tom-bang Oct 16 '10 at 0:52
add comment

Instead of sleeping to regulate game speed, use the time elapsed per frame to give everything a consistent speed.

myObject.Move(elapsedTime*moveSpeed,0,0);

Something to that effect. No matter what speed the processor runs at or the framerate, the object would always move at the same speed. Make sure any movement or rotation that requires a specific speed uses the same idea.

share|improve this answer
1  
how do I get elapsed time –  Adam Coburn Oct 14 '10 at 13:49
1  
Depends on what you're using. If it's a game engine, check the documentation - there may be something built in. If not, you have to calculate it yourself using whatever time functions are available on your platform. –  beezir Oct 14 '10 at 14:58
2  
Do not use this exact method if you want physics that react the same way each time a simulation is run. The physics will look almost the same, but there will be small errors that accumulate and through through chaos theory, the physics will be much different each time. What happens if the game lags for 2 seconds? What about 10 seconds? Stuff might tunnel through walls. Your character might fall through the floors. Springs could "explode". I posted a better answer. –  AttackingHobo Oct 14 '10 at 16:33
    
Everything gets harder with a variable timestep, so while it is an option it is not a great one (IMO). –  dash-tom-bang Oct 14 '10 at 19:09
    
Agreed, AttackingHobo's link could be considered the canonical reference for managing your timestep. –  jpaver Oct 14 '10 at 19:51
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.