Use static typing in all demos (#1063)

This leads to code that is easier to understand and runs
faster thanks to GDScript's typed instructions.

The untyped declaration warning is now enabled on all projects
where type hints were added. All projects currently run without
any untyped declration warnings.

Dodge the Creeps and Squash the Creeps demos intentionally don't
use type hints to match the documentation, where type hints haven't
been adopted yet (given its beginner focus).
This commit is contained in:
Hugo Locurcio
2024-06-01 12:12:18 +02:00
committed by GitHub
parent 8e9c180278
commit bac1e69164
498 changed files with 5218 additions and 4776 deletions

View File

@@ -8,28 +8,28 @@ const BULLET_COUNT = 500
const SPEED_MIN = 20
const SPEED_MAX = 80
const bullet_image = preload("res://bullet.png")
const bullet_image := preload("res://bullet.png")
var bullets := []
var shape
var shape := RID()
class Bullet:
var position = Vector2()
var speed = 1.0
var position := Vector2()
var speed := 1.0
# The body is stored as a RID, which is an "opaque" way to access resources.
# With large amounts of objects (thousands or more), it can be significantly
# faster to use RIDs compared to a high-level approach.
var body = RID()
var body := RID()
func _ready():
func _ready() -> void:
shape = PhysicsServer2D.circle_shape_create()
# Set the collision shape's radius for each bullet in pixels.
PhysicsServer2D.shape_set_data(shape, 8)
for _i in BULLET_COUNT:
var bullet = Bullet.new()
var bullet := Bullet.new()
# Give each bullet its own random speed.
bullet.speed = randf_range(SPEED_MIN, SPEED_MAX)
bullet.body = PhysicsServer2D.body_create()
@@ -45,22 +45,22 @@ func _ready():
randf_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x,
randf_range(0, get_viewport_rect().size.y)
)
var transform2d = Transform2D()
var transform2d := Transform2D()
transform2d.origin = bullet.position
PhysicsServer2D.body_set_state(bullet.body, PhysicsServer2D.BODY_STATE_TRANSFORM, transform2d)
bullets.push_back(bullet)
func _process(_delta):
func _process(_delta: float) -> void:
# Order the CanvasItem to update every frame.
queue_redraw()
func _physics_process(delta):
var transform2d = Transform2D()
var offset = get_viewport_rect().size.x + 16
for bullet in bullets:
func _physics_process(delta: float) -> void:
var transform2d := Transform2D()
var offset := get_viewport_rect().size.x + 16
for bullet: Bullet in bullets:
bullet.position.x -= bullet.speed * delta
if bullet.position.x < -16:
@@ -73,15 +73,15 @@ func _physics_process(delta):
# Instead of drawing each bullet individually in a script attached to each bullet,
# we are drawing *all* the bullets at once here.
func _draw():
var offset = -bullet_image.get_size() * 0.5
for bullet in bullets:
func _draw() -> void:
var offset := -bullet_image.get_size() * 0.5
for bullet: Bullet in bullets:
draw_texture(bullet_image, bullet.position + offset)
# Perform cleanup operations (required to exit without error messages in the console).
func _exit_tree():
for bullet in bullets:
func _exit_tree() -> void:
for bullet: Bullet in bullets:
PhysicsServer2D.free_rid(bullet.body)
PhysicsServer2D.free_rid(shape)

View File

@@ -4,32 +4,32 @@ extends Node2D
# efficient than using instancing and nodes, but requires more programming and
# is less visual. Bullets are managed together in the `bullets.gd` script.
# The number of bullets currently touched by the player.
var touching = 0
## The number of bullets currently touched by the player.
var touching := 0
@onready var sprite = $AnimatedSprite2D
@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
func _ready():
func _ready() -> void:
# The player follows the mouse cursor automatically, so there's no point
# in displaying the mouse cursor.
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
func _input(event):
func _input(event: InputEvent) -> void:
# Getting the movement of the mouse so the sprite can follow its position.
if event is InputEventMouseMotion:
position = event.position - Vector2(0, 16)
func _on_body_shape_entered(_body_id, _body, _body_shape, _local_shape):
func _on_body_shape_entered(_body_id: RID, _body: Node2D, _body_shape_index: int, _local_shape_index: int) -> void:
# Player got touched by a bullet so sprite changes to sad face.
touching += 1
if touching >= 1:
sprite.frame = 1
func _on_body_shape_exited(_body_id, _body, _body_shape, _local_shape):
func _on_body_shape_exited(_body_id: RID, _body: Node2D, _body_shape_index: int, _local_shape_index: int) -> void:
touching -= 1
# When non of the bullets are touching the player,
# sprite changes to happy face.

View File

@@ -17,6 +17,10 @@ run/main_scene="res://shower.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -1,13 +1,13 @@
extends TileMap
var secret_layer: int # You can have multiple layers if you make this an array.
var player_in_secret: bool
# You can have multiple layers if you make this an array.
var secret_layer := 0
var player_in_secret := false
var layer_alpha := 1.0
func _init() -> void:
for i in get_layers_count(): # Find the secret layer by name.
for i in get_layers_count():
# Find the secret layer by name.
if get_layer_name(i) == "Secret":
secret_layer = i
@@ -19,7 +19,8 @@ func _ready() -> void:
func _process(delta: float) -> void:
if player_in_secret:
if layer_alpha > 0.3:
layer_alpha = move_toward(layer_alpha, 0.3, delta) # Animate the layer transparency.
# Animate the layer transparency.
layer_alpha = move_toward(layer_alpha, 0.3, delta)
set_layer_modulate(secret_layer, Color(1, 1, 1, layer_alpha))
else:
set_process(false)
@@ -32,17 +33,17 @@ func _process(delta: float) -> void:
func _use_tile_data_runtime_update(layer: int, _coords: Vector2i) -> bool:
if layer == secret_layer:
return true
return false
return layer == secret_layer
func _tile_data_runtime_update(_layer: int, _coords: Vector2i, tile_data: TileData) -> void:
tile_data.set_collision_polygons_count(0, 0) # Remove collision for secret layer.
# Remove collision for secret layer.
tile_data.set_collision_polygons_count(0, 0)
func _on_secret_detector_body_entered(body: Node2D) -> void:
if not body is CharacterBody2D: # Detect player only.
if not body is CharacterBody2D:
# Detect the player only.
return
player_in_secret = true

View File

@@ -5,11 +5,11 @@ const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300
const JUMP_SPEED = 200
@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
@onready var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta):
func _physics_process(delta: float) -> void:
# Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
var walk := WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
# Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned.

View File

@@ -14,10 +14,14 @@ config/name="Dynamic TileMap Layers"
config/description="Example of how to make a kinematic character controller in 2D using
CharacterBody2D. The character moves around, is affected by moving
platforms, can jump through one-way collision platforms, etc."
config/tags=PackedStringArray("2d", "demo", "official", "tilemap")
run/main_scene="res://world.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.png"
config/tags=PackedStringArray("2d", "demo", "official", "tilemap")
[debug]
gdscript/warnings/untyped_declaration=1
[display]

View File

@@ -1,14 +1,16 @@
extends Panel
@onready var fsm_node = get_node(^"../../Player/StateMachine")
@onready var fsm_node: Node = get_node(^"../../Player/StateMachine")
func _process(_delta):
var states_names = ""
var numbers = ""
var index = 0
for state in fsm_node.states_stack:
states_names += String(state.get_name()) + "\n"
func _process(_delta: float) -> void:
var states_names := ""
var numbers := ""
var index := 0
for state: Node in fsm_node.states_stack:
states_names += String(state.name) + "\n"
numbers += str(index) + "\n"
index += 1
%States.text = states_names
%Numbers.text = numbers

View File

@@ -1,23 +1,23 @@
extends CharacterBody2D
var direction = Vector2()
@export var speed: float = 1000.0
var direction := Vector2()
@export var speed := 1000.0
@onready var root = get_tree().root
@onready var root := get_tree().root
func _ready():
func _ready() -> void:
set_as_top_level(true)
func _physics_process(delta):
func _physics_process(delta: float) -> void:
if not root.get_visible_rect().has_point(position):
queue_free()
var motion = direction * speed * delta
var collision_info = move_and_collide(motion)
var motion := direction * speed * delta
var collision_info := move_and_collide(motion)
if collision_info:
queue_free()
func _draw():
func _draw() -> void:
draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color.WHITE)

View File

@@ -1,18 +1,18 @@
extends Node2D
var bullet = preload("Bullet.tscn")
var bullet := preload("Bullet.tscn")
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("fire"):
fire()
func fire():
func fire() -> void:
if not $CooldownTimer.is_stopped():
return
$CooldownTimer.start()
var new_bullet = bullet.instantiate()
var new_bullet := bullet.instantiate()
add_child(new_bullet)
new_bullet.position = global_position
new_bullet.direction = owner.look_direction

View File

@@ -3,25 +3,26 @@ extends CharacterBody2D
# It can move, collide with the world, etc...
# The player has a state machine, but the body and the state machine are separate.
signal direction_changed(new_direction)
signal direction_changed(new_direction: Vector2)
var look_direction = Vector2.RIGHT:
var look_direction := Vector2.RIGHT:
set(value):
look_direction = value
set_look_direction(value)
func take_damage(attacker, amount, effect = null):
func take_damage(attacker: Node, amount: float, effect: Node = null) -> void:
if is_ancestor_of(attacker):
return
$States/Stagger.knockback_direction = (attacker.global_position - global_position).normalized()
$Health.take_damage(amount, effect)
func set_dead(value):
func set_dead(value: bool) -> void:
set_process_input(not value)
set_physics_process(not value)
$CollisionPolygon2D.disabled = value
func set_look_direction(value):
func set_look_direction(value: Vector2) -> void:
direction_changed.emit(value)

View File

@@ -1,12 +1,12 @@
extends "res://state_machine/state_machine.gd"
@onready var idle = $Idle
@onready var move = $Move
@onready var jump = $Jump
@onready var stagger = $Stagger
@onready var attack = $Attack
@onready var idle: Node = $Idle
@onready var move: Node = $Move
@onready var jump: Node = $Jump
@onready var stagger: Node = $Stagger
@onready var attack: Node = $Attack
func _ready():
func _ready() -> void:
states_map = {
"idle": idle,
"move": move,
@@ -16,7 +16,7 @@ func _ready():
}
func _change_state(state_name):
func _change_state(state_name: String) -> void:
# The base state_machine interface this node extends does most of the work.
if not _active:
return
@@ -24,10 +24,11 @@ func _change_state(state_name):
states_stack.push_front(states_map[state_name])
if state_name == "jump" and current_state == move:
jump.initialize(move.speed, move.velocity)
super._change_state(state_name)
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
# Here we only handle input that can interrupt states, attacking in this case,
# otherwise we let the state node handle it.
if event.is_action_pressed("attack"):
@@ -35,4 +36,5 @@ func _unhandled_input(event):
return
_change_state("attack")
return
current_state.handle_input(event)

View File

@@ -1,8 +1,8 @@
extends "res://state_machine/state.gd"
func enter():
func enter() -> void:
owner.get_node(^"AnimationPlayer").play("idle")
func _on_Sword_attack_finished():
func _on_Sword_attack_finished() -> void:
finished.emit("previous")

View File

@@ -3,10 +3,10 @@ extends "res://state_machine/state.gd"
# The animation only affects the Body Sprite2D's modulate property so it
# could stack with other animations if we had two AnimationPlayer nodes.
func enter():
func enter() -> void:
owner.get_node(^"AnimationPlayer").play("stagger")
func _on_animation_finished(anim_name):
func _on_animation_finished(anim_name: String) -> void:
assert(anim_name == "stagger")
finished.emit("previous")

View File

@@ -1,14 +1,14 @@
extends Label
var start_position = Vector2()
var start_position := Vector2()
func _ready():
func _ready() -> void:
start_position = position
func _physics_process(_delta):
func _physics_process(_delta: float) -> void:
position = $"../BodyPivot".position + start_position
func _on_StateMachine_state_changed(current_state):
text = String(current_state.get_name())
func _on_StateMachine_state_changed(current_state: Node) -> void:
text = String(current_state.name)

View File

@@ -1,10 +1,10 @@
extends "res://state_machine/state.gd"
# Initialize the state. E.g. change the animation.
func enter():
func enter() -> void:
owner.set_dead(true)
owner.get_node(^"AnimationPlayer").play("die")
func _on_animation_finished(_anim_name):
func _on_animation_finished(_anim_name: String) -> void:
finished.emit("dead")

View File

@@ -1,23 +1,23 @@
extends "../motion.gd"
@export var base_max_horizontal_speed: float = 400.0
@export var base_max_horizontal_speed := 400.0
@export var air_acceleration: float = 1000.0
@export var air_deceleration: float = 2000.0
@export var air_steering_power: float = 50.0
@export var air_acceleration := 1000.0
@export var air_deceleration := 2000.0
@export var air_steering_power := 50.0
@export var gravity: float = 1600.0
@export var gravity := 1600.0
var enter_velocity = Vector2()
var enter_velocity := Vector2()
var max_horizontal_speed = 0.0
var horizontal_speed = 0.0
var horizontal_velocity = Vector2()
var max_horizontal_speed := 0.0
var horizontal_speed := 0.0
var horizontal_velocity := Vector2()
var vertical_speed = 0.0
var height = 0.0
var vertical_speed := 0.0
var height := 0.0
func initialize(speed, velocity):
func initialize(speed: float, velocity: Vector2) -> void:
horizontal_speed = speed
if speed > 0.0:
max_horizontal_speed = speed
@@ -26,8 +26,8 @@ func initialize(speed, velocity):
enter_velocity = velocity
func enter():
var input_direction = get_input_direction()
func enter() -> void:
var input_direction := get_input_direction()
update_look_direction(input_direction)
if input_direction:
@@ -39,8 +39,8 @@ func enter():
owner.get_node(^"AnimationPlayer").play("idle")
func update(delta):
var input_direction = get_input_direction()
func update(delta: float) -> void:
var input_direction := get_input_direction()
update_look_direction(input_direction)
move_horizontally(delta, input_direction)
@@ -49,22 +49,22 @@ func update(delta):
finished.emit("previous")
func move_horizontally(delta, direction):
func move_horizontally(delta: float, direction: Vector2) -> void:
if direction:
horizontal_speed += air_acceleration * delta
else:
horizontal_speed -= air_deceleration * delta
horizontal_speed = clamp(horizontal_speed, 0, max_horizontal_speed)
var target_velocity = horizontal_speed * direction.normalized()
var steering_velocity = (target_velocity - horizontal_velocity).normalized() * air_steering_power
var target_velocity := horizontal_speed * direction.normalized()
var steering_velocity := (target_velocity - horizontal_velocity).normalized() * air_steering_power
horizontal_velocity += steering_velocity
owner.velocity = horizontal_velocity
owner.move_and_slide()
func animate_jump_height(delta):
func animate_jump_height(delta: float) -> void:
vertical_speed -= gravity * delta
height += vertical_speed * delta
height = max(0.0, height)

View File

