One of the main missing things in Ascent is “Being able to shoot at things”. To solve this, the first question is “What to shoot?”. Ok, there are rockets. But what about the almost-unlimited-basic-weaponry? Many space games feature laser guns. But, lasers, if implemented they way they’d actually look like and work, are boring. Just long lines, going on forever; not the fancy thing you know from Star Wars. You could also implement them to work like railguns – still, boring. But I remember that one of the coolest things of WWI flight simulators was firing bullets at enemies with the on-board cannon. And I’m sure one can find a satisfactory explanation why firing bullets in space is a reasonable thing to do :) The only thing that feels odd to me is that those bullets will keep on traveling forever until they hit anything…
So, bullets it is. Initially, my first idea was implementing bullets as particles, because I thought it would lead to better performance than using meshes. But my attempts to do so were not successful, it seems particles are just not the right thing to do this. In the end, you want “real” objects, so my next attempt was using meshes. And it worked out quite well!
Here’s a demo I made to show how “shooting at things” will feel like:
Instructions: Move the mouse to look around until you find some random colored boxes (hint: they are to the left). Then, hold down the left mouse button to fire bullets. Each box takes five hits until it disappears. When hit, the color of that box will become lighter. And, after having destroyed all boxes, you’ll also get a score! ;)
I am pretty content with the result. Shooting feels good, and seeing how the bullets make their way through space is really fancy.
The implementation is pretty simple: bullets are simple meshes – spheres, or maybe cylinders – with a simple material (I know, spheres and cylinders aren’t that simple, but at least you can keep the polygon count low). There’s a certain interval in which bullets can be fired, and in the render loop I add the time deltas until the interval time is reached, and another bullet is ready to go. That implementation is not 100% accurate, as the player might have to wait up the interval amount of time after he starts holding down the mouse button until the first bullet is released, but that delay is hard to notice.
Each bullets starts in the direction the camera is facing and goes on in that direction until it hits something or it’s lifetime is reached. So far, so good.
What’s still very wrong, is collision detection. Currently, I’m casting a ray for every bullet, because that seems to be the easiest way to determine whether a point is inside of a mesh. For this, I’m using the Three.js Ray class. There’s two issues with that: first, it doesn’t yield reliable results. In the demo, you can see that many bullets just pass through a mesh and are not being reported as hits. Second, it’s a big hit on performance and memory. Instantiating a new Ray() creates many new objects (around ten) which all need to be garbage collected – now imagine you have a thousand bullets flying around. The way to go here is to modify the ray class to make it re-usable and make a ray instance itself re-use it’s objects.
So, after I fixed the issues with ray casting, this can make it’s way into Ascent!