Player - acbarker19/Godot-Action-RPG GitHub Wiki
How to Create the Player
- Add a new KinematicBody2D
- Make sure it is a child of World
- Rename to Player
- Add a Sprite as a child
- Create the sprite animation
- Click on the Player node
- Attach a script
- Make sure the script path leads to the Player folder
Player Movement
Inside the Player.gd script, add the following:
const ACCELERATION = 10
const MAX_SPEED = 100
const FRICTION = 10
var velocity = Vector2.ZERO
func _physics_process(delta):
var input_vector = Vector2.ZERO
input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
input_vector = input_vector.normalized()
if input_vector != Vector2.ZERO:
velocity = velocity.move_toward(input_vector * MAX_SPEED, ACCELERATION * delta)
else:
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
velocity = move_and_slide(velocity)
delta
is the time it took the last frame to processinput_vector = input_vector.normalized()
will normalize the velocity so that the player character will always travel at the same speed regardless of how many keys are held at the same time- At the end of the function, you can use
move_and_collide(velocity * delta)
if you want the player to stop when they run into a collidable object, or you can usevelocity = move_and_slide(velocity)
if you want the player to be able to slide around a collidable object - Setting
velocity
equal tomove_and_slide(velocity)
reduces the amount of shaking that the player does when moving into some collidable corners
Player Collisions
- Click on the Player node
- Add a new CollisionShape2D
- Select Shape > New CapsuleShape2D
- Change size of capsule using handles around capsule outline. If desired, turn on pixel snapping
- Move the capsule using the alt key
- Rotate the capsule if desired
Player Movement Animations
Once you have created an AnimationTree containing the idle and run animations and added transitions between them, go inside the Player.gd script and add the following (only the relevant code is shown):
onready var animationTree = $AnimationTree
onready var animationState = animationTree.get("parameters/playback")
func _physics_process(delta):
if input_vector != Vector2.ZERO:
animationTree.set("parameters/Idle/blend_position", input_vector)
animationTree.set("parameters/Run/blend_position", input_vector)
animationState.travel("Run")
else:
animationState.travel("Idle")
Create a State Machine to Control States the Character Can Be In
State machines can be used to control what state an object is in, such as moving, rolling, or attacking in this game. Only one state at a time should be used for the character. To create a state machine, go inside the Player.gd script and add the following (only the relevant code is shown):
enum {
MOVE,
ROLL,
ATTACK
}
var state = MOVE
func _physics_process(delta):
match state:
MOVE:
move_state(delta)
ROLL:
roll_state(delta)
ATTACK:
attack_state(delta)
func move_state(delta):
// code for controlling movement
// since MOVE is the default state, if must determine what the next state is
if Input.is_action_just_pressed("attack"):
state = ATTACK
elif Input.is_action_just_pressed("roll"):
state = ROLL
func attack_state(delta):
// velocity must be set to zero to avoid character moving slightly after the attack animation is finished
velocity = Vector2.ZERO
animationState.travel("Attack")
func roll_state(delta):
// velocity must be set to zero to avoid character moving slightly after the roll animation is finished
velocity = Vector2.ZERO
animationState.travel("Roll")
func attack_animation_finished():
state = MOVE
The state should return to MOVE after the other states have completed their animation. To call animation_finished when the animation is complete, see Call a Function During an Animation. There must also be transitions between animations.
Add the Ability to Roll
- Create animations for rolling and add them to the player's AnimationTree
- Add a custom action for rolling
- Go inside the Player.gd script and add the following to the state machine as shown in the state machine tutorial (only the relevant code is shown):
const ROLL_SPEED = 120
var roll_vector = Vector2.DOWN
func move_state(delta):
// code for controlling movement
if input_vector != Vector2.ZERO:
roll_vector = input_vector
// code for setting animationTree animations and handing inputs - make sure Roll is set up like Attack
func roll_state(delta):
velocity = roll_vector * ROLL_SPEED
animationState.travel("Roll")
move()
func move():
velocity = move_and_slide(velocity)
func roll_animation_finished():
velocity = velocity * 0.8
state = MOVE
How to Create Player Stats That can be Accessed Anywhere
- In the top navigation bar, select Scene > New Inherited Scene...
- Select Stats.tscn to create a scene with a Stats node
- In the right menu, set Max Health to the desired amount
- Save the scene as PlayerStats.tscn
- In the top navigation bar, select Project > Project Settings
- In the popup, click the AutoLoad tab
- Select the path to the PlayerStats file and click Add
- Open the Player script and add the following:
var stats = PlayerStats
func _ready():
stats.connect("no_health", self, "queue_free")
- Add a Hurtbox to the player
- In the right menu, select Collision > Layer > PlayerHurtbox
- In the right menu, select the Node tab
- In the right menu, double click area_entered(area: Area2D) to create a signal function in the Player script
- In the Player script, add the following:
func _on_Hurtbox_area_entered(area):
stats.health -= 1