@@ -1,19 +1,18 @@
extends "res://state_machine/state.gd"
# Collection of important methods to handle direction and animation.
func handle_input(event):
func handle_input(event: InputEvent) -> void:
if event.is_action_pressed("simulate_damage"):
finished.emit("stagger")
func get_input_direction():
var input_direction = Vector2(
func get_input_direction() -> Vector2:
return Vector2(
Input.get_axis(&"move_left", &"move_right"),
Input.get_axis(&"move_up", &"move_down")
)
return input_direction
func update_look_direction(direction):
func update_look_direction(direction: Vector2) -> void:
if direction and owner.look_direction != direction:
owner.look_direction = direction

View File

@@ -1,14 +1,14 @@
extends "on_ground.gd"
func enter():
func enter() -> void:
owner.get_node(^"AnimationPlayer").play("idle")
func handle_input(event):
func handle_input(event: InputEvent) -> void:
return super.handle_input(event)
func update(_delta):
var input_direction = get_input_direction()
func update(_delta: float) -> void:
var input_direction: Vector2 = get_input_direction()
if input_direction:
finished.emit("move")

View File

@@ -1,23 +1,23 @@
extends "on_ground.gd"
@export var max_walk_speed: float = 450
@export var max_run_speed: float = 700
@export var max_walk_speed := 450.0
@export var max_run_speed := 700.0
func enter():
func enter() -> void:
speed = 0.0
velocity = Vector2()
var input_direction = get_input_direction()
var input_direction := get_input_direction()
update_look_direction(input_direction)
owner.get_node(^"AnimationPlayer").play("walk")
func handle_input(event):
func handle_input(event: InputEvent) -> void:
return super.handle_input(event)
func update(_delta):
var input_direction = get_input_direction()
func update(_delta: float) -> void:
var input_direction := get_input_direction()
if input_direction.is_zero_approx():
finished.emit("idle")
update_look_direction(input_direction)
@@ -27,16 +27,17 @@ func update(_delta):
else:
speed = max_walk_speed
var collision_info = move(speed, input_direction)
var collision_info := move(speed, input_direction)
if not collision_info:
return
if speed == max_run_speed and collision_info.collider.is_in_group("environment"):
return null
return
func move(speed, direction):
owner.velocity = direction.normalized() * speed
func move(p_speed: float, direction: Vector2) -> KinematicCollision2D:
owner.velocity = direction.normalized() * p_speed
owner.move_and_slide()
if owner.get_slide_collision_count() == 0:
return
return null
return owner.get_slide_collision(0)

View File

@@ -1,10 +1,10 @@
extends "../motion.gd"
# warning-ignore-all:unused_class_variable
var speed = 0.0
var velocity = Vector2()
var speed := 0.0
var velocity := Vector2()
func handle_input(event):
func handle_input(event: InputEvent) -> void:
if event.is_action_pressed("jump"):
finished.emit("jump")
return super.handle_input(event)

View File

@@ -2,41 +2,50 @@ extends Area2D
signal attack_finished
enum States { IDLE, ATTACK }
var state = null
enum States {
IDLE,
ATTACK,
}
enum AttackInputStates { IDLE, LISTENING, REGISTERED }
var attack_input_state = AttackInputStates.IDLE
var ready_for_next_attack = false
enum AttackInputStates {
IDLE,
LISTENING,
REGISTERED,
}
var state: States = States.IDLE
var attack_input_state := AttackInputStates.IDLE
var ready_for_next_attack := false
const MAX_COMBO_COUNT = 3
var combo_count = 0
var combo_count := 0
var attack_current = {}
var combo = [{
var attack_current := {}
var combo := [{
"damage": 1,
"animation": "attack_fast",
"effect": null
"effect": null,
},
{
"damage": 1,
"animation": "attack_fast",
"effect": null
"effect": null,
},
{
"damage": 3,
"animation": "attack_medium",
"effect": null
}]
"effect": null,
}
]
var hit_objects = []
var hit_objects := []
func _ready():
func _ready() -> void:
$AnimationPlayer.animation_finished.connect(_on_animation_finished)
body_entered.connect(_on_body_entered)
_change_state(States.IDLE)
func _change_state(new_state):
func _change_state(new_state: States) -> void:
match state:
States.ATTACK:
hit_objects = []
@@ -57,7 +66,7 @@ func _change_state(new_state):
state = new_state
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
if not state == States.ATTACK:
return
if attack_input_state != AttackInputStates.LISTENING:
@@ -66,36 +75,37 @@ func _unhandled_input(event):
attack_input_state = AttackInputStates.REGISTERED
func _physics_process(_delta):
func _physics_process(_delta: float) -> void:
if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack:
attack()
func attack():
func attack() -> void:
combo_count += 1
_change_state(States.ATTACK)
# Use with AnimationPlayer func track.
func set_attack_input_listening():
func set_attack_input_listening() -> void:
attack_input_state = AttackInputStates.LISTENING
# Use with AnimationPlayer func track.
func set_ready_for_next_attack():
func set_ready_for_next_attack() -> void:
ready_for_next_attack = true
func _on_body_entered(body):
func _on_body_entered(body: Node2D) -> void:
if not body.has_node("Health"):
return
if body.get_rid().get_id() in hit_objects:
return
hit_objects.append(body.get_rid().get_id())
body.take_damage(self, attack_current["damage"], attack_current["effect"])
func _on_animation_finished(_name):
func _on_animation_finished(_name: String) -> void:
if attack_current.is_empty():
return
@@ -106,6 +116,6 @@ func _on_animation_finished(_name):
attack_finished.emit()
func _on_StateMachine_state_changed(current_state):
func _on_StateMachine_state_changed(current_state: Node) -> void:
if current_state.name == "Attack":
attack()

View File

@@ -1,13 +1,13 @@
extends Marker2D
var z_index_start = 0
var z_index_start := 0
func _ready():
func _ready() -> void:
owner.direction_changed.connect(_on_Parent_direction_changed)
z_index_start = z_index
func _on_Parent_direction_changed(direction):
func _on_Parent_direction_changed(direction: Vector2) -> void:
rotation = direction.angle()
match direction:
Vector2.UP:

View File

@@ -19,6 +19,10 @@ run/main_scene="res://Demo.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/size/viewport_width=1280

View File

@@ -4,25 +4,25 @@ extends Node
# and makes sure every State object had all of these methods.
# warning-ignore:unused_signal
signal finished(next_state_name)
signal finished(next_state_name: String)
# Initialize the state. E.g. change the animation.
func enter():
func enter() -> void:
pass
# Clean up the state. Reinitialize values like a timer.
func exit():
func exit() -> void:
pass
func handle_input(_event):
func handle_input(_event: InputEvent) -> void:
pass
func update(_delta):
func update(_delta: float) -> void:
pass
func _on_animation_finished(_anim_name):
func _on_animation_finished(_anim_name: String) -> void:
pass

View File

@@ -5,39 +5,39 @@ extends Node
# and changing the current/active state.
# See the PlayerV2 scene for an example on how to use it.
signal state_changed(current_state)
signal state_changed(current_state: Node)
# You should set a starting node from the inspector or on the node that inherits
# from this state machine interface. If you don't, the game will default to
# the first state in the state machine's children.
@export var start_state: NodePath
var states_map = {}
var states_map := {}
var states_stack = []
var current_state = null
var _active = false:
var states_stack := []
var current_state: Node = null
var _active := false:
set(value):
_active = value
set_active(value)
func _enter_tree():
func _enter_tree() -> void:
if start_state.is_empty():
start_state = get_child(0).get_path()
for child in get_children():
var err = child.finished.connect(_change_state)
var err: bool = child.finished.connect(_change_state)
if err:
printerr(err)
initialize(start_state)
func initialize(initial_state):
func initialize(initial_state: NodePath) -> void:
_active = true
states_stack.push_front(get_node(initial_state))
current_state = states_stack[0]
current_state.enter()
func set_active(value):
func set_active(value: bool) -> void:
set_physics_process(value)
set_process_input(value)
if not _active:
@@ -45,21 +45,22 @@ func set_active(value):
current_state = null
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
current_state.handle_input(event)
func _physics_process(delta):
func _physics_process(delta: float) -> void:
current_state.update(delta)
func _on_animation_finished(anim_name):
func _on_animation_finished(anim_name: String) -> void:
if not _active:
return
current_state._on_animation_finished(anim_name)
func _change_state(state_name):
func _change_state(state_name: String) -> void:
if not _active:
return
current_state.exit()

View File

@@ -2,11 +2,11 @@ extends Node2D
const CAVE_LIMIT = 1000
var glow_map = preload("res://glow_map.webp")
var glow_map := preload("res://glow_map.webp")
@onready var cave = $Cave
@onready var cave: Node2D = $Cave
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseMotion and event.button_mask > 0:
cave.position.x = clampf(cave.position.x + event.relative.x, -CAVE_LIMIT, 0)

View File

@@ -37,7 +37,6 @@ environment = SubResource("1")
[node name="Camera2D" type="Camera2D" parent="."]
offset = Vector2(540, 360)
current = true
[node name="Label" type="Label" parent="."]
visible = false

View File

@@ -20,6 +20,10 @@ config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
run/name=""
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/size/viewport_width=1080

View File

@@ -11,4 +11,5 @@ format = 2
layer_0/tile_data = PackedInt32Array(-458747, 0, 0, -458746, 0, 0, -393212, 0, 0, -393211, 0, 0, -393210, 0, 0, -393209, 0, 0, -393208, 0, 0, -393207, 0, 0, -327678, 0, 0, -327677, 0, 0, -327676, 0, 0, -327675, 6, 0, -327674, 6, 0, -327673, 6, 0, -327672, 6, 0, -327671, 0, 0, -327670, 0, 0, -327669, 0, 0, -262142, 0, 0, -262141, 0, 0, -262140, 6, 0, -262139, 6, 0, -262138, 6, 0, -262137, 6, 0, -262136, 6, 0, -262135, 0, 0, -262134, 0, 0, -262133, 0, 0, -262132, 0, 0, -262131, 0, 0, -196606, 0, 0, -196605, 0, 0, -196604, 6, 0, -196603, 6, 0, -196602, 6, 0, -196601, 6, 0, -196600, 1, 0, -196599, 0, 0, -196598, 1, 0, -196597, 1, 0, -196596, 0, 0, -196595, 0, 0, -196594, 0, 0, -131071, 9, 0, -131070, 0, 0, -131069, 0, 0, -131068, 2, 0, -131067, 2, 0, -131066, 0, 0, -131065, 21, 0, -131064, 19, 0, -131063, 0, 0, -131062, 0, 0, -131061, 16, 0, -131060, 0, 0, -131059, 0, 0, -131058, 0, 0, -131057, 0, 0, -131056, 0, 0, -65534, 0, 0, -65533, 1, 0, -65532, 0, 0, -65531, 0, 0, -65530, 20, 0, -65529, 19, 0, -65528, 2, 0, -65527, 0, 0, -65526, 14, 0, -65525, 0, 0, -65524, 0, 0, -65523, 0, 0, -65522, 23, 0, -65521, 0, 0, -65520, 0, 0, -65519, 0, 0, 3, 1, 0, 4, 2, 0, 5, 0, 0, 6, 1, 0, 7, 1, 0, 8, 0, 0, 9, 10, 0, 10, 12, 0, 11, 0, 0, 12, 0, 0, 13, 8, 0, 14, 0, 0, 15, 0, 0, 16, 0, 0, 17, 0, 0, 65538, 0, 0, 65539, 0, 0, 65540, 2, 0, 65541, 0, 0, 65542, 1, 0, 65543, 15, 0, 65544, 0, 0, 65545, 0, 0, 65546, 0, 0, 65547, 0, 0, 65548, 0, 0, 65549, 25, 0, 65550, 8, 0, 65551, 0, 0, 65552, 21, 0, 65553, 0, 0, 131074, 0, 0, 131075, 1, 0, 131076, 0, 0, 131077, 1, 0, 131078, 0, 0, 131079, 0, 0, 131080, 0, 0, 131081, 5, 0, 131082, 0, 0, 131083, 0, 0, 131084, 0, 0, 131085, 0, 0, 131086, 0, 0, 131087, 0, 0, 131088, 0, 0, 131089, 0, 0, 196610, 0, 0, 196611, 0, 0, 196612, 0, 0, 196613, 23, 0, 196614, 0, 0, 196615, 0, 0, 196616, 0, 0, 196617, 5, 0, 196618, 5, 0, 196619, 0, 0, 196620, 0, 0, 196621, 0, 0, 196622, 0, 0, 196623, 23, 0, 196624, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 8, 0, 262153, 5, 0, 262154, 5, 0, 262155, 0, 0, 262156, 0, 0, 262157, 21, 0, 262158, 0, 0, 262159, 0, 0, 262160, 0, 0, 327686, 0, 0, 327687, 0, 0, 327688, 0, 0, 327689, 0, 0, 327690, 0, 0, 327691, 0, 0, 327692, 0, 0, 327693, 0, 0, 327694, 0, 0)
[node name="Troll" parent="." instance=ExtResource("2")]
modulate = Color(1.5, 1.5, 1.5, 1)
position = Vector2(602.819, -39.2876)

View File

@@ -17,6 +17,10 @@ run/main_scene="res://map.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -4,8 +4,8 @@ const MOTION_SPEED = 30
const FRICTION_FACTOR = 0.89
const TAN30DEG = tan(deg_to_rad(30))
func _physics_process(_delta):
var motion = Vector2()
func _physics_process(_delta: float) -> void:
var motion := Vector2()
motion.x = Input.get_axis(&"move_left", &"move_right")
motion.y = Input.get_axis(&"move_up", &"move_down")
# Make diagonal movement fit for hexagonal tiles.

View File

@@ -15,7 +15,9 @@ texture = ExtResource("2")
[node name="Shadow" type="Sprite2D" parent="."]
modulate = Color(0, 0, 0, 0.501961)
show_behind_parent = true
position = Vector2(3, 3)
position = Vector2(16.4422, 4.89438)
scale = Vector2(0.794259, 1.04505)
skew = 0.523599
texture = ExtResource("2")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
@@ -23,4 +25,3 @@ position = Vector2(3.24216, 19.453)
shape = SubResource("1")
[node name="Camera2D" type="Camera2D" parent="."]
current = true

View File

@@ -1,18 +1,18 @@
[gd_scene load_steps=4 format=2]
[gd_scene load_steps=4 format=3 uid="uid://cgx884jv27maj"]
[ext_resource path="res://bowling_ball.png" type="Texture2D" id=1]
[ext_resource type="Texture2D" uid="uid://cyqshsjd3qwo0" path="res://bowling_ball.png" id="1"]
[sub_resource type="PhysicsMaterial" id=1]
[sub_resource type="PhysicsMaterial" id="1"]
bounce = 0.4
[sub_resource type="CircleShape2D" id=2]
[sub_resource type="CircleShape2D" id="2"]
radius = 30.0
[node name="Ball" type="RigidDynamicBody2D"]
physics_material_override = SubResource( 1 )
[node name="Ball" type="RigidBody2D"]
physics_material_override = SubResource("1")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource( 1 )
texture = ExtResource("1")
[node name="Collision" type="CollisionShape2D" parent="."]
shape = SubResource( 2 )
shape = SubResource("2")

View File

@@ -2,15 +2,16 @@ extends Node2D
@export var ball_scene: PackedScene = preload("res://ball.tscn")
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
if event.is_echo():
return
if event is InputEventMouseButton and event.is_pressed():
if event.button_index == MOUSE_BUTTON_LEFT:
spawn(get_global_mouse_position())
func spawn(spawn_global_position):
var instance = ball_scene.instantiate()
func spawn(spawn_global_position: Vector2) -> void:
var instance: Node2D = ball_scene.instantiate()
instance.global_position = spawn_global_position
add_child(instance)

View File

@@ -18,6 +18,10 @@ run/main_scene="res://scene_instancing.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"
@@ -25,6 +29,7 @@ window/stretch/aspect="expand"
[physics]
common/physics_ticks_per_second=120
2d/default_gravity=300
[rendering]

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=13 format=3 uid="uid://rcsr8t4nw526"]
[ext_resource type="Script" path="res://ball_factory.gd" id="1"]
[ext_resource type="PackedScene" path="res://ball.tscn" id="2"]
[ext_resource type="PackedScene" uid="uid://cgx884jv27maj" path="res://ball.tscn" id="2"]
[sub_resource type="PhysicsMaterial" id="1"]
bounce = 0.4
@@ -35,7 +35,9 @@ bounce = 0.4
[node name="SceneInstancing" type="Node2D"]
[node name="InfoLabel" type="Label" parent="."]
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="InfoLabel" type="Label" parent="CanvasLayer"]
offset_left = 16.0
offset_top = 16.0
offset_right = 370.0

