How to calculate physical stats for a platformer game

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
ilovelove2019
Citizen
Posts: 78
Joined: Wed Sep 11, 2019 10:38 am

How to calculate physical stats for a platformer game

Post by ilovelove2019 » Wed Nov 20, 2019 3:20 pm

Hello everyone, I am in need of your help. I am trying to make a platform game with windfield. And I have difficulty with the physical index. I don't know how to calculate physics properly, or just relatively for my game, like the popular platformer games today. I do not know the gravity of the world, the force appliedForce (?,?). Sorry, my English is too poor and I don't know how to express it. My specific case is that the player is 24 pixels high and 16 pixels wide. Can everyone align me with some perfect stats? More specifically, it is world: setGravity (0,?). When I want the player to move right, left and jump, what is the force of applyForce (?,?). It would be great if you showed me how to calculate on a case-by-case basis so that I can later align (such as a character jumping 2 times his height or even 3?). The problem I need to solve is the index I leave the '?' suitable for a game platformer with a character 24pixel high and 16 pixels wide. Sorry my question was stupid and disturbed your valuable time. Hope you help me solve this problem. Thank you very much. Thank you.

User avatar
ivan
Party member
Posts: 1556
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: How to calculate physical stats for a platformer game

Post by ivan » Wed Nov 20, 2019 3:55 pm

I wrote a calculator that can find the missing constants for you:
https://2dengine.com/?p=platformers#Calculator
Note that you need to input at least 2 of the following 4 constants: jump height, gravity, initial velocity and time to apex.
The jump height you already know to be 24*2 (ideally you want to convert that to meters).
On planet earth gravity is ~9.8 m/s^2 so you can input that too if you want to be realistic.
The other 2 variables will be solved for you.
Once you know the initial velocity then you can find the force as follows: force = (velocity/time)*mass
Also, don't use damping or the formulas won't work.

User avatar
pgimeno
Party member
Posts: 2134
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to calculate physical stats for a platformer game

Post by pgimeno » Wed Nov 20, 2019 4:35 pm

