形状投射
一个方块在移动前先问自己会停在哪里。那个虚影就是投射返回的安全比例。
上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。
用到的 Godot 类
ShapeCast2DPolygon2DStaticBody2D
代码
scripts/main.gd
extends Node
const PROBE_SIZE: Vector2 = Vector2(70, 70)
const REACH: float = 420.0
var probe: Polygon2D
var ghost: Polygon2D
var cast: ShapeCast2D
var path: Line2D
var origin: Vector2
func _ready() -> void:
_add_background()
var view: Vector2 = get_viewport().get_visible_rect().size
origin = Vector2(view.x * 0.2, view.y * 0.5)
for at in [Vector2(view.x * 0.6, view.y * 0.35), Vector2(view.x * 0.75, view.y * 0.7)]:
_add_wall(at, Vector2(50, 260))
var shape: RectangleShape2D = RectangleShape2D.new()
shape.size = PROBE_SIZE
cast = ShapeCast2D.new()
cast.shape = shape
cast.position = origin
add_child(cast)
path = Line2D.new()
path.width = 2.0
path.default_color = Color(0.55, 0.65, 0.95, 0.3)
add_child(path)
ghost = _make_rect(PROBE_SIZE, Color(0.98, 0.5, 0.5, 0.35))
add_child(ghost)
probe = _make_rect(PROBE_SIZE, Color('#8da5f3'))
probe.position = origin
add_child(probe)
print('the ghost is where the box would stop, computed before moving')
func _physics_process(_delta: float) -> void:
var target: Vector2 = get_viewport().get_mouse_position()
var to: Vector2 = (target - origin).limit_length(REACH)
cast.target_position = to
cast.force_shapecast_update()
var fraction: float = cast.get_closest_collision_safe_fraction() if cast.is_colliding() else 1.0
ghost.position = origin + to * fraction
ghost.color = Color(0.98, 0.5, 0.5, 0.35) if cast.is_colliding() else Color(0.55, 0.94, 0.6, 0.25)
path.points = PackedVector2Array([origin, origin + to])
func _add_wall(center: Vector2, size: Vector2) -> void:
var shape: RectangleShape2D = RectangleShape2D.new()
shape.size = size
var collision: CollisionShape2D = CollisionShape2D.new()
collision.shape = shape
var wall: StaticBody2D = StaticBody2D.new()
wall.position = center
wall.add_child(_make_rect(size, Color('#2a2f3d')))
wall.add_child(collision)
add_child(wall)
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 _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)