Add proper meshes & materials for game objects

The asteroid circles have been replaced with polylines. I was going to
do a regular triangle mesh, but I don't want to figure out GLTF
loading or manually chunking the points into convex hulls.

Asteroid materials are now all populated and their GameAsset getters are
indexed correctly. I'm not sold on the size based color selection.
Later, I think I'll either remove the extra colors or let each of them
randomly apply to any asteroid.

The bullet is now a short line segment. Apparently I already wired in
the rotation logic, so pointing it correctly out of the ship already
works.
This commit is contained in:
2025-12-19 10:29:48 -06:00
parent de75e25ca6
commit 19ac032792
4 changed files with 79 additions and 23 deletions

View File

@@ -9,19 +9,21 @@ pub const UI_BUTTON_NORMAL: Color = Color::srgb(0.15, 0.15, 0.15); // Button col
pub const UI_BUTTON_HOVERED: Color = Color::srgb(0.25, 0.25, 0.25); // ... when it's hovered pub const UI_BUTTON_HOVERED: Color = Color::srgb(0.25, 0.25, 0.25); // ... when it's hovered
pub const UI_BUTTON_PRESSED: Color = Color::srgb(0.55, 0.55, 0.55); // ... when it's pressed pub const UI_BUTTON_PRESSED: Color = Color::srgb(0.55, 0.55, 0.55); // ... when it's pressed
pub(crate) const BACKGROUND_COLOR: Color = Color::srgb(0.3, 0.3, 0.3); pub(crate) const BACKGROUND_COLOR: Color = Color::srgb(0.1, 0.1, 0.1);
pub(crate) const PLAYER_SHIP_COLOR: Color = Color::srgb(1.0, 1.0, 1.0); 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_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 SHIP_THRUSTER_COLOR_INACTIVE: Color = Color::srgb(0.5, 0.5, 0.5);
pub(crate) const SHIP_FIRE_RATE: f32 = 3.0; // in bullets-per-second pub(crate) const SHIP_FIRE_RATE: f32 = 3.0; // in bullets-per-second
pub(crate) const ASTEROID_SMALL_COLOR: Color = Color::srgb(1.0, 0., 0.); pub(crate) const ASTEROID_SMALL_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
pub(crate) const BULLET_COLOR: Color = Color::srgb(0.0, 0.1, 0.9); pub(crate) const ASTEROID_MEDIUM_COLOR: Color = Color::srgb(0.8, 0.8, 0.8);
pub(crate) const ASTEROID_LARGE_COLOR: Color = Color::srgb(0.6, 0.6, 0.6);
pub(crate) const BULLET_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
// TODO: asteroid medium & large // TODO: asteroid medium & large
pub(crate) const SHIP_THRUST: f32 = 1.0; pub(crate) const SHIP_THRUST: f32 = 4.0;
pub(crate) const SHIP_ROTATION: f32 = 4.0; // +/- rotation speed in... radians per frame pub(crate) const SHIP_ROTATION: f32 = 4.0; // +/- rotation speed in... radians per frame
pub(crate) const BULLET_SPEED: f32 = 150.0; pub(crate) const BULLET_SPEED: f32 = 500.0;
pub(crate) const BULLET_LIFETIME: f32 = 2.0; pub(crate) const BULLET_LIFETIME: f32 = 2.0;
pub(crate) const ASTEROID_LIFETIME: f32 = 40.0; pub(crate) const ASTEROID_LIFETIME: f32 = 40.0;

View File

@@ -11,9 +11,9 @@ mod resources;
mod widgets; mod widgets;
use crate::config::{ use crate::config::{
ASTEROID_SMALL_COLOR, BACKGROUND_COLOR, BULLET_COLOR, BULLET_LIFETIME, BULLET_SPEED, ASTEROID_LARGE_COLOR, ASTEROID_MEDIUM_COLOR, ASTEROID_SMALL_COLOR, BACKGROUND_COLOR,
PLAYER_SHIP_COLOR, SHIP_ROTATION, SHIP_THRUST, SHIP_THRUSTER_COLOR_ACTIVE, BULLET_COLOR, BULLET_LIFETIME, BULLET_SPEED, PLAYER_SHIP_COLOR, SHIP_ROTATION, SHIP_THRUST,
SHIP_THRUSTER_COLOR_INACTIVE, SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE,
}; };
use crate::machinery::AsteroidSpawner; use crate::machinery::AsteroidSpawner;
use crate::objects::{Bullet, Ship, Weapon}; use crate::objects::{Bullet, Ship, Weapon};

View File

