Shape cast

Una caja que pregunta dónde se detendría antes de moverse. El fantasma es la fracción segura que devuelve el cast.

El editor de arriba está ejecutando este proyecto. Cambia una línea y se recarga.

Clases de Godot usadas

ShapeCast2DPolygon2DStaticBody2D

El código

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)

Más ejemplos de Física