Compare commits

..

4 Commits

Author SHA1 Message Date
Elijah Voigt 8c440317e7 Parallax system + example, need to integrate into flappy bird 2 months ago
Elijah Voigt 272543eff6 Made flap/rewind buttons bigger 2 months ago
Elijah Voigt 583b7a41c7 cargo fmt 2 months ago
Elijah Voigt 666d8f52b6 Make flap and rewind buttons shimmer 2 months ago

1
.gitattributes vendored

@ -1 +0,0 @@
*.ogg filter=lfs diff=lfs merge=lfs -text

@ -1,2 +1,3 @@
*.png filter=lfs diff=lfs merge=lfs -text *.ogg filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text *.xcf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text

@ -2,8 +2,10 @@ Programming: Elijah Voigt
Art Assets: Kenney.nl Art Assets: Kenney.nl
1-Bit Platformer Pack 1-Bit Platformer Pack
Impact Sounds
Engine: Bevy Engine: Bevy
Physics: Avian2D Physics: Avian2D
Inspired by Flappy Bird (2013) by Dong Nguyen Inspired by:
Flappy Bird (2013) by Dong Nguyen

BIN
assets/flappy/background-city.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/background-city.xcf (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/background-clouds.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/background-clouds.xcf (Stored with Git LFS)

Binary file not shown.

@ -0,0 +1,55 @@
use games::*;
fn main() {
App::new()
.add_plugins((BaseGamePlugin {
name: "parallax example".into(),
title: "Parallax".into(),
game_type: GameType::Two,
},))
.add_systems(Startup, spawn_background)
.add_systems(Update, move_camera)
.add_systems(Update, parallax_gizmos)
.run();
}
fn spawn_background(
mut commands: Commands,
) {
commands.spawn((Parallax(1.0), children![(Text2d("1.0".into()), Transform::from_xyz(0.0, 35.0, 0.0))]));
commands.spawn((Parallax(2.0), children![(Text2d("2.0".into()), Transform::from_xyz(0.0, 35.0, 0.0))]));
commands.spawn((Parallax(4.0), children![(Text2d("4.0".into()), Transform::from_xyz(0.0, 35.0, 0.0))]));
commands.spawn((Parallax(8.0), children![(Text2d("8.0".into()), Transform::from_xyz(0.0, 35.0, 0.0))]));
}
fn move_camera(
mut t: Single<&mut Transform, With<Camera2d>>,
keys: Res<ButtonInput<KeyCode>>,
) {
if keys.pressed(KeyCode::ArrowLeft) {
t.translation.x -= 5.0;
} else if keys.pressed(KeyCode::ArrowRight) {
t.translation.x += 5.0;
}
if keys.pressed(KeyCode::ArrowDown) {
t.translation.y -= 5.0;
} else if keys.pressed(KeyCode::ArrowUp) {
t.translation.y += 5.0;
}
}
fn parallax_gizmos(
mut gizmos: Gizmos,
q: Query<&Transform, With<Parallax>>,
) {
// Closest to camera
// Parallax(1)
q.iter().for_each(|t| {
gizmos.grid_2d(
t.translation.truncate(),
UVec2::new(5, 5),
Vec2::splat(10.),
RED,
).outer_edges();
});
}

@ -42,6 +42,7 @@ impl Plugin for BaseGamePlugin {
.add_plugins(MeshPickingPlugin) .add_plugins(MeshPickingPlugin)
.add_plugins(LoadingPlugin) .add_plugins(LoadingPlugin)
.add_plugins(BaseUiPlugin) .add_plugins(BaseUiPlugin)
.add_plugins(ParallaxPlugin)
.init_resource::<Rand>(); .init_resource::<Rand>();
match self.game_type { match self.game_type {

@ -39,9 +39,11 @@ fn main() {
), ),
) )
.add_systems(OnEnter(PlayerState::Alive), alive_bird) .add_systems(OnEnter(PlayerState::Alive), alive_bird)
.add_systems(OnEnter(PlayerState::Alive), reset_button::<FlapButton>)
.add_systems(OnEnter(PlayerState::Rewind), (start_rewinding, alive_bird)) .add_systems(OnEnter(PlayerState::Rewind), (start_rewinding, alive_bird))
.add_systems(OnEnter(PlayerState::Pause), pause_bird) .add_systems(OnEnter(PlayerState::Pause), pause_bird)
.add_systems(OnEnter(PlayerState::Stasis), pause_bird) .add_systems(OnEnter(PlayerState::Stasis), pause_bird)
.add_systems(OnExit(PlayerState::Stasis), reset_button::<RewindButton>)
.add_systems( .add_systems(
Update, Update,
( (
@ -85,14 +87,13 @@ fn main() {
sync_resource_to_ui::<Deaths>.run_if(resource_changed::<Deaths>), sync_resource_to_ui::<Deaths>.run_if(resource_changed::<Deaths>),
sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>), sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>),
), ),
( (update_tooltip, debug_trail).run_if(in_state(DebuggingState::On)),
update_tooltip,
debug_trail,
).run_if(in_state(DebuggingState::On)),
// TODO: Add run_if to this system // TODO: Add run_if to this system
update_batch_position.run_if(any_component_changed::<Batch>), update_batch_position.run_if(any_component_changed::<Batch>),
move_batches.run_if(on_event::<CollisionStarted>), move_batches.run_if(on_event::<CollisionStarted>),
manage_score.run_if(on_event::<CollisionStarted>.or(on_event::<CollisionEnded>)), manage_score.run_if(on_event::<CollisionStarted>.or(on_event::<CollisionEnded>)),
shimmer_button::<RewindButton>.run_if(in_state(PlayerState::Stasis)),
shimmer_button::<FlapButton>.run_if(in_state(PlayerState::Pause)),
), ),
) )
.add_observer(flap) .add_observer(flap)
@ -139,10 +140,7 @@ struct Tape {
rotations: Vec<Rotation>, rotations: Vec<Rotation>,
} }
fn init_bird( fn init_bird(mut commands: Commands, bird_assets: Res<BirdAssets>) {
mut commands: Commands,
bird_assets: Res<BirdAssets>,
) {
let name = Name::new("bird"); let name = Name::new("bird");
let t = Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(50.0)); let t = Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(50.0));
@ -407,12 +405,18 @@ fn init_assets(
#[derive(Component)] #[derive(Component)]
struct FlapSfx; struct FlapSfx;
#[derive(Component)]
struct FlapButton;
#[derive(Component)] #[derive(Component)]
struct BonkSfx; struct BonkSfx;
#[derive(Component)] #[derive(Component)]
struct RewindSfx; struct RewindSfx;
#[derive(Component)]
struct RewindButton;
fn init_ui(mut commands: Commands) { fn init_ui(mut commands: Commands) {
commands commands
.spawn(( .spawn((
@ -524,39 +528,63 @@ fn init_ui(mut commands: Commands) {
next.set(PlayerState::Alive); next.set(PlayerState::Alive);
} }
commands commands.spawn((
.spawn(( Node {
Node { align_self: AlignSelf::Center,
align_self: AlignSelf::Center, justify_self: JustifySelf::Center,
justify_self: JustifySelf::Center, flex_direction: FlexDirection::Column,
flex_direction: FlexDirection::Column, ..default()
..default() },
}, PlayerState::Pause,
Button, Text::new("PAUSED"),
PlayerState::Pause, ));
children![Text::new("Go!"),],
))
.observe(start_game);
commands commands
.spawn(Node { .spawn(Node {
align_self: AlignSelf::End, align_self: AlignSelf::End,
justify_self: JustifySelf::Center, justify_self: JustifySelf::Center,
flex_direction: FlexDirection::Row, flex_direction: FlexDirection::Row,
justify_content: JustifyContent::SpaceEvenly,
width: Val::Percent(100.0),
min_height: Val::Percent(10.0),
..default() ..default()
}) })
.with_children(|parent| { .with_children(|parent| {
parent parent
.spawn(( .spawn((
Node { ..default() }, Node {
width: Val::Percent(50.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Button, Button,
children![Text::new("Rewind!"),], BackgroundColor::default(),
RewindButton,
children![
Text::new("Rewind! (R)"),
TextLayout::new_with_justify(JustifyText::Center)
],
)) ))
.observe(start_rewind) .observe(start_rewind)
.observe(end_rewind); .observe(end_rewind);
parent parent
.spawn((Node { ..default() }, Button, children![Text::new("Flap!"),])) .spawn((
Node {
width: Val::Percent(50.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
Button,
FlapButton,
children![
Text::new("Flap! (Spacebar)"),
TextFont::from_font_size(30.0),
TextLayout::new_with_justify(JustifyText::Center)
],
))
.observe(flap_button); .observe(flap_button);
}); });
@ -567,9 +595,11 @@ fn init_ui(mut commands: Commands) {
..default() ..default()
}, },
BackgroundColor(WHITE.into()), BackgroundColor(WHITE.into()),
SyncResource::<Score>::default(), children![(
Text::default(), SyncResource::<Score>::default(),
TextLayout::new_with_justify(JustifyText::Center), Text::default(),
TextLayout::new_with_justify(JustifyText::Center),
)]
)); ));
} }
@ -585,7 +615,12 @@ fn flap_button(
_trigger: Trigger<Pointer<Pressed>>, _trigger: Trigger<Pointer<Pressed>>,
mut commands: Commands, mut commands: Commands,
bird: Single<Entity, With<Bird>>, bird: Single<Entity, With<Bird>>,
curr: Res<State<PlayerState>>,
mut next: ResMut<NextState<PlayerState>>,
) { ) {
if !matches!(curr.get(), PlayerState::Alive) {
next.set(PlayerState::Alive);
}
let e = *bird; let e = *bird;
debug!("Flapping {:?}", e); debug!("Flapping {:?}", e);
commands.trigger_targets(Flap, e); commands.trigger_targets(Flap, e);
@ -622,7 +657,10 @@ fn flap(
// Play flap sfx // Play flap sfx
commands.spawn(( commands.spawn((
AudioPlayer::new(server.load("flappy/bonk.ogg")), AudioPlayer::new(server.load("flappy/bonk.ogg")),
PlaybackSettings { mode: PlaybackMode::Despawn, ..default() }, PlaybackSettings {
mode: PlaybackMode::Despawn,
..default()
},
BonkSfx, BonkSfx,
)); ));
} }
@ -780,7 +818,10 @@ fn detect_dead(
// Play bonk sfx // Play bonk sfx
commands.spawn(( commands.spawn((
AudioPlayer::new(server.load("flappy/flap.ogg")), AudioPlayer::new(server.load("flappy/flap.ogg")),
PlaybackSettings { mode: PlaybackMode::Despawn, ..default() }, PlaybackSettings {
mode: PlaybackMode::Despawn,
..default()
},
FlapSfx, FlapSfx,
)); ));
} }
@ -912,7 +953,7 @@ fn move_batches(
} else if hitboxes.contains(*a) { } else if hitboxes.contains(*a) {
*a *a
} else { } else {
return return;
} }
}; };
@ -962,7 +1003,7 @@ fn update_tooltip(
} }
fn debug_trail( fn debug_trail(
mut physics_objects: Query<(Entity ,&Transform), With<Mass>>, mut physics_objects: Query<(Entity, &Transform), With<Mass>>,
mut gizmos: Gizmos, mut gizmos: Gizmos,
mut positions: Local<HashMap<Entity, VecDeque<Vec3>>>, mut positions: Local<HashMap<Entity, VecDeque<Vec3>>>,
) { ) {
@ -984,13 +1025,26 @@ fn debug_trail(
}) })
} }
fn start_rewinding( fn start_rewinding(server: ResMut<AssetServer>, mut commands: Commands) {
server: ResMut<AssetServer>,
mut commands: Commands,
) {
commands.spawn(( commands.spawn((
AudioPlayer::new(server.load("flappy/rewind-start.ogg")), AudioPlayer::new(server.load("flappy/rewind-start.ogg")),
PlaybackSettings { mode: PlaybackMode::Despawn, ..default() }, PlaybackSettings {
mode: PlaybackMode::Despawn,
..default()
},
RewindSfx, RewindSfx,
)); ));
} }
fn shimmer_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>, time: Res<Time>) {
let t = time.elapsed_secs();
let period = 3.0;
let r = (((t / period) % 1.0) * std::f32::consts::PI).cos();
let g = ((((t / period) + 0.3) % 1.0) * std::f32::consts::PI).cos();
let b = ((((t / period) + 0.6) % 1.0) * std::f32::consts::PI).cos();
bg.0 = Srgba::rgb(r, g, b).into();
}
fn reset_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>) {
bg.0 = WHITE.into();
}