@@ -83,9 +83,9 @@ pub fn spawn_asteroid(
}; };
let collider_radius = match spawn.size { let collider_radius = match spawn.size {
AsteroidSize::Small => 10.0, AsteroidSize::Small => 5.0,
AsteroidSize::Medium => 20.0, AsteroidSize::Medium => 10.0,
AsteroidSize::Large => 40.0, AsteroidSize::Large => 20.0,
}; };
commands.spawn(( commands.spawn((

View File

@@ -9,7 +9,7 @@ use bevy::{
}, },
math::{ math::{
Vec2, Vec2,
primitives::{Circle, Triangle2d}, primitives::{Polyline2d, Segment2d, Triangle2d},
}, },
mesh::Mesh, mesh::Mesh,
prelude::{Deref, DerefMut, Reflect, ReflectResource}, prelude::{Deref, DerefMut, Reflect, ReflectResource},
@@ -19,8 +19,9 @@ use bevy_inspector_egui::InspectorOptions;
use bevy_inspector_egui::inspector_options::ReflectInspectorOptions; use bevy_inspector_egui::inspector_options::ReflectInspectorOptions;
use crate::{ use crate::{
ASTEROID_SMALL_COLOR, BULLET_COLOR, PLAYER_SHIP_COLOR, SHIP_THRUSTER_COLOR_ACTIVE, ASTEROID_LARGE_COLOR, ASTEROID_MEDIUM_COLOR, ASTEROID_SMALL_COLOR, BULLET_COLOR,
SHIP_THRUSTER_COLOR_INACTIVE, config::WINDOW_SIZE, PLAYER_SHIP_COLOR, SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE,
config::WINDOW_SIZE,
}; };
#[derive(InspectorOptions, Reflect, Resource, Debug, Deref, Clone, Copy)] #[derive(InspectorOptions, Reflect, Resource, Debug, Deref, Clone, Copy)]
@@ -83,15 +84,15 @@ impl GameAssets {
} }
pub fn asteroid_small(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) { pub fn asteroid_small(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[1].clone(), self.materials[1].clone()) (self.meshes[1].clone(), self.materials[3].clone())
} }
pub fn asteroid_medium(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) { pub fn asteroid_medium(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[2].clone(), self.materials[2].clone()) (self.meshes[2].clone(), self.materials[4].clone())
} }
pub fn asteroid_large(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) { pub fn asteroid_large(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
(self.meshes[3].clone(), self.materials[3].clone()) (self.meshes[3].clone(), self.materials[5].clone())
} }
pub fn bullet(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) { pub fn bullet(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
@@ -124,10 +125,63 @@ impl FromWorld for GameAssets {
Vec2::new(-0.5, 0.45), Vec2::new(-0.5, 0.45),
Vec2::new(-0.5, -0.45), Vec2::new(-0.5, -0.45),
)), )),
world_meshes.add(Circle::new(10.0)), world_meshes.add(Polyline2d::new(
world_meshes.add(Circle::new(20.0)), [
world_meshes.add(Circle::new(40.0)), Vec2::new(0.1, 0.0),
world_meshes.add(Circle::new(0.2)), Vec2::new(0.8, 0.2),
Vec2::new(0.8, 0.3),
Vec2::new(0.1, 1.0),
Vec2::new(-0.5, 1.0),
Vec2::new(-0.3, 0.3),
Vec2::new(-1.0, 0.3),
Vec2::new(-1.0, -0.2),
Vec2::new(-0.5, -1.0),
Vec2::new(0.1, -0.8),
Vec2::new(0.5, -0.9),
Vec2::new(1.0, -0.4),
Vec2::new(0.1, 0.0),
]
.into_iter()
.map(|vert| vert * 5.0),
)),
world_meshes.add(Polyline2d::new(
[
Vec2::new(0.6, 0.3),
Vec2::new(1.0, 0.6),
Vec2::new(0.6, 1.0),
Vec2::new(0.1, 0.8),
Vec2::new(-0.4, 1.0),
Vec2::new(-1.0, 0.6),
Vec2::new(-0.8, -0.1),
Vec2::new(-1.0, -0.5),
Vec2::new(-0.4, -1.0),
Vec2::new(-0.3, -0.7),
Vec2::new(0.6, -1.0),
Vec2::new(1.0, -0.3),
Vec2::new(0.6, 0.3),
]
.into_iter()
.map(|vert| vert * 10.0),
)),
world_meshes.add(Polyline2d::new(
[
Vec2::new(1.0, -0.1),
Vec2::new(1.0, 0.3),
Vec2::new(0.4, 1.0),
Vec2::new(-0.2, 1.0),
Vec2::new(-0.9, 0.3),
Vec2::new(-0.5, 0.1),
Vec2::new(-0.9, -0.1),
Vec2::new(-0.5, -1.0),
Vec2::new(0.0, 0.0),
Vec2::new(0.0, -1.0),
Vec2::new(0.5, -1.0),
Vec2::new(1.0, -0.1),
]
.into_iter()
.map(|vert| vert * 20.0),
)),
world_meshes.add(Segment2d::new(Vec2::new(-0.1, 0.0), Vec2::new(0.1, 0.0))),
]; ];
let mut world_materials = world.resource_mut::<Assets<ColorMaterial>>(); let mut world_materials = world.resource_mut::<Assets<ColorMaterial>>();
let materials = [ let materials = [
@@ -136,8 +190,8 @@ impl FromWorld for GameAssets {
world_materials.add(SHIP_THRUSTER_COLOR_ACTIVE), world_materials.add(SHIP_THRUSTER_COLOR_ACTIVE),
world_materials.add(ASTEROID_SMALL_COLOR), world_materials.add(ASTEROID_SMALL_COLOR),
// TODO: asteroid medium and large colors // TODO: asteroid medium and large colors
world_materials.add(ASTEROID_SMALL_COLOR), world_materials.add(ASTEROID_MEDIUM_COLOR),
world_materials.add(ASTEROID_SMALL_COLOR), world_materials.add(ASTEROID_LARGE_COLOR),
world_materials.add(BULLET_COLOR), world_materials.add(BULLET_COLOR),
]; ];
let loader = world.resource_mut::<AssetServer>(); let loader = world.resource_mut::<AssetServer>();