Seguir e limitar
Uma Camera2D com suavização de posição e as quatro propriedades de limite. A cruz amarela é o centro da câmera, então dá para vê-la parar na borda enquanto o jogador continua andando.
O editor acima está rodando este projeto. Mude uma linha e ele recarrega.
Classes do Godot usadas
Camera2DLine2DPolygon2D
O código
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)