Compare commits
11 Commits
72f062ea10
...
v0.6.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 172b528138 | |||
| 70de4bb67d | |||
| ebee953955 | |||
| d2cb75c3a1 | |||
| 099926d368 | |||
| 76426094d3 | |||
| 4b101633e7 | |||
| a5a6f32037 | |||
| 4d899d3c97 | |||
| 6d5afc2445 | |||
| d34d0a31f2 |
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -242,7 +242,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asteroids"
|
name = "asteroids"
|
||||||
version = "0.6.0-dev3"
|
version = "0.6.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy-inspector-egui",
|
"bevy-inspector-egui",
|
||||||
@@ -4295,9 +4295,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.11.1"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic-util"
|
name = "portable-atomic-util"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "asteroids"
|
name = "asteroids"
|
||||||
version = "0.6.0-dev3"
|
version = "0.6.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -40,10 +40,10 @@ target/$(CARGO_TARGET)/$(CARGO_PROFILE)/asteroids.wasm: $(SRCS) Cargo.lock Cargo
|
|||||||
out:
|
out:
|
||||||
mkdir $@
|
mkdir $@
|
||||||
|
|
||||||
out/assets: out
|
out/assets: | out
|
||||||
mkdir $@
|
mkdir $@
|
||||||
|
|
||||||
out/assets/%.ogg: out/assets assets/%.ogg
|
out/assets/%.ogg: assets/%.ogg | out/assets
|
||||||
cp -ar assets/$*.ogg $@
|
cp -ar assets/$*.ogg $@
|
||||||
|
|
||||||
# Both the JS and WASM files are generated by the wasm-bindgen call, so both
|
# Both the JS and WASM files are generated by the wasm-bindgen call, so both
|
||||||
@@ -76,6 +76,8 @@ full-clean: clean
|
|||||||
# output into the web root. Only supports the "bundle-able" mode.
|
# output into the web root. Only supports the "bundle-able" mode.
|
||||||
install: web
|
install: web
|
||||||
install -dm0755 $(DESTDIR)
|
install -dm0755 $(DESTDIR)
|
||||||
|
install -dm0755 $(DESTDIR)/assets
|
||||||
install -m0644 out/asteroids.js $(DESTDIR)/
|
install -m0644 out/asteroids.js $(DESTDIR)/
|
||||||
install -m0644 out/asteroids_bg.wasm.gz $(DESTDIR)/
|
install -m0644 out/asteroids_bg.wasm.gz $(DESTDIR)/
|
||||||
install -m0644 out/asteroids.html $(DESTDIR)/
|
install -m0644 out/asteroids.html $(DESTDIR)/
|
||||||
|
install -m0644 $(ASSETS) $(DESTDIR)/assets/
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ fn input_ship_shoot(
|
|||||||
physics::Velocity(bullet_vel),
|
physics::Velocity(bullet_vel),
|
||||||
Mesh2d(game_assets.bullet().0),
|
Mesh2d(game_assets.bullet().0),
|
||||||
MeshMaterial2d(game_assets.bullet().1),
|
MeshMaterial2d(game_assets.bullet().1),
|
||||||
ship_pos.clone(), // clone ship transform
|
*ship_pos, // clone ship transform
|
||||||
Lifetime(Timer::from_seconds(BULLET_LIFETIME, TimerMode::Once)),
|
Lifetime(Timer::from_seconds(BULLET_LIFETIME, TimerMode::Once)),
|
||||||
AudioPlayer::new(game_assets.laser_sound()),
|
AudioPlayer::new(game_assets.laser_sound()),
|
||||||
PlaybackSettings::ONCE, // `Lifetime` already despawns the entity, so this doesn't need to
|
PlaybackSettings::ONCE, // `Lifetime` already despawns the entity, so this doesn't need to
|
||||||
|
|||||||
30
src/main.rs
30
src/main.rs
@@ -1,20 +1,28 @@
|
|||||||
use bevy::{prelude::*, window::WindowResolution};
|
use bevy::{prelude::*, window::WindowResolution};
|
||||||
|
|
||||||
use asteroids::{AsteroidPlugin, config::WINDOW_SIZE};
|
use asteroids::{AsteroidPlugin, config::WINDOW_SIZE};
|
||||||
|
|
||||||
|
#[cfg(feature = "debug_ui")]
|
||||||
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
||||||
|
#[cfg(feature = "debug_ui")]
|
||||||
|
use bevy_rapier2d::render::RapierDebugRenderPlugin;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
let mut app = App::new();
|
||||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
app.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
canvas: Some("#game-canvas".to_owned()),
|
canvas: Some("#game-canvas".to_owned()),
|
||||||
resolution: WindowResolution::new(WINDOW_SIZE.0, WINDOW_SIZE.1),
|
resolution: WindowResolution::new(WINDOW_SIZE.0, WINDOW_SIZE.1),
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
..default()
|
..default()
|
||||||
}))
|
}),
|
||||||
.add_plugins(AsteroidPlugin)
|
..default()
|
||||||
.add_plugins(EguiPlugin::default())
|
}))
|
||||||
|
.add_plugins(AsteroidPlugin);
|
||||||
|
|
||||||
|
#[cfg(feature = "debug_ui")]
|
||||||
|
app.add_plugins(EguiPlugin::default())
|
||||||
.add_plugins(WorldInspectorPlugin::new())
|
.add_plugins(WorldInspectorPlugin::new())
|
||||||
.run();
|
.add_plugins(RapierDebugRenderPlugin::default());
|
||||||
|
|
||||||
|
app.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ pub fn ship_impact_listener(
|
|||||||
Sparkler::at_interval(0.15),
|
Sparkler::at_interval(0.15),
|
||||||
Mesh2d(game_assets.thruster_mesh()), // borrow the thruster mesh for now
|
Mesh2d(game_assets.thruster_mesh()), // borrow the thruster mesh for now
|
||||||
MeshMaterial2d(game_assets.thruster_mat_active()), // ... and the active thruster material
|
MeshMaterial2d(game_assets.thruster_mat_active()), // ... and the active thruster material
|
||||||
player.0.clone(), // clone the player transform
|
*player.0, // clone the player transform
|
||||||
Velocity(vel),
|
Velocity(vel),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,29 +111,21 @@ pub fn collision_listener(
|
|||||||
if *one == *player {
|
if *one == *player {
|
||||||
if rocks.contains(*two) {
|
if rocks.contains(*two) {
|
||||||
// player-asteroid collision
|
// player-asteroid collision
|
||||||
dbg!("Writing ShipDestroy event");
|
|
||||||
ship_writer.write(messages::ShipDestroy);
|
ship_writer.write(messages::ShipDestroy);
|
||||||
} // else, we don't care
|
} // else, we don't care
|
||||||
} else if *two == *player {
|
} else if *two == *player && rocks.contains(*one) {
|
||||||
if rocks.contains(*one) {
|
ship_writer.write(messages::ShipDestroy);
|
||||||
dbg!("Writing ShipDestroy event");
|
|
||||||
ship_writer.write(messages::ShipDestroy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option 2: Bullet & Asteroid
|
// Option 2: Bullet & Asteroid
|
||||||
if bullets.contains(*one) {
|
if bullets.contains(*one) {
|
||||||
if rocks.contains(*two) {
|
if rocks.contains(*two) {
|
||||||
dbg!("Writing AsteroidDestroy & BulletDestroy events");
|
|
||||||
asteroid_writer.write(messages::AsteroidDestroy(*two));
|
asteroid_writer.write(messages::AsteroidDestroy(*two));
|
||||||
bullet_writer.write(messages::BulletDestroy(*one));
|
bullet_writer.write(messages::BulletDestroy(*one));
|
||||||
}
|
}
|
||||||
} else if rocks.contains(*one) {
|
} else if rocks.contains(*one) && bullets.contains(*two) {
|
||||||
if bullets.contains(*two) {
|
asteroid_writer.write(messages::AsteroidDestroy(*one));
|
||||||
dbg!("Writing AsteroidDestroy & BulletDestroy events");
|
bullet_writer.write(messages::BulletDestroy(*two));
|
||||||
asteroid_writer.write(messages::AsteroidDestroy(*one));
|
|
||||||
bullet_writer.write(messages::BulletDestroy(*two));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
color::palettes::css::{BLACK, DARK_GRAY, GREEN, LIGHT_BLUE, RED, WHITE},
|
color::palettes::css::{BLACK, DARK_GRAY, GREEN, RED, WHITE},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -180,9 +180,9 @@ fn spawn_get_ready(mut commands: Commands, mut timer: ResMut<ReadySetGoTimer>) {
|
|||||||
height: Val::Percent(30.),
|
height: Val::Percent(30.),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
BackgroundColor(LIGHT_BLUE.into()),
|
BackgroundColor(Color::NONE),
|
||||||
children![
|
children![
|
||||||
(Text::new("Get Ready!"), TextColor(BLACK.into())),
|
(Text::new("Get Ready!"), TextColor(WHITE.into())),
|
||||||
(
|
(
|
||||||
CountdownBar,
|
CountdownBar,
|
||||||
Node {
|
Node {
|
||||||
@@ -263,6 +263,7 @@ fn animate_get_ready_widget(
|
|||||||
/// on the HUD, this system would quit the game. The same will happen for
|
/// on the HUD, this system would quit the game. The same will happen for
|
||||||
/// returning to the title screen. This should be useful for making a pause
|
/// returning to the title screen. This should be useful for making a pause
|
||||||
/// menu, too.
|
/// menu, too.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn operate_buttons(
|
fn operate_buttons(
|
||||||
mut interactions: Query<
|
mut interactions: Query<
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
#prestart-controls,
|
||||||
canvas {
|
canvas {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
@@ -22,6 +23,26 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: rgb(40%, 40%, 40%);
|
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 {
|
main {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
@@ -41,13 +62,21 @@
|
|||||||
<h1>
|
<h1>
|
||||||
Robert's Bad Asteroids Game
|
Robert's Bad Asteroids Game
|
||||||
</h1>
|
</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>
|
<main>
|
||||||
<article>
|
<article>
|
||||||
<h2>Description</h2>
|
<h2>Description</h2>
|
||||||
<p>
|
<p>
|
||||||
A (work in progress) version of the Asteroids arcade game.
|
A (work in progress) version of the Asteroids arcade game.
|
||||||
</p>
|
</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>
|
||||||
<article>
|
<article>
|
||||||
<h3>Controls</h3>
|
<h3>Controls</h3>
|
||||||
@@ -90,23 +119,34 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Program Version</td>
|
<td>Program Version</td>
|
||||||
<!-- This version text is completely unchecked. I'll need to do something about that. -->
|
<!-- 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.1</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import init from './asteroids.js'
|
import init from './asteroids.js'
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
let compressed = await fetch("./asteroids_bg.wasm.gz")
|
let compressed = await fetch("./asteroids_bg.wasm.gz")
|
||||||
let wasm_stream = compressed.body.pipeThrough(new DecompressionStream("gzip"))
|
let wasm_stream = compressed.body.pipeThrough(new DecompressionStream("gzip"))
|
||||||
let blob = await new Response(wasm_stream).blob();
|
let blob = await new Response(wasm_stream).blob();
|
||||||
|
|
||||||
init(await blob.arrayBuffer()).catch((error) => {
|
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!")) {
|
if (!error.message.startsWith("Using exceptions for control flow, don't mind me. This isn't actually an error!")) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user