RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
Jump math

0 Members and 1 Guest are viewing this topic.

pokeball TDSOffline
***
Rep:
Level 84
-T D S-
Silver - GIAW 11 (Hard)Silver - Game In A Week VII
Yep, more math problems.

I've been compiling various methods to achieve common tasks in game programming, and the one that has been the most problematic is jumping.

What I am trying to achieve is to create a method that I can use to make a sprite jump towards a coordinate on the screen within a certain amount of frames, it would also have to allow to jump in place as well and be able to limit the height of the jump.



Sadly I cannot offer much in the ways of examples since I have very little understanding as to how to go about this properly. My many attempts have seem to have come close but are very broken when used in different circumstances.

If anyone could give me a hand in creating the method it would be greatly appreciated.

Thanks for reading and have a nice day.

*
Rep:
Level 82
I know this might sound a little... obvious... but can you not look at how VX handles Jumping and utilize that?

I'm not really sure what the context is for this. All I see is "how to do jumping" in which case, it's already done.

:confused:

In the event it is useful, the VX version is this:

Can be found at line 765 in Game_Character
Code: [Select]
def jump(x_plus, y_plus)
    if x_plus.abs > y_plus.abs            # Horizontal distance is longer
      x_plus < 0 ? turn_left : turn_right
    elsif x_plus.abs > y_plus.abs         # Vertical distance is longer
      y_plus < 0 ? turn_up : turn_down
    end
    @x += x_plus
    @y += y_plus
    distance = Math.sqrt(x_plus * x_plus + y_plus * y_plus).round
    @jump_peak = 10 + distance - @move_speed
    @jump_count = @jump_peak * 2
    @stop_count = 0
    straighten
  end

