Now it works!... but it runs every single frame, probably causing a
bunch of unnecessary text rendering and UI layout operations. I'll have
to come back and make it event-based at some point.
I've taken a lot directly from the Bevy UI button example.
(https://bevy.org/examples/ui-user-interface/button/)
I'll make it look better later. For now, it just needs to exist. Onward
to the UI operation system!
I want the different "scenes" to be their own plugins for ease of setup
and reading.
The main menu plugin has been renamed to have "Plugin" first. This is so
the lexical sort in the docs places all the plugins next to each other.
The "get-ready" plugin has been given an empty struct and an
`impl Plugin` to match the main menu plugin. I've started the game over
scene, but left it unimplemented.
Closes#16
Bevy provides Deref and DerefMut derives, so that's nice. I'm not sure
it makes any sense to keep the field private since those derefs expose
the Vec2 anyway. I added an `impl Default` anyway, though.
The non-gameplay scenes are really just a bunch of widgets. I'm going to
put them all together and then bundle the functionality with some
exported plugin builders.
I'm not sold on the name, but anyway.
This module will hold the systems that power the main game mechanics, as
well as a few extra items to support that (in particular, the Lifetime
component).
The player will be respawned, their lives decreased, and the board
cleared. The UI doesn't update, and the sudden snap to a freshly reset
board is quite jarring. The state transition to GameOver stops the game,
but there isn't anything else running in that state so it just looks
frozen.
Basically, there's a ton left to do, but technically I have handled
player ship destruction!
The spacebar fires the gun, bullets are spawned on top of the ship with
a velocity that sends them forward (relative to the ship).
I still need a despawn mechanism, and a fire rate control. To despawn
things, I'm already planning a `Lifetime` component. For rate of fire,
an additional component will be created and attached to the player ship.
The ship in Asteroids isn't expected to spin up while holding a steering
direction, but that's exactly what I just made it do.
Fix that problem by assigning, not accumulating, the angular velocity
for the ship.
The rotation component is also redundant with Bevy's transform
component.
This new component and system fill the physics role, but the input
handling code needs to be updated.
Player steering still functions because it uses the `Rotation` component
to direct the force vector. The force is correctly applied to the linear
velocity vector. An improvement would be to have a force/impulse
accumulator so I could account for mass, but I'm not going to do that
right now.
The position component is redundant with the built-in Bevy Transform.
I've updated the velocity integrator to use the transform directly.
Physics still works, but things still set their initial locations
through the Position component. I'll need to fix all those call sites.
The physics sim bits (that aren't Rapier2d) are now in their own
submodule. I've included the `Wrapping` marker component because it
doesn't really have anywhere else to live, and it's kinda sorta related
to the physics. It controls the motion of objects... that's physics. :p
There are name collisions between Rapier2d's `Velocity` and my own, but
that's a problem for later. I've used more specific type paths where
necessary to maintain the previous behavior.
The `physics::Position` component can go away completely. It's just an
extra copy of some of the built-in `Transform` data. I'm pretty sure it
only exists because I didn't realize I could rely on directly
manipulating the transform when I started this project.
I've added a new `event` module to contain all the game's events (which
it does not. I'll collect them all later).
Using these events, the CollisionEvent listening system can watch for
any two colliders intersecting, check on what role they play (asteroid,
ship, bullet, etc), and re-emit an event for that specific thing. Each
component can then handle it's own destruction process.
Rapier expects to have a RigidBody attached to the entity, but I do not.
I'm not going to make one, either, because the objects in a game of
Asteroids don't need collision handling the way most games do. I just
need to know if two objects have started overlapping.
According to this: https://rapier.rs/docs/user_guides/bevy_plugin/colliders#collision-groups-and-solver-groups
only one of the two objects involved needs to have the ActiveEvents and
ActiveCollisionTypes components attached, so I've placed them on the
player ship.
I'm going to grab the Rapier physics library so that I don't have to do
my own collision detection mechanism. The last time I did this, I
simplified everything into circles. This time I'd like to have convex
hulls, particularly for the player ship.
Also the last time, I ended up rolling my own quadtree impl. I'm not
particularly interested in doing that again, and I'd like to learn more
of the broader Bevy ecosystem.
The events are being emitted by the spawn manager, and consumed by the
spawn_asteroid system. Now to wire in the spawn properties, and then
make a good spawning manager.