Game Character Jumping Problem

I’ve been trying to make Mario jump, and I’m having many problems with it. Although I have many problems right now, i rather focus on the main one for now. Which is, how to make him jump up faster and then slower when he is about to reach the peak of his jump, and then fall faster once he touches the peak of his jump. Any way to fix this problem?

Here are the classes involved in his jump

Mario


import extrememario.Sprite;
import java.awt.Image;
import java.awt.event.KeyEvent;

/**
 *
 * @author ben
 */
public class Mario extends MarioSprites {

    public float x;
    public float y;
    public boolean mr = false, ml = false, jumping = false, falling = false;
    public int jCount = 0;

    public Mario() {
        currentSprite = new Sprite();
        idleRight();
        idleLeft();
        runningRight();
        runningLeft();
        jumpRight();
        jumpLeft();
        currentSprite.getAnimation(idleAnimRight);
        currentSprite.x = 250;
        currentSprite.y = 250;
        x = currentSprite.x;
        y = currentSprite.y;
    }

    public void update() {
        moveX();
        moveY();
    }

    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            if (!jumping || !falling) {
                currentSprite.getAnimation(runAnimRight);
            }
            mr = true;
            ml = false;
            dx = 2;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            if (!jumping || !falling) {
                currentSprite.getAnimation(runAnimLeft);
            }
            mr = false;
            ml = true;
            dx = -2;
        }
        if (keyCode == KeyEvent.VK_UP) {
            if (jCount == 0) {
                if (mr) {
                    currentSprite.getAnimation(jumpAnimRight);
                    dx = 2;
                } else if (ml) {
                    currentSprite.getAnimation(jumpAnimLeft);
                    dx = -2;
                }
                if (dy == 0) {
                    dy = 1;
                }
                dy = -(dy * (1 + (1 / 5)));
            }
        }
    }

    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            currentSprite.getAnimation(idleAnimRight);
            dx = 0;
            mr = false;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            currentSprite.getAnimation(idleAnimLeft);
            dx = 0;
            ml = false;
        }

        if (keyCode == KeyEvent.VK_UP) {

            if (mr) {
                currentSprite.getAnimation(jumpAnimRight);
            } else if (ml) {
                currentSprite.getAnimation(jumpAnimLeft);
            }
            if (dy < - 10) {
                if (dy == 0) {
                    dy = 1;
                }
                dy = dy * (1 + (1 / 5));
            }
            if (keyCode != KeyEvent.VK_RIGHT && keyCode != KeyEvent.VK_LEFT) {
                currentSprite.getAnimation(jumpAnimRight);
                dx = 0;
                jCount = 0;
            }
        }

    }

    public void keyTyped(KeyEvent e) {
    }

    public float moveX() {
        return x = x + dx;
    }

    public float moveY() {
        return y = y + dy;
    }

    public Sprite sprite() {
        return currentSprite;
    }

    public Image getFrame() {
        return currentSprite.getImage();
    }
}

MarioSprites


import extrememario.Animation;
import extrememario.Sprite;
import java.awt.Image;
import javax.swing.ImageIcon;

public class MarioSprites {

    public Animation idleAnimRight;
    public Sprite currentSprite;
    public float dx, dy;
    public Image r1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame0.png")).getImage();
    public Image r2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame1.png")).getImage();
    public Image r3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame2.png")).getImage();
    public Image r4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame3.png")).getImage();
    public Image r5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/IRFrame4.png")).getImage();

    public void idleRight() {
        idleAnimRight = new Animation();
        idleAnimRight.addFrame(r1, 110);
        idleAnimRight.addFrame(r2, 110);
        idleAnimRight.addFrame(r3, 110);
        idleAnimRight.addFrame(r4, 110);
        idleAnimRight.addFrame(r5, 110);
    }
    public Animation idleAnimLeft;
    public Image l1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft1.png")).getImage();
    public Image l2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft2.png")).getImage();
    public Image l3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft3.png")).getImage();
    public Image l4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft4.png")).getImage();
    public Image l5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/ILeft5.png")).getImage();