@ -9,11 +9,12 @@ pub mod physics3d;
mod scheduling; mod scheduling;
mod ui; mod ui;
mod version; mod version;
mod parallax;
// Rust stdlib // Rust stdlib
pub use std::collections::VecDeque;
pub use std::f32::consts::PI; pub use std::f32::consts::PI;
pub use std::fmt::Display; pub use std::fmt::Display;
pub use std::collections::VecDeque;
// Community libraries // Community libraries
pub use bevy::{ pub use bevy::{
@ -44,3 +45,4 @@ pub use loading::*;
pub use scheduling::*; pub use scheduling::*;
pub use ui::*; pub use ui::*;
pub use version::*; pub use version::*;
pub use parallax::*;

@ -0,0 +1,27 @@
use super::*;
pub struct ParallaxPlugin;
impl Plugin for ParallaxPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, move_parallax_items.run_if(any_component_changed::<Transform>));
}
}
#[derive(Component)]
#[require(Transform)]
pub struct Parallax(pub f32);
fn move_parallax_items(
mut q: Query<(&mut Transform, &Parallax), Without<Camera2d>>,
cam_t: Single<&Transform, With<Camera2d>>,
) {
let base = cam_t.translation.truncate();
q.iter_mut().for_each(|(mut t, p)| {
let val = base * (1.0 - (1.0 / p.0));
t.translation.x = val.x;
t.translation.y = val.y;
});
}
Loading…
Cancel
Save