Compare commits
14 Commits
b1fd2e5f73
...
v0.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 76426094d3 | |||
| 4b101633e7 | |||
| a5a6f32037 | |||
| 4d899d3c97 | |||
| 6d5afc2445 | |||
| d34d0a31f2 | |||
| 72f062ea10 | |||
| eecfbf5d7c | |||
| 1e09e3ce3a | |||
| 19ac032792 | |||
| de75e25ca6 | |||
| d7802bdbed | |||
| ae093d2c9c | |||
| 3963b548b9 |
26
Cargo.lock
generated
26
Cargo.lock
generated
@@ -242,7 +242,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "asteroids"
|
||||
version = "0.6.0-dev2"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bevy-inspector-egui",
|
||||
@@ -1848,9 +1848,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.49"
|
||||
version = "1.2.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215"
|
||||
checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@@ -4470,9 +4470,9 @@ checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
|
||||
|
||||
[[package]]
|
||||
name = "rangemap"
|
||||
version = "1.7.0"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbbbbea733ec66275512d0b9694f34102e7d5406fdbe2ad8d21b28dce92887c"
|
||||
checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
|
||||
|
||||
[[package]]
|
||||
name = "rapier2d"
|
||||
@@ -5167,9 +5167,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.4+spec-1.0.0"
|
||||
version = "0.7.5+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe3cea6b2aa3b910092f6abd4053ea464fab5f9c170ba5e9a6aead16ec4af2b6"
|
||||
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
@@ -5188,18 +5188,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.5+spec-1.0.0"
|
||||
version = "1.0.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c03bee5ce3696f31250db0bbaff18bc43301ce0e8db2ed1f07cbb2acf89984c"
|
||||
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.43"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
@@ -5219,9 +5219,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.35"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "asteroids"
|
||||
version = "0.6.0-dev2"
|
||||
version = "0.6.0"
|
||||
edition = "2024"
|
||||
license = "AGPL-3.0-only"
|
||||
|
||||
|
||||
17
Makefile
17
Makefile
@@ -12,23 +12,26 @@ CARGO_PROFILE := tiny
|
||||
SRC_DIR = ./src
|
||||
SRCS := $(wildcard $(SRC_DIR)/**)
|
||||
|
||||
ASSET_SOURCE := $(wildcard assets/**)
|
||||
ASSETS := $(patsubst assets/%.ogg, out/assets/%.ogg, $(ASSET_SOURCE))
|
||||
|
||||
.PHONY: clean full-clean tarball tarball-standalone web web-standalone
|
||||
|
||||
# "Standalone" version. It includes an index.html to serve as-is
|
||||
web-standalone: out/asteroids.js out/asteroids_bg.wasm.gz out/index.html
|
||||
web-standalone: out/asteroids.js out/asteroids_bg.wasm.gz out/index.html $(ASSETS)
|
||||
|
||||
# "Bundle-able" version. It has a page, but no index.html. Consumers are
|
||||
# expected to provide their own index.html and link to this page.
|
||||
web: out/asteroids.js out/asteroids_bg.wasm.gz out/asteroids.html
|
||||
web: out/asteroids.js out/asteroids_bg.wasm.gz out/asteroids.html $(ASSETS)
|
||||
|
||||
tarball: asteroids_web_root.tar
|
||||
|
||||
tarball_standalone: asteroids_web_root_standalone.tar
|
||||
|
||||
asteroids_web_root.tar: out/asteroids.js out/asteroids_bg.wasm.gz out/asteroids.html
|
||||
asteroids_web_root.tar: out/asteroids.js out/asteroids_bg.wasm.gz out/asteroids.html $(ASSETS)
|
||||
tar -caf $@ $^
|
||||
|
||||
asteroids_web_root_standalone.tar: out/asteroids.js out/asteroids_bg.wasm.gz out/index.html
|
||||
asteroids_web_root_standalone.tar: out/asteroids.js out/asteroids_bg.wasm.gz out/index.html $(ASSETS)
|
||||
tar -caf $@ $^
|
||||
|
||||
target/$(CARGO_TARGET)/$(CARGO_PROFILE)/asteroids.wasm: $(SRCS) Cargo.lock Cargo.toml
|
||||
@@ -37,6 +40,12 @@ target/$(CARGO_TARGET)/$(CARGO_PROFILE)/asteroids.wasm: $(SRCS) Cargo.lock Cargo
|
||||
out:
|
||||
mkdir $@
|
||||
|
||||
out/assets: | out
|
||||
mkdir $@
|
||||
|
||||
out/assets/%.ogg: assets/%.ogg | out/assets
|
||||
cp -ar assets/$*.ogg $@
|
||||
|
||||
# Both the JS and WASM files are generated by the wasm-bindgen call, so both
|
||||
# get to be on the target half of this recipe.
|
||||
out/asteroids.js out/asteroids_bg.wasm.gz &: target/$(CARGO_TARGET)/$(CARGO_PROFILE)/asteroids.wasm | out
|
||||
|
||||
BIN
assets/explosionCrunch_000.ogg
Normal file
BIN
assets/explosionCrunch_000.ogg
Normal file
Binary file not shown.
BIN
assets/laserSmall_001.ogg
Normal file
BIN
assets/laserSmall_001.ogg
Normal file
Binary file not shown.
BIN
assets/thrusterFire_004.ogg
Normal file
BIN
assets/thrusterFire_004.ogg
Normal file
Binary file not shown.
@@ -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_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 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_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 BULLET_COLOR: Color = Color::srgb(0.0, 0.1, 0.9);
|
||||
pub(crate) const ASTEROID_SMALL_COLOR: Color = Color::srgb(0.9, 0.9, 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
|
||||
|
||||
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 BULLET_SPEED: f32 = 150.0;
|
||||
pub(crate) const BULLET_SPEED: f32 = 500.0;
|
||||
pub(crate) const BULLET_LIFETIME: f32 = 2.0;
|
||||
|
||||
pub(crate) const ASTEROID_LIFETIME: f32 = 40.0;
|
||||
|
||||
32
src/lib.rs
32
src/lib.rs
@@ -11,9 +11,9 @@ mod resources;
|
||||
mod widgets;
|
||||
|
||||
use crate::config::{
|
||||
ASTEROID_SMALL_COLOR, BACKGROUND_COLOR, BULLET_COLOR, BULLET_LIFETIME, BULLET_SPEED,
|
||||
PLAYER_SHIP_COLOR, SHIP_ROTATION, SHIP_THRUST, SHIP_THRUSTER_COLOR_ACTIVE,
|
||||
SHIP_THRUSTER_COLOR_INACTIVE,
|
||||
ASTEROID_LARGE_COLOR, ASTEROID_MEDIUM_COLOR, ASTEROID_SMALL_COLOR, BACKGROUND_COLOR,
|
||||
BULLET_COLOR, BULLET_LIFETIME, BULLET_SPEED, PLAYER_SHIP_COLOR, SHIP_ROTATION, SHIP_THRUST,
|
||||
SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE,
|
||||
};
|
||||
use crate::machinery::AsteroidSpawner;
|
||||
use crate::objects::{Bullet, Ship, Weapon};
|
||||
@@ -111,14 +111,28 @@ fn spawn_camera(mut commands: Commands) {
|
||||
/// Checks if "W" is pressed and increases velocity accordingly.
|
||||
fn input_ship_thruster(
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
mut query: Query<(&mut physics::Velocity, &Transform, &mut Children), With<Ship>>,
|
||||
mut query: Query<
|
||||
(
|
||||
&mut physics::Velocity,
|
||||
&Transform,
|
||||
Option<&mut AudioSink>,
|
||||
&mut Children,
|
||||
),
|
||||
With<Ship>,
|
||||
>,
|
||||
mut commands: Commands,
|
||||
game_assets: Res<GameAssets>,
|
||||
) {
|
||||
// TODO: Maybe change for a Single<Ship>> so this only runs for the one ship
|
||||
// buuut... that would silently do nothing if there are 0 or >1 ships, and
|
||||
// I might want to crash on purpose in that case.
|
||||
let Ok((mut velocity, transform, children)) = query.single_mut() else {
|
||||
//
|
||||
// The AudioSink component doesn't exist for just one frame, forcing it to
|
||||
// be an optional system parameter. I'm not sure if I want to guard it with
|
||||
// a check like it does now, or finally switch to using a Single<...> query
|
||||
// parameter. I would lose ship control if the sound sink didn't spawn, but
|
||||
// that should be fine -- any time that fails, more has likely also failed.
|
||||
let Ok((mut velocity, transform, audio, children)) = query.single_mut() else {
|
||||
let count = query.iter().count();
|
||||
panic!("There should be exactly one player ship! Instead, there seems to be {count}.");
|
||||
};
|
||||
@@ -132,10 +146,16 @@ fn input_ship_thruster(
|
||||
commands
|
||||
.entity(*thrusters)
|
||||
.insert(MeshMaterial2d(game_assets.thruster_mat_active()));
|
||||
if let Some(audio) = audio {
|
||||
audio.play();
|
||||
}
|
||||
} else {
|
||||
commands
|
||||
.entity(*thrusters)
|
||||
.insert(MeshMaterial2d(game_assets.thruster_mat_inactive()));
|
||||
if let Some(audio) = audio {
|
||||
audio.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +219,8 @@ fn input_ship_shoot(
|
||||
MeshMaterial2d(game_assets.bullet().1),
|
||||
ship_pos.clone(), // clone ship transform
|
||||
Lifetime(Timer::from_seconds(BULLET_LIFETIME, TimerMode::Once)),
|
||||
AudioPlayer::new(game_assets.laser_sound()),
|
||||
PlaybackSettings::ONCE, // `Lifetime` already despawns the entity, so this doesn't need to
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ pub fn spawn_asteroid(
|
||||
};
|
||||
|
||||
let collider_radius = match spawn.size {
|
||||
AsteroidSize::Small => 10.0,
|
||||
AsteroidSize::Medium => 20.0,
|
||||
AsteroidSize::Large => 40.0,
|
||||
AsteroidSize::Small => 5.0,
|
||||
AsteroidSize::Medium => 10.0,
|
||||
AsteroidSize::Large => 20.0,
|
||||
};
|
||||
|
||||
commands.spawn((
|
||||
@@ -115,6 +115,7 @@ pub fn split_asteroids(
|
||||
mut respawn_events: MessageWriter<SpawnAsteroid>,
|
||||
mut commands: Commands,
|
||||
query: Query<(&Transform, &Asteroid, &Velocity)>,
|
||||
game_assets: Res<GameAssets>,
|
||||
) {
|
||||
for event in destroy_events.read() {
|
||||
if let Ok((transform, rock, velocity)) = query.get(event.0) {
|
||||
@@ -137,6 +138,12 @@ pub fn split_asteroids(
|
||||
// Always despawn the asteroid. New ones (may) be spawned in it's
|
||||
// place, but this one is gone.
|
||||
commands.entity(event.0).despawn();
|
||||
|
||||
// Play a sound for the asteroid exploding
|
||||
commands.spawn((
|
||||
AudioPlayer::new(game_assets.asteroid_crack_sound()),
|
||||
PlaybackSettings::DESPAWN,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,6 +168,12 @@ pub fn spawn_player(mut commands: Commands, game_assets: Res<GameAssets>) {
|
||||
Mesh2d(game_assets.ship().0),
|
||||
MeshMaterial2d(game_assets.ship().1),
|
||||
Transform::default().with_scale(Vec3::new(20.0, 20.0, 20.0)),
|
||||
AudioPlayer::new(game_assets.ship_thruster_sound()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Loop,
|
||||
paused: true,
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
.with_child((
|
||||
Mesh2d(game_assets.thruster_mesh()),
|
||||
@@ -237,7 +250,7 @@ pub fn ship_impact_listener(
|
||||
// STEP 5: Play crash sound
|
||||
commands.spawn((
|
||||
AudioPlayer::new(game_assets.wreck_sound()),
|
||||
PlaybackSettings::ONCE,
|
||||
PlaybackSettings::DESPAWN, // despawn this entity when playback ends.
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use bevy::{
|
||||
},
|
||||
math::{
|
||||
Vec2,
|
||||
primitives::{Circle, Triangle2d},
|
||||
primitives::{Polyline2d, Segment2d, Triangle2d},
|
||||
},
|
||||
mesh::Mesh,
|
||||
prelude::{Deref, DerefMut, Reflect, ReflectResource},
|
||||
@@ -19,8 +19,9 @@ use bevy_inspector_egui::InspectorOptions;
|
||||
use bevy_inspector_egui::inspector_options::ReflectInspectorOptions;
|
||||
|
||||
use crate::{
|
||||
ASTEROID_SMALL_COLOR, BULLET_COLOR, PLAYER_SHIP_COLOR, SHIP_THRUSTER_COLOR_ACTIVE,
|
||||
SHIP_THRUSTER_COLOR_INACTIVE, config::WINDOW_SIZE,
|
||||
ASTEROID_LARGE_COLOR, ASTEROID_MEDIUM_COLOR, ASTEROID_SMALL_COLOR, BULLET_COLOR,
|
||||
PLAYER_SHIP_COLOR, SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE,
|
||||
config::WINDOW_SIZE,
|
||||
};
|
||||
|
||||
#[derive(InspectorOptions, Reflect, Resource, Debug, Deref, Clone, Copy)]
|
||||
@@ -58,7 +59,7 @@ impl Default for WorldSize {
|
||||
pub struct GameAssets {
|
||||
meshes: [Handle<Mesh>; 5],
|
||||
materials: [Handle<ColorMaterial>; 7],
|
||||
sounds: [Handle<AudioSource>; 1],
|
||||
sounds: [Handle<AudioSource>; 4],
|
||||
}
|
||||
|
||||
impl GameAssets {
|
||||
@@ -83,15 +84,15 @@ impl GameAssets {
|
||||
}
|
||||
|
||||
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>) {
|
||||
(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>) {
|
||||
(self.meshes[3].clone(), self.materials[3].clone())
|
||||
(self.meshes[3].clone(), self.materials[5].clone())
|
||||
}
|
||||
|
||||
pub fn bullet(&self) -> (Handle<Mesh>, Handle<ColorMaterial>) {
|
||||
@@ -101,6 +102,18 @@ impl GameAssets {
|
||||
pub fn wreck_sound(&self) -> Handle<AudioSource> {
|
||||
self.sounds[0].clone()
|
||||
}
|
||||
|
||||
pub fn laser_sound(&self) -> Handle<AudioSource> {
|
||||
self.sounds[1].clone()
|
||||
}
|
||||
|
||||
pub fn asteroid_crack_sound(&self) -> Handle<AudioSource> {
|
||||
self.sounds[2].clone()
|
||||
}
|
||||
|
||||
pub fn ship_thruster_sound(&self) -> Handle<AudioSource> {
|
||||
self.sounds[3].clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWorld for GameAssets {
|
||||
@@ -112,10 +125,63 @@ impl FromWorld for GameAssets {
|
||||
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)),
|
||||
world_meshes.add(Circle::new(0.2)),
|
||||
world_meshes.add(Polyline2d::new(
|
||||
[
|
||||
Vec2::new(0.1, 0.0),
|
||||
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 materials = [
|
||||
@@ -124,12 +190,17 @@ impl FromWorld for GameAssets {
|
||||
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),
|
||||
world_materials.add(ASTEROID_MEDIUM_COLOR),
|
||||
world_materials.add(ASTEROID_LARGE_COLOR),
|
||||
world_materials.add(BULLET_COLOR),
|
||||
];
|
||||
let loader = world.resource_mut::<AssetServer>();
|
||||
let sounds = [loader.load("explosionCrunch_004.ogg")];
|
||||
let sounds = [
|
||||
loader.load("explosionCrunch_004.ogg"),
|
||||
loader.load("laserSmall_001.ogg"),
|
||||
loader.load("explosionCrunch_000.ogg"),
|
||||
loader.load("thrusterFire_004.ogg"),
|
||||
];
|
||||
GameAssets {
|
||||
meshes,
|
||||
materials,
|
||||
|
||||
@@ -180,9 +180,9 @@ fn spawn_get_ready(mut commands: Commands, mut timer: ResMut<ReadySetGoTimer>) {
|
||||
height: Val::Percent(30.),
|
||||
..default()
|
||||
},
|
||||
BackgroundColor(LIGHT_BLUE.into()),
|
||||
BackgroundColor(Color::NONE),
|
||||
children![
|
||||
(Text::new("Get Ready!"), TextColor(BLACK.into())),
|
||||
(Text::new("Get Ready!"), TextColor(WHITE.into())),
|
||||
(
|
||||
CountdownBar,
|
||||
Node {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
margin: auto;
|
||||
padding: 0.5em;
|
||||
}
|
||||
#prestart-controls,
|
||||
canvas {
|
||||
margin-top: 1em;
|
||||
margin-left: auto;
|
||||
@@ -22,6 +23,26 @@
|
||||
border-radius: 8px;
|
||||
background-color: rgb(40%, 40%, 40%);
|
||||
}
|
||||
#prestart-controls {
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
}
|
||||
button {
|
||||
font-size: 20px;
|
||||
text-shadow: 0.2em 0.2em 0px rgba(0, 0, 0, 75%);
|
||||
padding: 1em;
|
||||
border-radius: 2em;
|
||||
border-style: solid;
|
||||
border-color: black;
|
||||
color: rgb(90%, 90%, 90%);
|
||||
background-color: rgb(15%, 15%, 15%);
|
||||
}
|
||||
button:hover {
|
||||
background-color: rgb(25%, 25%, 25%);
|
||||
border-color: rgb(90%, 90%, 90%);
|
||||
}
|
||||
main {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
@@ -41,13 +62,21 @@
|
||||
<h1>
|
||||
Robert's Bad Asteroids Game
|
||||
</h1>
|
||||
<canvas id="game-canvas" width="1280" height="720"></canvas>
|
||||
<!-- <canvas id="game-canvas" width="800" height="600"></canvas> -->
|
||||
<div id="prestart-controls">
|
||||
<button id="gameload-button">Load Game</button>
|
||||
</div>
|
||||
<main>
|
||||
<article>
|
||||
<h2>Description</h2>
|
||||
<p>
|
||||
A (work in progress) version of the Asteroids arcade game.
|
||||
</p>
|
||||
<p>
|
||||
<em>Sound Warning!</em> The game now has sound effects, but there are no controls on the page for changing the
|
||||
volume (including to mute them). You can mute the browser tab by pressing <code>ctrl</code> + <code>m</code>.
|
||||
Proper volume controls are coming soon.
|
||||
</p>
|
||||
</article>
|
||||
<article>
|
||||
<h3>Controls</h3>
|
||||
@@ -90,7 +119,7 @@
|
||||
<tr>
|
||||
<td>Program Version</td>
|
||||
<!-- This version text is completely unchecked. I'll need to do something about that. -->
|
||||
<td><code>v0.5.0</code></td>
|
||||
<td><code>v0.6.0</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
</article>
|
||||
@@ -98,15 +127,26 @@
|
||||
<script type="module">
|
||||
import init from './asteroids.js'
|
||||
|
||||
let compressed = await fetch("./asteroids_bg.wasm.gz")
|
||||
let wasm_stream = compressed.body.pipeThrough(new DecompressionStream("gzip"))
|
||||
let blob = await new Response(wasm_stream).blob();
|
||||
let button = document.getElementById("gameload-button");
|
||||
button.onclick = async function loadGame() {
|
||||
console.log("Game Load button was pressed!");
|
||||
let canvas = document.createElement("canvas");
|
||||
// <canvas id="game-canvas" width="800" height="600"></canvas>
|
||||
canvas.setAttribute("id", "game-canvas");
|
||||
canvas.setAttribute("width", "800");
|
||||
canvas.setAttribute("height", "600");
|
||||
button.parentElement.replaceWith(canvas);
|
||||
|
||||
init(await blob.arrayBuffer()).catch((error) => {
|
||||
if (!error.message.startsWith("Using exceptions for control flow, don't mind me. This isn't actually an error!")) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
let compressed = await fetch("./asteroids_bg.wasm.gz")
|
||||
let wasm_stream = compressed.body.pipeThrough(new DecompressionStream("gzip"))
|
||||
let blob = await new Response(wasm_stream).blob();
|
||||
|
||||
init(await blob.arrayBuffer()).catch((error) => {
|
||||
if (!error.message.startsWith("Using exceptions for control flow, don't mind me. This isn't actually an error!")) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user