Reputation: 23
I'm new to Godot, and I'm making a personal project, a 2D platformer, a clone of Ninja Gaiden (1988), but I'm having trouble getting the aerial attack to work. The Player script is the following:
extends KinematicBody2D
onready var Animated_player = $AnimatedSprite
onready var Sword = $Sword/CollisionShape2D
export var Acceleration = 512
export var Max_speed = 64
export var Friction = 0.25
export var Air_resistance = 0.02
export var Gravity = 200
export var Jump_force = 100
var Is_attacking = false
var motion = Vector2.ZERO
func _physics_process(delta):
var x_input = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
if Input.is_action_just_pressed("Attack"):
Animated_player.play("Attack")
Sword.disabled = false
Is_attacking = true
motion.x = 0
if x_input != 0 and Is_attacking == false:
Sword.disabled = true
Animated_player.play("Walk")
motion.x += x_input * Acceleration * delta
motion.x = clamp(motion.x, -Max_speed, Max_speed )
Animated_player.flip_h = motion.x < 0
else:
if Is_attacking == false:
Sword.disabled = true
Animated_player.play("Idle")
motion.x = lerp(motion.x, 0, Friction * delta)
motion.y += Gravity * delta
if test_move(transform, Vector2.DOWN):
if x_input == 0:
motion.x = lerp(motion.x, 0, Friction)
if Input.is_action_just_pressed("Jump"):
motion.y = -Jump_force
else:
if Input.is_action_just_pressed("Attack"):
Sword.disabled = false
motion.x = lerp(motion.x, 0, Air_resistance)
Animated_player.play("Jump_Attack")
motion.x = lerp(motion.x, 0, Air_resistance)
if Is_attacking == false:
Sword.disabled = true
if motion.y < 0:
Animated_player.play("Jump")
if motion.y > 0:
Animated_player.play("Fall")
if Input.is_action_just_released("Jump") and motion.y < -Jump_force/2:
motion.y = -Jump_force/2
if x_input == 0:
motion.x = lerp(motion.x, 0, Air_resistance)
move_and_slide(motion)
motion = move_and_slide(motion, Vector2.UP)
func _on_AnimatedSprite_animation_finished():
if Animated_player.animation == "Attack" or Animated_player.animation == "Jump_Attack":
Is_attacking = false
Sword.disabled = true
The Jump_Attack animation plays right, but I want the "Air resistance" to be true while you attack on the air, but if you attack on the ground I want motion.x
to be zero.
but whenever I make motion.x = 0
inside the if Input.is_action_just_pressed:
it stops your movement on the air as well.
How can I solve this?
Upvotes: 0
Views: 471
Reputation: 36
When making any kind of platformer, a good thing to add to the movement script is a "grounded" variable, which determine if the player is on the ground or not. you can do so with something like this (when using is on floor, make sure you always have a gravity applied to your player, and set it after the move_and_slide()):
var grounded = false
func process(_delta):
#move_and_slide(...)
grounded = is_on_floor()
then in your if that check if the attack key is pressed, if the player is grounded, you cant set your motion.x to 0 and if not, don't.
As you mentioned in your comment, now when you land during an attack, the idle or walk animation doesn't play right away because you don't check if the player is grounded when you set your animation to walk or idle and that your condition for your walk and idle animation check if the player is attacking and the only time your variable Is_Attacking is set to false is when the animation ends. here is what I would try,
in your physics_process function:
physics_process(delta):
var x_input = Input.get_action_strength("ui_right") -Input.get_action_strength("ui_left")
if Input.is_action_just_pressed("Attack"):
Animated_player.play("Attack")
Sword.disabled = false
Is_attacking = true
if Is_Attacking and grounded:
motion.x = 0
#the rest of your code
move_and_slide(...)
grounded = is_on_floor()
So you check if the player is grounded and attacking then you set the motion to 0. the player should be able to move and attack in the air, but if he touch the ground while attacking, motion is set to 0, and when the animation end, the player can walk or idle. this solve the animation issue and the "gliding".
Now if you want to just cancel the attack animation when landing so the player can walk or idle as he touch the ground, you can add a variable "Is_air_attacking" and do:
physics_process(delta): var x_input = Input.get_action_strength("ui_right") -Input.get_action_strength("ui_left")
if Input.is_action_just_pressed("Attack"):
Animated_player.play("Attack")
Sword.disabled = false
Is_attacking = true
if !grounded:
Is_air_attacking = true
if Is_Attacking and grounded:
if Is_air_attacking:
Is_air_attacking = false
Is_Attacking = false
Sword.disabled = false
else:
motion.x = 0
#the rest of your code
move_and_slide(...)
grounded = is_on_floor()
Upvotes: 0