Compare commits

..

2 commits

Author SHA1 Message Date
21d98a4a1d
cli: skip to level 2022-08-25 15:52:28 +02:00
445f3850ca
Tutorial levels 2022-08-25 15:39:16 +02:00
10 changed files with 215 additions and 29 deletions

View file

@ -17,6 +17,7 @@
* (?) multiplayer * (?) multiplayer
* more audio * more audio
* "jumpable" component to avoid jumping on sensors * "jumpable" component to avoid jumping on sensors
* bug: in level2, move the blue character to win, then reset. The characters are lighter than expected.
## Build ## Build

View file

@ -21,6 +21,8 @@ pub enum AudioMsg {
Switch, Switch,
} }
pub struct FirstLevel(pub LevelId);
#[derive(Clone, Copy, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub struct LevelId(pub u32); pub struct LevelId(pub u32);
@ -99,12 +101,13 @@ pub struct CollisionCount(usize);
// Systems // Systems
fn setup( fn setup(
first_level: Res<FirstLevel>,
mut current_level: ResMut<CurrentLevel>, mut current_level: ResMut<CurrentLevel>,
mut level_startup_event: EventWriter<LevelStartupEvent>, mut level_startup_event: EventWriter<LevelStartupEvent>,
mut camera_query: Query<&mut Transform, With<Camera>>, mut camera_query: Query<&mut Transform, With<Camera>>,
) { ) {
if current_level.0.is_none() { if current_level.0.is_none() {
current_level.0 = Some(LevelId(0)); current_level.0 = Some(first_level.0);
} }
crate::levels::setup_level(&mut level_startup_event, &mut camera_query); crate::levels::setup_level(&mut level_startup_event, &mut camera_query);
@ -281,6 +284,25 @@ fn collision_event_system(
c_color.0 = filter.apply(c_color.0); c_color.0 = filter.apply(c_color.0);
*c_material = materials.add(ColorMaterial::from(c_color.0)); *c_material = materials.add(ColorMaterial::from(c_color.0));
if c_player.is_some() {
audio
.send(AudioMsg::Color([
c_color.0.r(),
c_color.0.g(),
c_color.0.b(),
]))
.ok();
}
} else if let (
Ok((mut c_color, _c_transform, mut c_material, c_player)),
Ok(filter),
) = (
character_query.get_mut(*e2),
pass_through_filter_query.get(*e1),
) {
c_color.0 = filter.apply(c_color.0);
*c_material = materials.add(ColorMaterial::from(c_color.0));
if c_player.is_some() { if c_player.is_some() {
audio audio
.send(AudioMsg::Color([ .send(AudioMsg::Color([
@ -425,7 +447,7 @@ fn win_setup(
"Press ENTER to level up", "Press ENTER to level up",
TextStyle { TextStyle {
font, font,
font_size: 32.0, font_size: 36.0,
color: Color::WHITE, color: Color::WHITE,
}, },
) )

View file

@ -3,6 +3,8 @@
mod game_over; mod game_over;
mod level0; mod level0;
mod level1; mod level1;
mod level2;
mod level3;
use crate::game::*; use crate::game::*;
@ -53,6 +55,22 @@ pub fn post_setup_level(
&audio, &audio,
&asset_server, &asset_server,
), ),
2 => level2::setup(
&mut commands,
&mut meshes,
&character_meshes,
&mut materials,
&audio,
&asset_server,
),
3 => level3::setup(
&mut commands,
&mut meshes,
&character_meshes,
&mut materials,
&audio,
&asset_server,
),
_ => game_over::setup( _ => game_over::setup(
&mut commands, &mut commands,
&mut meshes, &mut meshes,

View file

@ -54,7 +54,7 @@ pub fn setup(
character_meshes, character_meshes,
materials, materials,
audio, audio,
Transform::from_xyz(-128., -64., 0.), Transform::from_xyz(0., -64., 0.),
Color::RED, Color::RED,
true, true,
); );

View file

@ -1,3 +1,5 @@
// Movement tutorial
use crate::game::*; use crate::game::*;
use bevy::prelude::*; use bevy::prelude::*;
@ -14,7 +16,7 @@ pub fn setup(
commands commands
.spawn_bundle(Text2dBundle { .spawn_bundle(Text2dBundle {
text: Text::from_section( text: Text::from_section(
"Combine the colors to synthetize a white light.\nTab to switch; Arrows to move.", "Combine the colors to synthetize a white light.\nUse arrows to move.",
TextStyle { TextStyle {
font, font,
font_size: 32.0, font_size: 32.0,
@ -40,9 +42,9 @@ pub fn setup(
materials, materials,
audio, audio,
[ [
(Transform::from_xyz(-128., -64., 0.), Color::RED), (Transform::from_xyz(0., -192., 0.), Color::RED),
(Transform::from_xyz(0., -64., 0.), Color::GREEN), (Transform::from_xyz(-128., -192., 0.), Color::GREEN),
(Transform::from_xyz(128., -64., 0.), Color::BLUE), (Transform::from_xyz(128., -192., 0.), Color::BLUE),
], ],
); );
} }

View file

@ -1,3 +1,5 @@
// Switch tutorial
use crate::game::*; use crate::game::*;
use bevy::prelude::*; use bevy::prelude::*;
@ -10,6 +12,22 @@ pub fn setup(
audio: &Res<crossbeam_channel::Sender<AudioMsg>>, audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
asset_server: &Res<AssetServer>, asset_server: &Res<AssetServer>,
) { ) {
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
commands
.spawn_bundle(Text2dBundle {
text: Text::from_section(
"Press Tab to switch.",
TextStyle {
font,
font_size: 32.0,
color: Color::WHITE,
},
)
.with_alignment(TextAlignment::CENTER),
..Default::default()
})
.insert(Level);
spawn_platforms( spawn_platforms(
commands, commands,
meshes, meshes,
@ -20,8 +38,8 @@ pub fn setup(
Vec2 { x: 800.0, y: 16.0 }, Vec2 { x: 800.0, y: 16.0 },
), ),
( (
Transform::from_xyz(256.0, -128.0, 0.0), Transform::from_xyz(128.0, 256.0, 0.0),
Vec2 { x: 400.0, y: 16.0 }, Vec2 { x: 96.0, y: 16.0 },
), ),
], ],
); );
@ -32,25 +50,9 @@ pub fn setup(
materials, materials,
audio, audio,
[ [
(Transform::from_xyz(128., 64., 0.), Color::BLUE), (Transform::from_xyz(0., -192., 0.), Color::GREEN),
(Transform::from_xyz(-128., -128., 0.), Color::RED), (Transform::from_xyz(-128., -192., 0.), Color::RED),
(Transform::from_xyz(0., -128., 0.), Color::GREEN), (Transform::from_xyz(128., 320., 0.), Color::BLUE),
], ],
); );
spawn_absorbing_filter(
commands,
meshes,
materials,
Transform::from_xyz(0., 0., 2.),
Vec2 { x: 128.0, y: 16.0 },
Color::RED,
);
spawn_rotating_filter(
commands,
asset_server,
Transform::from_xyz(256., -224., 2.),
45.,
);
} }

72
src/levels/level2.rs Normal file
View file

@ -0,0 +1,72 @@
// Absorbing filter tutorial
use crate::game::*;
use bevy::prelude::*;
pub fn setup(
commands: &mut Commands,
meshes: &mut ResMut<Assets<Mesh>>,
character_meshes: &Res<CharacterMeshes>,
materials: &mut ResMut<Assets<ColorMaterial>>,
audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
asset_server: &Res<AssetServer>,
) {
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
commands
.spawn_bundle(Text2dBundle {
text: Text::from_section(
"Press R to reset.",
TextStyle {
font,
font_size: 32.0,
color: Color::WHITE,
},
)
.with_alignment(TextAlignment::CENTER),
..Default::default()
})
.insert(Level);
spawn_platforms(
commands,
meshes,
materials,
[
(
Transform::from_xyz(0.0, -256.0, 0.0),
Vec2 { x: 800.0, y: 16.0 },
),
(
Transform::from_xyz(0.0, -128.0, 0.0),
Vec2 { x: 800.0, y: 16.0 },
),
],
);
spawn_characters(
commands,
character_meshes,
materials,
audio,
[
(
Transform::from_xyz(-128., -192., 0.),
Color::rgba(1., 0.64, 0., 1.),
),
(
Transform::from_xyz(128., -192., 0.),
Color::rgba(0., 0.37, 1., 1.),
),
],
);
spawn_absorbing_filter(
commands,
meshes,
materials,
Transform::from_xyz(0., -192., 2.),
Vec2 { x: 16.0, y: 112.0 },
Color::RED,
);
}

59
src/levels/level3.rs Normal file
View file

@ -0,0 +1,59 @@
// Rotating filter tutorial
use crate::game::*;
use bevy::prelude::*;
pub fn setup(
commands: &mut Commands,
meshes: &mut ResMut<Assets<Mesh>>,
character_meshes: &Res<CharacterMeshes>,
materials: &mut ResMut<Assets<ColorMaterial>>,
audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
asset_server: &Res<AssetServer>,
) {
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
commands
.spawn_bundle(Text2dBundle {
text: Text::from_section(
"Let's rotate the hue!",
TextStyle {
font,
font_size: 32.0,
color: Color::WHITE,
},
)
.with_alignment(TextAlignment::CENTER),
..Default::default()
})
.insert(Level);
spawn_platforms(
commands,
meshes,
materials,
[(
Transform::from_xyz(0.0, -256.0, 0.0),
Vec2 { x: 800.0, y: 16.0 },
)],
);
spawn_characters(
commands,
character_meshes,
materials,
audio,
[
(Transform::from_xyz(0., -192., 0.), Color::RED),
(Transform::from_xyz(-128., -192., 0.), Color::RED),
(Transform::from_xyz(128., -192., 0.), Color::RED),
],
);
spawn_rotating_filter(
commands,
asset_server,
Transform::from_xyz(0., -64., 2.),
45.,
);
}

View file

@ -26,10 +26,20 @@ fn main() {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
std::thread::spawn(move || audio::setup(audio_event_receiver)); std::thread::spawn(move || audio::setup(audio_event_receiver));
#[cfg(not(target_arch = "wasm32"))]
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 = game::LevelId(0);
App::new() App::new()
.insert_resource(Msaa { samples: 4 }) .insert_resource(Msaa { samples: 4 })
.insert_resource(audio_event_sender) .insert_resource(audio_event_sender)
.add_state(AppState::Menu) .add_state(AppState::Menu)
.insert_resource(game::FirstLevel(first_level))
.insert_resource(ClearColor(Color::BLACK)) .insert_resource(ClearColor(Color::BLACK))
.add_plugins(DefaultPlugins) .add_plugins(DefaultPlugins)
.add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(64.0)) .add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(64.0))

View file

@ -26,7 +26,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
"BEVYJAM", "BEVYJAM",
TextStyle { TextStyle {
font: font.clone(), font: font.clone(),
font_size: 48.0, font_size: 96.0,
color: Color::WHITE, color: Color::WHITE,
}, },
) )