I don't think the character is 24 m high though, and since gravity is in m/s² the length units need conversion. The actual value to enter also depends on the metre length (the value you set with love.physics.setMeter), which in turn depends on the actual height of the character. So:
  • Determine how high your character would be in m, if it was real. 1.70m is a good average height, if your character looks like a normal person. But given its width vs height ratio, I'd say it's shorter.
  • Use Windfield functions? to set the setMeter value (I don't know if it supports this) to 24 / height. This value is in pixels/metre. If it doesn't allow you, I expect that you can use love.physics.setMeter directly.
  • Use that value to calculate every conversion of metres to pixels and vice versa. Always use the same units when using Ivan's calculator (either m, m/s, m/s², s or px, px/s, px/s², s).
  • Use Ivan's calculator.
  • If necessary, convert the result back so that length units are in px and enter it. I'm assuming that Windfield expects gravity values in px/s² just as love.physics.newWorld does, and forces in kg*px/s². Check the Windfield docs to be sure.
  • Also assign a mass to your character and set its density accordingly!
I haven't used Windfield so I don't know if it will work well.

Edit: Note though that platformers are rarely physically realistic (there are a few exceptions like Flashback and Prince of Persia). If you're after something like that, then sure, try to refine the physics to adapt them to the real world. If not, just play with the values until they look right to your game.

ilovelove2019
Citizen
Posts: 78
Joined: Wed Sep 11, 2019 10:38 am

Re: How to calculate physical stats for a platformer game

Post by ilovelove2019 » Wed Nov 20, 2019 10:47 pm

Yes, I am trying. My game doesn't need physics to be complete, I just need it like some popular platformer games today. I think I will leave the default of one meter equal to 30 pixels. I want the character to jump 3 times in height. So I have to fill in the computer of ivan the jump height is (24/30 * 3 = 2.4)? Is it right? And the gravity box I still have is 9.8? I don't need physics so right, I just need to index the character left and right proportionally and jump 3 times its height. If you look at the index in my file, I don't know why it is so big and it looks weird. Because I just tried refining the index, please understand because I haven't completed the jump method. Besides, I also want to disable acceleration, I want to play basic game, but I don't know how. It would be great if it could be adjusted so that the acceleration x is small and can limit the player's maximum speed x.
Attachments
testphysics.love
(43.83 KiB) Downloaded 32 times

User avatar
pgimeno
Party member
Posts: 2134
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to calculate physical stats for a platformer game

Post by pgimeno » Thu Nov 21, 2019 3:02 am

So, your character is 80 cm tall, and your conversion factor is 30 px/m.

Now, 9.8 m/s² = (9.8m/1s²)*(30px/1m) = 294 px/s². That's the value to enter in love.graphics.newWorld (or in world:setGravity).

About jumps: ivan's calculator returns an initial velocity of ~6.8586 m/s, i.e. ~205.758 px/s. Now you have a little problem: there's no function to add that vertical velocity directly. Your options are applyForce, applyLinearImpulse and setLinearVelocity.

applyForce divides the acceleration to apply, by the mass of the body, so you have to compensate for the mass in order to apply an acceleration. But you don't want to apply an acceleration, you want to apply a velocity. The acceleration determines how much velocity will be added after 'dt' seconds have passed, therefore in order to apply a specific velocity, you need to know in advance the dt that will be applied in the next world:update(dt) to compensate for that. In your example, you're applying the jump in love.keypressed, therefore you don't even have dt. I don't recommend this approach.

applyLinearImpulse divides the value by the mass of the body to obtain the velocity to apply, so you can compensate by multiplying it by the mass. This is a possibility.

setLinearVelocity can't be used directly, because you need to set both horizontal and vertical components. But you can retrieve the current velocity, add the values, and set the new one, so this option is not off the table. It has the additional advantage that you can easily set, rather than add to, the current vertical velocity.

My recommendation is to use applyLinearImpulse(0, getMass*-205.758).

Tried that in your world. I don't know much about Windfield, but apparently it gives you the actual world and bodies. Edited main.lua follows. I've moved setMeter before newWorld which is where it should be, even if it doesn't make a difference in this case. I've added a rectangle with the desired height for reference. The actual height seems to be a wee bit short, not sure if that's a miscalculation, rounding errors, or internal precision of Box2D.

Code: Select all

function love.load()
    Object = require'classic'
    anim8 = require 'anim8'
    love.graphics.setDefaultFilter('nearest', 'nearest')
    Camera = require "Camera"
    camera = Camera()
    --camera:setFollowStyle('PLATFORMER')
    camera:setFollowStyle('SCREEN_BY_SCREEN')
    camera.scale = 1
    ---- physics library
    wf = require 'windfield-master/windfield'
    love.physics.setMeter(30)
    world = wf.newWorld(0, 0, true)
    world:setGravity(0, 294)
    ---add player
    require 'player'
    player = Player(400, 300)
    -- add some platforms
    require 'block'
    block = Block(0, 500.5, 1000, 30)
end

function love.keypressed(key)
    if key == 'w' then
--        player.collider:applyForce(0, -10000)
        --local x, y =player.collider:getLinearVelocity()
        --player.collider:setLinearVelocity(0, y-205.758)
        player.collider:applyLinearImpulse(0, player.collider:getMass()*-205.758)
    end
end

function love.update(dt)
    camera:update(dt)
    camera:follow(player.x + player.width / 2, player.y + player.height / 2)
    player:update()
    --- update physics
    world:update(dt)
end

function love.draw()
  camera:attach()
    player:draw()
    block:draw()
    world:draw()
  camera:detach()
  camera:draw()
  love.graphics.rectangle("line", 300.5, 500.5-24*3, 17, 24*3-1)
  love.graphics.rectangle("line", 300.5, 500.5-24*2, 17, 24)
end

ilovelove2019
Citizen
Posts: 78
Joined: Wed Sep 11, 2019 10:38 am

Re: How to calculate physical stats for a platformer game

Post by ilovelove2019 » Thu Nov 21, 2019 4:04 am

Reasonable. Your answer is very detailed, I took out my calculator, paper and pen and thought about it, each of your explanations, it was like a lecture, very rewarding. I agree with the use of 'applyLearearImpulse'. And now I have to handle the x speed, when the player holds the key, the speed increases and reaches very fast after a short time. I want to disable acceleration, so the velocity x is immutable. Or still apply it but is there any way to limit the maximum speed or not? I briefly thought about self.collider: setX (self.collider: getX () + self.vx) with self.vx is a constant value, but seems to be ineffective, whether this will probably cause the player be teleported and the next collision will cause many errors? In short, I need to find a way to limit the speed or disable the acceleration of x, hope you can solve it for me. Thank you so much for all.

User avatar
ivan
Party member
Posts: 1556
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: How to calculate physical stats for a platformer game

Post by ivan » Thu Nov 21, 2019 6:05 am

applyForce divides the acceleration to apply, by the mass of the body, so you have to compensate for the mass in order to apply an acceleration.
The problem with applyForce is illustrated by the formula:
force = acceleration*mass
acceleration = change in velocity/time
where "time" is the amount of time your feet are pushing against the floor.
We don't use applyForce for jumping because Box2D is frame-based.
If you use applyForce it will work as thrust which is not what you want for jumping.
applyLinearImpulse divides the value by the mass of the body to obtain the velocity to apply, so you can compensate by multiplying it by the mass. This is a possibility.
You got it. Impulses are basically instant changes in velocity:
impulse = change in velocity*mass
Where the "change in velocity" is usually the same as the "initial jump velocity"
setLinearVelocity can't be used directly
It could as long as you preserve the X-component.
The actual height seems to be a wee bit short, not sure if that's a miscalculation, rounding errors, or internal precision of Box2D.
One of the problems is "world:update(dt)". You will never catch the apex of a jump on screen unless you use a constant time step.
Also, as mentioned in the link I posted "if the initial jump velocity is not a multiple of gravity the maximum height is reached between frames"

User avatar
pgimeno
Party member
Posts: 2134
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to calculate physical stats for a platformer game

Post by pgimeno » Thu Nov 21, 2019 11:28 am

ivan wrote:
Thu Nov 21, 2019 6:05 am
applyForce divides the acceleration to apply, by the mass of the body, so you have to compensate for the mass in order to apply an acceleration.
The problem with applyForce is illustrated by the formula:
force = acceleration*mass
Sorry about the poor wording. I'm aware of the formulas behind, I was just trying to put it in simple terms, but I'm afraid I made it more confusing. I meant that the acceleration applied to the body is the value passed to applyForce divided by the mass, therefore you need to compensate it by multiplying it by the mass, and you still get acceleration, which is not so useful as you and I explained.

User avatar
pgimeno
Party member
Posts: 2134
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to calculate physical stats for a platformer game

Post by pgimeno » Thu Nov 21, 2019 11:52 am

ilovelove2019 wrote:
Thu Nov 21, 2019 4:04 am
In short, I need to find a way to limit the speed or disable the acceleration of x, hope you can solve it for me. Thank you so much for all.
Just ceasing to apply force or impulse is not a good idea, because then the character is subject to friction and the velocity can decrease. There are several other ways.

One trick to achieve this is by applying a simplified model of drag: a force proportional to the velocity and opposed to it: applyForce(-getLinearVelocity*k) (in practice, do it component by component). This results in a terminal velocity, but I don't know the formula to obtain it, therefore you can play with the constant k to find an acceptable value.

Another way is to use getVelocity(), clamp it, and then use setVelocity(). This will probably look less realistic.

ilovelove2019
Citizen
Posts: 78
Joined: Wed Sep 11, 2019 10:38 am

Re: How to calculate physical stats for a platformer game

Post by ilovelove2019 » Thu Nov 21, 2019 10:11 pm

Yes, it is also a very effective solution. Now I realize that, for simple platformer games, you should not use windfield because it is quite complicated and unnecessary. In your experience, which physical library should I use?

Post Reply

Who is online

Users browsing this forum: No registered users and 55 guests