Godot Version
4.5.1
Question
Hi! I’m very new to godot and game dev in general, though I have done a wee bit of coding in R (mostly statistics and linear models).
I was trying to follow this tutorial to make an NPC that can move and talk to the player:
Here is most of the code:
extends CharacterBody2D
signal chatting
@export var speed = 30 # sets start state and gives move speed
var current_state = IDLE
var dir = Vector2.RIGHT
var start_pos
var is_roaming = true # makes the character move to begin with rather than being in chatting state
var is_chatting = false
var player
var player_in_chat_zone = false # to begin with, player is not in the chatting zone
enum {
IDLE,
NEW_DIR, # Adds states for the NPC to be in
MOVE
}
func _ready():
randomize()
start_pos = position # use this to restrict where the NPC goes
func _process(delta): # this says what to do in each state
if current_state == 0: # don't do anything in idle
$AnimatedSprite2D.play("default")
pass
elif current_state == 1: # changes direction and sprite
dir = choose([Vector2.RIGHT, Vector2.UP, Vector2.LEFT, Vector2.DOWN])
if dir.x == -1:
$AnimatedSprite2D.play("left_idle")
if dir.x == 1:
$AnimatedSprite2D.play("right_idle")
if dir.y == -1:
$AnimatedSprite2D.play("up_idle")
if dir.y == 1:
$AnimatedSprite2D.play("default")
elif current_state == 2 and !is_chatting: # move based on direction and if not chatting
if dir.x == -1:
$AnimatedSprite2D.play("left_idle")
move(delta)
if dir.x == 1:
$AnimatedSprite2D.play("right_idle")
move(delta)
if dir.y == -1:
$AnimatedSprite2D.play("up_idle")
move(delta)
if dir.y == 1:
$AnimatedSprite2D.play("default")
move(delta)
if Input.is_action_just_pressed("Chat") and player_in_chat_zone == true:
print("chatting with NPC")
$Dialogue.start()
is_roaming = false
is_chatting = true
$AnimatedSprite2D.play("default")
func choose(array): # shuffles what option is chosen and chooses one from an array
array.shuffle()
return array.front()
func move(delta): #makes it move if not having a chat
if !is_chatting:
position += dir * speed * delta
# for chat detection
func _on_chat_detection_zone_body_entered(body):
if body.has_method("player"):
player = body
player_in_chat_zone = true
func _on_chat_detection_zone_body_exited(body):
if body.has_method("player"):
player_in_chat_zone = false
is_chatting = false
# when the timer runs out, change the state
func _on_timer_timeout():
current_state = choose([IDLE, NEW_DIR, MOVE])
print(current_state)
# stop talking when it's over
func _on_dialogue_dialogue_finished():
is_chatting = false
is_roaming = true
I have three main issues with this code:
- The NPC doesn’t cycle through its states
- The chat detection zone doesn’t detect the presence of the player
- The dialogue doesn’t finish at the end.
All three of these are connected to the signals to and from other nodes, which makes me think that these signals just aren’t being emitted. The states definitely work (I can make it permanently any one of the three states and the part starting func _process(delta):also seems to work). Any help is appreciated!
(I realise there may be another problem with the sprites, but I’ll deal with that later haha)
