区域检测
一个统计有什么东西掉进来的区域,用的是 body_entered 和 body_exited 信号。
上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。
用到的 Godot 类
Area2DRigidBody2DLabel
代码
scripts/main.gd
extends Node
const ZONE_SIZE: Vector2 = Vector2(320, 220)
const BALL_RADIUS: float = 26.0
const IDLE_COLOR: Color = Color(0.55, 0.65, 0.95, 0.15)
const BUSY_COLOR: Color = Color(0.55, 0.94, 0.6, 0.35)
var zone_visual: Polygon2D
var counter: Label
var inside: int = 0
func _ready() -> void:
_add_background()
var view: Vector2 = get_viewport().get_visible_rect().size
var center: Vector2 = Vector2(view.x * 0.5, view.y * 0.62)
var shape: RectangleShape2D = RectangleShape2D.new()
shape.size = ZONE_SIZE
var collision: CollisionShape2D = CollisionShape2D.new()
collision.shape = shape
zone_visual = _make_rect(ZONE_SIZE, IDLE_COLOR)
var zone: Area2D = Area2D.new()
zone.position = center
zone.add_child(zone_visual)
zone.add_child(collision)
add_child(zone)
zone.body_entered.connect(_on_entered)
zone.body_exited.connect(_on_exited)
counter = Label.new()
counter.position = center + Vector2(-ZONE_SIZE.x * 0.5, -ZONE_SIZE.y * 0.5 - 30)
add_child(counter)
_update_label()
_spawn_loop(view)
func _spawn_loop(view: Vector2) -> void:
while is_inside_tree():
_add_ball(Vector2(randf_range(view.x * 0.3, view.x * 0.7), -40))
await get_tree().create_timer(0.7).timeout
func _on_entered(_body: Node) -> void:
inside += 1
zone_visual.color = BUSY_COLOR
_update_label()
func _on_exited(_body: Node) -> void:
inside = max(inside - 1, 0)
if inside <= 0:
zone_visual.color = IDLE_COLOR
_update_label()
func _update_label() -> void:
counter.text = 'bodies inside: %d' % inside
func _add_ball(at: Vector2) -> void:
var circle: CircleShape2D = CircleShape2D.new()
circle.radius = BALL_RADIUS
var collision: CollisionShape2D = CollisionShape2D.new()
collision.shape = circle
var ball: RigidBody2D = RigidBody2D.new()
ball.position = at
ball.add_child(_make_circle(BALL_RADIUS, Color('#fc7f7f')))
ball.add_child(collision)
add_child(ball)
await get_tree().create_timer(6.0).timeout
if is_instance_valid(ball):
ball.queue_free()
func _make_rect(size: Vector2, color: Color) -> Polygon2D:
var rect: Polygon2D = Polygon2D.new()
rect.polygon = PackedVector2Array([-size * 0.5, Vector2(size.x, -size.y) * 0.5, size * 0.5, Vector2(-size.x, size.y) * 0.5])
rect.color = color
return rect
func _make_circle(radius: float, color: Color) -> Polygon2D:
var points: PackedVector2Array = PackedVector2Array()
for i in 20:
points.append(Vector2(cos(TAU * i / 20.0), sin(TAU * i / 20.0)) * radius)
var circle: Polygon2D = Polygon2D.new()
circle.polygon = points
circle.color = color
return circle
func _add_background() -> void:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)