You should be able to modify the arguments passed in to account for coordinates instead of whole tiles like this does (I'm assuming you know enough of maths to do that).

If, on the other hand, you are wanting to write something more realistic then you want to look at kinematics, which would be a little more complex but I can help on that too (I think). I had to do something with kinematics for a C++ games project I did (involving trajectory and motion and gravity etc) during Uni and I still have those.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

pokeball TDSOffline
***
Rep:
Level 84
-T D S-
Silver - GIAW 11 (Hard)Silver - Game In A Week VII
Well, when I ask for any help I've already exhausted the most obvious ways to go about doing it.

I checked all jumping methods in XP, VX and VX Ace and they're all pretty much the same with a few varying names, and I was not able to convert them from tiles to coordinates while understanding why.

And the jumping method goes a little farther than just the method to set it's coordinates.

Code: [Select]
  #--------------------------------------------------------------------------
  # * Update While Jumping
  #--------------------------------------------------------------------------
  def update_jump
    @jump_count -= 1
    @real_x = (@real_x * @jump_count + @x * 256) / (@jump_count + 1)
    @real_y = (@real_y * @jump_count + @y * 256) / (@jump_count + 1)
    update_bush_depth
  end

Rather than just start changing variables anywhere the word jump is and hope it works, I would prefer to understand how it works and why. Otherwise there is no point in doing it and learning from it.

Also just because someone asks for help doesn't mean they're lazy or stupid, keep that in mind the future when trying to "Help" other people as the way you posted came off as very condescending.

*
Rep:
Level 82
Well, when I ask for any help I've already exhausted the most obvious ways to go about doing it.

I checked all jumping methods in XP, VX and VX Ace and they're all pretty much the same with a few varying names, and I was not able to convert them from tiles to coordinates while understanding why.

And the jumping method goes a little farther than just the method to set it's coordinates.

Code: [Select]
  #--------------------------------------------------------------------------
  # * Update While Jumping
  #--------------------------------------------------------------------------
  def update_jump
    @jump_count -= 1
    @real_x = (@real_x * @jump_count + @x * 256) / (@jump_count + 1)
    @real_y = (@real_y * @jump_count + @y * 256) / (@jump_count + 1)
    update_bush_depth
  end

Rather than just start changing variables anywhere the word jump is and hope it works, I would prefer to understand how it works and why. Otherwise there is no point in doing it and learning from it.

Also just because someone asks for help doesn't mean they're lazy or stupid, keep that in mind the future when trying to "Help" other people as the way you posted came off as very condescending.

I apologise if this is how it came across. I in no way intended to suggest you were 'lazy' or 'stupid'. Neither were I attempting to be condescending - just to make that clear.

What I wanted to find out was what grounding already exists. There's not very much information in the original post about what has been looked at, or what is not being understood that is making this problem a problem in the first place. With no information and no previous knowledge of you (outside of your recognition as a scripter), I simply took a neutral stance and tried to figure that out. The natural starting point is at the beginning and that's where I started.

Now, I know you have seen the way it is implemented in VX etc. I also know you are trying to understand how jumping works. I'm hoping it is safe to assume that you are doing this for personal interest and development, to understand the concept behind it, more than trying to write methods that already exist (in some shape or other). If I'd known this to start with - your original post doesn't imply this - I'd have gone about this a different way by suggesting my approach, with regards to the parameters you set, and going from there.

If you still want some assistance, that is up to you.

Also, I do not intend to come across as hostile or any other such things. I'm simply trying to explain my original intentions.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

*****
Rep:
Level 84
This text is way too personal.
Bronze - GIAW 11 (Hard)Silver - GIAW Halloween
The most basic method that I know in 2D with pixel collision is to have a constant gravity function that is constantly pulling your character down, and giving your character his own gravitational function where if it is negative, the character will go up and if it is positive, the character will go down according to the gravity. So say the constant "world" gravity is 1, and my character jumps and recieves a gravity of -10. Each frame he would go up 10, 9, 8...1, 0 and then go down -1, -2, ... until he lands, which the game should recognise. Horizontal movement could be calculated in a number of different ways, such as taking the speed at liftoff like Prinny:CIRBTH does or allowing for the player to halt their movement midway.

By limiting the peak of y, do you mean through obstacles or by allowing the player to utilise varying jump heights? Obstacles would require some sort of obstacle collision detection, where once the player hits the obstacle (at least in my example), the characters gravity automatically resets to 0 and the player begins his/her descent. Varying jump heights would easily be done by simply lowering the initial jump gravity (for example, -8).

pokeball TDSOffline
***
Rep:
Level 84
-T D S-
Silver - GIAW 11 (Hard)Silver - Game In A Week VII
@LoganForrests: If you can provide the assistance, I have no reason to decline the help. Just ask what you need to know and I will do my best to explain myself better.

The jumping I am trying to achieve is not the traditional jumping of platformer games, it's more like the jumping in RPG Maker. Except that instead of X and Y positions it would be more specific coordinates.

Here's an example of how I am trying to use it.

Let's say there's a battler sprite and it's damage is another sprite. I want the damage sprite to jump from the battler position to a specific location on the screen. Now, I could achieve this with a simple movement method where it would go directly to the position, but I am more interested in the arch like movement of jumping and possible improvements and add-ons such as bouncing.

I read a lot of tutorials, but the math and formulas used are sadly not stuff I understand because of my limited school knowledge.

As for limiting the peak of Y, it's the maximum height it would be allowed to jump up before starting to fall down towards it's destination.

As for the reason I am trying to learn more about jumping, is to apply it to a special module I use that contains many functions that are mixed into objects, and jumping is one of the functions that I have not been able to fully grasp.

*****
Rep:
Level 84
This text is way too personal.
Bronze - GIAW 11 (Hard)Silver - GIAW Halloween
Firstly, I just want to say that traditional platform jumping with gravity isn't that much different to how RPG Maker VX applies its jump method. Just replace @jump_method with gravity and reverse it's sign.

For the jump method, I assume you know what everything up till @x = x_plus works. I'll try to break this down step by step as well as I can before MA comes here and explains it much more neatly.

Code: [Select]
@x += x_plus
@y += y_plus

RPG Maker preemptively determines it's destination, much like it would with any other movement. Nothing too exciting there.

Code: [Select]
distance = Math.sqrt(x_plus * x_plus + y_plus * y_plus).round

Good ol' distance formula, the very same one that you learnt in Geometry. x_plus is your (x2 - x1), y_plus is your (y2 - y1)

Code: [Select]
@jump_peak = 10 + distance - @move_speed

A seemingly arbitrary number is chosen (10) for the initial jump, in case there is no distance covered. Distance is added to the @jump_peak since obviously it will take longer for the jump to occur if the distance is longer, and @move_speed is subtracted from @jump_peak because the faster your going, the less time it will take to reach your "peak". In a nutshell, @jump_peak is the frames it takes for your character to reach it's peak height. This is what you would alter to "limit" the peak of Y.

Code: [Select]
@jump_count = @jump_peak * 2

Enterbrain's little trick of counting how many frames the jump will be. Since parabola's are even functions, it will take the same time that it takes to go from the start to the halfway point as to go from halfway point to the finish.

Code: [Select]
@stop_count = 0
straighten

Irrelevant, but it's interesting to note that this is the part the disallows the character to perform any animation. Straighten just aligns the character to it's correct position so that the jump will look normal.

Next, onto the update_jump method:

Code: [Select]
  @jump_count -= 1

One frame in the characters jumphood has passed; this is equivalent to the gravity example I was giving earlier (sorta).

Code: [Select]
  @real_x = (@real_x * @jump_count + @x * 256) / (@jump_count + 1)
  @real_y = (@real_y * @jump_count + @y * 256) / (@jump_count + 1)

Recall that @real_x is x * 256, so (@real_x * @jump_count + @x * 256) is the same as (@real_x * (@jump_count + 1)). However, our x value has changed to the final x value, so the end @real_x will be greater than the initial @real_x. This is Enterbrain's way of calculating the horizontal and vertical movement in our jump method, by inching @real_x until it finally becomes the correct @x * 256 value.

So how does our character jump? The answer is in the screen_y method.

Code: [Select]
  #--------------------------------------------------------------------------
  # * Get Screen Y-Coordinates
  #--------------------------------------------------------------------------
  def screen_y
    y = ($game_map.adjust_y(@real_y) + 8007) / 8 - 1000 + 32
    y -= 4 unless object?
    if @jump_count >= @jump_peak
      n = @jump_count - @jump_peak
    else
      n = @jump_peak - @jump_count
    end
    return y - (@jump_peak * @jump_peak - n * n) / 2
  end

Last part is kind of interesting.

Code: [Select]
return y - (@jump_peak * @jump_peak - n * n) / 2

(@jump_peak * @jump_peak - n * n) is the formula of a circle (kinda), where ((x + h)^2 + (y + k)^2) = r^2. n^2 is subtracted because we don't want your y going over the "jump peak", and the division by two is probably there to make the jump look even more elliptical.

I'm confident that a programmer of your caliber should have no trouble understanding what the rest means, and I can't be bothered explaining it right now since I'm extremely tired. If you need any help understanding it you can always ask like you already have been. Anyways, hope I've been helpful, and I'd love to see what you can cook up with this jumping knowledge.


« Last Edit: December 07, 2011, 04:56:03 AM by cozziekuns »

pokeball TDSOffline
***
Rep:
Level 84
-T D S-
Silver - GIAW 11 (Hard)Silver - Game In A Week VII
Sorry cozziekuns, I already knew most of that stuff except for what "Math.sqrt" did.

My knowledge of math stopped at order of operations and exponents, after that pretty much everything is a mystery to me.
I have some vague ideas as to how some things work, but for the most part I tend to stay away from the more complex formulas and using the Math module.

I know it must be obvious to most people, but I just cannot seem to be able to convert the method to simplex X and Y values, and not use @real_x and @real_y and all that stuff.

Thank you for the help and I'll keep reading to see if I can somehow manage to convert it.

By the way this is the sprite I use for testing.

Code: [Select]
#==============================================================================
# ** Jumping_Square
#------------------------------------------------------------------------------
# Testing sprite for jumping.
#==============================================================================

class Jumping_Square < Sprite
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     viewport : viewport
  #--------------------------------------------------------------------------
  def initialize(viewport = nil)
    super(viewport)
    self.bitmap = Bitmap.new(32, 32)
    self.bitmap.fill_rect(self.bitmap.rect, Color.new(255, 255, 255))
  end 
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  def dispose
    super
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    update_jump
  end 
  #--------------------------------------------------------------------------
  # * Jump To Coordinates
  #--------------------------------------------------------------------------
  def jump_to(dest_x, dest_y, duration, peak_y)
       
  end
  #--------------------------------------------------------------------------
  # * Update Jump
  #--------------------------------------------------------------------------
  def update_jump 
   
  end
end


@jumping_square = Jumping_Square.new
@jumping_square.x = 50
@jumping_square.y = 100
@jumping_square.jump_to(100, 0, 20, 10)

loop do
  Graphics.update
  @jumping_square.update
end

pokeball TDSOffline
***
Rep:
Level 84
-T D S-
Silver - GIAW 11 (Hard)Silver - Game In A Week VII
I don't really like to double post, but this is the progress I was able to make.

Thanks to cozziekuns and his explanation of Geometry I decided to learn as much as possible about it and this was the result.

Code: [Select]
#==============================================================================
# ** Jumping_Square
#------------------------------------------------------------------------------
# Testing sprite for jumping.
#==============================================================================

class Jumping_Square < Sprite
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     viewport : viewport
  #--------------------------------------------------------------------------
  def initialize(viewport = nil)
    super(viewport)
    self.bitmap = Bitmap.new(32, 32)
    self.bitmap.fill_rect(self.bitmap.rect, Color.new(255, 255, 255))   
    @jump_count = 0
  end
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  def dispose
    super
  end
  #--------------------------------------------------------------------------
  # * Determine if jumping
  #--------------------------------------------------------------------------
  def jumping? ; @jump_count > 0 end 
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update ; super ; update_jump if jumping? ; end 
  #--------------------------------------------------------------------------
  # * Jump To Coordinates
  #--------------------------------------------------------------------------
  def jump_to(dest_x, dest_y, duration)

    @jump_dest_x = dest_x
    @jump_dest_y = dest_y
   
    distance = Math.sqrt(dest_x * dest_x + dest_y * dest_y).round

    speed = distance / duration

    @jump_peak = (distance / speed) / 2
    @jump_count = @jump_peak * 2   

    @jump_y = self.y   
  end
  #--------------------------------------------------------------------------
  # * Update Jump
  #--------------------------------------------------------------------------
  def update_jump 
       
    @jump_count -= 1

    self.x = (self.x * @jump_count + @jump_dest_x) / (@jump_count + 1)
    @jump_y = (@jump_y * @jump_count + @jump_dest_y) / (@jump_count + 1)
   
    n = (@jump_count - @jump_peak).abs
    self.y = (@jump_y - (@jump_peak * @jump_peak - n * n) / 2)       
   
   
  end
end


@jumping_square = Jumping_Square.new
@jumping_square.x = (544 - 32) / 2
@jumping_square.y = (416 - 32) / 2

@jumping_square2 = Jumping_Square.new
@jumping_square2.x = (544 - 32) / 2
@jumping_square2.y = (416 - 32) / 2

@jumping_square3 = Jumping_Square.new
@jumping_square3.x = (544 - 32) / 2
@jumping_square3.y = (416 - 32) / 2

  @count = 0
  @count2 = 0

loop do
  Graphics.update
  @jumping_square.update
  @jumping_square2.update
  @jumping_square3.update 
 
 
  if !@jumping_square.jumping?
    @count += 1
    @count %= 40
    x = [[rand(544), 0].max, 512].min   
    @jumping_square.jump_to(x, @jumping_square.y, 5 + @count)   

  end 

  if !@jumping_square2.jumping? 
    @count2 += 1
    @count2 %= 40   
    @jumping_square2.jump_to(@jumping_square2.x, @jumping_square2.y, 5 + @count2)
  end

  if !@jumping_square3.jumping? 
    x = [[rand(544), 0].max, 512].min
    y = [[rand(416), 0].max, 384].min       
    @jumping_square3.jump_to(x, y, 10 + rand(15))
  end
 
end

(Testing it should produce a few white boxes which jump around the screen)

The only thing really missing is proper manipulation of maximum jump elevation along with the speed/duration which are connected.

Let me know if this is headed the right way and if you could please explain a bit more about Geometry and the distance method and how to manipulate it. I have a few theories about it but they all seem to work partially and tend to return infinite numbers from time to time even if the "10" which is used to prevent it is added.
« Last Edit: December 09, 2011, 09:09:44 AM by TDS »

*
Rep:
Level 82
I'm basing this from what you said about your knowledge of maths.

I'm pretty sure there's a problem with what you have too, and I wouldn't mind some proof reading/analysing from someone else - maybe Cozzie if he comes about.

Basically, the problem I see is that your values are the coordinates of the point you want to jump to and not the values that they should be which are the values of the increase in x and y from the current point to the destination point. This might not look like an issue, but I'll explain why it is.

Quote from: default formula from VX
distance = Math.sqrt(x_plus * x_plus + y_plus * y_plus).round

Regarding the formula:

What it's actually doing is finding the length of the given vector using what is more commonly known as the Pythagoras' theorem. If the jump is +10 (pixels) along the x-axis and +3 pixels down the y-axis (based on screen coordinate system where (0, 0) is the top left of the screen), the length of the line starting from (0, 0) to (10, 3) - it's irrelevant on where the start coordinates are as long as the second set of coordinates has an x value that is +10 the first and the y value that is +3 the first - can be calculated based on triangle geometry.

Essentially, what VX does is apply the formula to a vector that starts at the origin (0, 0) (referred to as O from now on), to the "point" (referred to as P) that is based on the jump values of x and y. Thus, if we jump 10x and 5y the point P used is (10, 5). And because that line OP can be thought of as the hypotenuse of a triangle in relation to the coordinate grid, we can apply Pythagoras' theorem to find the distance of the line - or how far we're moving.

I drew up an image in paint to help illustrate it:

Spoiler for:


The orange line represents the side of the triangle with length x, the red line represents the side with length y and the green line is the hypotenuse of the triangle which is also the vector OP.

We can see that the orange line has length 10 and the red line length 3.

Pythagoras tells us that the length of the hypotenuse of a right angled triangle is the square root of x2 + y2, which is what the distance formula is.

Now, that formula used to calculate distance is always based on this idea; that we are calculating the distance based on a line from O to point P (where P is (x jump, y jump)).

However, what you have is this:

Code: [Select]
distance = Math.sqrt(dest_x * dest_x + dest_y * dest_y).round

These aren't actually the same thing. What you're finding with this formula is the length of the vector from O to point Q, where Q is an actual position on your screen - in other words, the distance the sprite will move will not be what you expect. What you wanted to do, though, is find the distance you need to go to get from P (where you are) to Q (where you want to go).

What you need to do is find the vector from point P to point Q. We can do this by subtracting the x and y of P from Q.

For example, P(5, 10) and Q(7, 15)

vector PQ = ((7 - 5), (15-10)) = (2, 5)

As an FYI, this vector PQ(2, 5) can be read as: "the x increases by 2 and the y increases by 5".

A definition would be (Wiki): "A vector is what is needed to "carry" the point A to the point B". And that's what we have there. Point Q is 2x's and 5y's from point P.

The two values, 2 and 5, are what is needed to go into the formula to calculate the distance of the jump.

I would like a second opinion on that, but I'm sure I have that right. It's been a while since I did anything involving this level of mathematics.

Moving on, what I've been looking into for you is polynomial curves. VX, as Cozzie described earlier, bases the jump arc on a circle - this I only learned in that post too. However, because you want to introduce a height, I figured it might be worth looking into. We could, on the other hand, reverse engineer (for lack of words) a circle that has the same properties including your height limitations and then calculate the arc based on that.

Regarding the curves, what you would do is create a third point, point R, based on the two other points P (the start point) and Q (the end point) and create a formula that would calculate the location of the next point to move to in our curve.

I drew another picture to show this:

Spoiler for Curve through PRQ:


Point R has an x value that is halfway between PQ and a y value that is P(y) + height. Then, with 3 points, we can create a quadratic equation that will give us the formula we need to plug values into to find the next drawing location for the sprite to move to until it reaches the end point Q.

Where I'm having issues, though, is that I'm not sure what to do when it comes to points with different y values - I've only ever done curves that intersect the x-axis where y = 0. If someone has a clue, that'd be appreciated. If not, I'll keep trying to figure it out/seek some expert help and get back with that.

Failing that, I'll see about reverse engineering the circle to fit it.
(Why do I always feel like it's the end of the world and I'm the last man standing?)