noobkoder noobkoder - 3 months ago 19
Android Question

Trying to do a simple Jump

I'm trying to learn how to make a 2D Game without Game Engines, anyways I already created a background scrolling right now my goal is to make my character jump. But the thing is whenever I start my app the character is spinning up and down and it will just go away to the background.

Here's my character code

public class Deer extends GameCharacter {

private Bitmap spritesheet;
private double dya;
private boolean playing;
private long startTime;
private boolean Jump;
private Animate Animation = new Animate();

public Deer(Bitmap res, int w, int h, int numFrames) {

x = 20;
y = 400;
dy = 0;
height = h;
width = w;

Bitmap[] image = new Bitmap[numFrames];
spritesheet = res;

for (int i = 0; i < image.length; i++)
{
image[i] = Bitmap.createBitmap(spritesheet, i*width, 0, width, height);
}

Animation.setFrames(image);
Animation.setDelay(10);
startTime = System.nanoTime();

}

public void setJump(boolean b){
Jump = b;
}

public void update()
{
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100)
{
}
Animation.update();

if(Jump){
dy = (int)(dya+=5.5);

}
else{
dy = (int)(dya+=5.5);
}

if(dy>14)dy = 14;
if(dy>14)dy = -14;

y += dy*2;
dy = 0;
}


public void draw(Canvas canvas)
{
canvas.drawBitmap(Animation.getImage(),x,y,null);
}
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
public void resetDYA(){dya = 0;}
}


x - character's horizontal position
y - character's vertical position
dx - character's horizontal acceleration
dy - character's vertical acceleration

public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN) {
if(!deer.getPlaying()) {
deer.setPlaying(true);
}
deer.setJump(true);
return true;
}

return super.onTouchEvent(event);
}

Answer

I can't say for sure if this is the only problem because you have other suspicious code but it looks like you jump no matter what.

if(Jump){
    dy = (int)(dya+=5.5);
} else {
    dy = (int)(dya+=5.5);
}

If Jump is true you set the vertical acceleration. But you also set the vertical acceleration to the same value if Jump is false. You also don't show in your code where Jump is ever set to false.

Another odd bit of code is:

if(dy>14)dy = 14;
if(dy>14)dy = -14;

Here, if dy>14 you set it to 14. Then you check dy>14 immediately after. Of course, this time it's false. But because those two conditions are the same the second one will never pass since the one before it ensures it won't. The only other option is they both fail. IOW, you'll never be able to enter the second if.


All that aside, I'm not sure why you're taking this approach. You can simply rely on physics equations with constant acceleration, give an initial velocity, check for a collision with the ground (or at least the original height), and just let it run. For example:

// These are the variables you need.
int x = 200, y0 = 0, y = 0, velocity = 15;
double t = 0.0, gravity = -9.8;

// This is the statement that should run when you update the GUI.
// It is the fundamental equation for motion with constant acceleration.
// The acceleration is the gravitational constant.
y = (int) (y0 + velocity * t + .5 * gravity * t * t);
if (y < 0) {
    y = y0 = 0; 
    //Stop jumping!
    Jump = false; 
} else {
    // Swap the y values.
    y0 = y;
    // Increase the time with the frame rate.
    t += frameRate;
}
// Draw the character using the y value

The best part about this is you don't need to worry about when you get to the maximum height because the equation will automatically bring you down. It also looks more natural as if the mechanics are real. Try it out.


A simple Swing example that you can play around with. Note that the values are different to deal with the way the components are drawn to the screen. Normally, you would deal with that with transformations but this will do for the task.

public class Main {

    static Timer timer;

    Main() {
        JFrame frame = new JFrame("Hello sample");
        frame.setSize(new Dimension(550, 550));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JPanel panel = new MyPanel();
        frame.add(panel);
        frame.setVisible(true);
        timer = new Timer(5, (e) -> panel.repaint());
        timer.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Main::new);
    }

    class MyPanel extends JPanel {
        int x = 200, y0 = 300, y = 0, w = 200, h = 200, v = -8;
        double t = 0.0, gravity = 9.8;
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            y = (int) (y0 + v * t + .5 * gravity * t * t);
            if (y > 300) {
                y = y0 = 300;
                // To prevent it from stopping comment the timer.stop() and 
                // uncomment the t = 0.0 statements.
                //t = 0.0;
                timer.stop();
            } else {
                y0 = y;
                t += .025;
            }
            g.drawOval(x, y, w, h);
        }
    }
}