summaryrefslogtreecommitdiff
path: root/character/character.gd
diff options
context:
space:
mode:
Diffstat (limited to 'character/character.gd')
-rw-r--r--character/character.gd223
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)