This code snippet enables a button to hit a 2D golf ball in a direction opposite the cursor. The code assumes a top-down view of the ball. It also has some other features:
- States for when the ball is moving and when it is ready to hit, so that it cannot be hit while it is still moving.
- Force limit so that excessive speeds will not cause the ball to clip through walls.
- Dynamic line to indicate where the ball is being hit from.
Node Setup
- RigidBody2D (Physics Material Override Bounce: 1, Linear Damp: 0.7)
- MeshInstance2D (Sphere mesh, radius: 20m, height: 40m)
- CollisionShape2D (CircleShape2D, radius: 20px)
- Line2D (Points array size: 2)
# ball.gd
extends RigidBody2D
enum BallState {READY, MOVING}
var state = BallState.READY
var force_multiplier = 10
var max_force = 2000
const stop_threshold = 7
func _physics_process(_delta):
ready_ball_if_stopped()
if Input.is_action_pressed("fire"):
draw_aim_line()
elif Input.is_action_just_released("fire"):
fire()
func ready_ball_if_stopped():
if (state == BallState.MOVING) and (linear_velocity.length() < stop_threshold):
linear_velocity = Vector2.ZERO
state = BallState.READY
func draw_aim_line():
if state == BallState.READY:
$Line2D.visible = true
$Line2D.set_point_position(0, Vector2.ZERO)
$Line2D.set_point_position(1, to_local(get_global_mouse_position()))
func fire():
if state == BallState.READY:
state = BallState.MOVING
$Line2D.visible = false
var direction = -(get_global_mouse_position() - position).normalized()
var force = min(global_position.distance_to(get_global_mouse_position()) * force_multiplier, max_force)
apply_central_impulse(direction * force)