Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | KV |
Hi, I’m currently having trouble implementing a mechanic into my first game, which is a Sokoban clone. I want it so that the player can pull boxes when they hold down the z key in addition to pushing boxes naturally.
I’ve implemented a basic version of the mechanic, however its very buggy, like you are unable to pull boxes if they are in contact with a wall, and the player can also get themselves stuck inside walls when trying to pull.
What I basically want to happen is for the player to pull the box when they press any key that isn’t in the box’s direction. However, if they do press it in the box’s direction, they’ll just push it like if they weren’t holding down the z key to pull. How can I go about implementing this mechanic?
Here’s my player code:
extends KinematicBody2D
onready var ray = $RayCast2D
onready var runTimer = $RunTimer
var grid_size = 8
var runDelay: float = 0.5
var inputs = {
'ui_up' : Vector2(0,-1),
'ui_down' : Vector2(0,1),
'ui_left' : Vector2(-1,0),
'ui_right' : Vector2(1,0)
}
func _unhandled_input(event):
for dir in inputs.keys():
if event.is_action(dir) and runTimer.is_stopped():
runTimer.stop()
if $Tween.is_active() == false:
move(dir)
if event.is_action_pressed(dir):
runTimer.start(runDelay)
if $Tween.is_active() == false:
move(dir)
if event.is_action_pressed("reset"):
get_tree().reload_current_scene()
func move(dir):
var game = get_parent()
var vector_pos = inputs[dir] * grid_size
ray.cast_to = vector_pos
if Input.is_key_pressed(KEY_Z):
ray.cast_to = -vector_pos
ray.force_raycast_update()
$Tween.interpolate_property(self, "position", position, position + vector_pos, 0.1, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
if !ray.is_colliding():
$Tween.start()
game.moves += 1
else:
var collider = ray.get_collider()
if collider.is_in_group('box'):
if collider.move(dir):
$Tween.start()
game.moves += 1
func _on_Tween_tween_all_completed():
get_parent().check_end()
And my box code since the two objects work in tandem to work right (I based my game off of a YouTube tutorial if you couldn’t tell already):
extends KinematicBody2D
onready var ray = $RayCast2D
var grid_size = 8
var inputs = {
'ui_up' : Vector2.UP,
'ui_down' : Vector2.DOWN,
'ui_left' : Vector2.LEFT,
'ui_right' : Vector2.RIGHT
}
func move(dir):
var vector_pos = inputs[dir] * grid_size
ray.cast_to = vector_pos
if Input.is_key_pressed(KEY_Z):
ray.cast_to = -vector_pos
ray.force_raycast_update()
$Tween.interpolate_property(
self, "position",
position, position + vector_pos, 0.1,
Tween.TRANS_SINE,
Tween.EASE_IN_OUT
)
if !ray.is_colliding():
$Tween.start()
return true
return false
If your game is grid-based, you don’t need raycasts at all.You should make two arrays: one is map of player, walls and boxes, and second array is map of target positions. Then you just check that player can move to desired location. If this location has box, you check that player can move this box (free space in moving direction). After that you check box positions with target positions. And you add animations between player moves.
And pulling is simpler - you check that there is box nearby and player can move in desired location. Then you update map accordingly to movement direction.
AlexTheRegent | 2021-01-07 23:42