Godot Lesson 3: Entity Class¶
Summary¶
This lesson moves a lot of the player movement loops into a separate entity class to be used my enemies and NPCs as well.
Prerequisites¶
A moving player with animations (Lessons 1 and 2)
Video¶
Code¶
Repository: https://github.com/los-alamos-steam-lab/godot-tutorial/tree/3-entity-class
Directions Code¶
Major Changes from the Video:
Relies on built in Vector2 enums instead of declaring dir.UP and so forth
class_name at the top makes this callable from other functions
class_name directions
extends Node
# We didn't add the constants here because they are built into
# Vector2 after 3.1
# return a random direction
func rand():
var d = randi() % 4
match d:
0:
return Vector2.LEFT
1:
return Vector2.RIGHT
2:
return Vector2.UP
3:
return Vector2.DOWN
Entity Code¶
Major Changes from the Video:
dir isn’t an autoload, since we didn’t include the vector directions in it
class_name at the top makes this callable by other functions
const is switched to var since 3.1 does not allow for child scripts to update const values
We added a _ready function because we need it in the child scripts
class_name entity
extends KinematicBody2D
# we put this here instead of autoloading it
# nothing wrong with autoload, but I prefer things in the code
var dir = directions.new()
# MOVEMENT
var movedir = Vector2.ZERO
var spritedir = "down"
var SPEED = 0
# Putting this here so that we can setup future calls from the
# child scripts and not have them fail
func _ready():
pass
func movement_loop():
# .normalized makes it so that diagonal movement is
# the same length as 4-driectional movement
var motion = movedir.normalized() * SPEED
# move_and_slide takes care of collisions and has you slide
# along walls that are blocking your path
move_and_slide(motion, Vector2.ZERO)
func spritedir_loop():
match movedir:
Vector2.LEFT:
spritedir = "left"
Vector2.RIGHT:
spritedir = "right"
Vector2.UP:
spritedir = "up"
Vector2.DOWN:
spritedir = "down"
# This changes our player animation. "animation" is a string
# of the sort "idle", "push", or "walk"
func anim_switch(animation):
var newanim = str(animation, spritedir)
if $anim.current_animation != newanim:
$anim.play(newanim)
Player Code¶
Major Changes from the Video:
Makes use of entity class by just extending entity instead of a file path
The _ready func is used to set SPEED and other “constants”
Still prioritizing idle
Using built in Vector2 enums
extends entity
# ready function lets us set "constants" when the file loads
func _ready():
SPEED = 70
# _physics_process is called by the game engine
func _physics_process(delta):
controls_loop()
movement_loop()
spritedir_loop()
# We're setting our animation here. I've replaced Vector2(0,-1)
# with Vector2.UP for readability, and so forth. These are new to godot 3.1
# I've also changed the order of the if statement to prioritize being
# idle if movedir is zero and created a single (very long) if statement
# for testing the push animation.
if movedir == Vector2.ZERO:
anim_switch("idle")
elif is_on_wall():
if (spritedir == "left" and test_move(transform, Vector2.LEFT))\
or (spritedir == "right" and test_move(transform, Vector2.RIGHT))\
or (spritedir == "up" and test_move(transform, Vector2.UP))\
or (spritedir == "down" and test_move(transform, Vector2.DOWN)):
anim_switch("push")
else:
anim_switch("walk")
# controls_loop looks for player input
func controls_loop():
var LEFT = Input.is_action_pressed("ui_left")
var RIGHT = Input.is_action_pressed("ui_right")
var UP = Input.is_action_pressed("ui_up")
var DOWN = Input.is_action_pressed("ui_down")
# By adding our values together, we make it so that one key
# stroke does not take precidence over another, i.e. pushing
# left and right keys at the same time
movedir.x = -int(LEFT) + int(RIGHT)
movedir.y = -int(UP) + int(DOWN)
Stalfos Code¶
Major Changes from the Video:
Makes use of entity class by just extending entity instead of a file path
The _ready func is used to set SPEED and other “constants”
extends entity
var movetimer_length = 15
var movetimer = 0
# ready function lets us set "constants" and perform
# other actions when the file loads
func _ready():
SPEED = 40
$anim.play("default")
movedir = dir.rand()
func _physics_process(delta):
movement_loop()
# count down the movetimer every tick
if movetimer > 0:
movetimer -= 1
# if the movetime reaches zero or the stalfos is on a wall
# change direction and reset the timer
if movetimer == 0 || is_on_wall():
movedir = dir.rand()
movetimer = movetimer_length