视野锥

二十八条射线朝鼠标呈扇形展开。碰到墙的那条会变红,这就是最简单形式的视线判断。

上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。

用到的 Godot 类

RayCast2DLine2DStaticBody2D

代码

scripts/main.gd
extends Node

const RAYS: int = 28
const SPREAD: float = 1.0
const LENGTH: float = 560.0
const CLEAR_COLOR: Color = Color(0.55, 0.65, 0.95, 0.35)
const HIT_COLOR: Color = Color(0.98, 0.5, 0.5, 0.9)

var origin: Vector2
var rays: Array[RayCast2D] = []
var lines: Array[Line2D] = []


func _ready() -> void:
	_add_background()

	var view: Vector2 = get_viewport().get_visible_rect().size
	origin = Vector2(view.x * 0.5, view.y * 0.78)

	for at in [Vector2(view.x * 0.25, view.y * 0.4), Vector2(view.x * 0.6, view.y * 0.3), Vector2(view.x * 0.78, view.y * 0.55)]:
		_add_wall(at, Vector2(160, 40))

	for i in RAYS:
		var ray: RayCast2D = RayCast2D.new()
		ray.position = origin
		add_child(ray)
		rays.append(ray)

		var line: Line2D = Line2D.new()
		line.width = 2.0
		add_child(line)
		lines.append(line)

	add_child(_make_circle(origin, 16.0, Color('#8eef97')))

	print('the cone follows the mouse, a ray turns red where it hits a wall')


func _process(_delta: float) -> void:
	var aim: float = (get_viewport().get_mouse_position() - origin).angle()

	for i in RAYS:
		var angle: float = aim + (float(i) / (RAYS - 1) - 0.5) * SPREAD
		var direction: Vector2 = Vector2(cos(angle), sin(angle))

		rays[i].target_position = direction * LENGTH
		rays[i].force_raycast_update()

		var hit: bool = rays[i].is_colliding()
		var to: Vector2 = rays[i].get_collision_point() if hit else origin + direction * LENGTH

		lines[i].points = PackedVector2Array([origin, to])
		lines[i].default_color = HIT_COLOR if hit else CLEAR_COLOR


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 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('#2a2f3d')

	var wall: StaticBody2D = StaticBody2D.new()
	wall.position = center
	wall.add_child(rect)
	wall.add_child(collision)
	add_child(wall)


func _make_circle(at: Vector2, 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
	circle.position = at

	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)

更多物理示例