Suivi et limites

Une Camera2D avec lissage de position et les quatre propriétés de limite. La croix jaune est le centre de la caméra, on la voit donc s'arrêter au bord pendant que le joueur continue.

L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.

Classes Godot utilisées

Camera2DLine2DPolygon2D

Le code

scripts/main.gd
extends Node

const MAP: Vector2 = Vector2(2600, 1500)
const SPEED: float = 520.0

var player: Node2D
var camera: Camera2D
var crosshair: Node2D
var readout: Label
var angle: float = PI
var manual: bool = false


func _ready() -> void:
	_add_background()
	_add_map()

	player = _make_square(52.0, Color('#8eef97'))
	player.position = _orbit_point()
	add_child(player)

	camera = Camera2D.new()
	camera.position_smoothing_enabled = true
	camera.position_smoothing_speed = 4.0
	camera.limit_left = 0
	camera.limit_top = 0
	camera.limit_right = int(MAP.x)
	camera.limit_bottom = int(MAP.y)
	camera.limit_smoothed = true
	player.add_child(camera)
	camera.make_current()

	crosshair = _make_crosshair()
	add_child(crosshair)

	_add_hud()

	print('the green square walks the map on its own, arrows drive it, the camera stops at the border')


func _process(delta: float) -> void:
	var drive: Vector2 = Vector2(
		float(Input.is_key_pressed(KEY_RIGHT)) - float(Input.is_key_pressed(KEY_LEFT)),
		float(Input.is_key_pressed(KEY_DOWN)) - float(Input.is_key_pressed(KEY_UP))
	)

	if drive != Vector2.ZERO:
		manual = true

	if manual:
		player.position += drive.normalized() * SPEED * delta
		player.position = player.position.clamp(Vector2(60, 60), MAP - Vector2(60, 60))
	else:
		angle += delta * 0.6
		player.position = _orbit_point()

	var center: Vector2 = camera.get_screen_center_position()
	crosshair.position = center
	readout.text = 'player %d, %d      camera %d, %d' % [player.position.x, player.position.y, center.x, center.y]


func _orbit_point() -> Vector2:
	return MAP * 0.5 + Vector2(cos(angle) * MAP.x * 0.46, sin(angle) * MAP.y * 0.44)


func _add_map() -> void:
	var floor_rect: Polygon2D = Polygon2D.new()
	floor_rect.polygon = PackedVector2Array([Vector2.ZERO, Vector2(MAP.x, 0), MAP, Vector2(0, MAP.y)])
	floor_rect.color = Color('#12141a').lerp(Color('#2a2f3d'), 0.55)
	add_child(floor_rect)

	for x in range(200, int(MAP.x), 200):
		_add_line(Vector2(x, 0), Vector2(x, MAP.y), 2.0, Color('#2a2f3d'))

	for y in range(200, int(MAP.y), 200):
		_add_line(Vector2(0, y), Vector2(MAP.x, y), 2.0, Color('#2a2f3d'))

	var rng: RandomNumberGenerator = RandomNumberGenerator.new()
	rng.seed = 9

	for row in 4:
		for column in 6:
			var block: Node2D = _make_square(rng.randf_range(70, 140), Color('#8da5f3').lerp(Color('#12141a'), 0.35))
			block.position = Vector2(300 + column * 400, 260 + row * 340) + Vector2(rng.randf_range(-80, 80), rng.randf_range(-80, 80))
			add_child(block)

	var border: Line2D = Line2D.new()
	border.points = PackedVector2Array([Vector2(8, 8), Vector2(MAP.x - 8, 8), MAP - Vector2(8, 8), Vector2(8, MAP.y - 8), Vector2(8, 8)])
	border.width = 16.0
	border.default_color = Color('#fc7f7f')
	add_child(border)


func _add_line(from: Vector2, to: Vector2, width: float, color: Color) -> void:
	var line: Line2D = Line2D.new()
	line.points = PackedVector2Array([from, to])
	line.width = width
	line.default_color = color
	add_child(line)


func _make_square(size: float, color: Color) -> Node2D:
	var square: Polygon2D = Polygon2D.new()
	square.polygon = PackedVector2Array([Vector2(-size, -size) * 0.5, Vector2(size, -size) * 0.5, Vector2(size, size) * 0.5, Vector2(-size, size) * 0.5])
	square.color = color

	return square


func _make_crosshair() -> Node2D:
	var mark: Node2D = Node2D.new()

	for points in [PackedVector2Array([Vector2(-34, 0), Vector2(34, 0)]), PackedVector2Array([Vector2(0, -34), Vector2(0, 34)])]:
		var line: Line2D = Line2D.new()
		line.points = points
		line.width = 4.0
		line.default_color = Color('#f3d48d')
		mark.add_child(line)

	return mark


func _add_hud() -> void:
	var hud: CanvasLayer = CanvasLayer.new()
	add_child(hud)

	var title: Label = Label.new()
	title.text = 'green square: player          yellow cross: camera center'
	title.add_theme_font_size_override('font_size', 20)
	title.add_theme_color_override('font_color', Color('#8da5f3'))
	title.position = Vector2(40, 34)
	hud.add_child(title)

	readout = Label.new()
	readout.add_theme_font_size_override('font_size', 20)
	readout.add_theme_color_override('font_color', Color('#f3d48d'))
	readout.position = Vector2(40, 64)
	hud.add_child(readout)


func _add_background() -> void:
	var layer: CanvasLayer = CanvasLayer.new()
	layer.layer = -1
	add_child(layer)

	var background: ColorRect = ColorRect.new()
	background.color = Color('#12141a')
	layer.add_child(background)
	background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)

Plus d'exemples de Caméra