Look man, I appreciate you trying to help, but I really do not believe the issue has to do with physics. Like I said before, it was only after implementing the timer that Pac-Man stopped moving. And in fact, when I edit the code so that allow_input is always set to true, he’s able to move around just fine with no issues.
Again, I really appreciate you taking the time out to help me, but I don’t think this line of logic is gonna get us anywhere.
I think you have to set one_shot to false. As i understand it: one_shot stops the timer from resetting the time_left to 0 when its done, but you want to reuse the timer, so when you call timer.start() its already done. Thats why you would want to turn it off
How does the timer know when to stop? Like the code presented doesn’t state how many ms/seconds are needed to pass before it stops.
Is there a signal being emitted to the timer (and is it being caught?)?
When the timer stops, how does it know it needs to be restarted?
When the timer elapses, does that timer get culled/turned into a null value and thus you need to create a new timer each time the old one elapsed?
It might be useful to have print messages before the _on_timer_timeout() function is called. To see if it is even reaching this section of the codebase, period.
Final question… since it is V4.3 why is the _on_timer_timeout() function written without a return value? ie
func _on_timer_timeout() → void: #for returning no value.
I assume that’s what the timer.start() thing is for
Does the One Shot setting on the timer not restart it?
Is that default behavior? I certainly didn’t program it to do so.
What do you mean by this? If I put a print command before _on_timer_timeout(), it gives me the error “Unexpected ‘Identifier’ in class body”, which is because it doesn’t have a function behind it. Telling it what to do, but not when to do it. Or something like that.
The tutorial I followed (Brackeys’) didn’t mention anything about that, and it works just fine in the thing I made using that.
As i said one_shot only sets the remaining time either back to 0 (if turned off) or let it stay at the end (if turned on). You want to reuse the timer so you want it turned off
Instead, I would wait for Pacman to cross the snap line, then check if the player recently gave an input in the perpendicular direction.
Something like this:
Decide how long an input should persist
On input store the last input and start a timer(inputTimer = value from 1.)
On update:
inputTimer -= delta
IF vector from last position → current position has crossed the perpendicular direction snap line AND the last input is a perpendicular direction AND the timer has not expired(inputTimer > 0) THEN snap to the new direction line
Store current position to last position
Easier to implement is to just check if a key in the perpendicular direction is being held using Input.is_key_pressed(keycode: Key). In this case, if you are holding the key while crossing the snap line, then change directions.
This probably needs some tweaking. I usually write scripts in C# and I did not test it.
You will need to play with your layout and the grid settings to get them to line up.
extends CharacterBody2D
@onready var animated_sprite = $AnimatedSprite2D
@onready var ray_cast_right = $RayCastRight
@onready var ray_cast_down = $RayCastDown
@onready var ray_cast_left = $RayCastLeft
@onready var ray_cast_up = $RayCastUp
@onready var timer = $Timer
const SPEED = 100
const GRID_OFFSET_X = 0 # offset of the grid in the x axis
const GRID_OFFSET_Y = 0 # offset of the grid in the y axis
const GRID_SIZE = 32 # size of the grid in pixels, this creates the grid the character will move on
const INPUT_PERSISTENCE = 0.1 # how long the input will be considered after the key is pressed in seconds
enum { UpDown, LeftRight }
enum { None, Up, Down, Left, Right }
var direction = UpDown
var last_input = None
var input_timer = 0
var last_position = Vector2.ZERO
func _input(event):
#Track last input
if(event.is_action_pressed("right")):
last_input = Up
input_timer = INPUT_PERSISTENCE
elif(event.is_action_pressed("down")):
last_input = Down
input_timer = INPUT_PERSISTENCE
elif(event.is_action_pressed("left")):
last_input = Left
input_timer = INPUT_PERSISTENCE
elif(event.is_action_pressed("up")):
last_input = Right
input_timer = INPUT_PERSISTENCE
func _physics_process(delta):
# Handle Input and Snapping to Grid
if(input_timer > 0): #If no recent input has happened, do nothing
input_timer -= delta
if direction == UpDown and (last_input == Left or last_input == Right):
var last_grid_x = round((last_position.x - GRID_OFFSET_X) / GRID_SIZE)
var grid_x = round((position.x - GRID_OFFSET_X) / GRID_SIZE)
if last_grid_x != grid_x: # Has the player moved to a new grid cell in x direction?
direction = LeftRight
if last_input == Right:
position.x = grid_x * GRID_SIZE + GRID_OFFSET_X # snap to current grid cell
velocity = Vector2.right * SPEED
elif last_input == Left:
position.x = last_grid_x * GRID_SIZE + GRID_OFFSET_X # snap to last grid cell
velocity = Vector2.left * SPEED
elif direction == LeftRight and (last_input == Down or last_input == Up):
var last_grid_y = round((last_position.y - GRID_OFFSET_Y) / GRID_SIZE)
var grid_y = round((position.y - GRID_OFFSET_Y) / GRID_SIZE)
if last_grid_y != grid_y: # Has the player moved to a new grid cell in y direction?
direction = UpDown
if last_input == Down:
position.y = grid_y * GRID_SIZE + GRID_OFFSET_Y # snap to current grid cell
velocity = Vector2.down * SPEED
elif last_input == Up:
position.y = last_grid_y * GRID_SIZE + GRID_OFFSET_Y # snap to last grid cell
velocity = Vector2.up * SPEED
# Handle Movement
last_position = position # save last position before moving
var collision = move_and_collide(velocity * delta) # move_and_collide stops at first collision
# Stop if there is a collision
if collision:
velocity = Vector2.ZERO # stop moving
# Set Animation based on velocity
if velocity == Vector2.ZERO:
animated_sprite.play("Idle")
elif velocity.x > 0:
animated_sprite.play("Right")
elif velocity.x < 0:
animated_sprite.play("Left")
elif velocity.y > 0:
animated_sprite.play("Down")
elif velocity.y < 0:
animated_sprite.play("Up")