|
|
|
 |
Reply From: |
godot_dev_ |
How I have coded momentum animations in the past is as follows, and it may help you. I started with defined the most basic object to define movement, a basicMovement
. It has speed, angle, max/min speed, acceleration, and duration members. With these properties you can configure basic linear velocity. By combining them together, you can obtain more complex movement like gravity + horitontal walk speed. Add an additional basicMovement
that sends the player into the air and now you have a running jump.
Every frame, in the _physics_process
loop, all the basicMovement
that their duration hasn’t ellapsed yet I aggregate all their speed properties (those basicMovement
with acceleration dynamically increase their own speed every frame) into a single movement vector velocity
, a Vector2D
, and I apply move_and_slide
using velocity
to apply the movement.
To have even more control on movement animations, I created the object complexMovement
, which is a parent that can have many basicMovement
child nodes, and has 3 important properties startTime
,type
, and gravityEffect
. The startTime
just indicates when to activate all the basicMovement
child nodes (e.g, startTime
= 5 means 5 frames (or you could define an actual time and compare it to the time ellapsed since the movement animation started) after the movement animation (parent of the complexMovement
) started, the movement properties of all basicMovement
of the complexMovement
activate and affect the player’s momentum. The next member is the type
, fundamentally, there is NEW
and ADD
movement. NEW
means any previous movement animations’ basicMovement
are stopped prematurely, and ADD
means the basicMovement
already activated are unaffected and new basicMovements
are applied. The gravityEffect
memeber will have 3 values REPLAY
,KEEP
, and STOP
. It indicates, when a complexMovement
activates it’s basicMovements
, whether to restart, keep, or stop the the current gravity (this assume you have a global basicMovement
for gravity that is always applying to the player), respectively.
For example:
- say the player is running forward. Playing the running backward animation should completely stop forward momentum and replace it with back momentum, so that type of animation would have at least one
complexMovement
with type
= NEW
and at least one of its basicMovement
would be angled backward. The gravity should be kept as is since we remain on the ground, so the gravityEffect
would be KEEP
.
- Now suppose you jump while running forward. You don’t want to lose your forward momentum and you want to gain upward momentum. The
complexMovement
to accomplish this would have type
= ADD
and gravityEffect
= REPLAY
. Without replaying the gravity, if gravity keeps accumulating even when on the floor, your jump upward momentum will barely lift you off the ground.
This is a complete solution to a nice movement system. For example, if you want to move in the air while keeping your upward momentum (like if you jump and try to A-D strafe in the air) this system can’t support this. You would need to add a new complexMovement
type that support stopping the last activated basicMovements
, so the upward momentum is unaffected but the left-right straffing (the last activated basicMovement
gets stopped)
Hope this helps
Thank you for the reply, but do u think u could type out the coding so that I can get a better understanding of what goes where, or a picture of how it looks together. Sorry, I sometimes need to see how it’s done to fully understand how it works.
HabastianLynx | 2022-08-29 06:49
Here is pseudo code below illustrating my suggestion:
MovementAniamtion Script
var ellapsedTime=0
var complexMovements=[]
var activeMvm = []
var gravity = null #this will be a reference to a basic movement node
var targetKinematicBody2d=null #thing we will move
func _physics_process(delta):
ellapsedTime = delta
#go over all complex movements involved in a movment animation
for cm in complexMovements:
#strat the complex movements that start late
if cm.startTime <=ellapsedTime:
#apply movement
if cm.type == NEW:
#stop all basic movement
for bm in activeMvm:
bm.stop()
activeMvm.clear()
#replace with new movement
for bm in cm.basicMovements:
activeMvm.append(bm)
elif cm.type == ADD:
#don't interupt the movement, add new movement
#replace with new movement
for bm in cm.basicMovements:
activeMvm.append(bm)
#apply gravity effect
if cm.gravityEffect == REPLAY:
#reset speed to 0 of gravity
gravity.xSpeed =0
gravity.ySpeed =0
gravity.set_physiscs_process(true)#make sure gravity enabled
elif cm.gravityEffect == KEEP:
pass #do nothing to gravity
elif cm.gravityEffect == STOP:
gravity.set_physiscs_process(false)#make sure gravity disabled
var velocity = Vector2(0,0)
#now apply the basic movement to get a final Vector2 that represents velocity
for bm in activeMvm:
if bm.is_physics_processing():
#the basic movements will need to keep track of their ellapsed time, and when the ellapsed time exceeds the duration, the basic movement stops physics processing (set_phsysics_process(false). That's why we check the is_physics_process here
velocity.x = velocity.x + bm.xSpeed #Xspeed is the speed (after acceleration, if any) normalized byt the bm.angle member
velocity.y = velocity.y + bm.ySpeed #yspeed is the speed (after acceleration, if any) normalized byt the bm.angle member
#add the gravity (if active)
if gravity.is_physics_processing():
velocity.y = velocity.y + gravity.ySpeed
#
targetKinematicBody2d.move_and_slide(velocity,...)#here is twhre u call move and slide once per frame, make sure to pass the appropriate paramgeters
godot_dev_ | 2022-08-29 14:28
Thank u so much mate, this’ll make things a lot easier for me.
HabastianLynx | 2022-08-30 04:28
Hi, sorry for asking this late, but in which node should I put this coding, my root node, or my character node?
HabastianLynx | 2023-02-14 03:13
I recommend adding it as a child node (or the character node itself) of the character node, because if you ever have more than 1 game node you want to move around, adding the code to the root node will become messy
godot_dev_ | 2023-02-14 17:29
Hi, just one more question, should I use the coding you showed me to replace the pre-existing one I have, or be with it? Here’s the coding I have for my character node so far.
extends KinematicBody2D
var velocity = Vector2(0,0)
const SPEED = 140
const GRAVITY = 37
const JUMPFORCE = -670
func _physics_process(delta):
if Input.is_action_pressed(“right”):
velocity.x = SPEED
if Input.is_action_pressed(“left”):
velocity.x = -SPEED
velocity.y = velocity.y + GRAVITY
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMPFORCE
velocity = move_and_slide(velocity,Vector2.UP)
velocity.x = lerp(velocity.x,0,0.2)
HabastianLynx | 2023-04-01 22:01