Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Stopping from a jump  (Read 3384 times)
0 Members and 1 Guest are viewing this topic.
Offline mneri

Senior Newbie





« Posted 2012-03-27 12:34:36 »

Hi, this is my first post here.
I'm developing my own 2D platform game. I'm only at the beginning. Now I'm trying to make the player jump.
The jump itself works fine but I'm not able to stop the player. Here is some code:

1  
2  
3  
4  
5  
6  
7  
8  
   public void tick() {
      [ some code ]
     
      if (_status == JUMPING) {
         jumpAnimator.tick();
         position.y = jumpAnimator.getValue();
      }
   }


jumpAnimator is an object that calculates the current y position. It works very well and the jump follows a realistic curve.
I want the player jumping, falling and when he reaches the bottom of the screen, stopping.
To stop the jump my idea was to set the _status variable to STOPPED when the player reaches the bottom of the screen.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
public void tick() {
      [ some code ]
     
      if (_status == JUMPING) {
         jumpAnimator.tick();
         position.y = jumpAnimator.getValue();
      }

      if ( /*reached the bottom*/ ) {
         _status = STOPPED;
      }
   }


If I add those lines, the player won't jump anymore because he starts to jump and immediately set his _status to STOPPED.

Any idea?
Offline Embedded

Junior Member


Medals: 1



« Reply #1 - Posted 2012-03-27 12:55:05 »

if(){

}else if(){

}

-.-
Offline R.D.

Senior Member


Medals: 2
Projects: 1


"For the last time, Hats ARE Awesome"


« Reply #2 - Posted 2012-03-27 13:00:00 »

if(){

}else if(){

}

-.-

Very helpful.

I can't see the problem because your hiding some code there. what happens in the "if" where you check if the player reached the bottom?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline mneri

Senior Newbie





« Reply #3 - Posted 2012-03-27 13:00:43 »

If you mean

1  
2  
3  
4  
5  
6  
      if (_status == JUMPING) {
         jumpAnimator.tick();
         position.y = jumpAnimator.getValue();
      } else if (/* reached the bottom */) {
         _status = STOPPED;
      }


It doesn't work. It doesn't change the state to STOPPED.
Offline mneri

Senior Newbie





« Reply #4 - Posted 2012-03-27 13:03:18 »

Well, at the moment the if statement is not very nice. But here it is:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
public void tick() {
      [ some code ]
     
      if (_status == JUMPING) {
         jumpAnimator.tick();
         position.y = jumpAnimator.getValue();
      }

      /* check if the player reached the bottom */
      if (position.y >= (int) 512 * 3 / 4 - 32) {
         _status = STOPPED;
      }
   }


Where 512 * 3 / 4 is the height of the screen and 32 is the height of the player.
Offline ReBirth
« Reply #5 - Posted 2012-03-27 15:00:41 »

Prepare a boolean, let's say if true then jump else not. Jump is assumed to be decreasing Y value every tick. Anytime when you need it to stop, just set the boolean to false. Ofc you need "if(jump) then jump" check every tick.

Offline Antiharpist

Senior Newbie


Medals: 2



« Reply #6 - Posted 2012-03-28 04:46:55 »

My first suggestion would be to create separate variables for your actions. There are many ways to do it, and you could go elegant and use bit-masks and enumerations (static finals) so that your _status variable could contain many statuses at the same time. You seem to have a jumpAnimator object, so I'm guessing you may just keep your variables in there. Since games are time/frame based, you'll probably want to allow impulse for a certain amount of time, and after that, you could switch into fall or no-collision mode. You can end fall mode when a collision occurs. You could stop your jumps on collisions, but for certain collision types you may not want that behavior, say if you jump through a collectible object.

Jumping can require a lot of checking. In games like Super Mario Bros. you jump higher based on how long you hold down the button, and if you end up hitting the ground while still having the button held down, you need to account for that too so the player doesn't repeatedly jump. If the player is in the air you don't want them to jump again on repeated button presses unless you allow a double jump, or are in water and swimming.

You should have a maximum impulse that you allow, and if you reach that, the jump is over until the button is let go and it is established your are on the ground again. If you collide with an object of the right type, the jump is over. I keep a variable called jump_counter to know how many frames in I am so I can keep track of the impulse. At first you might not even want to distinguish between top and bottom collisions. In the end the world just needs to work, and that can be very difficult.

The best advice I could give is to spend the time and figure out why it doesn't work. It isn't particularly helpful advice, but game programming can be done in wildly different ways, and as long as it works it is right. You should view yourself as the guru, because ultimately you will be providing most of the answers.

No, no, it's greater than keen; it's cugat.
Offline mneri

Senior Newbie





« Reply #7 - Posted 2012-03-28 06:40:13 »

@Antiharpist Thank you for the reply. This is the code I written. It works for now.

These are the enums:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
   private static enum XMovement {
      MOVING, STOPPING, STOPPED;
   }
   
   private static enum YMovement {
      JUMPING, FALLING, LANDED;
   }
   
   private XMovement xMovement = XMovement.STOPPED;
   private YMovement yMovement = YMovement.LANDED;


I had to break the _jumpAnimator in two pieces:
  • The first is named _jumpAnimator and it calculates the y position from the beginning to the vertex of the parabola;
  • The second is named _fallAnimator and it calculates the y position from the vertex of the parabola to the end.

