Info:
OS: Arch Linux
Version: 4.2 stable
Language: GDscript
Hello!
Im working on a recoil system for a 2D game im making. You shoot a bullet and it launches you in the opposite direction. func recoil(strength, delta): var mousepos = get_local_mouse_position() velocity.x = int(-mousepos.normalized().x * strength) velocity.y = int(-mousepos.normalized().y * strength) print(velocity) My Code.
When I run this, the velocity on the Y axis works fine, but the distance caused by the velocity on the X axis seems to be capped at a certain number. There is no reason for this to be this way, the character script that this is in is just a simple base character script. This effect is only present on the X axis. Reply if you require more information.
Outputs -750, 0 when pointing directly to the left. This seems to not be a velocity issue, but a problem with something else. Its like movement in the horizontal direction is just suddenly blocked at a point.
if it’s pointing to the left, shouldnt it be recoil to the right? and output 750,0 should be the right one, no? anyway can you show the code of how do you apply the movement from the velocity got here?
Sorry, That was a typo. I meant pointing to the right.
full characterBody code:
extends CharacterBody2D
var SPEED = 600.0
var gravity = 1250
func recoil(strength, delta):
var mousepos = get_local_mouse_position()
velocity.x = int(-mousepos.normalized().x * strength)
velocity.y = int(-mousepos.normalized().y * strength)
print(velocity)
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
if velocity.y < 0:
velocity.y += gravity * 1.5 * delta
else:
velocity.y += gravity * delta
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("left", "right")
if direction:
if velocity.x > 0:
$AnimatedSprite2D.play("walkR")
velocity.x = direction * SPEED
else:
$AnimatedSprite2D.play("idleR")
velocity.x = move_toward(velocity.x, 0, SPEED)
if Input.is_action_just_pressed("freeze"):
velocity = Vector2(0,0)
print(velocity)
if Input.is_action_just_pressed("shoot"):
recoil(get_node("/root/Node2D/SETTINGS/Invis").get_meta("Recoil"),delta)
move_and_slide()
oh i see, then it made simple, put print(velocity) on the func _physics_process(delta):, run and try get recoil and check if the velocity suddenly drop from 750 to 0
var direction = Input.get_axis("left", "right")
if direction:
if velocity.x > 0:
$AnimatedSprite2D.play("walkR")
velocity.x = direction * SPEED
else:
$AnimatedSprite2D.play("idleR")
velocity.x = move_toward(velocity.x, 0, SPEED)
that made the velocity.x reduce without notice, try remove or comment those line and use shoot?
Delta in move_toward() takes a value between 0 and 1. SPEED is 600. The velocity will be set to 0 any time the player isn’t moving. I’d change it to move_toward(velocity.x, 0, SPEED*delta).
What is the intent of this line? It seems to me like it would be here that you’d do dampening/friction, but you’re using move_toward which does not do that. What this actually means is “change the x velocity to a value up to 600 units closer to zero than the current value”.
So if the current speed is between -600 and 600 it will become zero here.
If you want to gradually stop, you want lerp(velocity.x, 0, 0.1)
Change that 0.1 to a value of linear dampening you want to use.
Or you could use an actual physics force, which would be more stable. Depends on your game.
Here’s the cleanest and simplest way to do this (imho):
Calculate recoil as a vector opposite to direction_to vector to mouse position.
Calculate velocity normally, then simply add this recoil vector to velocity at the end.
Use lerp or move_toward to reduce the recoil vector every frame until it’s zero.
This way you keep your recoil and velocity calculations separate, easier to debug and understand.
var SPEED = 600.0
var gravity = 1250
var recoil: Vector2 = Vector2.ZERO
var recoil_resistance: float = 1 # adjust as needed, this is units per frame
func add_recoil(strength):
recoil = global_position.direction_to(get_global_mouse_position()).rotated(deg_to_rad(180)) * strength
func _physics_process(delta):
if Input.is_action_just_pressed("shoot"):
add_recoil(get_node("/root/Node2D/SETTINGS/Invis").get_meta("Recoil")) # this hard-coded path looks really sketchy btw
# do your normal velocity calculation without worrying about recoil
# then just add recoil to the final velocity vector
velocity += recoil
recoil.move_toward(Vector2.ZERO, recoil_resistance) # reduce recoil back to zero recoil_resistance worth of units every frame
I wrote this off the top of my head without testing so I hope it works on the first run . Cheers!