Compare commits
No commits in common. "f1e88d34606b4374e4ada8b6222bde4fd57d2865" and "cc2877c9d88ad8606b35515c25cb7e93e6e346ca" have entirely different histories.
f1e88d3460
...
cc2877c9d8
10 changed files with 202 additions and 1135 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -588,25 +588,6 @@ dependencies = [
|
|||
"glam",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_mod_picking"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db42ac84b1409452bbfa696d9071b9a7a2505c73620c939b758b5bf23573976a"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bevy_mod_raycast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_mod_raycast"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aead49a20f5e694f4fb59c7312f9a1813b65a2a0ac2c385d53d40f25cae896f"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_pbr"
|
||||
version = "0.8.1"
|
||||
|
@ -930,7 +911,6 @@ dependencies = [
|
|||
"bevy",
|
||||
"bevy-inspector-egui",
|
||||
"bevy_common_assets",
|
||||
"bevy_mod_picking",
|
||||
"bevy_rapier2d",
|
||||
"cpal 0.14.0",
|
||||
"crossbeam-channel",
|
||||
|
@ -939,7 +919,6 @@ dependencies = [
|
|||
"rand_distr",
|
||||
"rapier2d",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"ticktock",
|
||||
]
|
||||
|
||||
|
@ -1584,9 +1563,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.3.23"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11"
|
||||
checksum = "003000e712ad0f95857bd4d2ef8d1890069e06554101697d12050668b2f6f020"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
|
|
@ -8,6 +8,7 @@ edition = "2021"
|
|||
[dependencies]
|
||||
bevy = "0.8.1"
|
||||
bevy_common_assets = { version = "0.3.0", features = ["json"] }
|
||||
bevy-inspector-egui = "0.12.1"
|
||||
bevy_rapier2d = "0.16.2"
|
||||
crossbeam-channel = "0.5.6"
|
||||
rand = "0.8.5"
|
||||
|
@ -16,11 +17,8 @@ rapier2d = "0.14.0"
|
|||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
|
||||
bevy-inspector-egui = "0.12.1"
|
||||
bevy_mod_picking = "0.9.0"
|
||||
cpal = "0.14.0"
|
||||
hexodsp = { git = "https://github.com/WeirdConstructor/HexoDSP", default-features = false }
|
||||
serde_json = "1.0.85"
|
||||
ticktock = "0.8.0"
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies]
|
||||
|
|
13
README.md
13
README.md
|
@ -45,19 +45,6 @@ This game uses [HexoDSP](https://github.com/WeirdConstructor/HexoDSP) for audio
|
|||
|
||||
The synthetizer matrix can be edited using [HexoSynth](https://github.com/WeirdConstructor/HexoSynth) visual editor.
|
||||
|
||||
## Develop
|
||||
|
||||
Skip to level `N: u32` with the command `bevyjam <N>`.
|
||||
|
||||
Edit the level `N: u32` with the command `bevyjam <N> e`.
|
||||
|
||||
### Editor controls
|
||||
|
||||
* **Select**: left click to select, click in void to deselect, CTRL+click to select many, CTRL+A to select all
|
||||
* **Move selection**: arrows to move one step, Shift+arrows to move continuously
|
||||
* **Move camera**: CTRL+arrows
|
||||
* **Save**: CTRL+S
|
||||
|
||||
## License
|
||||
|
||||
GNU AGPL v3, CopyLeft 2022 Pascal Engélibert, Nixon Cheng
|
||||
|
|
|
@ -1,346 +1,119 @@
|
|||
{
|
||||
"levels": [
|
||||
{
|
||||
"comment": "Movement tutorial",
|
||||
"characters": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
-128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-256.0
|
||||
],
|
||||
"size": [
|
||||
800.0,
|
||||
16.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"font_size": 32.0,
|
||||
"text": "Combine the colors to synthetize a white light.\nUse arrows to move."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Switch tutorial",
|
||||
"characters": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
-128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
128.0,
|
||||
320.0
|
||||
],
|
||||
"color": [
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-256.0
|
||||
],
|
||||
"size": [
|
||||
800.0,
|
||||
16.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
128.0,
|
||||
256.0
|
||||
],
|
||||
"size": [
|
||||
96.0,
|
||||
16.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"font_size": 32.0,
|
||||
"text": "Press Tab to switch."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Absorbing filter tutorial",
|
||||
"characters": [
|
||||
{
|
||||
"pos": [
|
||||
-128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.64,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
0.0,
|
||||
0.37,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-256.0
|
||||
],
|
||||
"size": [
|
||||
800.0,
|
||||
16.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-128.0
|
||||
],
|
||||
"size": [
|
||||
800.0,
|
||||
16.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"absorbing_filters": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-192.0
|
||||
],
|
||||
"size": [
|
||||
16.0,
|
||||
112.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"font_size": 32.0,
|
||||
"text": "Press R to reset."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Rotating filter tutorial",
|
||||
"characters": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
-128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
128.0,
|
||||
-192.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-256.0
|
||||
],
|
||||
"size": [
|
||||
800.0,
|
||||
16.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-64.0
|
||||
],
|
||||
"angle": 45.0
|
||||
}
|
||||
],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"font_size": 32.0,
|
||||
"text": "Let's rotate the hue!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Game over",
|
||||
"characters": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-64.0
|
||||
],
|
||||
"color": [
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
-256.0
|
||||
],
|
||||
"size": [
|
||||
800.0,
|
||||
16.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
128.0
|
||||
],
|
||||
"font_size": 48.0,
|
||||
"text": "Thank you for playing!"
|
||||
},
|
||||
{
|
||||
"pos": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"font_size": 32.0,
|
||||
"text": "There is no more light to combine."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
"levels": [
|
||||
{
|
||||
"comment": "Movement tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -192], "color": [1,0,0,1]},
|
||||
{"pos": [-128, -192], "color": [0,1,0,1]},
|
||||
{"pos": [128, -192], "color": [0,0,1,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Combine the colors to synthetize a white light.\nUse arrows to move."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Switch tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]},
|
||||
{"pos": [128, 256], "size": [96, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -192], "color": [0,1,0,1]},
|
||||
{"pos": [-128, -192], "color": [1,0,0,1]},
|
||||
{"pos": [128, 320], "color": [0,0,1,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Press Tab to switch."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Absorbing filter tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]},
|
||||
{"pos": [0, -128], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [-128, -192], "color": [1,0.64,0,1]},
|
||||
{"pos": [128, -192], "color": [0,0.37,1,1]}
|
||||
],
|
||||
"absorbing_filters": [
|
||||
{
|
||||
"pos": [0, -192],
|
||||
"size": [16, 112],
|
||||
"color": [1,0,0,1]
|
||||
}
|
||||
],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Press R to reset."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Rotating filter tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -192], "color": [1,0,0,1]},
|
||||
{"pos": [-128, -192], "color": [1,0,0,1]},
|
||||
{"pos": [128, -192], "color": [1,0,0,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [
|
||||
{
|
||||
"pos": [0, -64],
|
||||
"angle": 45
|
||||
}
|
||||
],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Let's rotate the hue!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Game over",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -64], "color": [1,0,0,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 128],
|
||||
"font_size": 48,
|
||||
"text": "Thank you for playing!"
|
||||
},
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "There is no more light to combine."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
cargo build --release --target wasm32-unknown-unknown || exit 1
|
||||
echo "==> wasm-bindgen..."
|
||||
wasm-bindgen --out-name bevyjam --out-dir target --target web target/wasm32-unknown-unknown/release/bevyjam.wasm || exit 1
|
||||
cargo build --release --target wasm32-unknown-unknown
|
||||
wasm-bindgen --out-name bevyjam --out-dir target --target web target/wasm32-unknown-unknown/release/bevyjam.wasm
|
||||
|
|
613
src/editor.rs
613
src/editor.rs
|
@ -1,613 +0,0 @@
|
|||
#![allow(clippy::type_complexity)]
|
||||
use crate::{levels::stored::*, AppState};
|
||||
|
||||
use bevy::{
|
||||
input::{keyboard::KeyCode, Input},
|
||||
prelude::{
|
||||
shape::{Circle, Quad},
|
||||
*,
|
||||
},
|
||||
sprite::Mesh2dHandle,
|
||||
};
|
||||
use bevy_mod_picking::*;
|
||||
|
||||
pub struct EditorPlugin;
|
||||
|
||||
impl Plugin for EditorPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_event::<DragEndEvent>()
|
||||
.add_plugins(DefaultPickingPlugins)
|
||||
.add_system_set(SystemSet::on_enter(AppState::Editor).with_system(setup))
|
||||
.add_system_set(
|
||||
SystemSet::on_update(AppState::Editor)
|
||||
.with_system(move_system)
|
||||
.with_system(input_control_system)
|
||||
.with_system(follow_ends_system),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
struct DragEndEvent(Entity);
|
||||
|
||||
// Resources
|
||||
|
||||
struct CharacterList(Vec<Entity>);
|
||||
|
||||
// Components
|
||||
|
||||
#[derive(Component)]
|
||||
struct Platform;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Ends(Entity, Entity);
|
||||
|
||||
#[derive(Component)]
|
||||
struct Draggable;
|
||||
|
||||
#[derive(Component)]
|
||||
struct End(Entity);
|
||||
|
||||
#[derive(Component)]
|
||||
struct CharacterColor(Color);
|
||||
|
||||
#[derive(Component)]
|
||||
struct Size(Vec2);
|
||||
|
||||
#[derive(Component)]
|
||||
struct RotatingFilterAngle(f32);
|
||||
|
||||
#[derive(Component)]
|
||||
struct AbsorbingFilterColor(Color);
|
||||
|
||||
// Bundles
|
||||
|
||||
#[derive(Bundle)]
|
||||
struct PlatformBundle {
|
||||
#[bundle]
|
||||
mesh: ColorMesh2dBundle,
|
||||
size: Size,
|
||||
platform: Platform,
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
struct EndBundle {
|
||||
#[bundle]
|
||||
mesh: ColorMesh2dBundle,
|
||||
#[bundle]
|
||||
pickable: PickableBundle,
|
||||
draggable: Draggable,
|
||||
end: End,
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
struct CharacterBundle {
|
||||
#[bundle]
|
||||
mesh: ColorMesh2dBundle,
|
||||
color: CharacterColor,
|
||||
#[bundle]
|
||||
pickable: PickableBundle,
|
||||
draggable: Draggable,
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
struct AbsorbingFilterBundle {
|
||||
#[bundle]
|
||||
mesh: ColorMesh2dBundle,
|
||||
size: Size,
|
||||
color: AbsorbingFilterColor,
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
struct RotatingFilterBundle {
|
||||
#[bundle]
|
||||
mesh: ColorMesh2dBundle,
|
||||
angle: RotatingFilterAngle,
|
||||
#[bundle]
|
||||
pickable: PickableBundle,
|
||||
draggable: Draggable,
|
||||
}
|
||||
|
||||
// Functions
|
||||
|
||||
fn spawn_platform(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
|
||||
transform: Transform,
|
||||
size: Vec2,
|
||||
) {
|
||||
let platform = commands
|
||||
.spawn_bundle(PlatformBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
|
||||
material: materials.add(ColorMaterial::from(Color::GRAY)),
|
||||
transform,
|
||||
..default()
|
||||
},
|
||||
size: Size(size),
|
||||
platform: Platform,
|
||||
})
|
||||
.id();
|
||||
let ends = Ends(
|
||||
commands
|
||||
.spawn_bundle(EndBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Circle {
|
||||
radius: 8.,
|
||||
vertices: 12,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
|
||||
transform: Transform::from_xyz(
|
||||
transform.translation.x - size.x / 2.,
|
||||
transform.translation.y - size.y / 2.,
|
||||
0.5,
|
||||
),
|
||||
..default()
|
||||
},
|
||||
pickable: PickableBundle::default(),
|
||||
draggable: Draggable,
|
||||
end: End(platform),
|
||||
})
|
||||
.id(),
|
||||
commands
|
||||
.spawn_bundle(EndBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Circle {
|
||||
radius: 8.,
|
||||
vertices: 12,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
|
||||
transform: Transform::from_xyz(
|
||||
transform.translation.x + size.x / 2.,
|
||||
transform.translation.y + size.y / 2.,
|
||||
0.5,
|
||||
),
|
||||
..default()
|
||||
},
|
||||
pickable: PickableBundle::default(),
|
||||
draggable: Draggable,
|
||||
end: End(platform),
|
||||
})
|
||||
.id(),
|
||||
);
|
||||
commands.entity(platform).insert(ends);
|
||||
}
|
||||
|
||||
fn spawn_character(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
asset_server: &Res<AssetServer>,
|
||||
|
||||
transform: Transform,
|
||||
color: Color,
|
||||
index: usize,
|
||||
) -> Entity {
|
||||
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
|
||||
commands
|
||||
.spawn_bundle(CharacterBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Quad {
|
||||
size: Vec2 { x: 64., y: 64. },
|
||||
flip: false,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(color)),
|
||||
transform,
|
||||
..default()
|
||||
},
|
||||
color: CharacterColor(color),
|
||||
pickable: PickableBundle::default(),
|
||||
draggable: Draggable,
|
||||
})
|
||||
.with_children(|c| {
|
||||
c.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
&index.to_string(),
|
||||
TextStyle {
|
||||
font: font.clone(),
|
||||
font_size: 32.,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
.with_alignment(TextAlignment::CENTER),
|
||||
transform: Transform::from_xyz(0., 0., 1.),
|
||||
..Default::default()
|
||||
});
|
||||
})
|
||||
.id()
|
||||
}
|
||||
|
||||
fn spawn_absorbing_filter(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
|
||||
transform: Transform,
|
||||
size: Vec2,
|
||||
color: Color,
|
||||
) {
|
||||
let absorbing_filter = commands
|
||||
.spawn_bundle(AbsorbingFilterBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
|
||||
material: materials.add(ColorMaterial::from(color)),
|
||||
transform,
|
||||
..default()
|
||||
},
|
||||
size: Size(size),
|
||||
color: AbsorbingFilterColor(color),
|
||||
})
|
||||
.id();
|
||||
let ends = Ends(
|
||||
commands
|
||||
.spawn_bundle(EndBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Circle {
|
||||
radius: 8.,
|
||||
vertices: 12,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
|
||||
transform: Transform::from_xyz(
|
||||
transform.translation.x - size.x / 2.,
|
||||
transform.translation.y - size.y / 2.,
|
||||
0.5,
|
||||
),
|
||||
..default()
|
||||
},
|
||||
pickable: PickableBundle::default(),
|
||||
draggable: Draggable,
|
||||
end: End(absorbing_filter),
|
||||
})
|
||||
.id(),
|
||||
commands
|
||||
.spawn_bundle(EndBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Circle {
|
||||
radius: 8.,
|
||||
vertices: 12,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
|
||||
transform: Transform::from_xyz(
|
||||
transform.translation.x + size.x / 2.,
|
||||
transform.translation.y + size.y / 2.,
|
||||
0.5,
|
||||
),
|
||||
..default()
|
||||
},
|
||||
pickable: PickableBundle::default(),
|
||||
draggable: Draggable,
|
||||
end: End(absorbing_filter),
|
||||
})
|
||||
.id(),
|
||||
);
|
||||
commands.entity(absorbing_filter).insert(ends);
|
||||
}
|
||||
|
||||
fn spawn_rotating_filter(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
asset_server: &Res<AssetServer>,
|
||||
|
||||
transform: Transform,
|
||||
angle: f32,
|
||||
) -> Entity {
|
||||
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
|
||||
commands
|
||||
.spawn_bundle(RotatingFilterBundle {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Circle {
|
||||
radius: 32.,
|
||||
vertices: 36,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(Color::WHITE)),
|
||||
transform,
|
||||
..default()
|
||||
},
|
||||
angle: RotatingFilterAngle(angle),
|
||||
pickable: PickableBundle::default(),
|
||||
draggable: Draggable,
|
||||
})
|
||||
.with_children(|c| {
|
||||
c.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
&angle.to_string(),
|
||||
TextStyle {
|
||||
font: font.clone(),
|
||||
font_size: 32.,
|
||||
color: Color::RED,
|
||||
},
|
||||
)
|
||||
.with_alignment(TextAlignment::CENTER),
|
||||
transform: Transform::from_xyz(0., 0., 1.),
|
||||
..Default::default()
|
||||
});
|
||||
})
|
||||
.id()
|
||||
}
|
||||
|
||||
fn spawn_stored_level(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
asset_server: &Res<AssetServer>,
|
||||
|
||||
stored_level: &StoredLevel,
|
||||
) {
|
||||
for platform in stored_level.platforms.iter() {
|
||||
spawn_platform(
|
||||
commands,
|
||||
meshes,
|
||||
materials,
|
||||
Transform::from_xyz(platform.pos.x, platform.pos.y, 0.),
|
||||
platform.size,
|
||||
);
|
||||
}
|
||||
|
||||
let mut character_list = Vec::new();
|
||||
for (i, character) in stored_level.characters.iter().enumerate() {
|
||||
character_list.push(spawn_character(
|
||||
commands,
|
||||
meshes,
|
||||
materials,
|
||||
asset_server,
|
||||
Transform::from_xyz(character.pos.x, character.pos.y, 0.),
|
||||
character.color.into(),
|
||||
i,
|
||||
));
|
||||
}
|
||||
commands.insert_resource(CharacterList(character_list));
|
||||
|
||||
for absorbing_filter in stored_level.absorbing_filters.iter() {
|
||||
spawn_absorbing_filter(
|
||||
commands,
|
||||
meshes,
|
||||
materials,
|
||||
Transform::from_xyz(absorbing_filter.pos.x, absorbing_filter.pos.y, 0.),
|
||||
absorbing_filter.size,
|
||||
absorbing_filter.color.into(),
|
||||
);
|
||||
}
|
||||
|
||||
for rotating_filter in stored_level.rotating_filters.iter() {
|
||||
spawn_rotating_filter(
|
||||
commands,
|
||||
meshes,
|
||||
materials,
|
||||
asset_server,
|
||||
Transform::from_xyz(rotating_filter.pos.x, rotating_filter.pos.y, 0.),
|
||||
rotating_filter.angle,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn save_level(
|
||||
level_id: &Res<crate::game::FirstLevel>,
|
||||
stored_levels_assets: &mut ResMut<Assets<StoredLevels>>,
|
||||
stored_levels_handle: &Res<Handle<StoredLevels>>,
|
||||
character_list: &Res<CharacterList>,
|
||||
character_query: &Query<(&Transform, &CharacterColor), Without<Platform>>,
|
||||
platform_query: &Query<(&Transform, &Size), With<Platform>>,
|
||||
absorbing_filter_query: &Query<(&Transform, &Size, &AbsorbingFilterColor), Without<Platform>>,
|
||||
rotating_filter_query: &Query<
|
||||
(&Transform, &RotatingFilterAngle),
|
||||
(Without<Platform>, Without<CharacterColor>),
|
||||
>,
|
||||
) {
|
||||
let stored_levels = stored_levels_assets.get_mut(stored_levels_handle).unwrap();
|
||||
if let Some(stored_level) = stored_levels.levels.get_mut(level_id.0 .0 as usize) {
|
||||
stored_level.platforms.clear();
|
||||
for (transform, size) in platform_query.iter() {
|
||||
stored_level.platforms.push(StoredPlatform {
|
||||
pos: Vec2 {
|
||||
x: transform.translation.x,
|
||||
y: transform.translation.y,
|
||||
},
|
||||
size: size.0,
|
||||
})
|
||||
}
|
||||
|
||||
stored_level.characters.clear();
|
||||
for entity in character_list.0.iter() {
|
||||
if let Ok((transform, color)) = character_query.get(*entity) {
|
||||
stored_level.characters.push(StoredCharacter {
|
||||
pos: Vec2 {
|
||||
x: transform.translation.x,
|
||||
y: transform.translation.y,
|
||||
},
|
||||
color: color.0.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
stored_level.absorbing_filters.clear();
|
||||
for (transform, size, color) in absorbing_filter_query.iter() {
|
||||
stored_level.absorbing_filters.push(StoredAbsorbingFilter {
|
||||
pos: Vec2 {
|
||||
x: transform.translation.x,
|
||||
y: transform.translation.y,
|
||||
},
|
||||
size: size.0,
|
||||
color: color.0.into(),
|
||||
})
|
||||
}
|
||||
|
||||
stored_level.rotating_filters.clear();
|
||||
for (transform, angle) in rotating_filter_query.iter() {
|
||||
stored_level.rotating_filters.push(StoredRotatingFilter {
|
||||
pos: Vec2 {
|
||||
x: transform.translation.x,
|
||||
y: transform.translation.y,
|
||||
},
|
||||
angle: angle.0,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
match std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open("assets/game.levels.json")
|
||||
{
|
||||
Ok(mut file) => {
|
||||
serde_json::to_writer_pretty(&mut file, stored_levels).unwrap();
|
||||
println!("Saved!");
|
||||
}
|
||||
Err(e) => eprintln!("Error writing levels file: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// Systems
|
||||
|
||||
fn setup(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
camera_query: Query<Entity, With<Camera>>,
|
||||
level_id: Res<crate::game::FirstLevel>,
|
||||
stored_levels_assets: Res<Assets<StoredLevels>>,
|
||||
stored_levels_handle: Res<Handle<StoredLevels>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
commands
|
||||
.entity(camera_query.single())
|
||||
.insert_bundle(PickingCameraBundle::default());
|
||||
|
||||
if let Some(stored_level) = stored_levels_assets
|
||||
.get(&stored_levels_handle)
|
||||
.unwrap()
|
||||
.levels
|
||||
.get(level_id.0 .0 as usize)
|
||||
{
|
||||
spawn_stored_level(
|
||||
&mut commands,
|
||||
&mut meshes,
|
||||
&mut materials,
|
||||
&asset_server,
|
||||
stored_level,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn input_control_system(
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
level_id: Res<crate::game::FirstLevel>,
|
||||
mut stored_levels_assets: ResMut<Assets<StoredLevels>>,
|
||||
stored_levels_handle: Res<Handle<StoredLevels>>,
|
||||
character_list: Res<CharacterList>,
|
||||
character_query: Query<(&Transform, &CharacterColor), Without<Platform>>,
|
||||
platform_query: Query<(&Transform, &Size), With<Platform>>,
|
||||
absorbing_filter_query: Query<(&Transform, &Size, &AbsorbingFilterColor), Without<Platform>>,
|
||||
rotating_filter_query: Query<
|
||||
(&Transform, &RotatingFilterAngle),
|
||||
(Without<Platform>, Without<CharacterColor>),
|
||||
>,
|
||||
) {
|
||||
if keyboard_input.just_released(KeyCode::S)
|
||||
&& (keyboard_input.pressed(KeyCode::LControl) || keyboard_input.pressed(KeyCode::RControl))
|
||||
{
|
||||
save_level(
|
||||
&level_id,
|
||||
&mut stored_levels_assets,
|
||||
&stored_levels_handle,
|
||||
&character_list,
|
||||
&character_query,
|
||||
&platform_query,
|
||||
&absorbing_filter_query,
|
||||
&rotating_filter_query,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn move_system(
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
mut camera_query: Query<&mut Transform, (With<Camera>, Without<Draggable>)>,
|
||||
mut drag_query: Query<(&mut Transform, &Selection, Option<&End>), With<Draggable>>,
|
||||
mut drag_end_event: EventWriter<DragEndEvent>,
|
||||
) {
|
||||
if keyboard_input.pressed(KeyCode::LControl) || keyboard_input.pressed(KeyCode::RControl) {
|
||||
let mut transform = camera_query.single_mut();
|
||||
let drag = Vec3 {
|
||||
x: (keyboard_input.pressed(KeyCode::Right) as i8
|
||||
- keyboard_input.pressed(KeyCode::Left) as i8) as _,
|
||||
y: (keyboard_input.pressed(KeyCode::Up) as i8
|
||||
- keyboard_input.pressed(KeyCode::Down) as i8) as _,
|
||||
z: 0.,
|
||||
} * 8.;
|
||||
transform.translation += drag;
|
||||
return;
|
||||
}
|
||||
|
||||
let drag = if keyboard_input.pressed(KeyCode::LShift) || keyboard_input.pressed(KeyCode::RShift)
|
||||
{
|
||||
Vec3 {
|
||||
x: (keyboard_input.pressed(KeyCode::Right) as i8
|
||||
- keyboard_input.pressed(KeyCode::Left) as i8) as _,
|
||||
y: (keyboard_input.pressed(KeyCode::Up) as i8
|
||||
- keyboard_input.pressed(KeyCode::Down) as i8) as _,
|
||||
z: 0.,
|
||||
}
|
||||
} else {
|
||||
Vec3 {
|
||||
x: (keyboard_input.just_pressed(KeyCode::Right) as i8
|
||||
- keyboard_input.just_pressed(KeyCode::Left) as i8) as _,
|
||||
y: (keyboard_input.just_pressed(KeyCode::Up) as i8
|
||||
- keyboard_input.just_pressed(KeyCode::Down) as i8) as _,
|
||||
z: 0.,
|
||||
}
|
||||
} * 8.;
|
||||
if drag != Vec3::ZERO {
|
||||
for (mut transform, selection, end) in drag_query.iter_mut() {
|
||||
if selection.selected() {
|
||||
transform.translation += drag;
|
||||
if let Some(End(entity)) = end {
|
||||
drag_end_event.send(DragEndEvent(*entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn follow_ends_system(
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut follower_query: Query<(&mut Transform, &mut Mesh2dHandle, &mut Size, &Ends)>,
|
||||
end_query: Query<&Transform, Without<Ends>>,
|
||||
mut drag_end_event: EventReader<DragEndEvent>,
|
||||
) {
|
||||
for DragEndEvent(entity) in drag_end_event.iter() {
|
||||
if let Ok((mut transform, mut mesh, mut size, Ends(end1, end2))) =
|
||||
follower_query.get_mut(*entity)
|
||||
{
|
||||
if let (Ok(end1), Ok(end2)) = (end_query.get(*end1), end_query.get(*end2)) {
|
||||
transform.translation.x = (end1.translation.x + end2.translation.x) / 2.;
|
||||
transform.translation.y = (end1.translation.y + end2.translation.y) / 2.;
|
||||
size.0 = Vec2 {
|
||||
x: (end2.translation.x - end1.translation.x).abs(),
|
||||
y: (end2.translation.y - end1.translation.y).abs(),
|
||||
};
|
||||
*mesh = meshes
|
||||
.add(Mesh::from(Quad {
|
||||
size: size.0,
|
||||
flip: false,
|
||||
}))
|
||||
.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -471,13 +471,14 @@ fn move_camera(
|
|||
|
||||
let size: Vec2 = camera.logical_viewport_size().unwrap();
|
||||
let half_height: f32 = size.y * 0.5;
|
||||
let mut target_translation = character_transform.translation;
|
||||
let mut target_translation = character_transform.translation;
|
||||
// prevent camera from going too low
|
||||
target_translation.y = target_translation.y.max(half_height - MARGIN);
|
||||
|
||||
camera_transform.translation = camera_transform
|
||||
.translation
|
||||
.lerp(target_translation, time.delta_seconds() * FOLLOW_SPEED);
|
||||
camera_transform.translation = camera_transform.translation.lerp(
|
||||
target_translation,
|
||||
time.delta_seconds() * FOLLOW_SPEED,
|
||||
);
|
||||
|
||||
// always make sure that camera is away from the object in order to render them
|
||||
camera_transform.translation.z = 999.0;
|
||||
|
|
114
src/levels.rs
114
src/levels.rs
|
@ -1,7 +1,5 @@
|
|||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub use stored::*;
|
||||
|
||||
use crate::game::*;
|
||||
|
||||
use bevy::{prelude::*, reflect::TypeUuid};
|
||||
|
@ -57,6 +55,60 @@ pub fn post_setup_level(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "1fbba930-644b-0d62-2514-4b302b945327"]
|
||||
pub struct StoredLevels {
|
||||
levels: Vec<StoredLevel>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "a1464a30-1f57-a654-d56c-ded41032af0b"]
|
||||
pub struct StoredLevel {
|
||||
pub comment: String,
|
||||
pub characters: Vec<StoredCharacter>,
|
||||
pub platforms: Vec<StoredPlatform>,
|
||||
pub absorbing_filters: Vec<StoredAbsorbingFilter>,
|
||||
pub rotating_filters: Vec<StoredRotatingFilter>,
|
||||
pub texts: Vec<StoredText>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "1c798f8c-ef15-c528-693e-76becdef6b10"]
|
||||
pub struct StoredCharacter {
|
||||
pub pos: Vec2,
|
||||
pub color: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "31696095-59de-93be-b5e9-333c2afbc900"]
|
||||
pub struct StoredPlatform {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "bcad7fff-0605-c4e3-3cd4-42d5bbaad926"]
|
||||
pub struct StoredAbsorbingFilter {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
pub color: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "fa2843f2-6e34-601b-6c46-4827b0370b3f"]
|
||||
pub struct StoredRotatingFilter {
|
||||
pub pos: Vec2,
|
||||
pub angle: f32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "72f6321a-f01f-6eea-9b17-3159837a2fd3"]
|
||||
pub struct StoredText {
|
||||
pub pos: Vec2,
|
||||
pub font_size: f32,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
pub fn spawn_stored_level(
|
||||
commands: &mut Commands,
|
||||
character_meshes: &Res<CharacterMeshes>,
|
||||
|
@ -127,61 +179,3 @@ pub fn spawn_stored_level(
|
|||
.insert(Level);
|
||||
}
|
||||
}
|
||||
|
||||
pub mod stored {
|
||||
use super::*;
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "1fbba930-644b-0d62-2514-4b302b945327"]
|
||||
pub struct StoredLevels {
|
||||
pub levels: Vec<StoredLevel>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "a1464a30-1f57-a654-d56c-ded41032af0b"]
|
||||
pub struct StoredLevel {
|
||||
pub comment: String,
|
||||
pub characters: Vec<StoredCharacter>,
|
||||
pub platforms: Vec<StoredPlatform>,
|
||||
pub absorbing_filters: Vec<StoredAbsorbingFilter>,
|
||||
pub rotating_filters: Vec<StoredRotatingFilter>,
|
||||
pub texts: Vec<StoredText>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "1c798f8c-ef15-c528-693e-76becdef6b10"]
|
||||
pub struct StoredCharacter {
|
||||
pub pos: Vec2,
|
||||
pub color: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "31696095-59de-93be-b5e9-333c2afbc900"]
|
||||
pub struct StoredPlatform {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "bcad7fff-0605-c4e3-3cd4-42d5bbaad926"]
|
||||
pub struct StoredAbsorbingFilter {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
pub color: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "fa2843f2-6e34-601b-6c46-4827b0370b3f"]
|
||||
pub struct StoredRotatingFilter {
|
||||
pub pos: Vec2,
|
||||
pub angle: f32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "72f6321a-f01f-6eea-9b17-3159837a2fd3"]
|
||||
pub struct StoredText {
|
||||
pub pos: Vec2,
|
||||
pub font_size: f32,
|
||||
pub text: String,
|
||||
}
|
||||
}
|
||||
|
|
92
src/main.rs
92
src/main.rs
|
@ -1,9 +1,5 @@
|
|||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod audio;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod editor;
|
||||
mod filters;
|
||||
mod game;
|
||||
mod levels;
|
||||
|
@ -11,7 +7,6 @@ mod menu;
|
|||
mod particle_effect;
|
||||
|
||||
use bevy::{
|
||||
asset::{Asset, HandleId, LoadState},
|
||||
prelude::*,
|
||||
window::{WindowId, WindowMode},
|
||||
};
|
||||
|
@ -20,22 +15,9 @@ use bevy_rapier2d::prelude::*;
|
|||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
enum AppState {
|
||||
Loading,
|
||||
Menu,
|
||||
Game,
|
||||
Win,
|
||||
Editor,
|
||||
}
|
||||
|
||||
struct UseEditor(bool);
|
||||
|
||||
struct LoadingAssets(Vec<HandleId>);
|
||||
|
||||
impl LoadingAssets {
|
||||
fn add<T: Asset>(&mut self, handle: Handle<T>) -> Handle<T> {
|
||||
self.0.push(handle.id);
|
||||
handle
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -46,45 +28,32 @@ fn main() {
|
|||
std::thread::spawn(move || audio::setup(audio_event_receiver));
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let (first_level, use_editor) = {
|
||||
let mut args = std::env::args().skip(1);
|
||||
(
|
||||
game::LevelId(args.next().map_or(0, |s| s.parse().unwrap_or(0))),
|
||||
args.next().map_or(false, |s| s == "e"),
|
||||
)
|
||||
};
|
||||
let first_level = game::LevelId(
|
||||
std::env::args()
|
||||
.nth(1)
|
||||
.map_or(0, |s| s.parse().unwrap_or(0)),
|
||||
);
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let (first_level, use_editor) = (game::LevelId(0), false);
|
||||
let first_level = game::LevelId(0);
|
||||
|
||||
let mut app = App::new();
|
||||
app.insert_resource(Msaa { samples: 4 })
|
||||
App::new()
|
||||
.insert_resource(Msaa { samples: 4 })
|
||||
.insert_resource(audio_event_sender)
|
||||
.insert_resource(UseEditor(use_editor))
|
||||
.add_state(AppState::Loading)
|
||||
.add_state(AppState::Menu)
|
||||
.insert_resource(game::FirstLevel(first_level))
|
||||
.insert_resource(ClearColor(Color::BLACK))
|
||||
.add_plugins(DefaultPlugins)
|
||||
//.add_plugin(RapierDebugRenderPlugin::default())
|
||||
//.add_plugin(bevy_inspector_egui::WorldInspectorPlugin::new())
|
||||
.add_plugin(JsonAssetPlugin::<levels::StoredLevels>::new(&[
|
||||
"levels.json",
|
||||
]));
|
||||
|
||||
if !use_editor {
|
||||
app.add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(64.0))
|
||||
.add_plugin(menu::MenuPlugin)
|
||||
.add_plugin(game::GamePlugin)
|
||||
.add_plugin(particle_effect::ParticleEffectPlugin);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if use_editor {
|
||||
app.add_plugin(editor::EditorPlugin);
|
||||
}
|
||||
|
||||
app.add_system(keyboard_util_system)
|
||||
]))
|
||||
.add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(64.0))
|
||||
//.add_plugin(RapierDebugRenderPlugin::default())
|
||||
.add_plugin(menu::MenuPlugin)
|
||||
.add_plugin(game::GamePlugin)
|
||||
.add_plugin(particle_effect::ParticleEffectPlugin)
|
||||
//.add_plugin(bevy_inspector_egui::WorldInspectorPlugin::new())
|
||||
.add_system(keyboard_util_system)
|
||||
.add_startup_system(setup)
|
||||
.add_system_set(SystemSet::on_update(AppState::Loading).with_system(loading_system))
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -94,13 +63,9 @@ fn setup(mut commands: Commands, mut windows: ResMut<Windows>, asset_server: Res
|
|||
.unwrap()
|
||||
.set_title(String::from("Bevyjam"));
|
||||
|
||||
let mut assets = LoadingAssets(Vec::new());
|
||||
commands.insert_resource(
|
||||
assets.add(asset_server.load::<levels::StoredLevels, _>("game.levels.json")),
|
||||
);
|
||||
commands.insert_resource(assets.add(asset_server.load::<Font, _>("UacariLegacy-Thin.ttf")));
|
||||
commands.insert_resource(assets.add(asset_server.load::<Image, _>("bevy.png")));
|
||||
commands.insert_resource(assets);
|
||||
commands.insert_resource(asset_server.load::<levels::StoredLevels, _>("game.levels.json"));
|
||||
commands.insert_resource(asset_server.load::<Font, _>("UacariLegacy-Thin.ttf"));
|
||||
commands.insert_resource(asset_server.load::<Image, _>("bevy.png"));
|
||||
|
||||
commands.spawn_bundle(Camera2dBundle::default());
|
||||
commands.insert_resource(AmbientLight {
|
||||
|
@ -109,23 +74,6 @@ fn setup(mut commands: Commands, mut windows: ResMut<Windows>, asset_server: Res
|
|||
});
|
||||
}
|
||||
|
||||
fn loading_system(
|
||||
asset_server: Res<AssetServer>,
|
||||
use_editor: Res<UseEditor>,
|
||||
assets: Res<LoadingAssets>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
) {
|
||||
if asset_server.get_group_load_state(assets.0.iter().copied()) == LoadState::Loaded {
|
||||
app_state
|
||||
.replace(if use_editor.0 {
|
||||
AppState::Editor
|
||||
} else {
|
||||
AppState::Menu
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn keyboard_util_system(keyboard_input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ impl FromWorld for ParticleMesh {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(bevy_inspector_egui::Inspectable)]
|
||||
pub struct ParticleEffectResource {
|
||||
pub translation: Vec3,
|
||||
pub prev_translation: Vec3,
|
||||
|
|
Loading…
Reference in a new issue