Calculating Initial Velocity for a Ballistic Bullet

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Juxxec

I am making a 2D Badminton game. I have implemented a Shuttlecock in the following way:

Shuttlecock Scene

To simulate motion through the air, I have placed a shadow Sprite that follows the Shuttlecock. The Shuttlecock sprite is drawn further up from the shadow, the higher the Shuttlecock is in the air.

My code looks like this:

class_name Shuttlecock
extends Area2D


const MAX_HEIGHT = 500.0
const HEIGHT_UNIT = 22.0
const MAX_UNIT_HEIGHT = 5
const INITIAL_HEIGHT = 50.0
const GRAVITY = 425.0
const FRICTION = 2.0
const MAX_SPEED = 120.0

signal fell_on_ground()

@export var gravity_strength : float = GRAVITY
@export var friction : float = FRICTION

var height := INITIAL_HEIGHT
var velocity := Vector3.ZERO : set = set_velocity
var on_ground := false


func _ready():
	_update_height()
	
	
func _physics_process(delta):
	self.velocity.z -= self.gravity_strength * delta
	
	self.velocity.x = lerp(
		self.velocity.x, 0.0, self.friction * delta)
	self.velocity.y = lerp(
		self.velocity.y, 0.0, self.friction * delta)
		
	self.height += self.velocity.z * delta
	
	if self.height <= 0.0:
		self.height = 0.0
		self.velocity = Vector3.ZERO
		if not self.on_ground:
			self.on_ground = true
			emit_signal("fell_on_ground")
			
	self.global_position += Vector2(self.velocity.x, self.velocity.y) * delta
	
	_update_height()
	
	var direction = Vector2(velocity.x, velocity.z).normalized()
	if direction.length() > 0.0:
		var angle = direction.angle()
		$Graphics.rotation =  deg_to_rad(-90) - angle
	
	
func set_velocity(value):
	velocity = value
	set_physics_process(true)
	
	
func get_initial_velocity(target_position: Vector2) -> Vector3:
	# TODO: Implement me!
	return Vector3.ZERO
	
	
func hit(type, force : Vector3):
	if on_ground:
		return
	set_physics_process(true)
	self.velocity = force
	
	
func reset():
	self.velocity = Vector3.ZERO
	self.on_ground = false
	self.height = INITIAL_HEIGHT
	_update_height()
	set_physics_process(false)


func _update_height():
	$Graphics.position.y = \
		-self.height \
			* (MAX_UNIT_HEIGHT / MAX_HEIGHT) \
			* HEIGHT_UNIT

How can I calculate the initial velocity so that my Shuttlecock lands on a given target position?

You are coming at this problem from a weird angle and you are asking for quite a bit of physics. There is also not one correct answer since there are many correct velocities (the ball can go high in an arch, barely skim over the ground, or anything in between).

I think there are two reasonable approaches for you here:

  1. Simulate the physics and just tweak the numbers so the shuttlecock moves the way you want and then have the shadow follow it. In other words, first decide the how your shuttlecock moves, then just test what initial velocities give you something you want. If you don’t want to do some serious physics, then testing is gonna be way easier than calculating your way to what you want.
  2. Do some math to find a parabola that starts and ends where you want. This is not too difficult, there are probably some equations for it you can find online. You can then easily choose how high or straight you want the shuttlecock to go. Use the parabola to make a Path2D and have your shuttlecock follow it as a PathFollow2D

Vadalken | 2023-04-11 11:25

Very interesting. I like your second approach a lot. I think I will experiment with it. Thanks for the suggestions.

Juxxec | 2023-04-12 08:25