thombruce / verse

🚀 A universe in progress
Other
8 stars 0 forks source link

Ship-to-ship Combat #53

Closed thombruce closed 10 months ago

thombruce commented 11 months ago

Ahead of implementing #52, which I think sounds like a lot of fun, we need... even just one more ship on screen - an enemy.

Both ships should be able to turn, pursue and fire on one another, dealing damage for each successful hit (maybe numeral indicators?).

When a ship is below or equal to 0 health, it should be destroyed in an explosion and should spawn cargo and crew the player can scoop up.

Initially, lets create one enemy ship that has the same flight system as the player (albeit controlled by an AI controller, rather than the player - we can think about using big-brain for this: https://github.com/zkat/big-brain).

If the player is within a certain distance of the enemy ship, it should attack and pursue the player until one of them comes up the victor - this is going to require some tweaking in terms of what's the right amount of challenge for a single encounter considered "equal".

The player should be able to either destroy or escape the enemy.


Following this implementation, ships should also be spawnable/unspawnable perhaps in the vicinity of planets (taking off or landing on them on a semi-random timer).

thombruce commented 11 months ago

A few things need to happen here:

  1. Spawn an enemy ship
  2. Provide it AI
  3. Weapons system: spawn projectile on a button press and fire it in the facing direction of the firing ship
  4. Hit detection and damage

I'm wondering whether 3 and in particular 4 will use the Rapier2d physics engine or not. I'm increasingly unsure how much I need it at all (though it does provide a relationship between mass and forces that I haven't thought about reworking).

I mean... it's easy to spawn a projectile at a point in space (defined as the nose of the firing entity) and it's easy to give it a velocity component.

Hit detection, I'm unsure about. The Rapier physics engine provides colliders to handle this.

My own naive approach would be to... assume a circle around any hittable entity and determine whether the projectile falls within that circle. If so, IT'S A HIT! We despawn the projectile and deal damage to the hit entity. That's very straightforward and very easy. We're just calculating the distance between entities. But it gets tricky if the shape we're trying to hit isn't a circle...

In such a case, we would need to... take the position of the projectile and then determine whether it falls within the shape drawn by the entity to be hit. So, we have the projectiles coordinates and we ask "does this fall within this shape at this point?" And if the shape is a square, a hexagon, a circle, an ellipse, or I suppose any regular polygon... I suppose that's pretty easy. We can draw a virtual line out from the origin of the hitbox through the projectile and the edge of the shape... and if the edge of the shape is further away than the projectile, that's a hit. Right? How easy is it to calculate the "radius" for any point on the circumference of a regular polygon?

I realise I'm suggesting doing the same for other polygons as I would do for circles there... and I don't know the geometry involved in doing that. Wait... no, I know a bit. For a square, for instance, if we know its edge length, then we know how to divide it into triangles and do the geometry on those... Imagine a triangle with one corner at the centre of the square and another corner halfway along one edge; we can easily obtain the angle of the approaching projectile and this draws our third line, creating our third corner... If we draw a line up from the corner that is halfway along one edge of the square, we know the starting coordinates of both, so we can easily get their intersection. The length of the distance from the centre to that intersection is then the "hit distance". And yes, any other regular polygon can be similarly divided into triangles; different equations, I'm sure, but fundamentally the same technique works.

But... Rapier2d will also handle convex meshes and other advanced cases: https://rapier.rs/docs/user_guides/bevy_plugin/colliders#convex-meshes And of course it takes the legwork out of doing those geometry calculations ourselves... which I could very easily get wrong.

To be honest, even if hit-detection is the only thing we end up using Rapier2d for in the finished game, I still think it's worth it.

As for velocity part and the mass of objects... I'm going to look for opportunities to play around with that. It might not be necessary... 🤔 Then again, we're absolutely going to end up doing the F=ma calculations ourselves, which involves the mass and enables us to get velocity once we introduce a time variable. So again, Rapier is doing something for us that is probably something we do want. And it's probably doing so very efficiently.

I might eventually think about testing out my own best guess at an implementation, maybe, and we can benchmark it... but I'm not in pursuit of perfectly efficient right now. We're cobbling together pieces into a working... thing. Rapier stays.

thombruce commented 11 months ago

For spawning projectiles, even though I have high confidence in how I would do that, it's still worth taking another look at how Kataster does it: https://github.com/BorisBoutillier/Kataster