How to edit rotation while drawing from _draw()

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

Hello, I am attempting to make a bullet hell pattern maker, and I am running into a problem when drawing the bullets in the _draw() function. The spawner node is rotating, and I need the bullets to not rotate with it. I am able to do that to a point, but I am not able to keep the original rotation of the bullet.

    bpic = frame[image_offset]
    Vector2 offset = (b.scale()*bpic.size) / 2.0;
    Rect2 rect;
    rect.position = b.get_current_position().rotated(-get_rotation()) - offset;
    rect.size = bpic.size * b.scale
    draw_texture(bpic, get_global_position())

This code (in the _draw fucntion of the spawner node) is allowing the bullets to be drawn in the correct location, but they are still spinning in place. If anyone has any ideas or alternatives to spinning the entire spawer node, that would be greatly appreciated o7

:bust_in_silhouette: Reply From: stormreaver

I don’t know your overall game structure, so take this for what it’s worth. I think you’re going to run into early performance problems using _draw() to render your bullets. Using MultiMesh is going to give you much better rendering performance. In both cases, through, collision detection will become your most significant bottleneck (raycasts will probably be most efficient).

The MultiMesh is also a simple way to fix your rotation issue. Make the MultiMesh a parent of something other than the spawner node, and create each new bullet’s global transform with the spawner’s global transform, and the bullets will not change orientation as the spawner rotates.

As for MultiMesh performance, one of my benchmarks of one of my games showed a major performance hit for individual KinematicBody objects at a few thousand objects, while using a MultiMesh allowed me to have close to a million instances before seeing a significant performance penalty. I had no collision detection using the MultiMesh, as MultiMesh doesn’t support collision detection, but I was interested in the rendering performance.

I originally had used this method, but could not figure out how to access and delete individual instances from the mesh. Like when the player hits a bullet, I need it to delete itself. I am writing the code in c++ though, so performance is not too much of an issue.

DaZel77 | 2023-04-08 20:44

Since you’re using C++, you might be able to get away with brute-forcing it. Assuming you use raycasts from the bullets’ positions, you will know which instance index needs to be removed. You can iterate through all the instances, moving their respective transforms up one instance, then change the instance count of the multimesh. This might be feasible in C++. I haven’t benchmarked this idea, though, so it may or not be feasible.

stormreaver | 2023-04-08 21:38

Do you think you could write some pseudocode for me? I am still not understanding how I would go about deleting one instance using the index.

DaZel77 | 2023-04-12 18:34

Okay, but I always overlook some mundane detail that ends up skimming dollars instead of fractions of a cent…

# Iterate through all the instances
For i = 0 to multimesh.instances:
	# Shoot a ray from the bullet for collision detection.
	Raycast from bullets[i].global_transform.origin
	If bullet[i] collision:
		# The raycast collides with something, so move
		# all the transforms for all the following
		# bullets up one slot. You might be able to gain
		# a little extra performance by moving just the
		# origins rather than the entire transforms.
		for j = 0 to bullets.size - i - 1:
			bullet[i + j].global_transform = bullets[i + j + 1].global_transform
# Tell the multimesh that it has one fewer item to display.
multimesh.instances -= 1

That’s the general gist.

stormreaver | 2023-04-13 00:17