class_name Character extends Node2D const BASE_SPEED := 50.0 const VERTICAL_DISTANCE := 24 signal speed_changed var speed_modifier := 1.0: set(value): speed_modifier = value speed_changed.emit() enum Type { Rock, Paper, Scissors, } signal type_change_finished signal type_changed @export var current_type: Type = Type.Rock: set(value): current_type = value type_changed.emit() enum Direction { None, Left, Right, } enum State { Idle, Walk, Jump, Fall, Transform, } var current_state: State = State.Idle var vertical_tween: Tween @onready var sprite: AnimatedSprite2D = $AnimatedSprite2D func _ready() -> void: speed_changed.connect(func(): $AnimatedSprite2D.speed_scale = speed_modifier ) type_changed.connect(func(): if current_state == State.Jump: $AnimatedSprite2D.play("%s_jump" % get_type_name()) elif current_state == State.Fall: $AnimatedSprite2D.play("%s_fall" % get_type_name()) ) func get_type_name(type: Type = current_type): match type: Type.Rock: return "rock" Type.Paper: return "paper" Type.Scissors: return "scissors" func idle(): current_state = State.Idle $AnimatedSprite2D.play("%s_idle" % get_type_name()) func walk(direction: Direction): current_state = State.Walk $AnimatedSprite2D.flip_h = direction == Direction.Left $AnimatedSprite2D.play("%s_walk" % get_type_name()) if is_on_wall(direction): return var direction_vector: Vector2 match direction: Direction.Left: direction_vector = Vector2.LEFT Direction.Right: direction_vector = Vector2.RIGHT position.x = lerp( position.x, position.x + (BASE_SPEED * speed_modifier * direction_vector.x), get_process_delta_time() ) func jump(): if is_below_ceiling(): return current_state = State.Jump $AnimatedSprite2D.play("%s_jump" % get_type_name()) vertical_tween = get_tree().create_tween() vertical_tween.tween_property( self, "position", position - Vector2(0, VERTICAL_DISTANCE), min(1.0 / speed_modifier, 1.0) ) await vertical_tween.finished if not is_on_floor(): fall() else: current_state = State.Idle func fall(): current_state = State.Fall $AnimatedSprite2D.play("%s_fall" % get_type_name()) vertical_tween = get_tree().create_tween() vertical_tween.tween_property( self, "position", position + Vector2(0, VERTICAL_DISTANCE), min(1.0 / speed_modifier, 1.0) ) await vertical_tween.finished if not is_on_floor(): fall() else: current_state = State.Idle func is_on_floor() -> bool: $RayDownLeft.force_raycast_update() $RayDownRight.force_raycast_update() return $RayDownLeft.is_colliding() or $RayDownRight.is_colliding() func is_on_ledge() -> bool: return true pass # TODO: add two more down Rays # and up rays for is_below wall and is_below_ledge # to fix falling through wall # funktion im base-game aber auch gar nicht vorhanden:) func is_on_bottom_floor() -> bool: var stage: Stage = get_tree().current_scene var map: TileMapLayer = get_tree().get_first_node_in_group("tilemap") var bottom = position.y + (get_sprite_size().y / 2) + map.tile_set.tile_size.y return bottom >= stage.get_world_boundaries()[Vector2.DOWN] func is_below_ceiling() -> bool: return $RayUpLeft.is_colliding() or $RayUpRight.is_colliding() func is_on_wall(direction: Direction) -> bool: var stage: Stage = get_tree().current_scene match direction: Direction.None: return $RayLeft.is_colliding() or $RayRight.is_colliding() Direction.Left: var left = position.x - (get_sprite_size().x / 2) return $RayLeft.is_colliding() or left <= stage.get_world_boundaries()[Vector2.LEFT] Direction.Right: var right = position.x + (get_sprite_size().x / 2) return $RayRight.is_colliding() or right >= stage.get_world_boundaries()[Vector2.RIGHT] return false func change_type_random(): var types = Type.values() types.erase(current_type) current_type = types.pick_random() func animate_type_change(): var previous_state := current_state current_state = State.Transform var tween_was_running := false if vertical_tween and vertical_tween.is_running(): vertical_tween.pause() tween_was_running = true $AnimatedSprite2D.play("transform") await $AnimatedSprite2D.animation_finished current_state = previous_state type_change_finished.emit() if tween_was_running: vertical_tween.play() func get_sprite_size() -> Vector2: var sprite_frames: SpriteFrames = $AnimatedSprite2D.sprite_frames var texture := sprite_frames.get_frame_texture($AnimatedSprite2D.animation, $AnimatedSprite2D.frame) return texture.get_size() - Vector2(4, 0)