views:

862

answers:

4

I have been all around with this question and I can't find the correct answer! So, behold, the description of my question:

I'm working in J2ME, I have my gameloop that do the following:

public void run() {
        Graphics g = this.getGraphics();
        while (running) {
            long diff = System.currentTimeMillis() - lastLoop;
            lastLoop = System.currentTimeMillis();
            input();
            this.level.doLogic();
            render(g, diff);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                stop(e);
            }
        }
    }

so it's just a basic gameloop, the doLogic() function calls for all the logic functions of the characters in the scene and render(g, diff) calls the animateChar function of every character on scene, following this, the animChar function in the Character class sets up everything in the screen as this:

protected void animChar(long diff) {
        this.checkGravity();
        this.move((int) ((diff * this.dx) / 1000), (int) ((diff * this.dy) / 1000));
        if (this.acumFrame > this.framerate) {
            this.nextFrame();
            this.acumFrame = 0;
        } else {
            this.acumFrame += diff;
        }
    }

This ensures me that everything must to move according to the time that the machine takes to go from cycle to cycle (remember it's a phone, not a gaming rig). I'm sure it's not the most efficient way to achieve this behavior so I'm totally open for criticism of my programming skills in the comments, but here my problem: When I make I character jump, what I do is that I put his dy to a negative value, say -200 and I set the boolean jumping to true, that makes the character go up, and then I have this function called checkGravity() that ensure that everything that goes up has to go down, checkGravity also checks for the character being over platforms so I will strip it down a little for the sake of your time:

public void checkGravity() {
        if (this.jumping) {
            this.jumpSpeed += 10;
            if (this.jumpSpeed > 0) {
                this.jumping = false;
                this.falling = true;
            }
            this.dy = this.jumpSpeed;
        }
        if (this.falling) {
            this.jumpSpeed += 10;
            if (this.jumpSpeed > 200) this.jumpSpeed = 200;
            this.dy = this.jumpSpeed;
            if (this.collidesWithPlatform()) {
                this.falling = false;
                this.standing = true;
                this.jumping = false;
                this.jumpSpeed = 0;
                this.dy = this.jumpSpeed;
            }
        }
    }

So, the problem is, that this function updates the dy regardless of the diff, making the characters fly like Superman in slow machines, and I have no idea how to implement the diff factor so that when a character is jumping, his speed decrement in a proportional way to the game speed. Can anyone help me fix this issue? or give me pointers on how to make a 2D Jump in J2ME the right way. Thank you very much for your time.

+2  A: 

Why not just scale all constants by diff?

By the way, I'm embarrassed to say this, but I worked on a commercial game where gravity was twice as strong on characters going down as going up. For some reason, people preferred this.

Nosredna
My upvote is on the understanding that you didn't just make that up.
Tom Hawtin - tackline
Nosredna
When I was developing, I tested it with my friends to get their reactions, we always mentioned the SNES Mario series, where Mario has a lower gravity going down, giving him a "feather" feel. It's interesting, how people idealize physics.
ONi
Oh maybe I got it backwards. It was a long time ago. :-)
Nosredna
+2  A: 

Shouldn't you be adjusting the jumpSpeed based on the elapsed time? That is, perhaps the speed changes by -75/sec, so your diff should be a weight for the amount of change applied to the jumpSpeed.

So pass in diff to checkGrav and do something like... jumpSpeed += (diff * (rate_per_second)) / 1000;

(assuming diff in milliseconds)

(Ideally, this would make it just like real gravity :D)

gregd
this totally solved the issue, I made unit testing and all the phones benched a similar peak altitude of the jump! man, I really need to read those physics books again, thanks Gregd!!
ONi
A: 

This seems to be more of a question about game design than the math of a jump. It is a common problem that in games running on different processors one game will be executed faster and on other games it will be executed slower (thus changing the entire speed of the game). I'm not sure what common practice is in games, but whenever I made home-brewed 2D games (they were fun to make) I would have the concept of a game-tick. On faster machines

long diff = System.currentTimeMillis() - lastLoop;
lastLoop = System.currentTimeMillis();

Would be lower. A wait time would be derived from the diff so that the game would run at the same speed on most machines. I would also have the render method in a separate thread so that the game speed isn't dependent on the graphics.

Patrick Gryciuk
Could you elaborate on a way to make the wait time diff-dependant?
ONi
A: 

I can give a formula like this (I use it everywhere). The X is the parameter of it starting from zero and ending on the length of jump. if you want someone to jump at some Height (H) and at some Length (L), then function of the jump will look like this (and it wont' be able to ever look different):

y = minus(power(x - Length of Jump divided by two) multiply by 4 and multiply by Height of the jump) divide by power of Length and add Height of jump in the very end. y = -(X-L/2)(X-L/2)*4*H/(L*L) + H

And if you want the jumping object to land on something, then you can check every new X if it's approximately standing on a platform and if it is standing on something, then don't make it just stop, make it's Y position exactly equal to the Y of platform.

If you're using something like Flash or other base which has inverted y axis, then multiply the function output by -1;

Konstantin