class_name Level extends Node3D signal started_playing signal gravity_change signal ring_collected signal completed const gravity_strength_normal = 7 const gravity_strength_strong = gravity_strength_normal * 3 ## Lowercase, spaceless name of the level var id: String var thumbnail: CompressedTexture2D var music: Music var rings: Array[Ring] = [] var finished_rings_count: int = 0 var velocity: float = 0.0 var has_started_playing: bool = false func _init() -> void: assert(len(id) > 0, self.name + " has no id!") func _ready() -> void: PhysicsServer3D.area_set_param( get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, Vector3(0, 0, 0) ) PhysicsServer3D.area_set_param( get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, 0 ) var children = get_children() for child in children: if is_instance_of(child, Music): music = child assert(is_instance_valid(music), self.name + " has no music!") var rings_node = get_node("Rings") assert(is_instance_valid(rings_node), self.name + " has no Rings node!") var rings_node_children = rings_node.get_children() for ring in rings_node_children: if is_instance_of(ring, Ring): rings.push_back(ring) ring.connect("collect_signal", collect_ring) func collect_ring(): finished_rings_count = len(rings.filter(func(ring: Ring): return ring.collected)) ring_collected.emit() if finished_rings_count >= len(rings): completed.emit() func _input(_event: InputEvent) -> void: if Input.is_action_pressed("gravity_strong") or Input.is_action_just_released("gravity_strong"): PhysicsServer3D.area_set_param( get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, gravity_strength_strong if Input.is_action_pressed("gravity_strong") else gravity_strength_normal ) var up := Input.is_action_just_pressed("gravity_up") var left := Input.is_action_just_pressed("gravity_left") var right := Input.is_action_just_pressed("gravity_right") var down := Input.is_action_just_pressed("gravity_down") if up or left or right or down: if !has_started_playing: has_started_playing = true started_playing.emit() PhysicsServer3D.area_set_param( get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, gravity_strength_strong if Input.is_action_pressed("gravity_strong") else gravity_strength_normal ) var direction: Vector3 if up: direction = Vector3.UP elif left: direction = Vector3.LEFT elif right: direction = Vector3.RIGHT elif down: direction = Vector3.DOWN if direction && direction != PhysicsServer3D.area_get_param( get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR ): PhysicsServer3D.area_set_param( get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, direction ) gravity_change.emit(direction)