Hussein Albirouti
Hussein Albirouti

Reputation: 63

How do I make my character jump using JavaFx?

I want to make my character jump using JavaFx. When I click SPACE many times fast, the character fall down rapidly and disappear. When I click SPACE many times but slower, the character jumps as it should.

I am not sure what the problem is but I think it has something to do with AnimationTimer and its frames. Maybe I am using a wrong way to make my character jump, so if it is that, can someone give me the right way? I have to use JavaFx.
Avatar: image of my character. I used gravity and AnimationTimer to make curve like a jump.

int gravity = 0;
boolean left, right;
window.getScene().setOnKeyPressed(ePress -> {
           KeyCode keycode = ePress.getCode();
           if(keycode.equals(keycode.D)){
               avatar.setTranslateX(avatar.getTranslateX() + 35);
               right = true;
           }
           if(keycode.equals(keycode.A)){
               avatar.setTranslateX(avatar.getTranslateX() - 35);
               left = true;
           }
           if(keycode.equals(keycode.W)){
               avatar.setTranslateY(avatar.getTranslateY() - 35);
           }
           if(keycode.equals(keycode.S)){
               avatar.setTranslateY(avatar.getTranslateY() + 35);
           }
           if(keycode.equals(keycode.SPACE)){
               double ypreviousPos = avatar.getTranslateY();
               jumpTimer = new AnimationTimer(){
                   @Override
                   public void handle(long now) {
                       avatar.setTranslateY(avatar.getTranslateY() - 10 + gravity);
                       gravity = gravity + 1;
                       if(ypreviousPos == avatar.getTranslateY()){
                             jumpTimer.stop();
                             gravity = 0;
                         }
                       if(right == true ){
                         avatar.setTranslateX(avatar.getTranslateX() + 10);
                         avatar.setTranslateY(avatar.getTranslateY() - 10 + gravity);
                         gravity = gravity + 1;
                         if(ypreviousPos == avatar.getTranslateY()){
                             jumpTimer.stop();
                             gravity = 0;
                         }
                       }  
                        if(left == true ){
                         avatar.setTranslateX(avatar.getTranslateX() - 10);
                         avatar.setTranslateY(avatar.getTranslateY() - 10 + gravity);
                         gravity = gravity + 1;
                         if(ypreviousPos == avatar.getTranslateY()){
                             jumpTimer.stop();
                             gravity = 0;
                         }
                       }
                   }

               };
                   jumpTimer.start();
           }                
        });

        window.getScene().setOnKeyReleased(eRel -> {
             KeyCode keycode = eRel.getCode();
           if(keycode.equals(keycode.D)){
               right = false;
           }
           if(keycode.equals(keycode.A)){
               left = false;
           }
        });
    });

Upvotes: 2

Views: 1633

Answers (1)

James_D
James_D

Reputation: 209694

You need to avoid starting a new AnimationTimer if one is already running: otherwise two (or more) AnimationTimers will be modifying the translateY property, and the gravity field, simultaneously. As a consequence, you are probably skipping the start position and at least one of the animation timers fails to stop.

Replacing

if(keycode.equals(keycode.SPACE))

with

if(keycode.equals(keycode.SPACE) && gravity==0)

should work.

Note also that it's generally a bad idea to test for equality with floating point types. Because of possible rounding errors in floating point arithmetic, you might never get exact equality where you expect it. (In this case, I think it will work, since you are only adding integer values to your double; however, you should follow best practice anyway.) You should probably also replace

if(ypreviousPos == avatar.getTranslateY())

with

if(ypreviousPos <= avatar.getTranslateY())

Finally, you might consider refactoring this so there is only a single AnimationTimer, running constantly, and just arrange for your key handler to change values that cause the timer to make a jump happen.

Upvotes: 2

Related Questions