Controlling Orbiting Projectiles

Godot Version

Question

Hey Everyone,

I’m trying to create a weapon that orbits the player character but running into an issue when it comes to multiple projectiles along this orbit. The orbit does work however, currently they just stack in the same spot. Ideally I would be able to have multiple projectiles on this path and be able to have them spread to equal distances based on the number of projectiles.

All projectiles start their orbit at the bottom right of the circle, then travel counter clockwise as intended.

Any ideas on where to get started with this?

var D = 0.0
var radius = 200
var speed = 1

func _physics_process(delta):
	rotation += deg_to_rad(-5)
	D += delta
	var tween = create_tween()
	var target_pos = Vector2(sin(D * speed) * radius, cos(D * speed) * radius) + player.global_position 
	tween.tween_property(self, "position", target_pos,.1).set_ease(Tween.EASE_IN)
	tween.play()
  1. Create a node where you will place your orbiting object, and add it to the player so the player is the parent. Be sure to center it on the player. Put nothing else into this node except the orbiting objects.

  2. Generate points evenly on a unit circle (6.28 units / number of points). I created a separate class for easy reuseability. When generating the points, scale their positions according to how large you want the circle.

  3. When you add a new orbiting projectile, erase all the projectiles from the node you created in step 1, generate a new set of points, and re-add all the orbiting projectiles to the node you created in step 1.

  4. Rotate the node that contains all the projectiles, and all the projectiles will appear to orbit the player.

1 Like

Not the solution I was expecting but looks pretty easy based off of how you summed it up!

I’ll give it a shot and let you know if I run into issues!

1 Like

It’s pretty easy.

1 Like

Could you expand on how to setup the circle, create points, scaling, and adding of the first projectile?

My player rotates so I’ve added a “Node2D” to my game scene with the following code to ensure that it sticks on the player. I added a projectile as a child in the scene hierarchy to test and it spins as desired.

Thanks for your help!

extends Node
@onready var player = get_tree().get_first_node_in_group("player_group")


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
	self.global_position = player.global_position
	self.rotation += deg_to_rad(1)

Here is the complete class I wrote for Seas of Reverence. It’s 3D, but I leave it as an exercise for the reader to convert it to 2D.

extends Node3D
class_name CircleGenerator

##
## The number of points to calculate.
##
var m_nItems : int

##
## An array to hold the generated points.
##
var m_aCoordinates = []

##
## The number of degrees around the circle to distribute the points.
##
var m_nTotalSpan = 360

##
## The scaling factor to make the generated circle larger or smaller.
##
var m_nScale : float = 3

func _ready():
	pass

func getCoordinates():
	return m_aCoordinates

func getScale():
	return m_nScale
	
func setItems(a):
	m_nItems = a

func setTotalSpan(a):
	m_nTotalSpan = a

func setScale(a : float):
	m_nScale = a
	
func generateXY():
	if m_nItems != 0:
		var nIncrement = float(m_nTotalSpan) / float(m_nItems)
		var nAngle = 0

		m_aCoordinates.clear()
		while nAngle < float(m_nTotalSpan):
			var x = cos(deg_to_rad(nAngle))
			var y = sin(deg_to_rad(nAngle))

			m_aCoordinates.append(Vector3(x * m_nScale,y * m_nScale,0))
			nAngle += nIncrement

func generateXZ():
	if m_nItems != 0:
		var nIncrement = float(m_nTotalSpan) / float(m_nItems)
		var nAngle = 0

		m_aCoordinates.clear()
		while nAngle < float(m_nTotalSpan):
			var x = cos(deg_to_rad(nAngle))
			var z = sin(deg_to_rad(nAngle))

			m_aCoordinates.append(Vector3(x * m_nScale,0,z * m_nScale))
			nAngle += nIncrement
1 Like