diff options
Diffstat (limited to 'character/character.gd')
-rw-r--r-- | character/character.gd | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/character/character.gd b/character/character.gd new file mode 100644 index 0000000..ef18bbc --- /dev/null +++ b/character/character.gd @@ -0,0 +1,223 @@ +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) |