    public void idleLeft() {
        idleAnimLeft = new Animation();
        idleAnimLeft.addFrame(l1, 110);
        idleAnimLeft.addFrame(l2, 110);
        idleAnimLeft.addFrame(l3, 110);
        idleAnimLeft.addFrame(l4, 110);
        idleAnimLeft.addFrame(l5, 110);
    }
    
    public Animation runAnimRight;
    
    public Image rr1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR1.png")).getImage();
    public Image rr2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR2.png")).getImage();
    public Image rr3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR3.png")).getImage();
    public Image rr4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR4.png")).getImage();
    public Image rr5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR5.png")).getImage();
    public Image rr6 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR6.png")).getImage();
    public Image rr7 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR7.png")).getImage();
    public Image rr8 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR8.png")).getImage();
    public Image rr9 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR9.png")).getImage();
    public Image rr10 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RR10.png")).getImage();

    public void runningRight() {
        runAnimRight = new Animation();
        runAnimRight.addFrame(rr1, 70);
        runAnimRight.addFrame(rr2, 70);
        runAnimRight.addFrame(rr3, 70);
        runAnimRight.addFrame(rr4, 70);
        runAnimRight.addFrame(rr5, 70);
        runAnimRight.addFrame(rr6, 70);
        runAnimRight.addFrame(rr7, 70);
        runAnimRight.addFrame(rr8, 70);
        runAnimRight.addFrame(rr9, 70);
        runAnimRight.addFrame(rr10, 70);
    }
    public Animation runAnimLeft;
    public Image rl1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL1.png")).getImage();
    public Image rl2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL2.png")).getImage();
    public Image rl3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL3.png")).getImage();
    public Image rl4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL4.png")).getImage();
    public Image rl5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL5.png")).getImage();
    public Image rl6 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL6.png")).getImage();
    public Image rl7 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL7.png")).getImage();
    public Image rl8 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL8.png")).getImage();
    public Image rl9 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL9.png")).getImage();
    public Image rl10 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL10.png")).getImage();

    public void runningLeft() {
        runAnimLeft = new Animation();
        runAnimLeft.addFrame(rl1, 70);
        runAnimLeft.addFrame(rl2, 70);
        runAnimLeft.addFrame(rl3, 70);
        runAnimLeft.addFrame(rl4, 70);
        runAnimLeft.addFrame(rl5, 70);
        runAnimLeft.addFrame(rl6, 70);
        runAnimLeft.addFrame(rl7, 70);
        runAnimLeft.addFrame(rl8, 70);
        runAnimLeft.addFrame(rl9, 70);
        runAnimLeft.addFrame(rl10, 70);
    }
    
        
    public Animation jumpAnimRight;
    
    public Image jr1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JR1.png")).getImage();
    public Image jr2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JR2.png")).getImage();
    public Image jr3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JR3.png")).getImage();
    public Image jr4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JR4.png")).getImage();
    public Image jr5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JR5.png")).getImage();
    public Image jr6 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JR6.png")).getImage();

    public void jumpRight() {
        jumpAnimRight = new Animation();
        jumpAnimRight.addFrame(jr1, 70);
        jumpAnimRight.addFrame(jr2, 70);
        jumpAnimRight.addFrame(jr3, 70);
        jumpAnimRight.addFrame(jr4, 70);
        jumpAnimRight.addFrame(jr5, 70);
        jumpAnimRight.addFrame(jr6, 70);
        jumpAnimRight.addFrame(jr5, 70);
        jumpAnimRight.addFrame(jr4, 70);
        jumpAnimRight.addFrame(jr3, 140);
        jumpAnimRight.addFrame(jr2, 70);
        jumpAnimRight.addFrame(jr1, 70);
    }
    public Animation jumpAnimLeft;
    public Image jl1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JL1.png")).getImage();
    public Image jl2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JL2.png")).getImage();
    public Image jl3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JL3.png")).getImage();
    public Image jl4 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JL4.png")).getImage();
    public Image jl5 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JL5.png")).getImage();
    public Image jl6 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/JL6.png")).getImage();

