Impulso de clique

Uma parede de 54 caixas e um clique que as afasta, com a força caindo pela distância.

O editor acima está rodando este projeto. Mude uma linha e ele recarrega.

Classes do Godot usadas

RigidBody2DInputEventMouseButtonCollisionShape2D

O código

scripts/main.gd
extends Node

const BOX_SIZE: Vector2 = Vector2(44, 44)
const COLUMNS: int = 9
const ROWS: int = 6
const BLAST_RADIUS: float = 320.0
const BLAST_FORCE: float = 900.0

var boxes: Array[RigidBody2D] = []


func _ready() -> void:
	_add_background()

	var view: Vector2 = get_viewport().get_visible_rect().size

	_add_wall(Vector2(view.x * 0.5, view.y - 30), Vector2(view.x, 60))
	_add_wall(Vector2(20, view.y * 0.5), Vector2(40, view.y))
	_add_wall(Vector2(view.x - 20, view.y * 0.5), Vector2(40, view.y))

	var start: Vector2 = Vector2(view.x * 0.5 - COLUMNS * BOX_SIZE.x * 0.5, view.y - 90)

	for row in ROWS:
		for column in COLUMNS:
			boxes.append(_add_box(start + Vector2(column * (BOX_SIZE.x + 2), -row * (BOX_SIZE.y + 2))))

	print('click anywhere to push the stack, the force falls off with distance')


func _unhandled_input(event: InputEvent) -> void:
	if not (event is InputEventMouseButton and event.pressed):
		return

	var at: Vector2 = (event as InputEventMouseButton).position

	for box in boxes:
		if not is_instance_valid(box):
			continue

		var offset: Vector2 = box.position - at
		var distance: float = offset.length()

		if distance > BLAST_RADIUS:
			continue

		var falloff: float = 1.0 - distance / BLAST_RADIUS
		box.apply_impulse(offset.normalized() * BLAST_FORCE * falloff)


func _add_box(at: Vector2) -> RigidBody2D:
	var shape: RectangleShape2D = RectangleShape2D.new()
	shape.size = BOX_SIZE

	var collision: CollisionShape2D = CollisionShape2D.new()
	collision.shape = shape

	var box: RigidBody2D = RigidBody2D.new()
	box.position = at
	box.add_child(_make_rect(BOX_SIZE, Color.from_hsv(randf_range(0.5, 0.7), 0.4, 0.9)))
	box.add_child(collision)
	add_child(box)

	return box


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)
	# ColorRect defaults to MOUSE_FILTER_STOP and would eat the click before _unhandled_input
	background.mouse_filter = Control.MOUSE_FILTER_IGNORE
	background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)

Mais exemplos de Física