3 Commits

Author SHA1 Message Date
0eac337c00 Update spawn_player to use new GameAssets
Some checks failed
Basic checks / Basic build-and-test supertask (push) Has been cancelled
2025-07-29 11:54:39 -05:00
3d4e0afc58 Swap asteroid-spawning to use new GameAssets 2025-07-29 11:51:12 -05:00
f62ab2c95d New GameAssets resource to hold all my assets
I'm finally getting around to centralizing all the assets instead of
letting spawners load their own.

I'm missing some assets, which may eventually be filled by textures
instead of solid-colors and simple shapes

I also need to hook up all the functions to use this thing instead.
2025-07-29 11:48:02 -05:00
2 changed files with 81 additions and 28 deletions

View File

@@ -11,6 +11,8 @@ pub(crate) const BACKGROUND_COLOR: Color = Color::srgb(0.3, 0.3, 0.3);
pub(crate) const PLAYER_SHIP_COLOR: Color = Color::srgb(1.0, 1.0, 1.0);
pub(crate) const SHIP_THRUSTER_COLOR_ACTIVE: Color = Color::srgb(1.0, 0.2, 0.2);
pub(crate) const SHIP_THRUSTER_COLOR_INACTIVE: Color = Color::srgb(0.5, 0.5, 0.5);
pub(crate) const ASTEROID_SMALL_COLOR: Color = Color::srgb(1.0, 0., 0.);
// TODO: asteroid medium & large
pub(crate) const SHIP_THRUST: f32 = 1.0;
pub(crate) const SHIP_ROTATION: f32 = 0.1; // +/- rotation speed in... radians per frame

View File

@@ -10,7 +10,7 @@ use bevy::{color::palettes::css::GRAY, prelude::*};
use bevy_inspector_egui::prelude::ReflectInspectorOptions;
use bevy_inspector_egui::InspectorOptions;
use config::{SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE};
use config::{ASTEROID_SMALL_COLOR, SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE};
pub struct AsteroidPlugin;
@@ -31,6 +31,7 @@ impl Plugin for AsteroidPlugin {
.insert_resource(AsteroidSpawner {
timer: Timer::new(Duration::from_secs(3), TimerMode::Repeating),
})
.init_resource::<GameAssets>()
.add_systems(Startup, spawn_camera)
.add_systems(OnEnter(GameState::Playing), (spawn_player, spawn_ui))
.add_systems(
@@ -126,28 +127,80 @@ struct WorldSize {
height: f32,
}
#[derive(Resource)]
struct GameAssets {
meshes: [Handle<Mesh>; 4],
materials: [Handle<ColorMaterial>; 6],
}
impl GameAssets {
fn ship(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[0].clone(), self.materials[0].clone())
}
// The thruster mesh is actually just the ship mesh
fn thruster_mesh(&self) -> Handle<Mesh> {
self.meshes[0].clone()
}
// TODO: Look into parameterizing the material
// A shader uniform should be able to do this, but I don't know how to
// load those in Bevy.
fn thruster_mat_inactive(&self) -> Handle<ColorMaterial> {
self.materials[1].clone()
}
fn thruster_mat_active(&self) -> Handle<ColorMaterial> {
self.materials[2].clone()
}
fn asteroid_small(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[1].clone(), self.materials[1].clone())
}
fn asteroid_medium(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[2].clone(), self.materials[2].clone())
}
fn asteroid_large(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[3].clone(), self.materials[3].clone())
}
}
impl FromWorld for GameAssets {
fn from_world(world: &mut World) -> Self {
let mut world_meshes = world.resource_mut::<Assets<Mesh>>();
let meshes = [
world_meshes.add(Triangle2d::new(
Vec2::new(0.5, 0.0),
Vec2::new(-0.5, 0.45),
Vec2::new(-0.5, -0.45),
)),
world_meshes.add(Circle::new(10.0)),
world_meshes.add(Circle::new(20.0)),
world_meshes.add(Circle::new(40.0)),
];
let mut world_materials = world.resource_mut::<Assets<ColorMaterial>>();
let materials = [
world_materials.add(PLAYER_SHIP_COLOR),
world_materials.add(SHIP_THRUSTER_COLOR_INACTIVE),
world_materials.add(SHIP_THRUSTER_COLOR_ACTIVE),
world_materials.add(ASTEROID_SMALL_COLOR),
// TODO: asteroid medium and large colors
world_materials.add(ASTEROID_SMALL_COLOR),
world_materials.add(ASTEROID_SMALL_COLOR),
];
GameAssets { meshes, materials }
}
}
fn spawn_camera(mut commands: Commands) {
commands.spawn(Camera2d);
}
fn spawn_player(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let triangle = Triangle2d::new(
Vec2::new(0.5, 0.0),
Vec2::new(-0.5, 0.45),
Vec2::new(-0.5, -0.45),
);
let thruster_firing_id = materials.add(SHIP_THRUSTER_COLOR_ACTIVE);
let thruster_stopped_id = materials.add(SHIP_THRUSTER_COLOR_INACTIVE);
let ship_material = materials.add(PLAYER_SHIP_COLOR);
let ship_mesh = meshes.add(triangle);
let thruster_material = materials.add(PLAYER_SHIP_COLOR);
let thruster_mesh = meshes.add(triangle);
fn spawn_player(mut commands: Commands, game_assets: Res<GameAssets>) {
let thruster_firing_id = game_assets.thruster_mat_active();
let thruster_stopped_id = game_assets.thruster_mat_inactive();
commands
.spawn((
@@ -156,14 +209,14 @@ fn spawn_player(
Position(Vec2::default()),
Velocity(Vec2::ZERO),
Rotation(0.0),
Mesh2d(ship_mesh),
MeshMaterial2d(ship_material),
Mesh2d(game_assets.ship().0),
MeshMaterial2d(game_assets.ship().1),
ThrusterColors(thruster_firing_id, thruster_stopped_id),
Transform::default().with_scale(Vec3::new(20.0, 20.0, 20.0)),
))
.with_child((
Mesh2d(thruster_mesh),
MeshMaterial2d(thruster_material),
Mesh2d(game_assets.thruster_mesh()),
MeshMaterial2d(game_assets.thruster_mat_inactive()),
Transform::default()
.with_scale(Vec3::splat(0.5))
.with_translation(Vec3::new(-0.5, 0.0, -0.1)),
@@ -175,9 +228,7 @@ fn spawn_player(
fn tick_asteroid_manager(
mut commands: Commands,
mut spawner: ResMut<AsteroidSpawner>,
// TODO: move the mesh & material loading somewhere else
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
game_assets: Res<GameAssets>,
time: Res<Time>,
) {
spawner.timer.tick(time.delta());
@@ -187,8 +238,8 @@ fn tick_asteroid_manager(
Position(Vec2::new(40.0, 40.0)),
Velocity(Vec2::new(10.0, 0.0)),
Rotation(0.0),
Mesh2d(meshes.add(Circle::new(10.0))),
MeshMaterial2d(materials.add(Color::from(GRAY))),
Mesh2d(game_assets.asteroid_small().0),
MeshMaterial2d(game_assets.asteroid_small().1),
));
}
}