View File

@@ -1,5 +1,5 @@
extends Node
func _on_body_entered(body):
func _on_body_entered(body: Node2D) -> void:
if body.name == "Player":
$"../WinText".show()

View File

@@ -5,11 +5,11 @@ const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300
const JUMP_SPEED = 200
@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
@onready var gravity := float(ProjectSettings.get_setting("physics/2d/default_gravity"))
func _physics_process(delta):
func _physics_process(delta: float) -> void:
# Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
var walk := WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
# Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned.

View File

@@ -19,6 +19,10 @@ run/main_scene="res://world.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/size/viewport_width=530

View File

@@ -17,6 +17,10 @@ run/main_scene="res://lightmask.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -1,7 +1,7 @@
extends Node2D
func _input(event):
func _input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_directional_light"):
$DirectionalLight2D.visible = not $DirectionalLight2D.visible

View File

@@ -18,6 +18,10 @@ run/main_scene="res://light_shadows.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/size/viewport_width=800

View File

@@ -1,11 +1,10 @@
extends CharacterBody2D
var movement_speed := 200.0
var movement_speed: float = 200.0
@onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D
func _ready():
func _ready() -> void:
# These values need to be adjusted for the actor's speed
# and the navigation layout.
navigation_agent.path_desired_distance = 2.0
@@ -15,17 +14,18 @@ func _ready():
# The "click" event is a custom input action defined in
# Project > Project Settings > Input Map tab.
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
if not event.is_action_pressed("click"):
return
set_movement_target(get_global_mouse_position())
func set_movement_target(movement_target: Vector2):
func set_movement_target(movement_target: Vector2) -> void:
navigation_agent.target_position = movement_target
func _physics_process(_delta):
func _physics_process(_delta: float) -> void:
if navigation_agent.is_navigation_finished():
return

View File

@@ -19,6 +19,10 @@ run/main_scene="res://navigation.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/size/viewport_width=800
@@ -33,6 +37,10 @@ click={
]
}
[physics]
common/physics_ticks_per_second=120
[rendering]
renderer/rendering_method="gl_compatibility"

View File

@@ -1,29 +1,33 @@
extends Node2D
enum State { IDLE, FOLLOW }
enum State {
IDLE,
FOLLOW,
}
const MASS = 10.0
const ARRIVE_DISTANCE = 10.0
@export var speed: float = 200.0
@export_range(10, 500, 0.1, "or_greater") var speed := 200.0
var _state = State.IDLE
var _velocity = Vector2()
var _state := State.IDLE
var _velocity := Vector2()
@onready var _tile_map = $"../TileMap"
var _click_position := Vector2()
var _path := PackedVector2Array()
var _next_point := Vector2()
var _click_position = Vector2()
var _path = PackedVector2Array()
var _next_point = Vector2()
@onready var _tile_map: TileMap = $"../TileMap"
func _ready():
func _ready() -> void:
_change_state(State.IDLE)
func _process(_delta):
func _process(_delta: float) -> void:
if _state != State.FOLLOW:
return
var arrived_to_next_point = _move_to(_next_point)
var arrived_to_next_point := _move_to(_next_point)
if arrived_to_next_point:
_path.remove_at(0)
if _path.is_empty():
@@ -32,7 +36,7 @@ func _process(_delta):
_next_point = _path[0]
func _unhandled_input(event):
func _unhandled_input(event: InputEvent) -> void:
_click_position = get_global_mouse_position()
if _tile_map.is_point_walkable(_click_position):
if event.is_action_pressed(&"teleport_to", false, true):
@@ -42,16 +46,16 @@ func _unhandled_input(event):
_change_state(State.FOLLOW)
func _move_to(local_position):
var desired_velocity = (local_position - position).normalized() * speed
var steering = desired_velocity - _velocity
func _move_to(local_position: Vector2) -> float:
var desired_velocity := (local_position - position).normalized() * speed
var steering := desired_velocity - _velocity
_velocity += steering / MASS
position += _velocity * get_process_delta_time()
rotation = _velocity.angle()
return position.distance_to(local_position) < ARRIVE_DISTANCE
func _change_state(new_state):
func _change_state(new_state: State) -> void:
if new_state == State.IDLE:
_tile_map.clear_path()
elif new_state == State.FOLLOW:

View File

@@ -1,19 +1,23 @@
extends TileMap
enum Tile { OBSTACLE, START_POINT, END_POINT }
enum Tile {
OBSTACLE,
START_POINT,
END_POINT,
}
const CELL_SIZE = Vector2i(64, 64)
const BASE_LINE_WIDTH = 3.0
const DRAW_COLOR = Color.WHITE * Color(1, 1, 1, 0.5)
# The object for pathfinding on 2D grids.
var _astar = AStarGrid2D.new()
var _astar := AStarGrid2D.new()
var _start_point = Vector2i()
var _end_point = Vector2i()
var _path = PackedVector2Array()
var _start_point := Vector2i()
var _end_point := Vector2i()
var _path := PackedVector2Array()
func _ready():
func _ready() -> void:
# Region should match the size of the playable area plus one (in tiles).
# In this demo, the playable area is 17×9 tiles, so the rect size is 18×10.
_astar.region = Rect2i(0, 0, 18, 10)
@@ -26,35 +30,35 @@ func _ready():
for i in range(_astar.region.position.x, _astar.region.end.x):
for j in range(_astar.region.position.y, _astar.region.end.y):
var pos = Vector2i(i, j)
var pos := Vector2i(i, j)
if get_cell_source_id(0, pos) == Tile.OBSTACLE:
_astar.set_point_solid(pos)
func _draw():
func _draw() -> void:
if _path.is_empty():
return
var last_point = _path[0]
var last_point := _path[0]
for index in range(1, len(_path)):
var current_point = _path[index]
var current_point := _path[index]
draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true)
draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR)
last_point = current_point
func round_local_position(local_position):
func round_local_position(local_position: Vector2i) -> Vector2i:
return map_to_local(local_to_map(local_position))
func is_point_walkable(local_position):
var map_position = local_to_map(local_position)
func is_point_walkable(local_position: Vector2i) -> bool:
var map_position := local_to_map(local_position)
if _astar.is_in_boundsv(map_position):
return not _astar.is_point_solid(map_position)
return false
func clear_path():
func clear_path() -> void:
if not _path.is_empty():
_path.clear()
erase_cell(0, _start_point)
@@ -63,7 +67,7 @@ func clear_path():
queue_redraw()
func find_path(local_start_point, local_end_point):
func find_path(local_start_point: Vector2i, local_end_point: Vector2i) -> PackedVector2Array:
clear_path()
_start_point = local_to_map(local_start_point)

View File

@@ -18,6 +18,10 @@ run/main_scene="res://game.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
extends Label
func _input(event):
func _input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_pause"):
get_tree().paused = not get_tree().paused

View File

@@ -17,6 +17,10 @@ run/main_scene="res://particles.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"

View File

@@ -1,8 +1,8 @@
class_name Coin
extends Area2D
var taken = false
var taken := false
func _on_body_enter(body):
func _on_body_enter(body: Node2D) -> void:
if not taken and body is Player:
($AnimationPlayer as AnimationPlayer).play("taken")

View File

@@ -1,7 +1,6 @@
class_name Enemy
extends RigidBody2D
const WALK_SPEED = 50
enum State {

View File

@@ -48,7 +48,7 @@ tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"update": 1,
"values": [4]
}
tracks/1/type = "value"

View File

@@ -1,13 +1,13 @@
class_name Bullet
extends RigidBody2D
var disabled = false
var disabled := false
func _ready():
func _ready() -> void:
($Timer as Timer).start()
func disable():
func disable() -> void:
if disabled:
return

View File

@@ -50,7 +50,7 @@ func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
if spawn:
_spawn_enemy_above.call_deferred()
# Deapply prev floor velocity.
# Deapply previous floor velocity.
velocity.x -= floor_h_velocity
floor_h_velocity = 0.0
@@ -59,7 +59,7 @@ func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
var floor_index := -1
for contact_index in state.get_contact_count():
var collision_normal = state.get_contact_local_normal(contact_index)
var collision_normal := state.get_contact_local_normal(contact_index)
if collision_normal.dot(Vector2(0, -1)) > 0.6:
found_floor = true

View File

@@ -20,6 +20,10 @@ run/main_scene="res://stage.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/size/viewport_width=800

View File

