sokoban
Diffstat (limited to 'Player.gd')
| -rw-r--r-- | Player.gd | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/Player.gd b/Player.gd new file mode 100644 index 0000000..6514c08 --- /dev/null +++ b/Player.gd @@ -0,0 +1,159 @@ +extends CollisionObject2D + +signal level_reset_requested + +const GRID_SIZE = 16 + +var moves = 0 setget set_moves + +var last_move = null +var last_move_crate = null +var world: Node2D +var count = 0 +var started = false +var won := false + +signal won + +onready var cam = $Camera2D +onready var tween = $Tween +onready var ray = $RayCast2D +onready var dir = $Direction +onready var anitree: AnimationTree = $AnimationTree +onready var anistate = anitree.get("parameters/playback") + + +func _ready(): + anitree.active = true + + +func initialize(): + won = false + set_physics_process(false) + yield(get_tree().create_timer(2), "timeout") + set_physics_process(true) + + +func _physics_process(_delta): + if Input.is_action_just_pressed("level_reload"): + emit_signal("level_reset_requested") + anistate.travel("Idle") + set_moves(0) + last_move = null + last_move_crate = null + return + + if not world: + return + + if Utils.stop_input: + return + + if get_parent().get_parent().just_started: + return + + if world.over: + anistate.travel("Idle") + return + + if tween.is_active(): + return + + var move_intent = Vector2.ZERO + + move_intent = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + + if Input.is_action_just_pressed("undo_last_move"): + if last_move != null: + self.position -= last_move * GRID_SIZE + if last_move_crate != null: + last_move_crate.position -= last_move * GRID_SIZE + set_moves(moves - 1) + last_move = null + last_move_crate = null + return + + if move_intent.x != 0 && move_intent.y != 0: + move_intent = Vector2.ZERO + + if move_intent != Vector2.ZERO: + if not started: + get_parent().get_parent().start_stopwatch() + started = true + var offset = move_intent * GRID_SIZE + + apply_rotation(offset) + + if ray.is_colliding(): + var collider = ray.get_collider() + if collider.is_in_group("crates"): + if !collider.push(offset): + anistate.travel("Idle") + return + + last_move_crate = collider + + else: + anistate.travel("Idle") + return + + else: + last_move_crate = null + + set_moves(moves + 1) + last_move = move_intent + + tween.interpolate_property( + self, + "position", + self.position, + self.position + offset, + 0.35, + Tween.TRANS_LINEAR, + Tween.EASE_IN_OUT + ) + tween.start() + + SoundFx.play("walk", -10, rand_range(.9, 1.1)) + anistate.travel("Run") + anitree.set("parameters/Run/blend_position", move_intent) + else: + anistate.travel("Idle") + + +func set_moves(new_moves: int): + moves = new_moves + $"../../CanvasLayer/HUD/MovesLabel".text = "Moves: " + str(moves) + + +func apply_rotation(offset: Vector2): + ray.cast_to = offset + + var new_rot := offset.angle() + + ray.force_raycast_update() + + var future_rot := lerp_angle(dir.rotation, new_rot, 1) + + if future_rot != dir.rotation: + tween.interpolate_property( + dir, "rotation", dir.rotation, future_rot, 0.3, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT + ) + tween.start() + + +func _over(): + if won: + return + emit_signal("won") + won = true + + +func _on_Player_body_exited(_body): + pass + # if not body.name == "Player" and not body.is_in_group("crates"): + # print("emitting won") + # if won: + # return + # emit_signal("won") + # won = true |