    public void jumpLeft() {
        jumpAnimLeft = new Animation();
        jumpAnimLeft.addFrame(jl1, 70);
        jumpAnimLeft.addFrame(jl2, 70);
        jumpAnimLeft.addFrame(jl3, 70);
        jumpAnimLeft.addFrame(jl4, 70);
        jumpAnimLeft.addFrame(jl5, 70);
        jumpAnimLeft.addFrame(jl6, 70);
        jumpAnimLeft.addFrame(jl5, 70);
        jumpAnimLeft.addFrame(jl4, 140);
        jumpAnimLeft.addFrame(jl3, 70);
        jumpAnimLeft.addFrame(jl2, 70);
        jumpAnimLeft.addFrame(jl1, 70);
    }    
}

MainConfig


import extrememario.mario.*;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class MainConfig extends JPanel implements Runnable {

    public Mario mario;
    public Thread mainLoop;

    public MainConfig() {
        mario = new Mario();
        setFocusable(true);
        addKeyListener(new KL());
    }

    @Override
    public void addNotify() {
        super.addNotify();
        mainLoop = new Thread(this);
        mainLoop.start();
    }
    public Image bg = new ImageIcon(this.getClass().getResource("/extrememario/BackgroundDemoStage.png")).getImage();

    @Override
    public void paint(Graphics g) {
        g.drawImage(bg, 0, 0, null);
        g.drawImage(mario.getFrame(),Math.round(mario.moveX()), Math.round(mario.moveY()), null);
        g.dispose();
    }

    public class KL extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {
            mario.keyPressed(e);
        }

        @Override
        public void keyReleased(KeyEvent e) {
            mario.keyReleased(e);
        }
    }

    @Override
    public void run() {
        long lastTime = System.currentTimeMillis();
        while (true) {
            long nowTime = System.currentTimeMillis();
            long timePassed = nowTime - lastTime;
            lastTime = nowTime;
            mario.sprite().update(timePassed);
            mario.update();
            repaint();
            try {
                Thread.sleep(20);
            } catch (Exception e) {
            }
        }

    }
}

Isn’t any jump a classic parabola? The best way to do this is to have a gravity variable that you constantly subtract from the Y velocity.


    public Image rl1 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL1.png")).getImage();
    public Image rl2 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL2.png")).getImage();
    public Image rl3 = new ImageIcon(this.getClass().getResource("/extrememario/mario/sprites/RL3.png")).getImage();
...etc...

Psst. List. Or hell, even Image[]

I’ve tried out your advice, but for some reason he still won’t go up faster and then slower, and then go down slower and then faster.Any thoughts?

Here is the new keyPressed() and keyReleased() in the Mario class


    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        float g = 6;
        if (keyCode == KeyEvent.VK_RIGHT) {
            if (!jumping || !falling) {
                currentSprite.getAnimation(runAnimRight);
            }
            mr = true;
            ml = false;
            dx = 2;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            if (!jumping || !falling) {
                currentSprite.getAnimation(runAnimLeft);
            }
            mr = false;
            ml = true;
            dx = -2;
        }
        if (keyCode == KeyEvent.VK_UP) {
            if (jCount == 0) {
                if (mr) {
                    currentSprite.getAnimation(jumpAnimRight);
                    dx = 2;
                } else if (ml) {
                    currentSprite.getAnimation(jumpAnimLeft);
                    dx = -2;
                }
                if (dy == 0) {
                    dy = 1;
                }
                dy = (float) -(g * (1.002));
                dy = dy + g;
                System.out.println(dy);
            }
        }
    }

    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        float g = 6;
        if (keyCode == KeyEvent.VK_RIGHT) {
            currentSprite.getAnimation(idleAnimRight);
            dx = 0;
            mr = false;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            currentSprite.getAnimation(idleAnimLeft);
            dx = 0;
            ml = false;
        }

        if (keyCode == KeyEvent.VK_UP) {
            if (mr) {
                currentSprite.getAnimation(jumpAnimRight);
            } else if (ml) {
                currentSprite.getAnimation(jumpAnimLeft);
            }
            dy = (float) (g * (1.002));
            dy = dy + g;
            if (keyCode != KeyEvent.VK_RIGHT && keyCode != KeyEvent.VK_LEFT) {
                currentSprite.getAnimation(jumpAnimRight);
                dx = 0;
                jCount = 0;
            }
        }

    }