This is the code of interest in the tick() method.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
      if (_controls.getKey(Controls.JUMP_BUTTON).isDown)
         if (yMovement == YMovement.LANDED) {
            yMovement = YMovement.JUMPING;
            _jumpAnimator = new JumpAnimator(JUMP_DURATION, JUMP_HEIGHT, position.y);
         }
     
      if (yMovement == YMovement.FALLING) {
         _fallAnimator.tick();
         position.y = _fallAnimator.getValue();
      }
     
      if (yMovement == YMovement.JUMPING) {
         _jumpAnimator.tick();
         position.y = _jumpAnimator.getValue();
         
         if (_jumpAnimator.finished()) {
            _fallAnimator = new FallAnimator(JUMP_DURATION, JUMP_HEIGHT, position.y);
            yMovement = YMovement.FALLING;
         }
      }
     
      if (yMovement == YMovement.FALLING) {
         /* For testing the ground is at y = 200 */
         if (position.y >= 200) /* This is ugly. The fall animator returns double values and it's hard that the value returned it's equal to 200.00 */
            position.y = 200;
            yMovement = YMovement.LANDED;
      }


It works, but I don't think it's what that can be said beautiful code.
Every comment/suggestion is appreciated. I want to make good code first.
Offline 65K
« Reply #8 - Posted 2012-03-28 09:15:32 »

Some possibilities:
* You could set up a state machine for this, with states for MOVING, STOPPING, FALLING, etc. instead of numerous if-statements
* Do collision checking with the environment instead using coordinates.
* Before updating positions, let the collision detector verify the new position, upon approval do the update
* Calculate collision check points of your game entities, based on the current entities heading direction, like if someone is moving to the left, check the right hand side

Offline mneri

Senior Newbie





« Reply #9 - Posted 2012-03-28 09:38:43 »

* You could set up a state machine for this, with states for MOVING, STOPPING, FALLING, etc. instead of numerous if-statements

This is an interesting point. Can you elaborate more on that?

* Do collision checking with the environment instead using coordinates.

This is my first game and the coordinates check was for testing purposes. Clearly I will implement collision detection with environment objects.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline 65K
« Reply #10 - Posted 2012-03-28 09:52:37 »

In my top-down-shooter there are entities like droids and bullets.
Each entity is always in one state like moving or waiting.
Basic collision detection for example, is the same for both kinds of entities, so the detection invocation goes into the parent state class. But the reaction on collision is different: droids just stop at walls whereas bullets explode. And if a droid happens to run into a closed door, the door shall be opened.
So, there are additional inherited state classes for droids and bullets for handling events.
Relatively easy to implement different behaviours and easier to test.

Look up for finite state machines or keep asking  Smiley

Offline mneri

Senior Newbie





« Reply #11 - Posted 2012-03-28 13:38:17 »

Look up for finite state machines or keep asking  Smiley

I googled up "finite state machines" and now I'm asking. Smiley (dear administrator, smileys in this site are ugly Sad)
I found some examples on how to implement finite state machines in Java, but how can I implement them in a game? Can you (or someone else) give me a 10-lines example for the states JUMPING, FALLING, LANDED, please?

--------
EDIT:

I mean an example of finite state machine coded into classes.
Offline 65K
« Reply #12 - Posted 2012-03-28 15:41:20 »

Here is a rough sketch:

1  
2  
3  
4  
5  
6  
public interface State {
   void enter();  
   void process();
   void exit();  
   void onInputEvent();  
}

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public class Actor {

   private State state;
 
   public Actor() {
      state = new StoppedState();
   }
 
   public void act(){
      state.process();
   }
 
   public void setState(State newState) {
      state.exit();
      state = newState;
      state.enter();  
  }
}


Actor#act() is called repeatedly from the game loop
In State#process() do whatever you need to do: update actor positions, do collision checks, perform state changes, look for the meaning of life...

For example, a FallingState would calculate a new y-coordinate, asks the opinion of the collision detector about. In case of ground collision, a state change would be done:

1  
2  
StoppedState state = new StoppedState();
actor.setState(state);


Now, in StoppedState#enter() any movement/velocity/heading would be cleared, and in StoppedState#process() no position updates are necessary. But, in case of incoming input events and upon approval of the collision detector, a state change to WalkingState or whatever is done.

Input events should be delegated from actor to state in order to keep the state encapsulated.

Basic principle is very simple. However, as always, details can be tricky Grin

Offline mneri

Senior Newbie





« Reply #13 - Posted 2012-03-28 16:02:12 »

Is it a good thing to implement the frame management inside a State object?

I mean...

When the player jumps, the jump animation is needed. When the player falls, the fall animation is needed. The jump and fall animation are 4-5 frames long. I wonder if it is a good thing to encapsulate the frame-changing mechanism inside the State object. The State interface will be like this:

1  
2  
3  
4  
5  
6  
7  
public interface State {
   void enter();  
   void process();
   void exit();  
   void onInputEvent();  
   BufferedImage getCurrentFrame();
}


Is this a violation of the State Pattern?
Offline 65K
« Reply #14 - Posted 2012-03-28 17:07:52 »

No, I wouldn't put no image stuff into states.
However, states could decide the current look of the character and store in the character.
1  
2  
3  
4  
public FallingState {
   public void enter() {
      actor.setLook(LookEnum.FALLING);
   }

Offline mneri

Senior Newbie





« Reply #15 - Posted 2012-03-28 17:11:46 »

That's clear. Thank you a lot for your replys. I think it's all right for the moment.
You and _Riven (on IRC) helped me a lot. Thank you again!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (53 views)
2014-04-15 18:08:23

BurntPizza (51 views)
2014-04-15 03:46:01

UprightPath (65 views)
2014-04-14 17:39:50

UprightPath (48 views)
2014-04-14 17:35:47

Porlus (65 views)
2014-04-14 15:48:38

tom_mai78101 (89 views)
2014-04-10 04:04:31

BurntPizza (149 views)
2014-04-08 23:06:04

tom_mai78101 (245 views)
2014-04-05 13:34:39

trollwarrior1 (203 views)
2014-04-04 12:06:45

CJLetsGame (210 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!