character can now only jump on platforms
This commit is contained in:
parent
4fc53c04aa
commit
3c721c3225
1 changed files with 170 additions and 131 deletions
301
src/game.rs
301
src/game.rs
|
@ -57,6 +57,8 @@ impl Plugin for GamePlugin {
|
|||
.with_system(character_particle_effect_system)
|
||||
.with_system(move_win_text_system),
|
||||
)
|
||||
.add_system_to_stage(CoreStage::PostUpdate, char_char_collision_event_system)
|
||||
.add_system_to_stage(CoreStage::PostUpdate, char_airbound_event_system)
|
||||
.add_system_to_stage(CoreStage::PostUpdate, collision_event_system);
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +104,10 @@ pub struct CharacterColor(pub Color);
|
|||
pub struct Player;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct CollisionCount(usize);
|
||||
pub struct Platform;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Airbound(bool);
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Melty(pub Color);
|
||||
|
@ -198,7 +203,7 @@ pub fn spawn_character(
|
|||
.insert(Sensor)
|
||||
.insert(Collider::cuboid(30., 0.5))
|
||||
.insert(ActiveEvents::COLLISION_EVENTS)
|
||||
.insert(CollisionCount(0));
|
||||
.insert(Airbound(true));
|
||||
});
|
||||
|
||||
character_list.0.insert(entity_commands.id());
|
||||
|
@ -239,7 +244,8 @@ pub fn spawn_platform(
|
|||
..default()
|
||||
})
|
||||
.insert(Collider::cuboid(size.x / 2., size.y / 2.))
|
||||
.insert(Level);
|
||||
.insert(Level)
|
||||
.insert(Platform);
|
||||
}
|
||||
|
||||
pub fn spawn_melty_platform(
|
||||
|
@ -275,9 +281,113 @@ pub fn spawn_melty_platform(
|
|||
});
|
||||
}
|
||||
|
||||
fn char_char_collision_event_system(
|
||||
mut commands: Commands,
|
||||
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
character_query: Query<(
|
||||
&mut CharacterColor,
|
||||
&Transform,
|
||||
&mut Handle<ColorMaterial>,
|
||||
Option<&Player>,
|
||||
)>,
|
||||
|
||||
mut character_list: ResMut<CharacterList>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
character_meshes: Res<CharacterMeshes>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
) {
|
||||
for collision_event in collision_events.iter() {
|
||||
if let CollisionEvent::Started(e1, e2, _flags) = collision_event {
|
||||
if let (
|
||||
Ok((c1_color, c1_transform, _c1_material, c1_player)),
|
||||
Ok((c2_color, c2_transform, _c2_material, c2_player)),
|
||||
) = (character_query.get(*e1), character_query.get(*e2)) {
|
||||
character_list.0.remove(e1);
|
||||
character_list.0.remove(e2);
|
||||
commands.entity(*e1).despawn_recursive();
|
||||
commands.entity(*e2).despawn_recursive();
|
||||
|
||||
let new_color = (Vec4::from(c1_color.0) + Vec4::from(c2_color.0))
|
||||
.clamp(Vec4::ZERO, Vec4::ONE);
|
||||
|
||||
// If color approximately white
|
||||
if app_state.current() == &AppState::Game && new_color.min_element() >= 0.9 {
|
||||
app_state.replace(AppState::Win).ok();
|
||||
}
|
||||
|
||||
// position character based on current player location
|
||||
spawn_character(
|
||||
&mut commands,
|
||||
&character_meshes,
|
||||
&mut materials,
|
||||
&audio,
|
||||
&mut character_list,
|
||||
if c1_player.is_some() {
|
||||
*c1_transform
|
||||
} else if c2_player.is_some() {
|
||||
*c2_transform
|
||||
} else {
|
||||
Transform::identity().with_translation(
|
||||
(c1_transform.translation + c2_transform.translation) * 0.5,
|
||||
)
|
||||
},
|
||||
new_color.into(),
|
||||
c1_player.is_some() || c2_player.is_some(),
|
||||
);
|
||||
|
||||
audio.send(AudioMsg::Fusion).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn char_airbound_event_system(
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
mut airbound_query: Query<&mut Airbound>,
|
||||
platform_query: Query<&Platform>,
|
||||
) {
|
||||
// detect platform + player collisions only
|
||||
for collision_event in collision_events.iter() {
|
||||
match collision_event {
|
||||
CollisionEvent::Started(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut airbound), Ok(_)) = (
|
||||
airbound_query.get_mut(*e1),
|
||||
platform_query.get(*e2),
|
||||
) {
|
||||
airbound.0 = false;
|
||||
} else if let (Ok(mut airbound), Ok(_)) = (
|
||||
airbound_query.get_mut(*e2),
|
||||
platform_query.get(*e1),
|
||||
) {
|
||||
airbound.0 = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CollisionEvent::Stopped(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut airbound), Ok(_)) = (
|
||||
airbound_query.get_mut(*e1),
|
||||
platform_query.get(*e2),
|
||||
) {
|
||||
airbound.0 = true;
|
||||
} else if let (Ok(mut airbound), Ok(_)) = (
|
||||
airbound_query.get_mut(*e2),
|
||||
platform_query.get(*e1),
|
||||
) {
|
||||
airbound.0 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collision_event_system(
|
||||
mut commands: Commands,
|
||||
character_meshes: Res<CharacterMeshes>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
mut character_query: Query<(
|
||||
|
@ -288,134 +398,64 @@ fn collision_event_system(
|
|||
)>,
|
||||
pass_through_filter_query: Query<&PassThroughFilter>,
|
||||
melty_query: Query<&Melty>,
|
||||
mut collision_counter_query: Query<&mut CollisionCount>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
mut character_list: ResMut<CharacterList>,
|
||||
) {
|
||||
for collision_event in collision_events.iter() {
|
||||
match collision_event {
|
||||
CollisionEvent::Started(e1, e2, flags) => {
|
||||
if flags.is_empty() {
|
||||
if let (
|
||||
Ok((c1_color, c1_transform, _c1_material, c1_player)),
|
||||
Ok((c2_color, c2_transform, _c2_material, c2_player)),
|
||||
) = (character_query.get(*e1), character_query.get(*e2))
|
||||
{
|
||||
character_list.0.remove(e1);
|
||||
character_list.0.remove(e2);
|
||||
commands.entity(*e1).despawn_recursive();
|
||||
commands.entity(*e2).despawn_recursive();
|
||||
if let CollisionEvent::Started(e1, e2, flags) = collision_event {
|
||||
if flags.is_empty() {
|
||||
if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) =
|
||||
(character_query.get_mut(*e1), melty_query.get(*e2))
|
||||
{
|
||||
if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. {
|
||||
commands.entity(*e2).despawn_recursive();
|
||||
}
|
||||
} else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) =
|
||||
(character_query.get_mut(*e2), melty_query.get(*e1))
|
||||
{
|
||||
if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. {
|
||||
commands.entity(*e1).despawn_recursive();
|
||||
}
|
||||
}
|
||||
} else if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok((mut c_color, _c_transform, mut c_material, c_player)), Ok(filter)) = (
|
||||
character_query.get_mut(*e1),
|
||||
pass_through_filter_query.get(*e2),
|
||||
) {
|
||||
c_color.0 = filter.apply(c_color.0);
|
||||
*c_material = materials.add(ColorMaterial::from(c_color.0));
|
||||
|
||||
let new_color = (Vec4::from(c1_color.0) + Vec4::from(c2_color.0))
|
||||
.clamp(Vec4::ZERO, Vec4::ONE);
|
||||
if c_player.is_some() {
|
||||
audio
|
||||
.send(AudioMsg::Color([
|
||||
c_color.0.r(),
|
||||
c_color.0.g(),
|
||||
c_color.0.b(),
|
||||
]))
|
||||
.ok();
|
||||
audio.send(AudioMsg::Switch).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 color approximately white
|
||||
if app_state.current() == &AppState::Game && new_color.min_element() >= 0.9
|
||||
{
|
||||
app_state.replace(AppState::Win).ok();
|
||||
}
|
||||
|
||||
// position character based on current player location
|
||||
spawn_character(
|
||||
&mut commands,
|
||||
&character_meshes,
|
||||
&mut materials,
|
||||
&audio,
|
||||
&mut character_list,
|
||||
if c1_player.is_some() {
|
||||
*c1_transform
|
||||
} else if c2_player.is_some() {
|
||||
*c2_transform
|
||||
} else {
|
||||
Transform::identity().with_translation(
|
||||
(c1_transform.translation + c2_transform.translation) / 2.,
|
||||
)
|
||||
},
|
||||
new_color.into(),
|
||||
c1_player.is_some() || c2_player.is_some(),
|
||||
);
|
||||
|
||||
audio.send(AudioMsg::Fusion).ok();
|
||||
} else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) =
|
||||
(character_query.get_mut(*e1), melty_query.get(*e2))
|
||||
{
|
||||
if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. {
|
||||
commands.entity(*e2).despawn_recursive();
|
||||
}
|
||||
} else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) =
|
||||
(character_query.get_mut(*e2), melty_query.get(*e1))
|
||||
{
|
||||
if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. {
|
||||
commands.entity(*e1).despawn_recursive();
|
||||
}
|
||||
}
|
||||
} else if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok((mut c_color, _c_transform, mut c_material, c_player)), Ok(filter)) = (
|
||||
character_query.get_mut(*e1),
|
||||
pass_through_filter_query.get(*e2),
|
||||
) {
|
||||
c_color.0 = filter.apply(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();
|
||||
audio.send(AudioMsg::Switch).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() {
|
||||
audio
|
||||
.send(AudioMsg::Color([
|
||||
c_color.0.r(),
|
||||
c_color.0.g(),
|
||||
c_color.0.b(),
|
||||
]))
|
||||
.ok();
|
||||
audio.send(AudioMsg::Switch).ok();
|
||||
}
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e1),
|
||||
character_query.get_mut(*e2),
|
||||
) {
|
||||
collision_count.0 += 1;
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e2),
|
||||
character_query.get_mut(*e1),
|
||||
) {
|
||||
collision_count.0 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
CollisionEvent::Stopped(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e1),
|
||||
character_query.get_mut(*e2),
|
||||
) {
|
||||
collision_count.0 = collision_count.0.saturating_sub(1);
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e2),
|
||||
character_query.get_mut(*e1),
|
||||
) {
|
||||
collision_count.0 = collision_count.0.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if c_player.is_some() {
|
||||
audio
|
||||
.send(AudioMsg::Color([
|
||||
c_color.0.r(),
|
||||
c_color.0.g(),
|
||||
c_color.0.b(),
|
||||
]))
|
||||
.ok();
|
||||
audio.send(AudioMsg::Switch).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +498,7 @@ fn change_character_system(
|
|||
fn player_movement_system(
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
mut characters: Query<(&mut Velocity, &Children), With<Player>>,
|
||||
collision_counter_query: Query<&CollisionCount>,
|
||||
airbound_query: Query<&Airbound>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
let right_pressed: bool =
|
||||
|
@ -469,9 +509,8 @@ fn player_movement_system(
|
|||
for (mut velocity, children) in characters.iter_mut() {
|
||||
velocity.linvel.x = 200. * (right_pressed as i8 - left_pressed as i8) as f32;
|
||||
|
||||
if keyboard_input.just_pressed(KeyCode::Space)
|
||||
&& collision_counter_query.get(children[0]).unwrap().0 != 0
|
||||
{
|
||||
let airbound: &Airbound = airbound_query.get(children[0]).unwrap();
|
||||
if keyboard_input.just_pressed(KeyCode::Space) && !airbound.0 {
|
||||
audio.send(AudioMsg::Jump).ok();
|
||||
velocity.linvel.y = 700.;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue