timebased movement problem

hi

Im making a breakout clone for j2me midp2 phones and im having some trouble with timebased movement(i think thats the problem)…
Here is my moveBall method that should make the ball move 20 pixels pr second.


private void moveBall(double elapsedTime) {
        
        float speed = 20; // adjust by experiment
        
        double bxmov = (speed * elapsedTime) / 1000;
        double bymov = (speed * elapsedTime) / 1000;
ut("bxmov double = "+bxmov);
        if (!ball.isDirectionXPositive()) {
            bxmov *= -1;
        }
        if (!ball.isDirectionYPositive()) {
            bymov *= -1;
        }
        //System.out.println("bxmov=" + bxmov);
        ball.setSpeed((int)bxmov, (int)bymov);
        wallCrashCheck();
        brickCrashCheck();
        //ball.setPosition(ball.getX() + bxmov, ball.getY() + bymov );
        ball.setPosition(ball.getX() + ball.speedX(), ball.getY()
                + ball.speedY());

    }

The sleep of the main loop is 20 milliseconds.
This gives different problems. Some times the bxmov is less then 1 or 0.67 etc. that makes the ball move 0 pixles on that frame. This works on the emulator actually, the ball moves quite slowly but ok,and it hits all the bricks ( its a breakout clone) and the collision code works properly.

When i transfer the game to my mobile phone SE K750i it runs like crazy…the ball moves very fast and it just runs through the bricks. IS there something wrong with my timecode or should I just add to the collision detection so that it calculates a hit when the ball moves too far?

How can I make sure that if the game runs on nokia phone it wont act crazy because of different sleep times etc…even if i sleep 20 milliseconds, will it sleep 21 milliseconds on SE and 25 ms on nokia and 50 ms on the emulator?

Developing for j2me wasnt as easy as i thought. Lots of problems hehe ::slight_smile:
If someone wants to look at the full source it is here:
http://www.vestheimonline.com/bricker2mesource.zip

How are you calculating elapsedTime?

shmoove

elapsedTime is calculated in the tick() method:


public void tick() {

        long currentFrameTime = System.currentTimeMillis();

        //first time set it to 0
        if (lastFrameTime == 0) {
            lastFrameTime = currentFrameTime;
        }

        double elapsed = (currentFrameTime - lastFrameTime);
        //System.out.println("elapsed:" + elapsed);

        lastFrameTime = currentFrameTime;
        
        moveBall(elapsed);
        movePaddle(elapsed);
    }

My guess:
On the emulator most of the frames are so quick that the ball moves 0 pixels. Since you are not accumulating these small changes, all these frames actually do nothing to the ball, and only on the ocasional frame where the delta is big enough the ball actually moves.
On the phone, the time delta is big enough so that the ball actually moves on every frame, hence you get a lot faster movement.

A solution would be to make the ball’s speed and position variables floating point as well, and only clamp them to an integer when you draw them on screen. This way, even on the frames where the movement is less than one, the actual position of the ball will be affected - you just won’t see the difference on screen. But on the next frame, when you add another fraction, there will be a difference. This will probably make the phone and the emulator behave more consistently.

EDIT:
Here’s an example of what I mean:
Frame 1 - ball is at 1.0. Movement is 0.25.
Frame 2 - ball is at 1.25. Movement is 0.3.
Frame 3 - ball is at 1.55. Movement is 0.35.
Frame 4 - ball is at 1.90. Movement is 0.2.
Frame 5 - ball is at 2.1 - Only now you actually see the “effect” of all the previous frames.
The way you are currently doing things, the movement would have been 0 in all these frames, so the ball would’ve stayed at 1.0.

You could also round instead of clamp to an integer and then the movement would be seen on Frame 3.

shmoove

Thank you that was a good idea, I have changed the position and speed variables to float. I think i have to create my own sprite class because i cant override j2me’s getX() and then I would have to change all the calls in my code. But i think this float solution is going to work, thanks again :slight_smile: