platformer-game-test/src/Actors/Player.gd
Sagi Dayan 08cf3e1462 Player movement tweaks and a Goblin
- Player now has an attack move
 - Player wall jump more refined
 - New Enemy superclass for patrol type enemies
 - Goblin enemy.
 - Player abilty toggles. Can turn on/off wall_jump/attack/dash [WIP]
2020-09-26 23:18:34 -04:00

214 lines
5.8 KiB
GDScript

extends KinematicBody2D
class_name Player
export var run_speed := 100.0
export var jump_power := 180.0
export var gravity: = 500.0
export var max_gravity:= 450.0
export var respawn_position:=Vector2.ZERO
export var wall_slide_friction:=.2
export var wall_jump_speed_factor := Vector2(2.5 ,.85)
export var dash_thrust = 500.0
export var max_wall_slide_gravity := 100.0
var LandingDust = load("res://src/Actors/LandingDust.tscn")
var JumpDust = load("res://src/Actors/JumpDust.tscn")
signal landed
signal jumping
signal died
var _velocity: Vector2 = Vector2.ZERO
var _landing_position:Vector2 = Vector2.ZERO
var _in_air = false;
var _is_wall_jumping := false
var _alive := false;
var _is_wall_sliding := false;
var _is_dashing := false;
var _can_dash := true;
var _is_attaking := false;
enum Direction{
RIGHT = 1,
LEFT = -1
}
export var abilities:= {
"dash": false,
"wall_jump": false,
"attack": false
}
func _ready() -> void:
$AnimationPlayer.play("fade_in")
respawn_position = position
func _physics_process(delta: float) -> void:
if _alive:
var is_jump_canceled: = Input.is_action_just_released("jump") and !_is_wall_jumping and _velocity.y < 0.0
var direction: = get_direction()
var prev_wall_slide_state = _is_wall_sliding
_is_wall_sliding = _velocity.y >=0 and is_on_wall() and _in_air
_velocity = calculate_move_velocity(direction,is_jump_canceled, delta)
if _is_wall_sliding and not prev_wall_slide_state:
_velocity.y=0
_velocity = move_and_slide(_velocity, Vector2.UP)
update_sprite(direction)
if is_on_floor() and !_is_dashing: _can_dash = true;
if is_on_floor() and _in_air and !_is_dashing:
var dust = LandingDust.instance()
dust.position = position
get_parent().add_child(dust)
_in_air = false
_is_wall_jumping = false
emit_signal("landed", position)
if _is_wall_sliding:
_is_wall_jumping = false
func get_direction() -> Vector2:
var right_strength = min(Input.get_action_strength("direction_right") , 1)
var left_strength = min(Input.get_action_strength("direction_left"), 1)
return Vector2(
right_strength - left_strength if _in_air or not _is_attaking else 0,
-1.0 if Input.is_action_just_pressed("jump") and (is_on_floor() or _is_wall_sliding) else 1.0
)
func calculate_move_velocity(direction:Vector2, is_jump_canceled:bool, delta:float)->Vector2:
var output: = _velocity
var current_gravity = gravity * wall_slide_friction if _is_wall_sliding else gravity
output.x = lerp(_velocity.x, run_speed * direction.x, .09 if _in_air else .5)
output.y += current_gravity * delta
if direction.y == -1.0: # we are jumping
_in_air = true
if _is_wall_sliding:
# wall jump
var walljump__x_direction = -1 * direction.x
_is_wall_jumping = true
var desired = (run_speed * wall_jump_speed_factor.x * walljump__x_direction)
output.x = desired
output.y = jump_power * wall_jump_speed_factor.y * direction.y
else:
#jump
output.y = jump_power * direction.y
var dust = JumpDust.instance()
dust.position = position;
get_parent().add_child(dust)
emit_signal("jumping", position)
if not _is_dashing:
if is_jump_canceled:
output.y = 0
if output.y < max_gravity * -1:
output.y = max_gravity
if output.y > 0 and !is_on_floor():
_in_air = true;
if _is_dashing:
return _velocity
if _is_wall_sliding and output.y > max_wall_slide_gravity:
output.y = max_wall_slide_gravity
var dash_velocity := Vector2(
$Sprite.scale.x * dash_thrust,
0
)
if Input.is_action_just_pressed("dash") and _can_dash:
_can_dash = false
_is_dashing = true # turn off gravity while dashing
# Wall dash first
if _is_wall_sliding:
dash_velocity.x = $Sprite.scale.x * dash_thrust * -1
if dash_velocity.x < 0 :
$DashParticlesLeft.emitting = true;
else:
$DashParticlesRight.emitting = true
output = dash_velocity
$DashTimeout.start()
return output;
func _respawn():
position = respawn_position
_velocity = Vector2.ZERO
$AnimationPlayer.play("fade_in")
func _revive():
_alive = true
func update_sprite(_direction:Vector2) -> void:
var air_animation = "jump" if _velocity.y <= 0 else "fall"
if _is_attaking: return
var attack = Input.is_action_just_pressed("attack") and abilities.attack
if _velocity.x > .5 and not _is_wall_sliding:
$Sprite.scale = Vector2(1,1)
$AnimationPlayer.play("run" if is_on_floor() else air_animation)
elif _velocity.x < -.5 and not _is_wall_sliding:
$Sprite.scale = Vector2(-1,1)
$AnimationPlayer.play("run" if is_on_floor() else air_animation)
else:
if not _in_air: $AnimationPlayer.play("idle")
if _is_wall_sliding:
$AnimationPlayer.play("wall_slide")
return
if attack:
_is_attaking = true
var attack_animation = "attack_right" if $Sprite.scale.x > 0 else "attack_left"
$AnimationPlayer.play(attack_animation)
$AnimationPlayer.playback_speed = 2.5
$AnimationPlayer.seek(0)
yield($AnimationPlayer, "animation_finished")
$AnimationPlayer.playback_speed = 1
_is_attaking = false
return
if _in_air:
$AnimationPlayer.play(air_animation)
return
if _is_dashing:
$AnimationPlayer.play("jump")
return
func _on_die_animation_done():
emit_signal("died")
_respawn()
func die():
_alive = false
$AnimationPlayer.play("die")
func setAbility(ability:String, enabled:bool=false):
if ability == 'dash':
abilities.dash = enabled
elif ability == 'wall_jump':
abilities.wall_jump = enabled
elif ability == 'attack':
abilities.attack = enabled
else:
pass
func _on_DashTimeout_timeout() -> void:
$DashParticlesLeft.emitting = false
$DashParticlesRight.emitting = false
_velocity.x = run_speed * _velocity.normalized().x;
_is_dashing = false
pass # Replace with function body.
func _on_SordRange_body_entered(body: Node) -> void:
if body.is_in_group("Enemies"):
body.take_damage($Sprite.scale.x)
pass # Replace with function body.