@@ -3,7 +3,7 @@
[ext_resource type="Texture2D" uid="uid://1nmxl2dgdqro" path="res://assets/tileset/tiles_demo.png" id="1"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_4jjf0"]
texture = ExtResource( "1" )
texture = ExtResource("1")
0:0/next_alternative_id = 8
0:0/0 = 0
0:0/0/modulate = Color(0, 0, 1, 1)
@@ -18,4 +18,4 @@ texture = ExtResource( "1" )
[resource]
physics_layer_0/collision_layer = 1
sources/0 = SubResource( "TileSetAtlasSource_4jjf0" )
sources/0 = SubResource("TileSetAtlasSource_4jjf0")

View File

@@ -51,6 +51,8 @@ offset_top = -19.0
offset_right = 50.0
offset_bottom = -5.0
grow_vertical = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "FPS: 0"
script = ExtResource("1")
@@ -60,10 +62,12 @@ anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = -39.0
offset_right = 50.0
offset_bottom = -25.0
offset_top = -56.0
offset_right = 128.0
offset_bottom = -33.0
grow_vertical = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Physics engine:"
script = ExtResource("3")
@@ -73,10 +77,12 @@ anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = -59.0
offset_right = 50.0
offset_bottom = -45.0
offset_top = -84.0
offset_right = 125.0
offset_bottom = -61.0
grow_vertical = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Godot Version:"
script = ExtResource("2")
@@ -86,10 +92,12 @@ anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = -79.0
offset_top = -112.0
offset_right = 50.0
offset_bottom = -65.0
offset_bottom = -89.0
grow_vertical = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Test:"
script = ExtResource("5")

View File

@@ -21,6 +21,10 @@ config/icon="res://icon.webp"
Log="*res://utils/system_log.gd"
System="*res://utils/system.gd"
[debug]
gdscript/warnings/untyped_declaration=1
[display]
window/stretch/mode="canvas_items"
@@ -51,7 +55,7 @@ toggle_full_screen={
}
exit={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777217,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
toggle_debug_collision={
@@ -71,20 +75,21 @@ toggle_pause={
}
character_left={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":113,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
character_right={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
character_jump={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":122,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null)
]
}

View File

@@ -1,42 +1,40 @@
class_name Test
extends Node2D
signal wait_done()
@export var _enable_debug_collision = true
@export var _enable_debug_collision := true
var _timer
var _timer_started = false
var _timer: Timer
var _timer_started := false
var _wait_physics_ticks_counter = 0
var _wait_physics_ticks_counter := 0
class Circle2D:
extends Node2D
var center
var radius
var color
var center := Vector2()
var radius := 0.0
var color := Color()
func _draw():
func _draw() -> void:
draw_circle(center, radius, color)
var _drawn_nodes = []
var _drawn_nodes := []
func _enter_tree():
func _enter_tree() -> void:
if not _enable_debug_collision:
get_tree().debug_collisions_hint = false
func _physics_process(_delta):
func _physics_process(_delta: float) -> void:
if _wait_physics_ticks_counter > 0:
_wait_physics_ticks_counter -= 1
if _wait_physics_ticks_counter == 0:
wait_done.emit()
func add_line(pos_start, pos_end, color):
var line = Line2D.new()
func add_line(pos_start: Vector2, pos_end: Vector2, color: Color) -> void:
var line := Line2D.new()
line.points = [pos_start, pos_end]
line.width = 1.5
line.default_color = color
@@ -44,8 +42,8 @@ func add_line(pos_start, pos_end, color):
add_child(line)
func add_circle(pos, radius, color):
var circle = Circle2D.new()
func add_circle(pos: Vector2, radius: float, color: Color) -> void:
var circle := Circle2D.new()
circle.center = pos
circle.radius = radius
circle.color = color
@@ -53,8 +51,8 @@ func add_circle(pos, radius, color):
add_child(circle)
func add_shape(shape, shape_transform, color):
var collision = CollisionShape2D.new()
func add_shape(shape: Shape2D, shape_transform: Transform2D, color: Color) -> void:
var collision := CollisionShape2D.new()
collision.shape = shape
collision.transform = shape_transform
collision.modulate = color
@@ -62,36 +60,36 @@ func add_shape(shape, shape_transform, color):
add_child(collision)
func clear_drawn_nodes():
for node in _drawn_nodes:
func clear_drawn_nodes() -> void:
for node: Node in _drawn_nodes:
node.queue_free()
_drawn_nodes.clear()
func create_rigidbody(shape, pickable = false, shape_transform = Transform2D.IDENTITY):
var collision = CollisionShape2D.new()
func create_rigidbody(shape: Shape2D, pickable: bool = false, shape_transform: Transform2D = Transform2D.IDENTITY) -> RigidBody2D:
var collision := CollisionShape2D.new()
collision.shape = shape
collision.transform = shape_transform
var body = RigidBody2D.new()
var body := RigidBody2D.new()
body.add_child(collision)
if pickable:
var script = load("res://utils/rigidbody_pick.gd")
var script := load("res://utils/rigidbody_pick.gd")
body.set_script(script)
return body
func create_rigidbody_box(size, pickable = false, use_icon = false, shape_transform = Transform2D.IDENTITY):
var shape = RectangleShape2D.new()
func create_rigidbody_box(size: Vector2, pickable: bool = false, use_icon: bool = false, shape_transform: Transform2D = Transform2D.IDENTITY) -> RigidBody2D:
var shape := RectangleShape2D.new()
shape.size = size
var body = create_rigidbody(shape, pickable, shape_transform)
var body := create_rigidbody(shape, pickable, shape_transform)
if use_icon:
var texture = load("res://icon.webp")
var icon = Sprite2D.new()
var texture := load("res://icon.webp")
var icon := Sprite2D.new()
icon.texture = texture
icon.scale = size / texture.get_size()
body.add_child(icon)
@@ -99,14 +97,15 @@ func create_rigidbody_box(size, pickable = false, use_icon = false, shape_transf
return body
func find_node(node_name):
var nodes = find_children(node_name)
func find_node(node_name: String) -> Node:
var nodes := find_children(node_name)
if nodes.size() > 0:
return nodes[0]
return null
func start_timer(timeout):
func start_timer(timeout: float) -> Timer:
if _timer == null:
_timer = Timer.new()
_timer.one_shot = true
@@ -121,21 +120,21 @@ func start_timer(timeout):
return _timer
func cancel_timer():
func cancel_timer() -> void:
if _timer_started:
_timer.paused = true
_timer.timeout.emit()
_timer.paused = false
func is_timer_canceled():
func is_timer_canceled() -> bool:
return _timer and _timer.paused
func wait_for_physics_ticks(tick_count):
func wait_for_physics_ticks(tick_count: int) -> Test:
_wait_physics_ticks_counter = tick_count
return self
func _on_timer_done():
func _on_timer_done() -> void:
_timer_started = false

View File

@@ -1,7 +1,6 @@
extends Node
var _tests = [
var _tests := [
{
"id": "Functional Tests/Shapes",
"path": "res://tests/functional/test_shapes.tscn",
@@ -57,7 +56,7 @@ var _tests = [
]
func _ready():
var test_menu = $TestsMenu
for test in _tests:
func _ready() -> void:
var test_menu: OptionMenu = $TestsMenu
for test: Variant in _tests:
test_menu.add_test(test.id, test.path)

View File

@@ -1,8 +1,7 @@
extends Test
class_name TestCharacter
class_name Test
extends TestCharacter
enum E_BodyType {
enum BodyType {
CHARACTER_BODY,
CHARACTER_BODY_RAY,
RIGID_BODY,
@@ -19,31 +18,31 @@ const OPTION_MOVE_CHARACTER_STOP_ON_SLOPE = "Move Options/Use stop on slope (Cha
const OPTION_MOVE_CHARACTER_FLOOR_ONLY = "Move Options/Move on floor only (Character only)"
const OPTION_MOVE_CHARACTER_CONSTANT_SPEED = "Move Options/Use constant speed (Character only)"
@export var _initial_velocity = Vector2.ZERO
@export var _constant_velocity = Vector2.ZERO
@export var _motion_speed = 400.0
@export var _gravity_force = 50.0
@export var _jump_force = 1000.0
@export var _snap_distance = 0.0
@export var _floor_max_angle = 45.0
@export var _body_type: E_BodyType = 0
@export var _initial_velocity := Vector2.ZERO
@export var _constant_velocity := Vector2.ZERO
@export var _motion_speed := 400.0
@export var _gravity_force := 50.0
@export var _jump_force := 1000.0
@export var _snap_distance := 0.0
@export var _floor_max_angle := 45.0
@export var _body_type := BodyType.CHARACTER_BODY
@onready var options = $Options
@onready var options: OptionMenu = $Options
var _use_snap = true
var _use_stop_on_slope = true
var _use_floor_only = true
var _use_constant_speed = false
var _use_snap := true
var _use_stop_on_slope := true
var _use_floor_only := true
var _use_constant_speed := false
var _body_parent: Node = null
var _character_body_template = null
var _character_body_ray_template = null
var _rigid_body_template = null
var _rigid_body_ray_template = null
var _character_body_template: CharacterBody2D = null
var _character_body_ray_template: CharacterBody2D = null
var _rigid_body_template: RigidBody2D = null
var _rigid_body_ray_template: RigidBody2D = null
var _moving_body: PhysicsBody2D = null
func _ready():
func _ready() -> void:
options.option_selected.connect(_on_option_selected)
options.option_changed.connect(_on_option_changed)
@@ -51,28 +50,28 @@ func _ready():
if _character_body_template:
_body_parent = _character_body_template.get_parent()
_body_parent.remove_child(_character_body_template)
var enabled = _body_type == E_BodyType.CHARACTER_BODY
var enabled := _body_type == BodyType.CHARACTER_BODY
options.add_menu_item(OPTION_OBJECT_TYPE_CHARACTER, true, enabled, true)
_character_body_ray_template = find_child("CharacterBodyRay2D")
if _character_body_ray_template:
_body_parent = _character_body_ray_template.get_parent()
_body_parent.remove_child(_character_body_ray_template)
var enabled = _body_type == E_BodyType.CHARACTER_BODY_RAY
var enabled := _body_type == BodyType.CHARACTER_BODY_RAY
options.add_menu_item(OPTION_OBJECT_TYPE_CHARACTER_RAY, true, enabled, true)
_rigid_body_template = find_child("RigidBody2D")
if _rigid_body_template:
_body_parent = _rigid_body_template.get_parent()
_body_parent.remove_child(_rigid_body_template)
var enabled = _body_type == E_BodyType.RIGID_BODY
var enabled := _body_type == BodyType.RIGID_BODY
options.add_menu_item(OPTION_OBJECT_TYPE_RIGID_BODY, true, enabled, true)
_rigid_body_ray_template = find_child("RigidBodyRay2D")
if _rigid_body_ray_template:
_body_parent = _rigid_body_ray_template.get_parent()
_body_parent.remove_child(_rigid_body_ray_template)
var enabled = _body_type == E_BodyType.RIGID_BODY_RAY
var enabled := _body_type == BodyType.RIGID_BODY_RAY
options.add_menu_item(OPTION_OBJECT_TYPE_RIGID_BODY_RAY, true, enabled, true)
options.add_menu_item(OPTION_MOVE_CHARACTER_SNAP, true, _use_snap)
@@ -80,15 +79,15 @@ func _ready():
options.add_menu_item(OPTION_MOVE_CHARACTER_FLOOR_ONLY, true, _use_floor_only)
options.add_menu_item(OPTION_MOVE_CHARACTER_CONSTANT_SPEED, true, _use_constant_speed)
var floor_slider = find_child("FloorMaxAngle")
var floor_slider: Control = find_child("FloorMaxAngle")
if floor_slider:
floor_slider.get_node("HSlider").value = _floor_max_angle
_start_test()
func _process(_delta):
var label_floor = $LabelFloor
func _process(_delta: float) -> void:
var label_floor: Label = $LabelFloor
if _moving_body:
if _moving_body.is_on_floor():
label_floor.text = "ON FLOOR"
@@ -100,8 +99,8 @@ func _process(_delta):
label_floor.visible = false
func _input(event):
var key_event = event as InputEventKey
func _input(event: InputEvent) -> void:
var key_event := event as InputEventKey
if key_event and not key_event.pressed:
if key_event.keycode == KEY_1:
if _character_body_template:
@@ -117,7 +116,7 @@ func _input(event):
_on_option_selected(OPTION_OBJECT_TYPE_RIGID_BODY_RAY)
func _exit_tree():
func _exit_tree() -> void:
if _character_body_template:
_character_body_template.free()
if _character_body_ray_template:
@@ -128,23 +127,23 @@ func _exit_tree():
_rigid_body_ray_template.free()
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
match option:
OPTION_OBJECT_TYPE_CHARACTER:
_body_type = E_BodyType.CHARACTER_BODY
_body_type = BodyType.CHARACTER_BODY
_start_test()
OPTION_OBJECT_TYPE_CHARACTER_RAY:
_body_type = E_BodyType.CHARACTER_BODY_RAY
_body_type = BodyType.CHARACTER_BODY_RAY
_start_test()
OPTION_OBJECT_TYPE_RIGID_BODY:
_body_type = E_BodyType.RIGID_BODY
_body_type = BodyType.RIGID_BODY
_start_test()
OPTION_OBJECT_TYPE_RIGID_BODY_RAY:
_body_type = E_BodyType.RIGID_BODY_RAY
_body_type = BodyType.RIGID_BODY_RAY
_start_test()
func _on_option_changed(option, checked):
func _on_option_changed(option: String, checked: bool) -> void:
match option:
OPTION_MOVE_CHARACTER_SNAP:
_use_snap = checked
@@ -164,8 +163,8 @@ func _on_option_changed(option, checked):
_moving_body._constant_speed = _use_constant_speed
func _update_floor_max_angle(value):
if (value == _floor_max_angle):
func _update_floor_max_angle(value: float) -> void:
if value == _floor_max_angle:
return
_floor_max_angle = value
@@ -173,7 +172,7 @@ func _update_floor_max_angle(value):
_moving_body._floor_max_angle = _floor_max_angle
func _start_test():
func _start_test() -> void:
cancel_timer()
if _moving_body:
@@ -181,20 +180,19 @@ func _start_test():
_moving_body.queue_free()
_moving_body = null
var test_label = "Testing: "
var test_label := "Testing: "
var template = null
var template: PhysicsBody2D = null
match _body_type:
E_BodyType.CHARACTER_BODY:
BodyType.CHARACTER_BODY:
template = _character_body_template
E_BodyType.CHARACTER_BODY_RAY:
BodyType.CHARACTER_BODY_RAY:
template = _character_body_ray_template
E_BodyType.RIGID_BODY:
BodyType.RIGID_BODY:
template = _rigid_body_template
E_BodyType.RIGID_BODY_RAY:
BodyType.RIGID_BODY_RAY:
template = _rigid_body_ray_template
test_label += String(template.name)
_moving_body = template.duplicate()
_body_parent.add_child(_moving_body)

View File

@@ -1,29 +1,28 @@
extends TestCharacter
const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)"
const OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP = "Test Cases/Floor detection (Character Body)"
const OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES = "Test Cases/Floor detection with motion changes (Character Body)"
const MOTION_CHANGES_DIR = Vector2(1.0, 1.0)
const MOTION_CHANGES_SPEEDS = [0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0]
const MOTION_CHANGES_SPEEDS: Array[float] = [0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0]
var _test_floor_detection = false
var _test_motion_changes = false
var _floor_detected = false
var _floor_lost = false
var _test_floor_detection := false
var _test_motion_changes := false
var _floor_detected := false
var _floor_lost := false
var _failed_reason = ""
var _failed_reason := ""
func _ready():
func _ready() -> void:
super._ready()
options.add_menu_item(OPTION_TEST_CASE_ALL)
options.add_menu_item(OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP)
options.add_menu_item(OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES)
func _physics_process(delta):
func _physics_process(delta: float) -> void:
super._physics_process(delta)
if _moving_body:
@@ -35,24 +34,23 @@ func _physics_process(delta):
Log.print_log("Floor lost.")
if _test_motion_changes:
var speed_count = MOTION_CHANGES_SPEEDS.size()
var speed_index = randi() % speed_count
var speed = MOTION_CHANGES_SPEEDS[speed_index]
var velocity = speed * MOTION_CHANGES_DIR
var speed_count := MOTION_CHANGES_SPEEDS.size()
var speed_index := randi() % speed_count
var speed := MOTION_CHANGES_SPEEDS[speed_index]
var velocity := speed * MOTION_CHANGES_DIR
_moving_body._constant_velocity = velocity
#Log.print_log("Velocity: %s" % velocity)
func _input(event):
func _input(event: InputEvent) -> void:
super._input(event)
var key_event = event as InputEventKey
if key_event and not key_event.pressed:
if key_event.keycode == KEY_0:
if event is InputEventKey and not event.pressed:
if event.keycode == KEY_0:
await _on_option_selected(OPTION_TEST_CASE_ALL)
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
match option:
OPTION_TEST_CASE_ALL:
await _test_all()
@@ -66,7 +64,7 @@ func _on_option_selected(option):
super._on_option_selected(option)
func _start_test_case(option):
func _start_test_case(option: String) -> void:
Log.print_log("* Starting " + option)
match option:
@@ -74,7 +72,7 @@ func _start_test_case(option):
_test_floor_detection = true
_test_motion_changes = false
_use_snap = false
_body_type = E_BodyType.CHARACTER_BODY
_body_type = BodyType.CHARACTER_BODY
_start_test()
await start_timer(1.0).timeout
@@ -86,7 +84,7 @@ func _start_test_case(option):
_test_floor_detection = true
_test_motion_changes = true
_use_snap = false
_body_type = E_BodyType.CHARACTER_BODY
_body_type = BodyType.CHARACTER_BODY
_start_test()
await start_timer(4.0).timeout
@@ -102,7 +100,7 @@ func _start_test_case(option):
Log.print_error("Invalid test case.")
func _test_all():
func _test_all() -> void:
Log.print_log("* TESTING ALL...")
# Test floor detection with no snapping.
@@ -119,8 +117,8 @@ func _test_all():
Log.print_log("* Done.")
func _set_result(test_passed):
var result = ""
func _set_result(test_passed: bool) -> void:
var result := ""
if test_passed:
result = "PASSED"
else:
@@ -134,7 +132,7 @@ func _set_result(test_passed):
Log.print_log("Test %s" % result)
func _start_test():
func _start_test() -> void:
super._start_test()
_failed_reason = ""

View File

@@ -1,6 +1,5 @@
extends TestCharacter
const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)"
const OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID = "Test Cases/Jump through one-way tiles (Rigid Body)"
const OPTION_TEST_CASE_JUMP_ONE_WAY_CHARACTER = "Test Cases/Jump through one-way tiles (Character Body)"
@@ -8,16 +7,15 @@ const OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID = "Test Cases/Jump through one-
const OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_CHARACTER = "Test Cases/Jump through one-way corner (Character Body)"
const OPTION_TEST_CASE_FALL_ONE_WAY_CHARACTER = "Test Cases/Fall and pushed on one-way tiles (Character Body)"
var _test_jump_one_way = false
var _test_jump_one_way_corner = false
var _test_fall_one_way = false
var _test_jump_one_way := false
var _test_jump_one_way_corner := false
var _test_fall_one_way := false
var _extra_body: PhysicsBody2D = null
var _failed_reason = ""
var _failed_reason := ""
func _ready():
func _ready() -> void:
super._ready()
options.add_menu_item(OPTION_TEST_CASE_ALL)
@@ -28,16 +26,15 @@ func _ready():
options.add_menu_item(OPTION_TEST_CASE_FALL_ONE_WAY_CHARACTER)
func _input(event):
func _input(event: InputEvent) -> void:
super._input(event)
var key_event = event as InputEventKey
if key_event and not key_event.pressed:
if key_event.keycode == KEY_0:
if event is InputEventKey and not event.pressed:
if event.keycode == KEY_0:
await _on_option_selected(OPTION_TEST_CASE_ALL)
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
match option:
OPTION_TEST_CASE_ALL:
await _test_all()
@@ -60,34 +57,34 @@ func _on_option_selected(option):
super._on_option_selected(option)
func _start_test_case(option):
func _start_test_case(option: String) -> void:
Log.print_log("* Starting " + option)
match option:
OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID:
_body_type = E_BodyType.RIGID_BODY
_body_type = BodyType.RIGID_BODY
_test_jump_one_way_corner = false
await _start_jump_one_way()
OPTION_TEST_CASE_JUMP_ONE_WAY_CHARACTER:
_body_type = E_BodyType.CHARACTER_BODY
_body_type = BodyType.CHARACTER_BODY
_test_jump_one_way_corner = false
await _start_jump_one_way()
OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID:
_body_type = E_BodyType.RIGID_BODY
_body_type = BodyType.RIGID_BODY
_test_jump_one_way_corner = true
await _start_jump_one_way()
OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_CHARACTER:
_body_type = E_BodyType.CHARACTER_BODY
_body_type = BodyType.CHARACTER_BODY
_test_jump_one_way_corner = true
await _start_jump_one_way()
OPTION_TEST_CASE_FALL_ONE_WAY_CHARACTER:
_body_type = E_BodyType.CHARACTER_BODY
_body_type = BodyType.CHARACTER_BODY
await _start_fall_one_way()
_:
Log.print_error("Invalid test case.")
func _test_all():
func _test_all() -> void:
Log.print_log("* TESTING ALL...")
# RigidBody tests.
@@ -115,8 +112,8 @@ func _test_all():
Log.print_log("* Done.")
func _set_result(test_passed):
var result = ""
func _set_result(test_passed: bool) -> void:
var result := ""
if test_passed:
result = "PASSED"
else:
@@ -130,7 +127,7 @@ func _set_result(test_passed):
Log.print_log("Test %s" % result)
func _start_test():
func _start_test() -> void:
if _extra_body:
_body_parent.remove_child(_extra_body)
_extra_body.queue_free()
@@ -167,7 +164,7 @@ func _start_test():
$FallTargetArea2D/CollisionShape2D.disabled = false
func _start_jump_one_way():
func _start_jump_one_way() -> void:
_test_jump_one_way = true
_start_test()
@@ -178,7 +175,7 @@ func _start_jump_one_way():
_finalize_jump_one_way()
func _start_fall_one_way():
func _start_fall_one_way() -> void:
_test_fall_one_way = true
_start_test()
@@ -189,8 +186,8 @@ func _start_fall_one_way():
_finalize_fall_one_way()
func _finalize_jump_one_way():
var passed = true
func _finalize_jump_one_way() -> void:
var passed := true
if not $JumpTargetArea2D.overlaps_body(_moving_body):
passed = false
_failed_reason = ": the body wasn't able to jump all the way through."
@@ -201,8 +198,8 @@ func _finalize_jump_one_way():
$JumpTargetArea2D/CollisionShape2D.disabled = true
func _finalize_fall_one_way():
var passed = true
func _finalize_fall_one_way() -> void:
var passed := true
if $FallTargetArea2D.overlaps_body(_moving_body):
passed = false
_failed_reason = ": the body was pushed through the one-way collision."

View File

@@ -23,7 +23,7 @@ friction = 0.0
radius = 16.0
[node name="Test" type="Node2D"]
script = ExtResource( "1" )
script = ExtResource("1")
[node name="LabelTestType" type="Label" parent="."]
offset_left = 14.0
@@ -31,11 +31,8 @@ offset_top = 79.0
offset_right = 145.0
offset_bottom = 93.0
text = "Testing: "
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Options" parent="." instance=ExtResource( "3" )]
[node name="Options" parent="." instance=ExtResource("3")]
[node name="LabelFloor" type="Label" parent="."]
offset_left = 14.0
@@ -43,9 +40,6 @@ offset_top = 237.929
offset_right = 145.0
offset_bottom = 251.929
text = "ON FLOOR"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LabelControls" type="Label" parent="."]
offset_left = 14.0
@@ -54,82 +48,77 @@ offset_right = 145.0
offset_bottom = 277.291
text = "LEFT/RIGHT - MOVE
UP - JUMP"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CharacterBody2D" type="CharacterBody2D" parent="."]
position = Vector2(250, 460)
collision_mask = 2147483649
script = ExtResource( "7" )
script = ExtResource("7")
[node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBody2D"]
shape = SubResource( "2" )
shape = SubResource("2")
[node name="CharacterBodyRay2D" type="CharacterBody2D" parent="."]
position = Vector2(250, 460)
collision_mask = 2147483649
script = ExtResource( "7" )
script = ExtResource("7")
[node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBodyRay2D"]
position = Vector2(0, -8)
shape = SubResource( "RectangleShape2D_jx2e1" )
shape = SubResource("RectangleShape2D_jx2e1")
[node name="CollisionShapeRay2D" type="CollisionShape2D" parent="CharacterBodyRay2D"]
position = Vector2(0, 8)
shape = SubResource( "RayShape2D_206f5" )
shape = SubResource("RayShape2D_206f5")
[node name="CollisionShapeRay2DLeft" type="CollisionShape2D" parent="CharacterBodyRay2D"]
position = Vector2(-12, 8)
shape = SubResource( "RayShape2D_206f5" )
shape = SubResource("RayShape2D_206f5")
[node name="CollisionShapeRay2DRight" type="CollisionShape2D" parent="CharacterBodyRay2D"]
position = Vector2(12, 8)
shape = SubResource( "RayShape2D_206f5" )
shape = SubResource("RayShape2D_206f5")
[node name="RigidDynamicBody2D" type="RigidDynamicBody2D" parent="."]
[node name="RigidDynamicBody2D" type="RigidBody2D" parent="."]
position = Vector2(250, 460)
collision_mask = 2147483649
physics_material_override = SubResource( "1" )
contacts_reported = 4
contact_monitor = true
physics_material_override = SubResource("1")
lock_rotation = true
script = ExtResource( "6" )
contact_monitor = true
script = ExtResource("6")
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidDynamicBody2D"]
shape = SubResource( "2" )
shape = SubResource("2")
[node name="RigidBodyRay2D" type="RigidDynamicBody2D" parent="."]
[node name="RigidBodyRay2D" type="RigidBody2D" parent="."]
position = Vector2(250, 460)
collision_mask = 2147483649
physics_material_override = SubResource( "1" )
contacts_reported = 4
contact_monitor = true
physics_material_override = SubResource("1")
lock_rotation = true
script = ExtResource( "6" )
contact_monitor = true
script = ExtResource("6")
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBodyRay2D"]
position = Vector2(0, -8)
shape = SubResource( "RectangleShape2D_jx2e1" )
shape = SubResource("RectangleShape2D_jx2e1")
[node name="CollisionShapeRay2D" type="CollisionShape2D" parent="RigidBodyRay2D"]
position = Vector2(0, 8)
shape = SubResource( "RayShape2D_206f5" )
shape = SubResource("RayShape2D_206f5")
[node name="CollisionShapeRay2DLeft" type="CollisionShape2D" parent="RigidBodyRay2D"]
position = Vector2(-12, 8)
shape = SubResource( "RayShape2D_206f5" )
shape = SubResource("RayShape2D_206f5")
[node name="CollisionShapeRay2DRight" type="CollisionShape2D" parent="RigidBodyRay2D"]
position = Vector2(12, 8)
shape = SubResource( "RayShape2D_206f5" )
shape = SubResource("RayShape2D_206f5")
[node name="JumpTargetArea2D" type="Area2D" parent="."]
visible = false
position = Vector2(810, 390)
[node name="CollisionShape2D" type="CollisionShape2D" parent="JumpTargetArea2D"]
shape = SubResource( "5" )
shape = SubResource("5")
disabled = true
[node name="FallTargetArea2D" type="Area2D" parent="."]
@@ -137,15 +126,16 @@ visible = false
position = Vector2(250, 480)
[node name="CollisionShape2D" type="CollisionShape2D" parent="FallTargetArea2D"]
shape = SubResource( "5" )
shape = SubResource("5")
disabled = true
[node name="StaticSceneFlat" parent="." instance=ExtResource( "4" )]
[node name="StaticSceneFlat" parent="." instance=ExtResource("4")]
position = Vector2(0, 12)
[node name="TileMap" type="TileMap" parent="."]
texture_filter = 1
scale = Vector2(2, 2)
tile_set = ExtResource( "5" )
tile_set = ExtResource("5")
collision_visibility_mode = 1
format = 2
layer_0/tile_data = PackedInt32Array(786438, 65536, 0, 786439, 65536, 0, 786440, 65536, 0, 786441, 65536, 0, 458764, 65536, 0, 524300, 65536, 0, 589836, 65536, 0, 655372, 65536, 0, 720908, 65536, 0, 786444, 65536, 0, 851980, 65536, 0, 917516, 65536, 0, 983052, 65536, 0, 458765, 65536, 0, 524301, 65536, 0, 589837, 65536, 0, 655373, 65536, 0, 720909, 65536, 0, 786445, 65536, 0, 851981, 65536, 0, 917517, 65536, 0, 983053, 65536, 0, 458766, 65536, 0, 524302, 65536, 0, 589838, 65536, 0, 655374, 65536, 0, 720910, 65536, 0, 786446, 65536, 0, 851982, 65536, 0, 917518, 65536, 0, 983054, 65536, 0, 458767, 65536, 0, 524303, 65536, 0, 589839, 65536, 0, 655375, 65536, 0, 720911, 65536, 0, 786447, 65536, 0, 851983, 65536, 0, 917519, 65536, 0, 983055, 65536, 0, 458768, 65536, 0, 524304, 65536, 0, 589840, 65536, 0, 655376, 65536, 0, 720912, 65536, 0, 786448, 65536, 0, 851984, 65536, 0, 917520, 65536, 0, 983056, 65536, 0, 458769, 65536, 0, 524305, 65536, 0, 589841, 65536, 0, 655377, 65536, 0, 720913, 65536, 0, 786449, 65536, 0, 851985, 65536, 0, 917521, 65536, 0, 983057, 65536, 0, 458770, 65536, 0, 524306, 65536, 0, 589842, 65536, 0, 655378, 65536, 0, 720914, 65536, 0, 786450, 65536, 0, 851986, 65536, 0, 917522, 65536, 0, 983058, 65536, 0, 458771, 65536, 0, 524307, 65536, 0, 589843, 65536, 0, 655379, 65536, 0, 720915, 65536, 0, 786451, 65536, 0, 851987, 65536, 0, 917523, 65536, 0, 983059, 65536, 0, 851992, 0, 0, 851993, 0, 0, 720922, 0, 0, 851994, 0, 0, 720923, 0, 0, 851995, 0, 0, 720924, 0, 0, 720925, 0, 0)

View File

@@ -1,6 +1,5 @@
extends Test
const OPTION_TYPE_RECTANGLE = "Collision type/Rectangle (1)"
const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)"
const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)"
@@ -16,17 +15,16 @@ const OPTION_SHAPE_CONCAVE_SEGMENTS = "Shape type/Concave Segments"
const OFFSET_RANGE = 120.0
@export var offset = Vector2.ZERO
@export var offset := Vector2.ZERO
@onready var options = $Options
@onready var options: OptionMenu = $Options
var _update_collision = false
var _collision_test_index = 0
var _current_offset = Vector2.ZERO
var _collision_shapes = []
var _update_collision := false
var _collision_test_index := 0
var _collision_shapes: Array[Shape2D] = []
func _ready():
func _ready() -> void:
_initialize_collision_shapes()
options.add_menu_item(OPTION_TYPE_RECTANGLE)
@@ -52,8 +50,8 @@ func _ready():
_update_collision = true
func _input(event):
var key_event = event as InputEventKey
func _input(event: InputEvent) -> void:
var key_event := event as InputEventKey
if key_event and not key_event.pressed:
if key_event.keycode == KEY_1:
_on_option_selected(OPTION_TYPE_RECTANGLE)
@@ -67,7 +65,7 @@ func _input(event):
_on_option_selected(OPTION_TYPE_CONCAVE_SEGMENTS)
func _physics_process(delta):
func _physics_process(delta: float) -> void:
super._physics_process(delta)
if not _update_collision:
@@ -78,66 +76,64 @@ func _physics_process(delta):
_do_collision_test()
func set_h_offset(value):
func set_h_offset(value: float) -> void:
offset.x = value * OFFSET_RANGE
_update_collision = true
func set_v_offset(value):
func set_v_offset(value: float) -> void:
offset.y = -value * OFFSET_RANGE
_update_collision = true
func _initialize_collision_shapes():
func _initialize_collision_shapes() -> void:
_collision_shapes.clear()
for node in $Shapes.get_children():
var body = node as PhysicsBody2D
var shape = body.shape_owner_get_shape(0, 0)
for node: PhysicsBody2D in $Shapes.get_children():
var body: PhysicsBody2D = node
var shape := body.shape_owner_get_shape(0, 0)
shape.resource_name = String(node.name).substr("RigidBody".length())
_collision_shapes.push_back(shape)
func _do_collision_test():
func _do_collision_test() -> void:
clear_drawn_nodes()
var shape = _collision_shapes[_collision_test_index]
var shape := _collision_shapes[_collision_test_index]
Log.print_log("* Start %s collision tests..." % shape.resource_name)
var shape_query = PhysicsShapeQueryParameters2D.new()
var shape_query := PhysicsShapeQueryParameters2D.new()
shape_query.set_shape(shape)
var shape_scale = Vector2(0.5, 0.5)
var shape_scale := Vector2(0.5, 0.5)
shape_query.transform = Transform2D.IDENTITY.scaled(shape_scale)
for node in $Shapes.get_children():
for node: PhysicsBody2D in $Shapes.get_children():
if not node.visible:
continue
var body = node as PhysicsBody2D
var space_state = body.get_world_2d().direct_space_state
var body: PhysicsBody2D = node
var space_state := body.get_world_2d().direct_space_state
Log.print_log("* Testing: %s" % String(body.name))
var center = body.position
var center := body.position
# Collision at the center inside.
var res = _add_collision(space_state, center, shape, shape_query)
var res := _add_collision(space_state, center, shape, shape_query)
Log.print_log("Collision center inside: %s" % ("NO HIT" if res.is_empty() else "HIT"))
Log.print_log("* Done.")
func _add_collision(space_state, pos, shape, shape_query):
func _add_collision(space_state: PhysicsDirectSpaceState2D, pos: Vector2, shape: Shape2D, shape_query: PhysicsShapeQueryParameters2D) -> Array[Vector2]:
shape_query.transform.origin = pos + offset
var results = space_state.collide_shape(shape_query)
var results: Array[Vector2] = space_state.collide_shape(shape_query)
var color
var color := Color.GREEN
if results.is_empty():
color = Color.WHITE.darkened(0.5)
else:
color = Color.GREEN
# Draw collision query shape.
add_shape(shape, shape_query.transform, color)
@@ -149,7 +145,7 @@ func _add_collision(space_state, pos, shape, shape_query):
return results
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
match option:
OPTION_TYPE_RECTANGLE:
_collision_test_index = _find_type_index("Rectangle")
@@ -168,9 +164,9 @@ func _on_option_selected(option):
_update_collision = true
func _find_type_index(type_name):
func _find_type_index(type_name: String) -> int:
for type_index in range(_collision_shapes.size()):
var type_shape = _collision_shapes[type_index]
var type_shape := _collision_shapes[type_index]
if type_shape.resource_name.find(type_name) > -1:
return type_index
@@ -178,8 +174,8 @@ func _find_type_index(type_name):
return -1
func _on_option_changed(option, checked):
var node
func _on_option_changed(option: String, checked: bool) -> void:
var node: Node2D
match option:
OPTION_SHAPE_RECTANGLE:
@@ -201,8 +197,8 @@ func _on_option_changed(option, checked):
_update_collision = true
func _find_shape_node(type_name):
var node = $Shapes.find_child("RigidBody%s" % type_name)
func _find_shape_node(type_name: String) -> Node2D:
var node: Node2D = $Shapes.find_child("RigidBody%s" % type_name)
if not node:
Log.print_error("Invalid shape type: " + type_name)

View File

@@ -1,6 +1,5 @@
extends Test
const OPTION_JOINT_TYPE = "Joint Type/%s Joint (%d)"
const OPTION_TEST_CASE_BODIES_COLLIDE = "Test case/Attached bodies collide"
@@ -11,29 +10,27 @@ const OPTION_TEST_CASE_CHANGE_POSITIONS = "Test case/Set body positions after ad
const BOX_SIZE = Vector2(64, 64)
var _update_joint = false
var _selected_joint = null
var _update_joint := false
var _selected_joint: Joint2D = null
var _joint_type = PinJoint2D
var _bodies_collide = false
var _world_attachement = false
var _dynamic_attachement = false
var _destroy_body = false
var _change_positions = false
var _bodies_collide := false
var _world_attachement := false
var _dynamic_attachement := false
var _destroy_body := false
var _change_positions := false
var _joint_types = {}
var _joint_types := {}
func _ready() -> void:
var options: OptionMenu = $Options
func _ready():
var options = $Options
var joints = $Joints
for joint_index in range(joints.get_child_count()):
var joint_node = joints.get_child(joint_index)
var joints: Node2D = $Joints
for joint_index in joints.get_child_count():
var joint_node := joints.get_child(joint_index)
joint_node.visible = false
var joint_name = String(joint_node.name)
var joint_short = joint_name.substr(0, joint_name.length() - 7)
var option_name = OPTION_JOINT_TYPE % [joint_short, joint_index + 1]
var joint_name := String(joint_node.name)
var joint_short := joint_name.substr(0, joint_name.length() - 7)
var option_name := OPTION_JOINT_TYPE % [joint_short, joint_index + 1]
options.add_menu_item(option_name)
_joint_types[option_name] = joint_node
@@ -50,29 +47,28 @@ func _ready():
_update_joint = true
func _process(_delta):
func _process(_delta: float) -> void:
if _update_joint:
_update_joint = false
await _create_joint()
$LabelJointType.text = "Joint Type: " + String(_selected_joint.name)
func _input(event):
var key_event = event as InputEventKey
if key_event and not key_event.pressed:
var joint_index = key_event.keycode - KEY_1
func _input(event: InputEvent) -> void:
if event is InputEventKey and not event.pressed:
var joint_index: int = event.keycode - KEY_1
if joint_index >= 0 and joint_index < _joint_types.size():
_selected_joint = _joint_types.values()[joint_index]
_update_joint = true
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
if _joint_types.has(option):
_selected_joint = _joint_types[option]
_update_joint = true
func _on_option_changed(option, checked):
func _on_option_changed(option: String, checked: bool) -> void:
match option:
OPTION_TEST_CASE_BODIES_COLLIDE:
_bodies_collide = checked
@@ -91,18 +87,18 @@ func _on_option_changed(option, checked):
_update_joint = true
func _create_joint():
func _create_joint() -> void:
cancel_timer()
var root = $Objects
var root: Node2D = $Objects
while root.get_child_count():
var last_child_index = root.get_child_count() - 1
var last_child = root.get_child(last_child_index)
var last_child_index := root.get_child_count() - 1
var last_child := root.get_child(last_child_index)
root.remove_child(last_child)
last_child.queue_free()
var child_body = create_rigidbody_box(BOX_SIZE, true, true)
var child_body := create_rigidbody_box(BOX_SIZE, true, true)
if _change_positions:
root.add_child(child_body)
child_body.position = Vector2(0.0, 40)
@@ -110,7 +106,7 @@ func _create_joint():
child_body.position = Vector2(0.0, 40)
root.add_child(child_body)
var parent_body = null
var parent_body: PhysicsBody2D = null
if not _world_attachement:
parent_body = create_rigidbody_box(BOX_SIZE, true, true)
if _dynamic_attachement:
@@ -125,7 +121,7 @@ func _create_joint():
parent_body.position = Vector2(0.0, -40)
root.add_child(parent_body)
var joint = _selected_joint.duplicate()
var joint := _selected_joint.duplicate()
joint.visible = true
joint.disable_collision = not _bodies_collide
root.add_child(joint)

View File

@@ -4,7 +4,7 @@
[ext_resource type="PackedScene" uid="uid://blh3twy74kbkv" path="res://tests/test_options.tscn" id="4"]
[node name="JointTest2D" type="Node2D"]
script = ExtResource( "2" )
script = ExtResource("2")
[node name="LabelJointType" type="Label" parent="."]
offset_left = 14.0
@@ -12,11 +12,8 @@ offset_top = 79.0
offset_right = 145.0
offset_bottom = 93.0
text = "Joint Type: "
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Options" parent="." instance=ExtResource( "4" )]
[node name="Options" parent="." instance=ExtResource("4")]
[node name="Joints" type="Node2D" parent="."]
position = Vector2(512, 200)

View File

@@ -1,7 +1,6 @@
@tool
extends Test
signal all_tests_done()
signal test_done()
@@ -19,56 +18,56 @@ const OPTION_TEST_CASE_MOVING_PLATFORM_CHARACTER = "Test Cases/Moving Platform (
const TEST_ALL_ANGLES_STEP = 15.0
const TEST_ALL_ANGLES_MAX = 344.0
@export_range(64, 256, 0.1) var _platform_size = 128.0:
@export_range(64, 256, 0.1) var _platform_size := 128.0:
set(value):
if value == _platform_size:
return
_platform_size = value
_update_platform_size(value)
@export_range(0, 360, 0.1) var _platform_angle = 0.0:
@export_range(0, 360, 0.1) var _platform_angle := 0.0:
set(value):
if value == _platform_angle:
return
_platform_angle = value
_update_platform_angle(value)
@export var _platform_speed = 0.0
@export var _platform_speed := 0.0
@export_range(0, 360, 0.1) var _body_angle = 0.0:
@export_range(0, 360, 0.1) var _body_angle := 0.0:
set(value):
if value == _body_angle:
return
_body_angle = value
_update_rigidbody_angle(value)
@export var _body_velocity = Vector2(400.0, 0.0)
@export var _use_character_body = false
@export var _body_velocity := Vector2(400.0, 0.0)
@export var _use_character_body := false
@onready var options = $Options
@onready var options: OptionMenu = $Options
var _rigid_body_template = null
var _character_body_template = null
var _rigid_body_template: RigidBody2D = null
var _character_body_template: CharacterBody2D = null
var _moving_body: PhysicsBody2D = null
var _platform_template = null
var _platform_template: StaticBody2D = null
var _platform_body: PhysicsBody2D = null
var _platform_velocity = Vector2.ZERO
var _platform_velocity := Vector2.ZERO
@onready var _target_area = $TargetArea2D
@onready var _target_area: Area2D = $TargetArea2D
var _contact_detected = false
var _target_entered = false
var _test_passed = false
var _test_step = 0
var _contact_detected := false
var _target_entered := false
var _test_passed := false
var _test_step := 0
var _test_all_angles = false
var _lock_controls = false
var _test_all_angles := false
var _lock_controls := false
var _test_canceled = false
var _test_canceled := false
func _ready():
func _ready() -> void:
if not Engine.is_editor_hint():
options.add_menu_item(OPTION_OBJECT_TYPE_RIGIDBODY, true, not _use_character_body, true)
options.add_menu_item(OPTION_OBJECT_TYPE_CHARACTER, true, _use_character_body, true)
@@ -103,47 +102,46 @@ func _ready():
_start_test()
func _process(_delta):
func _process(_delta: float) -> void:
if not Engine.is_editor_hint():
if Input.is_action_just_pressed(&"ui_accept"):
await _reset_test(false)
func _physics_process(delta):
func _physics_process(delta: float) -> void:
super._physics_process(delta)
if not Engine.is_editor_hint():
if _moving_body and not _contact_detected:
if _use_character_body:
var collision = _moving_body.move_and_collide(_body_velocity * delta, false)
var collision := _moving_body.move_and_collide(_body_velocity * delta, false)
if collision:
var colliding_body = collision.get_collider()
var colliding_body := collision.get_collider()
await _on_contact_detected(colliding_body)
if _platform_body and _platform_velocity != Vector2.ZERO:
var motion = _platform_velocity * delta
var motion := _platform_velocity * delta
_platform_body.global_position += motion
func _input(event):
var key_event = event as InputEventKey
if key_event and not key_event.pressed:
if key_event.keycode == KEY_0:
func _input(event: InputEvent) -> void:
if event is InputEventKey and not event.pressed:
if event.keycode == KEY_0:
await _on_option_selected(OPTION_TEST_CASE_ALL)
if key_event.keycode == KEY_1:
if event.keycode == KEY_1:
await _on_option_selected(OPTION_OBJECT_TYPE_RIGIDBODY)
elif key_event.keycode == KEY_2:
elif event.keycode == KEY_2:
await _on_option_selected(OPTION_OBJECT_TYPE_CHARACTER)
func _exit_tree():
func _exit_tree() -> void:
if not Engine.is_editor_hint():
_rigid_body_template.free()
_character_body_template.free()
_platform_template.free()
func _update_platform_size(value, reset = true):
func _update_platform_size(value: float, reset: bool = true) -> void:
if _lock_controls:
return
if value == _platform_size:
@@ -153,11 +151,11 @@ func _update_platform_size(value, reset = true):
if Engine.is_editor_hint():
$OneWayStaticBody2D/CollisionShape2D.shape.size.x = value
else:
var platform_collision = _platform_template.get_child(0)
var platform_collision := _platform_template.get_child(0)
platform_collision.shape.size.x = value
if _platform_body:
# Bug: need to re-add when changing shape.
var child_index = _platform_body.get_index()
var child_index := _platform_body.get_index()
remove_child(_platform_body)
add_child(_platform_body)
move_child(_platform_body, child_index)
@@ -165,7 +163,7 @@ func _update_platform_size(value, reset = true):
await _reset_test()
func _update_platform_angle(value, reset = true):
func _update_platform_angle(value: float, reset: bool = true) -> void:
if _lock_controls:
return
if value == _platform_angle:
@@ -182,7 +180,7 @@ func _update_platform_angle(value, reset = true):
await _reset_test()
func _update_rigidbody_angle(value, reset = true):
func _update_rigidbody_angle(value: float, reset: bool = true) -> void:
if _lock_controls:
return
if value == _body_angle:
@@ -201,7 +199,7 @@ func _update_rigidbody_angle(value, reset = true):
await _reset_test()
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
match option:
OPTION_OBJECT_TYPE_CHARACTER:
_use_character_body = true
@@ -231,7 +229,7 @@ func _on_option_selected(option):
await _test_moving_platform()
func _start_test_case(option):
func _start_test_case(option: String) -> void:
Log.print_log("* Starting " + option)
await _on_option_selected(option)
@@ -239,13 +237,13 @@ func _start_test_case(option):
await all_tests_done
func _wait_for_test():
func _wait_for_test() -> void:
await _reset_test()
await test_done
func _test_all_rigid_body():
func _test_all_rigid_body() -> void:
Log.print_log("* All RigidBody test cases...")
await _update_platform_size(128.0, false)
@@ -271,7 +269,7 @@ func _test_all_rigid_body():
return
func _test_all_character_body():
func _test_all_character_body() -> void:
Log.print_log("* All CharacterBody test cases...")
await _update_platform_size(128.0, false)
@@ -297,7 +295,7 @@ func _test_all_character_body():
return
func _test_moving_platform():
func _test_moving_platform() -> void:
Log.print_log("* Start moving platform tests")
Log.print_log("* Platform moving away from body...")
@@ -334,7 +332,7 @@ func _test_moving_platform():
all_tests_done.emit()
func _test_all():
func _test_all() -> void:
Log.print_log("* TESTING ALL...")
await _test_all_rigid_body()
@@ -348,10 +346,10 @@ func _test_all():
Log.print_log("* Done.")
func _start_test():
var test_label = "Testing: "
func _start_test() -> void:
var test_label := "Testing: "
var platform_angle = _platform_template.rotation
var platform_angle := _platform_template.rotation
if _platform_body:
platform_angle = _platform_body.rotation
_platform_body.remove_child(_target_area)
@@ -377,9 +375,9 @@ func _start_test():
add_child(_moving_body)
if _platform_speed != 0.0:
var platform_pos = _platform_body.global_position
var body_pos = _moving_body.global_position
var dir = (platform_pos - body_pos).normalized()
var platform_pos := _platform_body.global_position
var body_pos := _moving_body.global_position
var dir := (platform_pos - body_pos).normalized()
_platform_velocity = dir * _platform_speed
else:
_platform_velocity = Vector2.ZERO
@@ -400,7 +398,7 @@ func _start_test():
$LabelResult.self_modulate = Color.WHITE
func _reset_test(cancel_test = true):
func _reset_test(cancel_test: bool = true) -> void:
_test_canceled = true
await _on_timeout()
_test_canceled = false
@@ -422,14 +420,14 @@ func _reset_test(cancel_test = true):
_next_test(true)
func _next_test(force_start = false):
func _next_test(force_start: bool = false) -> void:
if _moving_body:
remove_child(_moving_body)
_moving_body.queue_free()
_moving_body = null
if _test_all_angles:
var angle = rad_to_deg(_platform_body.rotation)
var angle := rad_to_deg(_platform_body.rotation)
if angle >= _platform_angle + TEST_ALL_ANGLES_MAX:
_platform_body.rotation = deg_to_rad(_platform_angle)
_lock_controls = true
@@ -448,7 +446,7 @@ func _next_test(force_start = false):
_start_test()
func _on_contact_detected(_body):
func _on_contact_detected(_body: PhysicsBody2D) -> void:
if _contact_detected or _target_entered:
return
@@ -458,7 +456,7 @@ func _on_contact_detected(_body):
await _on_timeout()
func _on_target_entered(_body):
func _on_target_entered(_body: PhysicsBody2D) -> void:
if _body != _moving_body:
return
@@ -471,14 +469,14 @@ func _on_target_entered(_body):
await _on_timeout()
func _should_collide():
var platform_rotation = round(rad_to_deg(_platform_body.rotation))
func _should_collide() -> bool:
var platform_rotation := roundf(rad_to_deg(_platform_body.rotation))
var angle = fposmod(platform_rotation, 360)
var angle := fposmod(platform_rotation, 360)
return angle > 180
func _on_timeout():
func _on_timeout() -> void:
cancel_timer()
if $Timer.is_stopped():
@@ -501,7 +499,7 @@ func _on_timeout():
all_tests_done.emit()
return
var was_all_angles = _test_all_angles
var was_all_angles := _test_all_angles
_next_test()
@@ -511,8 +509,8 @@ func _on_timeout():
all_tests_done.emit()
func _set_result():
var result = ""
func _set_result() -> void:
var result := ""
if _test_passed:
result = "PASSED"
$LabelResult.self_modulate = Color.GREEN
@@ -522,7 +520,7 @@ func _set_result():
$LabelResult.text = result
var platform_angle = rad_to_deg(_platform_body.rotation)
var platform_angle := rad_to_deg(_platform_body.rotation)
result += ": size=%.1f, angle=%.1f, body angle=%.1f" % [_platform_size, platform_angle, _body_angle]
Log.print_log("Test %s" % result)

View File

@@ -1,35 +1,33 @@
extends Test
@export_range(1, 100) var height := 10
@export var box_size := Vector2(40.0, 40.0)
@export var box_spacing := Vector2(0.0, 0.0)
@export_range(1, 100) var height = 10
@export var box_size = Vector2(40.0, 40.0)
@export var box_spacing = Vector2(0.0, 0.0)
func _ready():
func _ready() -> void:
_create_pyramid()
func _create_pyramid():
var root_node = $Pyramid
func _create_pyramid() -> void:
var root_node: Node2D = $Pyramid
var template_body = create_rigidbody_box(box_size, true)
var template_body := create_rigidbody_box(box_size, true)
var pos_y = -0.5 * box_size.y - box_spacing.y
var pos_y := -0.5 * box_size.y - box_spacing.y
for level in height:
var level_index = height - level - 1
var num_boxes = 2 * level_index + 1
var level_index := height - level - 1
var num_boxes := 2 * level_index + 1
var row_node = Node2D.new()
var row_node := Node2D.new()
row_node.position = Vector2(0.0, pos_y)
row_node.name = "Row%02d" % (level + 1)
root_node.add_child(row_node)
var pos_x = -0.5 * (num_boxes - 1) * (box_size.x + box_spacing.x)
var pos_x := -0.5 * (num_boxes - 1) * (box_size.x + box_spacing.x)
for box_index in range(num_boxes):
var box = template_body.duplicate()
for box_index in num_boxes:
var box := template_body.duplicate()
box.position = Vector2(pos_x, 0.0)
box.name = "Box%02d" % (box_index + 1)
row_node.add_child(box)

View File

@@ -4,9 +4,9 @@
[ext_resource type="PackedScene" uid="uid://cx2q80okt25o1" path="res://tests/static_scene_flat.tscn" id="2"]
[node name="Test" type="Node2D"]
script = ExtResource( "1" )
script = ExtResource("1")
[node name="Pyramid" type="Node2D" parent="."]
position = Vector2(512, 500)
[node name="StaticSceneFlat" parent="." instance=ExtResource( "2" )]
[node name="StaticSceneFlat" parent="." instance=ExtResource("2")]

View File

@@ -1,14 +1,12 @@
extends Test
const OPTION_TEST_CASE_HIT_FROM_INSIDE = "Test case/Hit from inside"
var _hit_from_inside = false
var _do_raycasts = false
var _hit_from_inside := false
var _do_raycasts := false
func _ready():
var options = $Options
func _ready() -> void:
var options: OptionMenu = $Options
options.add_menu_item(OPTION_TEST_CASE_HIT_FROM_INSIDE, true, false)
@@ -21,7 +19,7 @@ func _ready():
_do_raycasts = true
func _physics_process(delta):
func _physics_process(delta: float) -> void:
super._physics_process(delta)
if not _do_raycasts:
@@ -34,16 +32,16 @@ func _physics_process(delta):
clear_drawn_nodes()
for node in $Shapes.get_children():
var body = node as PhysicsBody2D
var space_state = body.get_world_2d().direct_space_state
var body_name = String(body.name).substr("RigidBody".length())
var body: PhysicsBody2D = node
var space_state := body.get_world_2d().direct_space_state
var body_name := String(body.name).substr("RigidBody".length())
Log.print_log("* Testing: %s" % body_name)
var center = body.position
var center := body.position
# Raycast entering from the top.
var res = _add_raycast(space_state, center - Vector2(0, 100), center)
var res: Dictionary = _add_raycast(space_state, center - Vector2(0, 100), center)
Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT"))
# Raycast exiting from inside.
@@ -63,25 +61,23 @@ func _physics_process(delta):
Log.print_log("Raycast inside face: %s" % ("HIT" if res else "NO HIT"))
func _on_option_changed(option, checked):
func _on_option_changed(option: String, checked: bool) -> void:
match option:
OPTION_TEST_CASE_HIT_FROM_INSIDE:
_hit_from_inside = checked
_do_raycasts = true
func _add_raycast(space_state, pos_start, pos_end):
var params = PhysicsRayQueryParameters2D.new()
func _add_raycast(space_state: PhysicsDirectSpaceState2D, pos_start: Vector2, pos_end: Vector2) -> Dictionary:
var params := PhysicsRayQueryParameters2D.new()
params.from = pos_start
params.to = pos_end
params.hit_from_inside = _hit_from_inside
var result = space_state.intersect_ray(params)
var color
var result: Dictionary = space_state.intersect_ray(params)
var color := Color.RED.darkened(0.5)
if result:
color = Color.GREEN.darkened(0.2)
else:
color = Color.RED.darkened(0.5)
# Draw raycast line.
add_line(pos_start, pos_end, color)
@@ -91,8 +87,8 @@ func _add_raycast(space_state, pos_start, pos_end):
add_line(pos_end, pos_end + Vector2(5, -10), color)
if result:
# Draw raycast hit pos.
var hit_pos = result.position
# Draw raycast hit position.
var hit_pos: Vector2 = result.position
add_circle(hit_pos, 4.0, Color.YELLOW)
# Draw raycast hit normal.

View File

@@ -1,33 +1,31 @@
extends Test
@export var height := 10
@export var width := 1
@export var box_size := Vector2(40.0, 40.0)
@export var box_spacing := Vector2(0.0, 0.0)
@export var height = 10
@export var width = 1
@export var box_size = Vector2(40.0, 40.0)
@export var box_spacing = Vector2(0.0, 0.0)
func _ready():
func _ready() -> void:
_create_stack()
func _create_stack():
var root_node = $Stack
func _create_stack() -> void:
var root_node := $Stack
var template_body = create_rigidbody_box(box_size, true)
var template_body := create_rigidbody_box(box_size, true)
var pos_y = -0.5 * box_size.y - box_spacing.y
var pos_y := -0.5 * box_size.y - box_spacing.y
for level in height:
var row_node = Node2D.new()
for level: int in height:
var row_node := Node2D.new()
row_node.position = Vector2(0.0, pos_y)
row_node.name = "Row%02d" % (level + 1)
root_node.add_child(row_node)
var pos_x = -0.5 * (width - 1) * (box_size.x + box_spacing.x)
var pos_x := -0.5 * (width - 1) * (box_size.x + box_spacing.x)
for box_index in range(width):
var box = template_body.duplicate()
for box_index in width:
var box := template_body.duplicate()
box.position = Vector2(pos_x, 0.0)
box.name = "Box%02d" % (box_index + 1)
row_node.add_child(box)

View File

@@ -1,20 +1,18 @@
extends Test
const BOX_SIZE = Vector2(40, 40)
const BOX_SPACE = Vector2(50, 50)
@export_range(1, 1000) var row_size = 100
@export_range(1, 1000) var column_size = 100
@export_range(1, 1000) var row_size := 100
@export_range(1, 1000) var column_size := 100
var _objects = []
var _objects: Array[Node2D] = []
var _log_physics = false
var _log_physics_time = 0
var _log_physics_time_start = 0
var _log_physics := false
var _log_physics_time := 0
var _log_physics_time_start := 0
func _ready():
func _ready() -> void:
await start_timer(1.0).timeout
if is_timer_canceled():
return
@@ -66,46 +64,46 @@ func _ready():
Log.print_log("* Done.")
func _exit_tree():
func _exit_tree() -> void:
for object in _objects:
object.free()
func _physics_process(delta):
func _physics_process(delta: float) -> void:
super._physics_process(delta)
if _log_physics:
var time = Time.get_ticks_usec()
var time_delta = time - _log_physics_time
var time_total = time - _log_physics_time_start
var time := Time.get_ticks_usec()
var time_delta := time - _log_physics_time
var time_total := time - _log_physics_time_start
_log_physics_time = time
Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total])
func _log_physics_start():
func _log_physics_start() -> void:
_log_physics = true
_log_physics_time_start = Time.get_ticks_usec()
_log_physics_time = _log_physics_time_start
func _log_physics_stop():
func _log_physics_stop() -> void:
_log_physics = false
func _create_objects():
func _create_objects() -> void:
_objects.clear()
Log.print_log("* Creating objects...")
var timer = Time.get_ticks_usec()
var timer := Time.get_ticks_usec()
var pos_x = -0.5 * (row_size - 1) * BOX_SPACE.x
var pos_x := -0.5 * (row_size - 1) * BOX_SPACE.x
for row in row_size:
var pos_y = -0.5 * (column_size - 1) * BOX_SPACE.y
var pos_y := -0.5 * (column_size - 1) * BOX_SPACE.y
for column in column_size:
# Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape.
var box = create_rigidbody_box(BOX_SIZE)
var box := create_rigidbody_box(BOX_SIZE)
box.gravity_scale = 0.0
box.position = Vector2(pos_x, pos_y)
_objects.push_back(box)
@@ -118,11 +116,11 @@ func _create_objects():
Log.print_log(" Create Time: %.3f ms" % (0.001 * timer))
func _add_objects():
var root_node = $Objects
func _add_objects() -> void:
var root_node: Node2D = $Objects
Log.print_log("* Adding objects...")
var timer = Time.get_ticks_usec()
var timer := Time.get_ticks_usec()
for object in _objects:
root_node.add_child(object)
@@ -131,9 +129,9 @@ func _add_objects():
Log.print_log(" Add Time: %.3f ms" % (0.001 * timer))
func _move_objects():
func _move_objects() -> void:
Log.print_log("* Moving objects...")
var timer = Time.get_ticks_usec()
var timer := Time.get_ticks_usec()
for object in _objects:
object.position += BOX_SPACE
@@ -142,15 +140,15 @@ func _move_objects():
Log.print_log(" Move Time: %.3f ms" % (0.001 * timer))
func _remove_objects():
var root_node = $Objects
func _remove_objects() -> void:
var root_node: Node2D = $Objects
Log.print_log("* Removing objects...")
var timer = Time.get_ticks_usec()
var timer := Time.get_ticks_usec()
# Remove objects in reversed order to avoid the overhead of changing children index in parent.
var object_count = _objects.size()
for object_index in range(object_count):
var object_count := _objects.size()
for object_index in object_count:
root_node.remove_child(_objects[object_count - object_index - 1])
timer = Time.get_ticks_usec() - timer

View File

@@ -3,10 +3,10 @@
[ext_resource type="Script" path="res://tests/performance/test_perf_broadphase.gd" id="1"]
[node name="Test" type="Node2D"]
script = ExtResource( "1" )
_enable_debug_collision = false
script = ExtResource("1")
row_size = 300
column_size = 300
_enable_debug_collision = false
[node name="Objects" type="Node2D" parent="."]
position = Vector2(512, 300)

View File

@@ -1,6 +1,5 @@
extends Test
const OPTION_TYPE_ALL = "Shape type/All"
const OPTION_TYPE_RECTANGLE = "Shape type/Rectangle"
const OPTION_TYPE_SPHERE = "Shape type/Sphere"
@@ -8,27 +7,27 @@ const OPTION_TYPE_CAPSULE = "Shape type/Capsule"
const OPTION_TYPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
const OPTION_TYPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
@export var spawns = []
@export var spawn_count = 100
@export var spawn_randomize = Vector2.ZERO
@export var spawns: Array[NodePath] = []
@export var spawn_count := 100
@export var spawn_randomize := Vector2.ZERO
@onready var options = $Options
@onready var options: OptionMenu = $Options
var _object_templates = []
var _object_templates: Array[Node2D] = []
var _log_physics = false
var _log_physics_time = 0
var _log_physics_time_start = 0
var _log_physics := false
var _log_physics_time := 0
var _log_physics_time_start := 0
func _ready():
func _ready() -> void:
await start_timer(0.5).timeout
if is_timer_canceled():
return
var dynamic_shapes = $DynamicShapes
var dynamic_shapes: Node2D = $DynamicShapes
while dynamic_shapes.get_child_count():
var type_node = dynamic_shapes.get_child(0)
var type_node: RigidBody2D = dynamic_shapes.get_child(0)
type_node.position = Vector2.ZERO
_object_templates.push_back(type_node)
dynamic_shapes.remove_child(type_node)
@@ -44,33 +43,33 @@ func _ready():
await _start_all_types()
func _physics_process(delta):
func _physics_process(delta: float) -> void:
super._physics_process(delta)
if _log_physics:
var time = Time.get_ticks_usec()
var time_delta = time - _log_physics_time
var time_total = time - _log_physics_time_start
var time := Time.get_ticks_usec()
var time_delta := time - _log_physics_time
var time_total := time - _log_physics_time_start
_log_physics_time = time
Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total])
func _log_physics_start():
func _log_physics_start() -> void:
_log_physics = true
_log_physics_time_start = Time.get_ticks_usec()
_log_physics_time = _log_physics_time_start
func _log_physics_stop():
func _log_physics_stop() -> void:
_log_physics = false
func _exit_tree():
func _exit_tree() -> void:
for object_template in _object_templates:
object_template.free()
func _on_option_selected(option):
func _on_option_selected(option: String) -> void:
cancel_timer()
_despawn_objects()
@@ -90,9 +89,9 @@ func _on_option_selected(option):
await _start_type(_find_type_index("ConcavePolygon"))
func _find_type_index(type_name):
func _find_type_index(type_name: String) -> int:
for type_index in range(_object_templates.size()):
var type_node = _object_templates[type_index]
var type_node := _object_templates[type_index]
if String(type_node.name).find(type_name) > -1:
return type_index
@@ -100,7 +99,7 @@ func _find_type_index(type_name):
return -1
func _start_type(type_index):
func _start_type(type_index: int) -> void:
if type_index < 0:
return
if type_index >= _object_templates.size():
@@ -142,7 +141,7 @@ func _start_type(type_index):
await start_timer(1.0).timeout
func _start_all_types():
func _start_all_types() -> void:
Log.print_log("* Start all types.")
for type_index in range(_object_templates.size()):
@@ -153,25 +152,25 @@ func _start_all_types():
Log.print_log("* Done all types.")
func _spawn_objects(type_index):
var template_node = _object_templates[type_index]
func _spawn_objects(type_index: int) -> void:
var template_node: RigidBody2D = _object_templates[type_index]
Log.print_log("* Spawning: " + String(template_node.name))
for spawn in spawns:
var spawn_parent = get_node(spawn)
var spawn_parent := get_node(spawn)
for _node_index in range(spawn_count):
# Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape.
var collision = template_node.get_child(0).duplicate()
var collision: Node2D = template_node.get_child(0).duplicate()
if collision is CollisionShape2D:
collision.shape = collision.shape.duplicate()
var body = template_node.duplicate()
var body: Node2D = template_node.duplicate()
body.transform = Transform2D.IDENTITY
if spawn_randomize != Vector2.ZERO:
body.position.x = randf() * spawn_randomize.x
body.position.y = randf() * spawn_randomize.y
var prev_collision = body.get_child(0)
var prev_collision: Node2D = body.get_child(0)
body.remove_child(prev_collision)
prev_collision.queue_free()
body.add_child(collision)
@@ -179,29 +178,29 @@ func _spawn_objects(type_index):
spawn_parent.add_child(body)
func _activate_objects():
func _activate_objects() -> void:
Log.print_log("* Activating")
for spawn in spawns:
var spawn_parent = get_node(spawn)
var spawn_parent := get_node(spawn)
for node_index in range(spawn_parent.get_child_count()):
var node = spawn_parent.get_child(node_index) as RigidBody2D
for node_index in spawn_parent.get_child_count():
var node := spawn_parent.get_child(node_index) as RigidBody2D
node.set_sleeping(false)
func _despawn_objects():
func _despawn_objects() -> void:
Log.print_log("* Despawning")
for spawn in spawns:
var spawn_parent = get_node(spawn)
var spawn_parent: Node2D = get_node(spawn)
var object_count = spawn_parent.get_child_count()
var object_count := spawn_parent.get_child_count()
if object_count == 0:
continue
# Remove objects in reversed order to avoid the overhead of changing children index in parent.
for object_index in range(object_count):
var node = spawn_parent.get_child(object_count - object_index - 1)
var node: Node2D = spawn_parent.get_child(object_count - object_index - 1)
spawn_parent.remove_child(node)
node.queue_free()

View File

@@ -15,41 +15,41 @@ radius = 15.0
height = 35.0
[node name="Test" type="Node2D"]
script = ExtResource( "2" )
_enable_debug_collision = false
spawns = [NodePath("SpawnTarget1")]
script = ExtResource("2")
spawns = Array[NodePath]([NodePath("SpawnTarget1")])
spawn_count = 500
spawn_randomize = Vector2(10, 10)
_enable_debug_collision = false
[node name="Options" parent="." instance=ExtResource( "4" )]
[node name="Options" parent="." instance=ExtResource("4")]
[node name="SpawnTarget1" type="Node2D" parent="."]
position = Vector2(512, 400)
[node name="StaticScene" parent="." instance=ExtResource( "1" )]
[node name="StaticScene" parent="." instance=ExtResource("1")]
position = Vector2(0, 125.017)
[node name="DynamicShapes" type="Node2D" parent="."]
[node name="RigidBodyRectangle" type="RigidDynamicBody2D" parent="DynamicShapes"]
[node name="RigidBodyRectangle" type="RigidBody2D" parent="DynamicShapes"]
position = Vector2(0, 1024)
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyRectangle"]
shape = SubResource( "1" )
shape = SubResource("1")
[node name="RigidBodySphere" type="RigidDynamicBody2D" parent="DynamicShapes"]
[node name="RigidBodySphere" type="RigidBody2D" parent="DynamicShapes"]
position = Vector2(100, 1024)
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodySphere"]
shape = SubResource( "2" )
shape = SubResource("2")
[node name="RigidBodyCapsule" type="RigidDynamicBody2D" parent="DynamicShapes"]
[node name="RigidBodyCapsule" type="RigidBody2D" parent="DynamicShapes"]
position = Vector2(200, 1024)
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyCapsule"]
shape = SubResource( "3" )
shape = SubResource("3")
[node name="RigidBodyConvexPolygon" type="RigidDynamicBody2D" parent="DynamicShapes"]
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"]
position = Vector2(300, 1024)
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConvexPolygon"]
@@ -59,9 +59,9 @@ polygon = PackedVector2Array(10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806,
[node name="GodotIcon" type="Sprite2D" parent="DynamicShapes/RigidBodyConvexPolygon"]
self_modulate = Color(1, 1, 1, 0.392157)
scale = Vector2(0.25, 0.25)
texture = ExtResource( "3" )
texture = ExtResource("3")
[node name="RigidBodyConcavePolygon" type="RigidDynamicBody2D" parent="DynamicShapes"]
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"]
position = Vector2(400, 1024)
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConcavePolygon"]
@@ -71,4 +71,4 @@ polygon = PackedVector2Array(-5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.
[node name="GodotIcon" type="Sprite2D" parent="DynamicShapes/RigidBodyConcavePolygon"]
self_modulate = Color(1, 1, 1, 0.392157)
scale = Vector2(0.25, 0.25)
texture = ExtResource( "3" )
texture = ExtResource("3")

View File

@@ -2,28 +2,27 @@ extends OptionMenu
class TestData:
var id
var scene_path
var id := ""
var scene_path := ""
var _test_list = []
var _test_list := []
var _current_test = null
var _current_test: TestData = null
var _current_test_scene: Node = null
func _ready():
func _ready() -> void:
option_selected.connect(_on_option_selected)
func _process(_delta):
func _process(_delta: float) -> void:
if Input.is_action_just_pressed(&"restart_test"):
if _current_test:
_start_test(_current_test)
func add_test(id, scene_path):
var test_data = TestData.new()
func add_test(id: String, scene_path: String) -> void:
var test_data := TestData.new()
test_data.id = id
test_data.scene_path = scene_path
_test_list.append(test_data)
@@ -31,13 +30,13 @@ func add_test(id, scene_path):
add_menu_item(id)
func _on_option_selected(item_path):
for test in _test_list:
func _on_option_selected(item_path: String) -> void:
for test: TestData in _test_list:
if test.id == item_path:
_start_test(test)
func _start_test(test):
func _start_test(test: TestData) -> void:
_current_test = test
if _current_test_scene:
@@ -45,10 +44,10 @@ func _start_test(test):
_current_test_scene = null
Log.print_log("*** STARTING TEST: " + test.id)
var scene = load(test.scene_path)
var scene := load(test.scene_path)
_current_test_scene = scene.instantiate()
get_tree().root.add_child(_current_test_scene)
get_tree().root.move_child(_current_test_scene, 0)
var label_test = get_node(^"../LabelTest")
var label_test: Label = $"../LabelTest"
label_test.test_name = test.id

View File

@@ -1,22 +1,21 @@
extends CharacterBody2D
var _initial_velocity = Vector2.ZERO
var _constant_velocity = Vector2.ZERO
var _motion_speed = 400.0
var _gravity_force = 50.0
var _jump_force = 1000.0
var _velocity = Vector2.ZERO
var _snap = 0.0
var _floor_max_angle = 45.0
var _stop_on_slope = false
var _move_on_floor_only = false
var _constant_speed = false
var _jumping = false
var _keep_velocity = false
var _initial_velocity := Vector2.ZERO
var _constant_velocity := Vector2.ZERO
var _motion_speed := 400.0
var _gravity_force := 50.0
var _jump_force := 1000.0
var _velocity := Vector2.ZERO
var _snap := 0.0
var _floor_max_angle := 45.0
var _stop_on_slope := false
var _move_on_floor_only := false
var _constant_speed := false
var _jumping := false
var _keep_velocity := false
func _physics_process(_delta):
func _physics_process(_delta: float) -> void:
if _initial_velocity != Vector2.ZERO:
_velocity = _initial_velocity
_initial_velocity = Vector2.ZERO

View File

@@ -1,31 +1,29 @@
extends Control
const MAX_ENTRIES = 100
var _entry_template
var _entry_template: Label
func _enter_tree():
func _enter_tree() -> void:
Log.entry_logged.connect(_on_log_entry)
_entry_template = get_child(0) as Label
_entry_template = get_child(0)
remove_child(_entry_template)
func _exit_tree():
func _exit_tree() -> void:
_entry_template.free()
func clear():
func clear() -> void:
while get_child_count():
var entry = get_child(get_child_count() - 1)
var entry := get_child(get_child_count() - 1)
remove_child(entry)
entry.queue_free()
func _on_log_entry(message, type):
var new_entry = _entry_template.duplicate() as Label
func _on_log_entry(message: String, type: Log.LogType) -> void:
var new_entry: Label = _entry_template.duplicate()
new_entry.set_text(message)
if type == Log.LogType.ERROR:
@@ -34,7 +32,7 @@ func _on_log_entry(message, type):
new_entry.modulate = Color.WHITE
if get_child_count() >= MAX_ENTRIES:
var first_entry = get_child(0) as Label
var first_entry: Label = get_child(0)
remove_child(first_entry)
first_entry.queue_free()

View File

@@ -1,12 +1,13 @@
extends Label
func _ready() -> void:
var engine_name := ""
func _process(_delta):
var engine_name = ""
match System.get_physics_engine():
System.PhysicsEngine.GODOT_PHYSICS:
engine_name = "GodotPhysics 2D"
System.PhysicsEngine.OTHER:
var engine_setting = ProjectSettings.get_setting("physics/2d/physics_engine")
var engine_setting := String(ProjectSettings.get_setting("physics/2d/physics_engine"))
engine_name = "Other (%s)" % engine_setting
set_text("Physics engine: %s" % engine_name)
text = "Physics engine: %s" % engine_name

View File

@@ -1,5 +1,4 @@
extends Label
func _process(_delta):
set_text("FPS: %d" % Engine.get_frames_per_second())
func _process(_delta: float) -> void:
text = "%d FPS (%.2f mspf)" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()]

View File

@@ -1,5 +1,5 @@
extends Label
func _process(_delta):
func _process(_delta: float) -> void:
visible = get_tree().paused

View File

@@ -2,6 +2,6 @@
extends Label
func _process(_delta):
var slider = get_node(^"../HSlider")
func _process(_delta: float) -> void:
var slider: HSlider = get_node(^"../HSlider")
text = "%.1f" % slider.value

View File

@@ -1,7 +1,6 @@
extends Label
var test_name = "":
var test_name := "":
set(value):
if (test_name != value):
return
@@ -9,5 +8,5 @@ var test_name = "":
set_text("Test: %s" % test_name)
func _ready():
func _ready() -> void:
set_text("Select a test from the menu to start it")

View File

@@ -1,5 +1,4 @@
extends Label
func _process(_delta):
set_text("Godot Version: %s" % Engine.get_version_info().string)
func _ready() -> void:
text = "Godot Version: %s" % Engine.get_version_info().string

View File

@@ -1,24 +1,23 @@
class_name OptionMenu
extends MenuButton
signal option_selected(item_path)
signal option_changed(item_path, checked)
signal option_selected(item_path: String)
signal option_changed(item_path: String, checked: bool)
func add_menu_item(item_path, checkbox = false, checked = false, radio = false):
var path_elements = item_path.split("/", false)
var path_element_count = path_elements.size()
func add_menu_item(item_path: String, checkbox: bool = false, checked: bool = false, radio: bool = false) -> void:
var path_elements := item_path.split("/", false)
var path_element_count := path_elements.size()
assert(path_element_count > 0)
var path = ""
var popup = get_popup()
var path := ""
var popup := get_popup()
for element_index in range(path_element_count - 1):
var popup_label = path_elements[element_index]
var popup_label := path_elements[element_index]
path += popup_label + "/"
popup = _add_popup(popup, path, popup_label)
var label = path_elements[path_element_count - 1]
var label := path_elements[path_element_count - 1]
if radio:
popup.add_radio_check_item(label)
popup.set_item_checked(popup.get_item_count() - 1, checked)
@@ -29,18 +28,18 @@ func add_menu_item(item_path, checkbox = false, checked = false, radio = false):
popup.add_item(label)
func _add_item(parent_popup, label):
func _add_item(parent_popup: PopupMenu, label: String) -> void:
parent_popup.add_item(label)
func _add_popup(parent_popup, path, label):
func _add_popup(parent_popup: PopupMenu, path: String, label: String) -> PopupMenu:
if parent_popup.has_node(label):
var popup_node = parent_popup.get_node(label)
var popup_menu = popup_node as PopupMenu
assert(popup_menu)
return popup_menu
var popup_node := parent_popup.get_node(label)
var new_popup_menu: PopupMenu = popup_node
assert(new_popup_menu)
return new_popup_menu
var popup_menu = PopupMenu.new()
var popup_menu := PopupMenu.new()
popup_menu.name = label
popup_menu.hide_on_checkable_item_selection = false
@@ -52,11 +51,11 @@ func _add_popup(parent_popup, path, label):
return popup_menu
func _on_item_pressed(item_index, popup_menu, path):
var item_path = path + popup_menu.get_item_text(item_index)
func _on_item_pressed(item_index: int, popup_menu: PopupMenu, path: String) -> void:
var item_path := path + popup_menu.get_item_text(item_index)
if popup_menu.is_item_radio_checkable(item_index):
var checked = popup_menu.is_item_checked(item_index)
var checked := popup_menu.is_item_checked(item_index)
if not checked:
popup_menu.set_item_checked(item_index, true)
for other_index in range(popup_menu.get_item_count()):
@@ -64,7 +63,7 @@ func _on_item_pressed(item_index, popup_menu, path):
popup_menu.set_item_checked(other_index, false)
option_selected.emit(item_path)
elif popup_menu.is_item_checkable(item_index):
var checked = not popup_menu.is_item_checked(item_index)
var checked := not popup_menu.is_item_checked(item_index)
popup_menu.set_item_checked(item_index, checked)
option_changed.emit(item_path, checked)
else:

View File

@@ -1,22 +1,21 @@
extends RigidBody2D
var _initial_velocity := Vector2.ZERO
var _constant_velocity := Vector2.ZERO
var _motion_speed := 400.0
var _gravity_force := 50.0
var _jump_force := 1000.0
var _velocity := Vector2.ZERO
var _floor_max_angle := 45.0
var _on_floor := false
var _jumping := false
var _keep_velocity := false
var _initial_velocity = Vector2.ZERO
var _constant_velocity = Vector2.ZERO
var _motion_speed = 400.0
var _gravity_force = 50.0
var _jump_force = 1000.0
var _velocity = Vector2.ZERO
var _floor_max_angle = 45.0
var _on_floor = false
var _jumping = false
var _keep_velocity = false
func _ready():
func _ready() -> void:
gravity_scale = 0.0
func _physics_process(_delta):
func _physics_process(_delta: float) -> void:
if _initial_velocity != Vector2.ZERO:
_velocity = _initial_velocity
_initial_velocity = Vector2.ZERO
@@ -54,12 +53,12 @@ func _physics_process(_delta):
linear_velocity = _velocity
func _integrate_forces(state):
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
_on_floor = false
var contacts = state.get_contact_count()
var contacts := state.get_contact_count()
for i in contacts:
var normal = state.get_contact_local_normal(i)
var normal := state.get_contact_local_normal(i)
# Detect floor.
if acos(normal.dot(Vector2.UP)) <= deg_to_rad(_floor_max_angle) + 0.01:
@@ -70,5 +69,5 @@ func _integrate_forces(state):
_jumping = false
_velocity.y = 0.0
func is_on_floor():
func is_on_floor() -> bool:
return _on_floor

View File

@@ -1,30 +1,29 @@
extends RigidBody2D
var _picked = false
var _last_mouse_pos = Vector2.ZERO
var _picked := false
var _last_mouse_pos := Vector2.ZERO
func _ready():
func _ready() -> void:
input_pickable = true
func _input(event):
var mouse_event = event as InputEventMouseButton
func _input(event: InputEvent) -> void:
var mouse_event := event as InputEventMouseButton
if mouse_event and not mouse_event.pressed:
_picked = false
func _input_event(_viewport, event, _shape_idx):
var mouse_event = event as InputEventMouseButton
func _input_event(_viewport: Node, event: InputEvent, _shape_idx: int) -> void:
var mouse_event := event as InputEventMouseButton
if mouse_event and mouse_event.pressed:
_picked = true
_last_mouse_pos = get_global_mouse_position()
func _physics_process(delta):
func _physics_process(delta: float) -> void:
if _picked:
var mouse_pos = get_global_mouse_position()
var mouse_pos := get_global_mouse_position()
if freeze:
global_position = mouse_pos
else:

View File

@@ -1,24 +1,22 @@
extends ScrollContainer
@export var auto_scroll := false
@export var auto_scroll = false
func _ready():
var scrollbar = get_v_scroll_bar()
func _ready() -> void:
var scrollbar := get_v_scroll_bar()
scrollbar.scrolling.connect(_on_scrolling)
func _process(_delta):
func _process(_delta: float) -> void:
if auto_scroll:
var scrollbar = get_v_scroll_bar()
var scrollbar := get_v_scroll_bar()
scrollbar.value = scrollbar.max_value
func _on_scrolling():
func _on_scrolling() -> void:
auto_scroll = false
$"../CheckBoxScroll".button_pressed = false
func _on_check_box_scroll_toggled(button_pressed):
func _on_check_box_scroll_toggled(button_pressed: bool) -> void:
auto_scroll = button_pressed

View File

@@ -1,10 +1,10 @@
extends HSlider
@export var snap_step = 1.0
@export var snap_step := 1.0
func _process(_delta):
func _process(_delta: float) -> void:
if Input.is_key_pressed(KEY_SHIFT):
step = 0.1
else:

View File

@@ -1,20 +1,20 @@
extends Node
enum PhysicsEngine {
GODOT_PHYSICS,
OTHER,
}
var _engine = PhysicsEngine.OTHER
var _engine: PhysicsEngine = PhysicsEngine.OTHER
func _enter_tree():
func _enter_tree() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
# Always enable visible collision shapes on startup
# (same as the Debug > Visible Collision Shapes option).
get_tree().debug_collisions_hint = true
var engine_string = ProjectSettings.get_setting("physics/2d/physics_engine")
var engine_string:= String(ProjectSettings.get_setting("physics/2d/physics_engine"))
match engine_string:
"DEFAULT":
_engine = PhysicsEngine.GODOT_PHYSICS
@@ -24,7 +24,7 @@ func _enter_tree():
_engine = PhysicsEngine.OTHER
func _process(_delta):
func _process(_delta: float) -> void:
if Input.is_action_just_pressed(&"toggle_full_screen"):
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
@@ -32,7 +32,7 @@ func _process(_delta):
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
if Input.is_action_just_pressed(&"toggle_debug_collision"):
var debug_collision_enabled = not _is_debug_collision_enabled()
var debug_collision_enabled := not _is_debug_collision_enabled()
_set_debug_collision_enabled(debug_collision_enabled)
if debug_collision_enabled:
Log.print_log("Debug Collision ON")
@@ -46,13 +46,13 @@ func _process(_delta):
get_tree().quit()
func get_physics_engine():
func get_physics_engine() -> PhysicsEngine:
return _engine
func _set_debug_collision_enabled(enabled):
func _set_debug_collision_enabled(enabled: bool) -> void:
get_tree().debug_collisions_hint = enabled
func _is_debug_collision_enabled():
func _is_debug_collision_enabled() -> bool:
return get_tree().debug_collisions_hint

View File

@@ -1,20 +1,18 @@
extends Node
enum LogType {
LOG,
ERROR,
}
signal entry_logged(message, type)
signal entry_logged(message: String, type: LogType)
func print_log(message):
func print_log(message: String) -> void:
print(message)
entry_logged.emit(message, LogType.LOG)
func print_error(message):
func print_error(message: String) -> void:
push_error(message)
printerr(message)
entry_logged.emit(message, LogType.ERROR)

View File

@@ -1,5 +1,5 @@
class_name Enemy extends CharacterBody2D
class_name Enemy
extends CharacterBody2D
enum State {
WALKING,

View File

@@ -1,4 +1,5 @@
class_name Game extends Node
class_name Game
extends Node
@onready var _pause_menu := $InterfaceLayer/PauseMenu as PauseMenu

View File

@@ -1,5 +1,5 @@
class_name CoinsCounter extends Panel
class_name CoinsCounter
extends Panel
var _coins_collected: int = 0

View File

@@ -1,4 +1,5 @@
class_name PauseMenu extends Control
class_name PauseMenu
extends Control
@export var fade_in_duration := 0.3

View File

@@ -1,4 +1,5 @@
class_name Coin extends Area2D
class_name Coin
extends Area2D
## Collectible that disappears when the player touches it.

View File

@@ -1,6 +1,5 @@
extends Node2D
const LIMIT_LEFT = -315
const LIMIT_TOP = -250
const LIMIT_RIGHT = 955

View File

@@ -1,4 +1,5 @@
class_name Bullet extends RigidBody2D
class_name Bullet
extends RigidBody2D
@onready var animation_player := $AnimationPlayer as AnimationPlayer

Some files were not shown because too many files have changed in this diff Show More