class_name PhysicsHelper extends Node # ----------------------------------------------------------------------------------------------- # ## Calculates the jump-off velocity to reach a certain height ## @param gravity Gravity affecting the actor (assumed to be constant) ## @param apex_height Height for which the required jump-off velocity will be calculated ## @param delta_seconds The average delta time of your physics updates ## @returns The jump-off velocity required to reach the specified height ## @remarks ## All integration methods for Newtonian physics (Euler, Midpoint, Verlet, Runge Kutta) ## introduce errors depending on delta time (physics framerate). For example, ## a jump force for 2.0 units will lead to the following heights: ## ## framerate | actual jump height ## 1200 fps | 1.99 units ## 120 fps | 1.97 units ## 60 fps | 1.94 units ## ## This method uses a compensation curve to achieve the desired apex height ## by slightly increasing the jump-off impulse according to height and framerate. ## For some amusing anecdotes, read about Quake3 jump height issues (a multiplayer ## shooter where players with high FPS could jump higher and further...) static func get_jump_off_impulse( gravity : float, apex_height : float, delta_seconds : float ) -> float: # Target jump height and actually required apex height to achieve it # at different framerates: # # target | 120 fps | 60 fps | 30 fps # ------------------------------------ # 1.0 | 1.042 | 1.090 | ? # 2.0 | 2.059 | 2.124 | 2.292 # 3.0 | 3.074 | 3.152 | 3.350 # 4.0 | 4.084 | 4.171 | 4.358 # 5.0 | 5.094 | 5.192 | 5.431 # 6.0 | 6.102 | 6.216 | 6.447 # 7.0 | 7.111 | 7.227 | 7.469 # 8.0 | 8.118 | 8.239 | 8.494 # 9.0 | 9.126 | 9.253 | 9.521 # 10.0 | 10.132 | 10.266 | 10.548 # 20.0 | 20.186 | 20.376 | 20.768 # 30.0 | 30.228 | 30.457 | 30.930 # 40.0 | 40.261 | 40.537 | 41.064 # 50.0 | 50.293 | 50.598 | 51.211 # 60.0 | 60.322 | 60.651 | 61.317 # 70.0 | 70.347 | 70.696 | 71.435 # 80.0 | 80.371 | 80.743 | 81.502 # 90.0 | 90.395 | 90.794 | 91.581 # 100.0 | 100.414 | 100.833 | 101.712 # if delta_seconds > 0.0: var adjust30 : float = 0.1880608 * pow(apex_height, 0.4751134) var adjust60 : float = 0.08728325 * pow(apex_height, 0.4898834) var adjust120 : float = 0.04207374 * pow(apex_height, 0.4967337) var t : float = log2((1.0 / delta_seconds) / 30.0) if t < 2.0: apex_height += lerp(adjust30, adjust60, t - 1.0) else: apex_height += lerp(adjust60, adjust120, t - 2.0) return sqrt(2.0 * gravity * apex_height) # ----------------------------------------------------------------------------------------------- # ## Calculates the required jump-off velocity to reach a certain height ## @param gravity Strength of gravity ## @param apex_height Height for which the required jump-off velocity will be calculated ## @returns The jump-off velocity required to reach the specified height ## @remarks ## Using this impulse on your character will not achieve the intended ## jump height unless you're runnning physics at crazy fast update intervals. ## See for a compensating version. static func get_theoretical_jump_off_impulse(gravity : float, apex_height : float) -> float: return sqrt(2.0 * gravity * apex_height) # ----------------------------------------------------------------------------------------------- # ## Calculates the base-2 logarithm of a number ## @param scalar Number of which the base-2 logarithm will be calculated ## @returns The base-2 logarithm of the specified number static func log2(scalar : float) -> float: return log(scalar) / log(2.0)