I think part of your problem is that you are using such a small amount that he moves by. It looks like you have him moving at 2 pixels. That will only give you a variance of 2, 1 or 0. I don’t think that’s very noticeable. What values are you getting from you output of dy?

Thanks for you reply.

This is what I get from the output of dy.


..........
-0.012000084
-0.012000084
-0.012000084
-0.012000084
-0.012000084
-0.012000084
...........

I think I see your problem, let’s see if I can explain the fix.
First you need an initial jump speed. say (5) five.
At each update, you reduce the jump speed by gravity, say dy.
When you call update and get y. You use the the current jump speed to add to the Y value.

This is what we should expect:
Mario starts at Y = 100
1st update jumpSpeed is 5, dy is 1
moveY substracts the jump speed form the current Y.
Y is changed to 95.
2nd update, jumpSpeed is changed to 4 (jumpSpeed - dy)
moveY changes Y to 91.
and so on…
When JumpSpeed reaches zero, you then need to add dy to jumpSpeed each update.

For some reason, Mario couldn’t jump this time. Did I code or misunderstand something?

New keyPressed() and keyReleased() under Mario


    public void keyPressed(KeyEvent e) {
        float g = 1;
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) {
            if (!jumping || !falling) {
                currentSprite.getAnimation(runAnimRight);
            }
            mr = true;
            ml = false;
            dx = 2;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            if (!jumping || !falling) {
                currentSprite.getAnimation(runAnimLeft);
            }
            mr = false;
            ml = true;
            dx = -2;
        }
        if (keyCode == KeyEvent.VK_UP) {
            if (jCount == 0) {
                if (mr) {
                    currentSprite.getAnimation(jumpAnimRight);
                    dx = 2;
                } else if (ml) {
                    currentSprite.getAnimation(jumpAnimLeft);
                    dx = -2;
                }
                dy = 10;
                dy = dy - g;
                if (dy <= 0) {
                    dy = dy + g;
                }
                if (y >= 250) {
                    dy = 0;
                }
                System.out.println(dy);
            }
        }
    }

    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        float g = 1;
        if (keyCode == KeyEvent.VK_RIGHT) {
            currentSprite.getAnimation(idleAnimRight);
            dx = 0;
            mr = false;
        } else if (keyCode == KeyEvent.VK_LEFT) {
            currentSprite.getAnimation(idleAnimLeft);
            dx = 0;
            ml = false;
        }

        if (keyCode == KeyEvent.VK_UP) {
            if (mr) {
                currentSprite.getAnimation(jumpAnimRight);
            } else if (ml) {
                currentSprite.getAnimation(jumpAnimLeft);
            }
            dy = 0;
            dy = dy + g;
            if(dy >= 10){
                dy = 10;
            }
            if (y >= 250) {
                dy = 0;
                jCount = 0;
            }
            if (keyCode != KeyEvent.VK_RIGHT && keyCode != KeyEvent.VK_LEFT) {
                currentSprite.getAnimation(jumpAnimRight);
                dx = 0;
                jCount = 0;
            }
        }

    }


You should not have to keep track of the key release of the UP button. When you press UP, it should set a flag that Mario is jumping. Then each update. It should check if jumping, then adjust for the jump speed, minus the gravity.

On Key press, set you flag for jumping.
On update, check if jumping. If jumping, get jump speed. The current jump speed minus the gravity. 10 - 1. Then you get the new Y location, current Y location plus the new jump speed (9).
Once your jump speed reach 0, you start adding gravity to the jump speed.

Pseudo code:


update()
if (jumping) {
  int newJumpSpeed = currentJumpSpeed - gravity
  if (jumpspeed == 0) {
    jumping = false;
    falling = true;
  }
  y = y - newJumpspeed;
}
else if (falling) {
   int new jumpSpeed = currentJumpSpeed + gravity;
   y = y + jumpSpeed;
}

Hope that helps. :slight_smile:

Thanks for the reply.

Thanks for the idea, but I already figured out the problem with the code.But I’ll also keep this idea in mind to :).