Compare commits

..

1 Commits

Author SHA1 Message Date
Elijah Voigt 1293a03968 pipes move when batch changes! 2 months ago

@ -14,10 +14,6 @@ codegen-units = 1
opt-level = "z" opt-level = "z"
lto = "thin" lto = "thin"
[profile.wasm-dev]
inherits = "dev"
codegen-backend = "llvm"
[profile.wasm-release] [profile.wasm-release]
inherits = "release" inherits = "release"
opt-level = "s" opt-level = "s"

3
.gitignore vendored

@ -14,6 +14,3 @@ VERSION
# Generated MONOLOGUES list for wasm build # Generated MONOLOGUES list for wasm build
assets/trees/MONOLOGUES assets/trees/MONOLOGUES
# Blender temp file(s)
*.blend1

@ -1,2 +0,0 @@
* setup CI template in web server running on port 8000
* setup mock bevy app running on port 8001 w/ first app running in iframe

@ -1,15 +1,11 @@
Flappy Bird Programming: Elijah Voigt
(with rewind)
A game by Elijah Voigt Art Assets: Kenney.nl
1-Bit Platformer Pack
Playtesters: Impact Sounds
Sam Hall
Ari (gamer)
Engine: Bevy Engine: Bevy
Physics: Avian2D Physics: Avian2D
Inspired by: Inspired by:
Flappy Bird (2013) Flappy Bird (2013) by Dong Nguyen
by Dong Nguyen

Binary file not shown.

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.

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

Binary file not shown.

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

Binary file not shown.

BIN
assets/flappy/bird.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/bonk.ogg (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/ceiling.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/flap.ogg (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/ground.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/logo.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/logo.xcf (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/pipe.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/play.xcf (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/rewind-start.ogg (Stored with Git LFS)

Binary file not shown.

BIN
assets/flappy/rewind.xcf (Stored with Git LFS)

Binary file not shown.

@ -5,7 +5,6 @@ fn main() {
.add_plugins((BaseGamePlugin { .add_plugins((BaseGamePlugin {
name: "2d game example".into(), name: "2d game example".into(),
game_type: GameType::Two, game_type: GameType::Two,
..default()
},)) },))
.add_systems(Startup, spawn_guy) .add_systems(Startup, spawn_guy)
.run(); .run();

@ -20,9 +20,7 @@ fn spawn_background(
) { ) {
commands.spawn(( commands.spawn((
Name::new("Depth: 1.0"), Name::new("Depth: 1.0"),
Transform::default() Transform::default().with_translation(Vec3::new(0.0, 0.0, 0.0)).with_scale(Vec3::splat(50.0)),
.with_translation(Vec3::new(0.0, 0.0, 0.0))
.with_scale(Vec3::splat(50.0)),
Mesh2d(meshes.add(Circle::new(1.0))), Mesh2d(meshes.add(Circle::new(1.0))),
MeshMaterial2d(materials.add(ColorMaterial { MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("bevy.png")), texture: Some(server.load("bevy.png")),
@ -34,9 +32,7 @@ fn spawn_background(
)); ));
commands.spawn(( commands.spawn((
Name::new("Depth: 2.0"), Name::new("Depth: 2.0"),
Transform::default() Transform::default().with_translation(Vec3::new(0.0, 0.0, -1.0)).with_scale(Vec3::splat(25.0)),
.with_translation(Vec3::new(0.0, 0.0, -1.0))
.with_scale(Vec3::splat(25.0)),
Mesh2d(meshes.add(Circle::new(2.0))), Mesh2d(meshes.add(Circle::new(2.0))),
MeshMaterial2d(materials.add(ColorMaterial { MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("bevy.png")), texture: Some(server.load("bevy.png")),
@ -48,9 +44,7 @@ fn spawn_background(
)); ));
commands.spawn(( commands.spawn((
Name::new("Depth: 4.0"), Name::new("Depth: 4.0"),
Transform::default() Transform::default().with_translation(Vec3::new(0.0, 0.0, -2.0)).with_scale(Vec3::splat(12.5)),
.with_translation(Vec3::new(0.0, 0.0, -2.0))
.with_scale(Vec3::splat(12.5)),
Mesh2d(meshes.add(Circle::new(4.0))), Mesh2d(meshes.add(Circle::new(4.0))),
MeshMaterial2d(materials.add(ColorMaterial { MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("bevy.png")), texture: Some(server.load("bevy.png")),
@ -62,9 +56,7 @@ fn spawn_background(
)); ));
commands.spawn(( commands.spawn((
Name::new("Depth: 8.0"), Name::new("Depth: 8.0"),
Transform::default() Transform::default().with_translation(Vec3::new(0.0, 0.0, -3.0)).with_scale(Vec3::splat(6.25)),
.with_translation(Vec3::new(0.0, 0.0, -3.0))
.with_scale(Vec3::splat(6.25)),
Mesh2d(meshes.add(Circle::new(8.0))), Mesh2d(meshes.add(Circle::new(8.0))),
MeshMaterial2d(materials.add(ColorMaterial { MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("bevy.png")), texture: Some(server.load("bevy.png")),

@ -1,40 +0,0 @@
use games::*;
fn main() {
App::new()
.add_plugins(BaseGamePlugin {
target_resolution: (360.0, 640.0).into(),
..default()
})
.add_systems(Startup, init_window_info)
.add_systems(
Update,
update_window_info.run_if(any_component_changed::<Window>),
)
.run();
}
#[derive(Component)]
struct WindowInfo;
fn init_window_info(mut commands: Commands) {
commands.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
children![(Text::new("Placeholder"), WindowInfo,)],
));
}
fn update_window_info(mut text: Single<&mut Text, With<WindowInfo>>, window: Single<&Window>) {
text.0 = format!(
"Logical: {}x{}\nPhysical: {}x{}\nScale Factor: {}",
window.resolution.physical_width(),
window.resolution.physical_height(),
window.resolution.width(),
window.resolution.height(),
window.resolution.scale_factor(),
);
}

@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1755615617, "lastModified": 1752480373,
"narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", "narHash": "sha256-JHQbm+OcGp32wAsXTE/FLYGNpb+4GLi5oTvCxwSoBOA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "20075955deac2583bb12f07151c2df830ef346b4", "rev": "62e0f05ede1da0d54515d4ea8ce9c733f12d9f08",
"type": "github" "type": "github"
}, },
"original": { "original": {

@ -51,8 +51,6 @@
git-bug git-bug
# wasm builder # wasm builder
wasm-bindgen-cli_0_2_100 wasm-bindgen-cli_0_2_100
# wasm-opt
binaryen
simple-http-server simple-http-server
# Itch.io uploads # Itch.io uploads
butler butler

@ -1,39 +1,19 @@
VERSION := `git rev-parse --short HEAD` VERSION := `git rev-parse --short HEAD`
bindgen profile name:
mkdir -p ./dist/{{name}}
wasm-bindgen \
--no-typescript \
--target web \
--out-dir ./dist/{{name}} \
--out-name "bin" \
${CARGO_TARGET_DIR}/wasm32-unknown-unknown/{{profile}}/{{name}}.wasm
optimize NAME:
# Size pass
wasm-opt -Oz \
-o dist/{{NAME}}/bin_bg-tmp.wasm \
./dist/{{NAME}}/bin_bg.wasm
# Replace old bin with new (compressed) bin
mv ./dist/{{NAME}}/bin_bg-tmp.wasm ./dist/{{NAME}}/bin_bg.wasm
build-example EXAMPLE:
cargo build --example {{EXAMPLE}} --profile wasm-dev --target wasm32-unknown-unknown
build-bin GAME:
# wasm binary
cargo build --bin {{GAME}} --profile wasm-release --target wasm32-unknown-unknown
example NAME: (build-example NAME) (bindgen "wasm-dev" "examples"/NAME)
cp web/example.html ./dist/examples/{{NAME}}/index.html
# Build the web version # Build the web version
web GAME: (build-bin GAME) (bindgen "wasm-release" GAME) (optimize GAME) web GAME:
# base directory # base directory
mkdir -p dist/{{GAME}}/assets/{{GAME}} mkdir -p dist/{{GAME}}/assets/{{GAME}}
# wasm binar
# cargo build --bin {{GAME}} --release --target wasm32-unknown-unknown
# wasm bindgen
wasm-bindgen --no-typescript --target web \
--out-dir ./dist/{{GAME}} \
--out-name "bin" \
${CARGO_TARGET_DIR}/wasm32-unknown-unknown/release/{{GAME}}.wasm
# index.html # index.html
cp ./web/{{GAME}}.html ./dist/{{GAME}}/index.html cp ./web/{{GAME}}.html ./dist/{{GAME}}/index.html
@ -43,13 +23,10 @@ web GAME: (build-bin GAME) (bindgen "wasm-release" GAME) (optimize GAME)
# Helpful shorthand to serve files # Helpful shorthand to serve files
serve GAME: (web GAME) serve GAME: (web GAME)
simple-http-server dist/{{GAME}} cd dist/{{GAME}} && simple-http-server
itchio-dry GAME: (web GAME)
butler push --dry-run dist/{{GAME}} popgame/{{GAME}}:html5 --userversion={{VERSION}}
itchio GAME: (web GAME) # itchio GAME: (web GAME)
butler push dist/{{GAME}} popgame/{{GAME}}:html5 --userversion={{VERSION}} # butler push dist/{{GAME}} popgame/{{GAME}}:html5 --userversion={{VERSION}}
clean: clean:
rm -rf dist/* rm -rf dist/*

@ -1,3 +1,5 @@
use bevy::platform::hash::RandomState;
use super::*; use super::*;
/// A good starting place for creating a game building on top of the base Bevy app /// A good starting place for creating a game building on top of the base Bevy app
@ -5,7 +7,6 @@ pub struct BaseGamePlugin {
pub title: String, pub title: String,
pub name: String, pub name: String,
pub game_type: GameType, pub game_type: GameType,
pub target_resolution: WindowResolution,
} }
pub enum GameType { pub enum GameType {
@ -19,7 +20,6 @@ impl Default for BaseGamePlugin {
title: "My Game".into(), title: "My Game".into(),
name: "mygame".into(), name: "mygame".into(),
game_type: GameType::Three, game_type: GameType::Three,
target_resolution: WindowResolution::default(),
} }
} }
} }
@ -31,24 +31,18 @@ impl Plugin for BaseGamePlugin {
.set(WindowPlugin { .set(WindowPlugin {
primary_window: Some(Window { primary_window: Some(Window {
fit_canvas_to_parent: true, fit_canvas_to_parent: true,
resolution: self.target_resolution.clone(), canvas: Some(format!("#{}-canvas", self.name)),
..default() ..default()
}), }),
..default() ..default()
}) })
.set(ImagePlugin::default_nearest()) .set(ImagePlugin::default_nearest()),
.set(AssetPlugin {
meta_check: AssetMetaCheck::Never,
..default()
}),
) )
.add_plugins(DebuggingPlugin) .add_plugins(DebuggingPlugin)
.add_plugins(MeshPickingPlugin) .add_plugins(MeshPickingPlugin)
.add_plugins(LoadingPlugin) .add_plugins(LoadingPlugin)
.add_plugins(BaseUiPlugin) .add_plugins(BaseUiPlugin)
.add_plugins(ParallaxPlugin) .add_plugins(ParallaxPlugin)
// .add_systems(Update, scale_game.run_if(any_component_changed::<Window>))
.insert_resource(TargetResolution(self.target_resolution.clone()))
.init_resource::<Rand>(); .init_resource::<Rand>();
match self.game_type { match self.game_type {
@ -58,9 +52,6 @@ impl Plugin for BaseGamePlugin {
} }
} }
#[derive(Resource)]
struct TargetResolution(WindowResolution);
/// System to toggle the visibility of entities based on their state /// System to toggle the visibility of entities based on their state
pub fn toggle_state_visibility<S: States + Component>( pub fn toggle_state_visibility<S: States + Component>(
mut q: Query<(Entity, &mut Visibility, &S)>, mut q: Query<(Entity, &mut Visibility, &S)>,
@ -94,22 +85,3 @@ pub fn create_camera_2d(mut commands: Commands) {
#[derive(Default, Resource)] #[derive(Default, Resource)]
pub struct Rand(pub RandomState); pub struct Rand(pub RandomState);
/// Scale the game based on the difference between the target and real resolution
fn scale_game(
mut window: Single<&mut Window>,
target_resolution: Res<TargetResolution>,
mut last_scale_factor: Local<f32>,
) {
let current_resolution: Vec2 = window.resolution.size();
let scale_width = current_resolution.x.round() / target_resolution.0.width().round();
let scale_height = current_resolution.y.round() / target_resolution.0.height().round();
let scale_factor = f32::min(scale_width, scale_height);
if window.resolution.scale_factor() != scale_factor {
// Need to check the previously set scale factor because the system can flip-flop otherwise
if scale_factor != *last_scale_factor {
*last_scale_factor = window.resolution.scale_factor();
window.resolution.set_scale_factor(scale_factor);
}
}
}

@ -1,8 +1,8 @@
// Bevy basically forces "complex types" with Querys // Bevy basically forces "complex types" with Querys
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use bevy::audio::PlaybackMode;
use bevy::image::{ImageLoaderSettings, ImageSampler}; use bevy::image::{ImageLoaderSettings, ImageSampler};
use bevy::platform::time::Instant;
use bevy::render::view::ColorGrading; use bevy::render::view::ColorGrading;
use games::physics2d::*; use games::physics2d::*;
use games::*; use games::*;
@ -15,8 +15,6 @@ fn main() {
title: "flappy bird (with rewind)".into(), title: "flappy bird (with rewind)".into(),
name: "flappy".into(), name: "flappy".into(),
game_type: GameType::Two, game_type: GameType::Two,
target_resolution: (360.0, 640.0).into(),
..default()
}, },
Physics2dPlugin, Physics2dPlugin,
)) ))
@ -29,7 +27,6 @@ fn main() {
.init_resource::<RewindFrames>() .init_resource::<RewindFrames>()
.init_resource::<Flaps>() .init_resource::<Flaps>()
.init_resource::<Deaths>() .init_resource::<Deaths>()
.init_resource::<LongestRun>()
.init_state::<PlayerState>() .init_state::<PlayerState>()
.add_systems( .add_systems(
Startup, Startup,
@ -43,12 +40,9 @@ fn main() {
tweak_camera.after(create_camera_2d), tweak_camera.after(create_camera_2d),
), ),
) )
.add_systems( .add_systems(OnEnter(PlayerState::Alive), alive_bird)
OnEnter(PlayerState::Alive), .add_systems(OnEnter(PlayerState::Alive), reset_button::<FlapButton>)
(alive_bird, start_run, reset_button::<FlapButton>), .add_systems(OnEnter(PlayerState::Rewind), (start_rewinding, alive_bird))
)
.add_systems(OnExit(PlayerState::Alive), end_run)
.add_systems(OnEnter(PlayerState::Rewind), 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(OnExit(PlayerState::Stasis), reset_button::<RewindButton>)
@ -91,9 +85,8 @@ fn main() {
// Stats that get synced to the UI // Stats that get synced to the UI
( (
sync_resource_to_ui::<Score>.run_if(resource_changed::<Score>), sync_resource_to_ui::<Score>.run_if(resource_changed::<Score>),
sync_resource_to_ui::<LongestRun>.run_if(resource_changed::<LongestRun>),
sync_resource_to_ui::<Deaths>.run_if(resource_changed::<Deaths>),
sync_resource_to_ui::<Flaps>.run_if(resource_changed::<Flaps>), sync_resource_to_ui::<Flaps>.run_if(resource_changed::<Flaps>),
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)),
@ -208,11 +201,11 @@ impl Tape {
fn init_bird(mut commands: Commands, bird_assets: Res<BirdAssets>) { fn init_bird(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::new(62.5, 50.0, 50.0)); let t = Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(50.0));
let physics = ( let physics = (
RigidBody::Static, RigidBody::Static,
Collider::rectangle(1.0, 1.0), Collider::rectangle(1.0, 1.2),
Mass(10.0), Mass(10.0),
ExternalImpulse::default().with_persistence(false), ExternalImpulse::default().with_persistence(false),
MaxLinearSpeed(500.0), MaxLinearSpeed(500.0),
@ -325,8 +318,8 @@ fn populate_ground(
ground_assets.mesh.clone(), ground_assets.mesh.clone(),
Name::new("ground"), Name::new("ground"),
RigidBody::Static, RigidBody::Static,
Collider::rectangle(1.0, 0.75), Collider::rectangle(1.0, 1.0),
Transform::from_xyz(100.0 * (*idx) as f32, -275.0, -1.0).with_scale(Vec3::splat(100.0)), Transform::from_xyz(100.0 * (*idx) as f32, -300.0, -1.0).with_scale(Vec3::splat(100.0)),
)); ));
} }
@ -343,7 +336,7 @@ fn populate_ceiling(
ceiling_assets.mesh.clone(), ceiling_assets.mesh.clone(),
Name::new("ceiling"), Name::new("ceiling"),
RigidBody::Static, RigidBody::Static,
Collider::rectangle(1.0, 0.75), Collider::rectangle(1.0, 1.0),
Transform::from_xyz(100.0 * (*idx) as f32, 300.0, -3.0).with_scale(Vec3::splat(100.0)), Transform::from_xyz(100.0 * (*idx) as f32, 300.0, -3.0).with_scale(Vec3::splat(100.0)),
)); ));
} }
@ -354,8 +347,7 @@ fn move_pipe(
rand: Res<Rand>, rand: Res<Rand>,
) { ) {
if let Ok((Batch(id), pipe, mut pipe_t)) = pipes.get_mut(trigger.target()) { if let Ok((Batch(id), pipe, mut pipe_t)) = pipes.get_mut(trigger.target()) {
*pipe_t = *pipe_t = {
{
let offset = { let offset = {
let val = rand.0.hash_one(id); let val = rand.0.hash_one(id);
@ -370,10 +362,12 @@ fn move_pipe(
}; };
match pipe { match pipe {
Pipe::Top => Transform::from_xyz(0.0, 300.0 + offset, -2.0) Pipe::Top => {
.with_scale(Vec3::splat(100.0)), Transform::from_xyz(0.0, 300.0 + offset, -2.0).with_scale(Vec3::splat(100.0))
Pipe::Bottom => Transform::from_xyz(0.0, -300.0 + offset, -2.0) }
.with_scale(Vec3::splat(100.0)), Pipe::Bottom => {
Transform::from_xyz(0.0, -300.0 + offset, -2.0).with_scale(Vec3::splat(100.0))
}
} }
}; };
} }
@ -479,14 +473,14 @@ fn init_assets(
ground_assets.material = MeshMaterial2d(materials.add(ColorMaterial { ground_assets.material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/ground.png")), texture: Some(server.load("flappy/ground.png")),
color: GREEN.into(), color: Srgba::new(0.1, 0.1, 0.1, 1.0).into(),
..default() ..default()
})); }));
ground_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0))); ground_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
ceiling_assets.material = MeshMaterial2d(materials.add(ColorMaterial { ceiling_assets.material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/ceiling.png")), texture: Some(server.load("flappy/ceiling.png")),
color: FIRE_BRICK.into(), color: Srgba::new(0.1, 0.1, 0.1, 1.0).into(),
..default() ..default()
})); }));
ceiling_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 0.777))); ceiling_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 0.777)));
@ -500,9 +494,18 @@ fn init_assets(
bird_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.2))); bird_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.2)));
} }
#[derive(Component)]
struct FlapSfx;
#[derive(Component)] #[derive(Component)]
struct FlapButton; struct FlapButton;
#[derive(Component)]
struct BonkSfx;
#[derive(Component)]
struct RewindSfx;
#[derive(Component)] #[derive(Component)]
struct RewindButton; struct RewindButton;
@ -515,50 +518,35 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
flex_direction: FlexDirection::Column, flex_direction: FlexDirection::Column,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)),
BackgroundColor(Color::WHITE),
BorderColor(BLACK.into()),
PlayerState::Stasis, PlayerState::Stasis,
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(( parent.spawn((
Text::new("Game Over...?"), Text::new("Game Over...?"),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)); ));
parent.spawn(( parent.spawn((
SyncResource::<Score>::default(), SyncResource::<Score>::default(),
Text::default(), Text::default(),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)); ));
parent.spawn(( parent.spawn((
SyncResource::<LongestRun>::default(), SyncResource::<Flaps>::default(),
Text::default(),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center),
));
parent.spawn((
SyncResource::<Deaths>::default(),
Text::default(), Text::default(),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)); ));
parent.spawn(( parent.spawn((
SyncResource::<Flaps>::default(), SyncResource::<RewindFrames>::default(),
Text::default(), Text::default(),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)); ));
parent.spawn(( parent.spawn((
SyncResource::<RewindFrames>::default(), SyncResource::<Deaths>::default(),
Text::default(), Text::default(),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)); ));
parent.spawn(( parent.spawn((
Text::new("Press R to Rewind"), Text::new("Press R to Rewind"),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)); ));
parent parent
@ -568,6 +556,14 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
..default() ..default()
},)) },))
.with_children(|parent| { .with_children(|parent| {
fn quit_game(
_trigger: Trigger<Pointer<Click>>,
mut exit: EventWriter<AppExit>,
) {
warn!("Quitting game");
exit.write(AppExit::Success);
}
fn show_credits( fn show_credits(
_trigger: Trigger<Pointer<Click>>, _trigger: Trigger<Pointer<Click>>,
mut state: ResMut<NextState<PlayerState>>, mut state: ResMut<NextState<PlayerState>>,
@ -578,33 +574,13 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
parent parent
.spawn(( .spawn((
Button, Button,
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
Node { ..default() }, Node { ..default() },
children![(TextColor(BLACK.into()), Text::new("Credits")),], children![Text::new("Credits")],
)) ))
.observe(show_credits); .observe(show_credits);
#[cfg(not(target_arch = "wasm32"))]
{
fn quit_game(
_trigger: Trigger<Pointer<Click>>,
mut exit: EventWriter<AppExit>,
) {
warn!("Quitting game");
exit.write(AppExit::Success);
}
parent parent
.spawn(( .spawn((Button, Node { ..default() }, children![Text::new("Quit"),]))
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
Button,
Node { ..default() },
children![(Text::new("Quit"), TextColor(BLACK.into()))],
))
.observe(quit_game); .observe(quit_game);
}
}); });
}); });
@ -622,13 +598,9 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
flex_direction: FlexDirection::Column, flex_direction: FlexDirection::Column,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)),
BackgroundColor(WHITE.into()),
BorderColor(BLACK.into()),
PlayerState::Credits, PlayerState::Credits,
children![( children![(
Text::new(credits_str), Text::new(credits_str),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center) TextLayout::new_with_justify(JustifyText::Center)
)], )],
)) ))
@ -638,56 +610,25 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
align_self: AlignSelf::Center, align_self: AlignSelf::Center,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
Button, Button,
children![(Text::new("Close"), TextColor(BLACK.into()))], children![Text::new("Close")],
)); ));
}) })
.observe(hide_credits); .observe(hide_credits);
let logo =
server.load_with_settings("flappy/logo.png", |settings: &mut ImageLoaderSettings| {
// Need to use nearest filtering to avoid bleeding between the slices with tiling
settings.sampler = ImageSampler::nearest();
});
commands.spawn(( commands.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,
align_items: AlignItems::Center,
justify_items: JustifyItems::Center,
..default() ..default()
}, },
BackgroundColor(Color::NONE),
PlayerState::Pause, PlayerState::Pause,
children![ Text::new("PAUSED"),
(
ImageNode {
image: logo,
..default()
},
Node {
width: Val::Px(256.0),
..default()
}
),
(
Node {
margin: UiRect::all(Val::Px(5.0)),
..default()
},
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
Text::new("(paused)"),
TextColor(BLACK.into()),
)
],
)); ));
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,
@ -695,7 +636,7 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
width: Val::Percent(100.0), width: Val::Percent(100.0),
min_height: Val::Percent(10.0), min_height: Val::Percent(10.0),
..default() ..default()
},)) })
.with_children(|parent| { .with_children(|parent| {
let rewind_image = server.load_with_settings( let rewind_image = server.load_with_settings(
"flappy/rewind.png", "flappy/rewind.png",
@ -713,10 +654,8 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
justify_content: JustifyContent::Center, justify_content: JustifyContent::Center,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE.with_alpha(0.9)),
Button, Button,
BackgroundColor::default(),
RewindButton, RewindButton,
children![ children![
( (
@ -731,9 +670,8 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
}, },
), ),
( (
Text::new("Rewind!\n(Hold R)"), Text::new("Rewind! (R)"),
TextColor(BLACK.into()), TextFont::from_font_size(30.0),
TextFont::from_font_size(20.0),
TextLayout::new_with_justify(JustifyText::Center) TextLayout::new_with_justify(JustifyText::Center)
), ),
], ],
@ -756,16 +694,12 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
justify_content: JustifyContent::Center, justify_content: JustifyContent::Center,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE.with_alpha(0.9)),
Button, Button,
FlapButton, FlapButton,
children![ children![
( (
Text::new("Flap!\n(Spacebar)"), Text::new("Flap! (Spacebar)"),
TextColor(BLACK.into()), TextFont::from_font_size(30.0),
TextFont::from_font_size(20.0),
TextLayout::new_with_justify(JustifyText::Center) TextLayout::new_with_justify(JustifyText::Center)
), ),
( (
@ -790,13 +724,10 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
justify_self: JustifySelf::Center, justify_self: JustifySelf::Center,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)), BackgroundColor(WHITE.into()),
BackgroundColor(Color::WHITE),
BorderColor(BLACK.into()),
children![( children![(
SyncResource::<Score>::default(), SyncResource::<Score>::default(),
Text::default(), Text::default(),
TextColor(BLACK.into()),
TextLayout::new_with_justify(JustifyText::Center), TextLayout::new_with_justify(JustifyText::Center),
)], )],
)); ));
@ -811,36 +742,36 @@ fn init_background(
{ {
let material = MeshMaterial2d(materials.add(ColorMaterial { let material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/background-city.png")), texture: Some(server.load("flappy/background-city.png")),
color: LIGHT_GREY.with_alpha(0.8).into(), color: Srgba::new(0.3, 0.3, 0.3, 1.0).into(),
alpha_mode: AlphaMode2d::Blend, alpha_mode: AlphaMode2d::Blend,
..default() ..default()
})); }));
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0))); let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
{ {
let t = Transform::from_xyz(-325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0)); let t = Transform::from_xyz(-325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(24.0), mesh.clone(), material.clone(), t)); commands.spawn((ParallaxDepth(4.0), mesh.clone(), material.clone(), t));
} }
{ {
let t = Transform::from_xyz(325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0)); let t = Transform::from_xyz(325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(24.0), mesh.clone(), material.clone(), t)); commands.spawn((ParallaxDepth(4.0), mesh.clone(), material.clone(), t));
} }
} }
{ {
let material = MeshMaterial2d(materials.add(ColorMaterial { let material = MeshMaterial2d(materials.add(ColorMaterial {
texture: Some(server.load("flappy/background-clouds.png")), texture: Some(server.load("flappy/background-clouds.png")),
color: WHITE_SMOKE.with_alpha(0.8).into(), color: Srgba::new(0.2, 0.2, 0.2, 1.0).into(),
alpha_mode: AlphaMode2d::Blend, alpha_mode: AlphaMode2d::Blend,
..default() ..default()
})); }));
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0))); let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
{ {
let t = Transform::from_xyz(-325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0)); let t = Transform::from_xyz(-325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(32.0), mesh.clone(), material.clone(), t)); commands.spawn((ParallaxDepth(8.0), mesh.clone(), material.clone(), t));
} }
{ {
let t = Transform::from_xyz(325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0)); let t = Transform::from_xyz(325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
commands.spawn((ParallaxDepth(32.0), mesh.clone(), material.clone(), t)); commands.spawn((ParallaxDepth(8.0), mesh.clone(), material.clone(), t));
} }
} }
} }
@ -885,6 +816,8 @@ fn flap(
trigger: Trigger<Flap>, trigger: Trigger<Flap>,
mut bird: Query<&mut ExternalImpulse, With<Bird>>, mut bird: Query<&mut ExternalImpulse, With<Bird>>,
mut flaps: ResMut<Flaps>, mut flaps: ResMut<Flaps>,
server: ResMut<AssetServer>,
mut commands: Commands,
) { ) {
debug!("real flap for {:?}", trigger.target()); debug!("real flap for {:?}", trigger.target());
// Increment flap stat // Increment flap stat
@ -893,6 +826,16 @@ fn flap(
// Flap birds wings // Flap birds wings
if let Ok(mut f) = bird.get_mut(trigger.target()) { if let Ok(mut f) = bird.get_mut(trigger.target()) {
f.apply_impulse(Vec2::Y * 5000.0 + Vec2::X * 1000.0); f.apply_impulse(Vec2::Y * 5000.0 + Vec2::X * 1000.0);
// Play flap sfx
commands.spawn((
AudioPlayer::new(server.load("flappy/bonk.ogg")),
PlaybackSettings {
mode: PlaybackMode::Despawn,
..default()
},
BonkSfx,
));
} }
} }
@ -1004,6 +947,8 @@ fn detect_dead(
bird: Single<&ColliderAabb, With<Bird>>, bird: Single<&ColliderAabb, With<Bird>>,
obstacles: Query<&ColliderAabb, Or<(With<Ground>, With<Pipe>, With<Ceiling>)>>, obstacles: Query<&ColliderAabb, Or<(With<Ground>, With<Pipe>, With<Ceiling>)>>,
mut next: ResMut<NextState<PlayerState>>, mut next: ResMut<NextState<PlayerState>>,
server: ResMut<AssetServer>,
mut commands: Commands,
) { ) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
debug_assert!( debug_assert!(
@ -1013,6 +958,16 @@ fn detect_dead(
if obstacles.iter().any(|obstacle| bird.intersects(obstacle)) { if obstacles.iter().any(|obstacle| bird.intersects(obstacle)) {
next.set(PlayerState::Stasis); next.set(PlayerState::Stasis);
// Play bonk sfx
commands.spawn((
AudioPlayer::new(server.load("flappy/flap.ogg")),
PlaybackSettings {
mode: PlaybackMode::Despawn,
..default()
},
FlapSfx,
));
} }
} }
@ -1072,61 +1027,6 @@ impl Display for Flaps {
} }
} }
/// Track the longest run a player has done
/// Store the latest run and upsert latest run to the longest run if it is longer
#[derive(Resource, Default)]
struct LongestRun {
/// Longest run start
start: Option<Instant>,
/// Longest run end
end: Option<Instant>,
/// Latest run start
latest_start: Option<Instant>,
/// Latest run start
latest_end: Option<Instant>,
}
impl Display for LongestRun {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match (self.start, self.end) {
(Some(a), Some(b)) => {
if b > a {
writeln!(f, "Longest Run: {:.2?}", b - a)
} else {
writeln!(f, "Longest Run: ???")
}
}
_ => writeln!(f, "Longest Run: ???"),
}
}
}
fn start_run(mut longest_run: ResMut<LongestRun>) {
longest_run.latest_start = Some(Instant::now());
longest_run.latest_end = None;
}
fn end_run(mut longest_run: ResMut<LongestRun>) {
longest_run.latest_end = Some(Instant::now());
match (longest_run.start, longest_run.end) {
// Longest run hasn't been set yet, so set it to the latest run
(None, None) => {
longest_run.start = longest_run.latest_start;
longest_run.end = longest_run.latest_end;
}
// Longest run was previously set
(Some(start), Some(end)) => {
// Check if latest run is longer than current longest run
if longest_run.latest_end.unwrap() - longest_run.latest_start.unwrap() > end - start {
longest_run.start = longest_run.latest_start;
longest_run.end = longest_run.latest_end;
}
}
_ => panic!("What?"),
}
}
// Track number of times player died // Track number of times player died
#[derive(Resource, Default)] #[derive(Resource, Default)]
struct Deaths(usize); struct Deaths(usize);
@ -1273,16 +1173,24 @@ fn debug_trail(
}) })
} }
fn start_rewinding(server: ResMut<AssetServer>, mut commands: Commands) {
commands.spawn((
AudioPlayer::new(server.load("flappy/rewind-start.ogg")),
PlaybackSettings {
mode: PlaybackMode::Despawn,
..default()
},
RewindSfx,
));
}
fn shimmer_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>, time: Res<Time>) { fn shimmer_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>, time: Res<Time>) {
let t = time.elapsed_secs(); let t = time.elapsed_secs();
let lightness = 0.5; let period = 3.0;
let chroma = 0.5; let r = (((t / period) % 1.0) * std::f32::consts::PI).cos();
let hue = (t * 60.0) % 360.0; let g = ((((t / period) + 0.3) % 1.0) * std::f32::consts::PI).cos();
bg.0 = Oklcha { let b = ((((t / period) + 0.6) % 1.0) * std::f32::consts::PI).cos();
lightness, chroma, hue, bg.0 = Srgba::rgb(r, g, b).into();
alpha: bg.0.alpha(),
}
.into();
} }
fn reset_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>) { fn reset_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>) {

@ -13,7 +13,6 @@ impl Plugin for DebuggingPlugin {
.init_resource::<ToolTip>() .init_resource::<ToolTip>()
.init_resource::<Fps>() .init_resource::<Fps>()
.init_resource::<EntityCount>() .init_resource::<EntityCount>()
.init_resource::<WindowInfo>()
.init_resource::<Notice>() .init_resource::<Notice>()
.add_systems(Startup, init_debug_ui) .add_systems(Startup, init_debug_ui)
.add_systems( .add_systems(
@ -34,9 +33,7 @@ impl Plugin for DebuggingPlugin {
track_fps, track_fps,
sync_resource_to_ui::<Fps>.run_if(resource_changed::<Fps>), sync_resource_to_ui::<Fps>.run_if(resource_changed::<Fps>),
track_entity_count, track_entity_count,
track_window_info.run_if(any_component_changed::<Window>),
sync_resource_to_ui::<EntityCount>.run_if(resource_changed::<EntityCount>), sync_resource_to_ui::<EntityCount>.run_if(resource_changed::<EntityCount>),
sync_resource_to_ui::<WindowInfo>.run_if(resource_changed::<WindowInfo>),
sync_resource_to_ui::<Notice>.run_if(resource_changed::<Notice>), sync_resource_to_ui::<Notice>.run_if(resource_changed::<Notice>),
) )
.run_if(in_state(DebuggingState::On)), .run_if(in_state(DebuggingState::On)),
@ -76,11 +73,8 @@ fn init_debug_ui(mut commands: Commands) {
commands.spawn(( commands.spawn((
DebuggingState::On, DebuggingState::On,
Name::new("Version #"), Name::new("Version #"),
children![(TextColor(BLACK.into()), Text::new(VERSION),)], children![Text::new(VERSION),],
GlobalZIndex(i32::MAX - 1), GlobalZIndex(i32::MAX - 1),
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE),
Node { Node {
max_width: Val::Percent(50.0), max_width: Val::Percent(50.0),
align_self: AlignSelf::End, align_self: AlignSelf::End,
@ -93,15 +87,8 @@ fn init_debug_ui(mut commands: Commands) {
.spawn(( .spawn((
DebuggingState::On, DebuggingState::On,
Name::new("Notice"), Name::new("Notice"),
children![( children![(Text::new(""), SyncResource::<Notice>::default(),)],
TextColor(BLACK.into()),
Text::new(""),
SyncResource::<Notice>::default(),
)],
GlobalZIndex(i32::MAX - 1), GlobalZIndex(i32::MAX - 1),
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE),
Node { Node {
max_width: Val::Percent(50.0), max_width: Val::Percent(50.0),
align_self: AlignSelf::End, align_self: AlignSelf::End,
@ -123,10 +110,7 @@ fn init_debug_ui(mut commands: Commands) {
DebuggingState::Off, DebuggingState::Off,
Name::new("Debug Indicator"), Name::new("Debug Indicator"),
GlobalZIndex(i32::MAX - 1), GlobalZIndex(i32::MAX - 1),
BorderRadius::all(Val::Px(5.0)), children![Text("Debug: OFF".into()),],
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE),
children![(Text("Debug: OFF".into()), TextColor(BLACK.into()),)],
Button, Button,
)) ))
.observe(toggle_debug); .observe(toggle_debug);
@ -140,9 +124,6 @@ fn init_debug_ui(mut commands: Commands) {
flex_direction: FlexDirection::Column, flex_direction: FlexDirection::Column,
..default() ..default()
}, },
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE),
)) ))
.with_children(|parent| { .with_children(|parent| {
parent parent
@ -151,7 +132,7 @@ fn init_debug_ui(mut commands: Commands) {
DebuggingState::On, DebuggingState::On,
Name::new("Debug Indicator"), Name::new("Debug Indicator"),
GlobalZIndex(i32::MAX - 1), GlobalZIndex(i32::MAX - 1),
children![(Text("Debug: ON".into()), TextColor(BLACK.into()),)], children![Text("Debug: ON".into()),],
Button, Button,
)) ))
.observe(toggle_debug); .observe(toggle_debug);
@ -161,7 +142,6 @@ fn init_debug_ui(mut commands: Commands) {
Name::new("FPS"), Name::new("FPS"),
GlobalZIndex(i32::MAX - 1), GlobalZIndex(i32::MAX - 1),
Text::new("FPS: ##.#"), Text::new("FPS: ##.#"),
TextColor(BLACK.into()),
SyncResource::<Fps>::default(), SyncResource::<Fps>::default(),
)); ));
parent.spawn(( parent.spawn((
@ -170,18 +150,8 @@ fn init_debug_ui(mut commands: Commands) {
Name::new("Entity Count"), Name::new("Entity Count"),
GlobalZIndex(i32::MAX - 1), GlobalZIndex(i32::MAX - 1),
Text::new("Entities: ###"), Text::new("Entities: ###"),
TextColor(BLACK.into()),
SyncResource::<EntityCount>::default(), SyncResource::<EntityCount>::default(),
)); ));
parent.spawn((
// Window info
DebuggingState::On,
Name::new("Window Info"),
GlobalZIndex(i32::MAX - 1),
Text::new("Window Info..."),
TextColor(BLACK.into()),
SyncResource::<WindowInfo>::default(),
));
}); });
// Tooltip // Tooltip
@ -191,9 +161,6 @@ fn init_debug_ui(mut commands: Commands) {
SyncResource::<ToolTip>::default(), SyncResource::<ToolTip>::default(),
Pickable::IGNORE, Pickable::IGNORE,
GlobalZIndex(i32::MAX), GlobalZIndex(i32::MAX),
BorderRadius::all(Val::Px(5.0)),
BorderColor(BLACK.into()),
BackgroundColor(Color::WHITE),
Node { Node {
position_type: PositionType::Absolute, position_type: PositionType::Absolute,
margin: UiRect { margin: UiRect {
@ -208,7 +175,6 @@ fn init_debug_ui(mut commands: Commands) {
.with_children(|parent| { .with_children(|parent| {
parent.spawn(( parent.spawn((
Text("Tooltip Placeholder".into()), Text("Tooltip Placeholder".into()),
TextColor(BLACK.into()),
SyncResource::<ToolTip>::default(), SyncResource::<ToolTip>::default(),
)); ));
}); });
@ -504,33 +470,6 @@ fn track_entity_count(query: Query<Entity>, mut count: ResMut<EntityCount>) {
count.0 = query.iter().len(); count.0 = query.iter().len();
} }
#[derive(Resource, Default, Debug)]
struct WindowInfo {
logical_size: (f32, f32),
physical_size: (f32, f32),
scale_factor: f32,
mode: String,
}
impl Display for WindowInfo {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
writeln!(
f,
"Res (Logi): {:?}\nRes (Phys): {:?}\nWindow Scale: {}\nWindow Mode: {}",
self.logical_size, self.physical_size, self.scale_factor, self.mode
)
}
}
fn track_window_info(window: Single<&Window>, mut info: ResMut<WindowInfo>) {
(info.logical_size.0, info.logical_size.1) =
(window.resolution.size().x, window.resolution.size().y);
(info.physical_size.0, info.physical_size.1) =
(window.resolution.size().x, window.resolution.size().y);
info.scale_factor = window.resolution.scale_factor();
info.mode = format!("{:?}", window.mode);
}
/// Toggle the debug state when a button is clicked /// Toggle the debug state when a button is clicked
fn toggle_debug( fn toggle_debug(
_trigger: Trigger<Pointer<Click>>, _trigger: Trigger<Pointer<Click>>,

@ -18,7 +18,7 @@ pub use std::fmt::Display;
// Community libraries // Community libraries
pub use bevy::{ pub use bevy::{
asset::{AssetLoader, AssetMetaCheck, LoadContext, LoadState, LoadedFolder, io::Reader}, asset::{AssetLoader, LoadContext, LoadState, LoadedFolder, io::Reader},
color::palettes::css::*, color::palettes::css::*,
gizmos::{aabb::AabbGizmoPlugin, light::LightGizmoPlugin}, gizmos::{aabb::AabbGizmoPlugin, light::LightGizmoPlugin},
input::{ input::{
@ -29,11 +29,11 @@ pub use bevy::{
mouse::{MouseScrollUnit, MouseWheel}, mouse::{MouseScrollUnit, MouseWheel},
}, },
pbr::wireframe::{WireframeConfig, WireframePlugin}, pbr::wireframe::{WireframeConfig, WireframePlugin},
platform::{collections::HashMap, hash::RandomState}, platform::collections::HashMap,
prelude::*, prelude::*,
reflect::TypePath, reflect::TypePath,
sprite::AlphaMode2d, sprite::AlphaMode2d,
window::{WindowResized, WindowResolution}, window::WindowResized,
}; };
pub use serde::Deserialize; pub use serde::Deserialize;
pub use thiserror::Error; pub use thiserror::Error;

@ -1,5 +1,5 @@
use bevy::render::mesh::MeshAabb;
use bevy::render::primitives::Aabb; use bevy::render::primitives::Aabb;
use bevy::render::mesh::MeshAabb;
use super::*; use super::*;
@ -12,7 +12,7 @@ impl Plugin for ParallaxPlugin {
( (
move_parallax_items.run_if(any_component_changed::<Transform>), move_parallax_items.run_if(any_component_changed::<Transform>),
wrap_parallax_items.run_if(any_component_changed::<ViewVisibility>), wrap_parallax_items.run_if(any_component_changed::<ViewVisibility>),
), )
); );
} }
} }
@ -57,14 +57,7 @@ fn move_parallax_items(
} }
fn wrap_parallax_items( fn wrap_parallax_items(
mut items: Query< mut items: Query<(&mut Transform, &GlobalTransform, &ViewVisibility, &Mesh2d), (With<ParallaxDepth>, Without<Camera2d>, Changed<ViewVisibility>)>,
(&mut Transform, &GlobalTransform, &ViewVisibility, &Mesh2d),
(
With<ParallaxDepth>,
Without<Camera2d>,
Changed<ViewVisibility>,
),
>,
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>, camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
window: Single<&Window>, window: Single<&Window>,
meshes: Res<Assets<Mesh>>, meshes: Res<Assets<Mesh>>,
@ -77,10 +70,7 @@ fn wrap_parallax_items(
let top_left = cam.viewport_to_world_2d(cam_gt, Vec2::ZERO).unwrap(); let top_left = cam.viewport_to_world_2d(cam_gt, Vec2::ZERO).unwrap();
let bottom_right = cam.viewport_to_world_2d(cam_gt, window.size()).unwrap(); let bottom_right = cam.viewport_to_world_2d(cam_gt, window.size()).unwrap();
Vec2::abs(Vec2::new( Vec2::abs(Vec2::new(bottom_right.x - top_left.x, bottom_right.y - top_left.y))
bottom_right.x - top_left.x,
bottom_right.y - top_left.y,
))
}; };
// for each item in the paralax items // for each item in the paralax items

@ -139,21 +139,21 @@ fn add_ui_node(
added.iter_mut().for_each(|(e, mut n)| { added.iter_mut().for_each(|(e, mut n)| {
debug!("Updating node: {:?}", e); debug!("Updating node: {:?}", e);
// Update Node border
n.border = UiRect::all(Val::Px(2.0));
let mut this = commands.entity(e); let mut this = commands.entity(e);
if text.contains(e) { if text.contains(e) {
// Only change text color for text // Only change text color for text
this.insert_if_new(TextColor(style.secondary)); this.insert(TextColor(style.secondary));
} else if images.contains(e) { } else if images.contains(e) {
// Do nothing // Do nothing
} else { } else {
// Update Node border
n.border = UiRect::all(Val::Px(2.0));
// Add extra stuff for non-text nodes // Add extra stuff for non-text nodes
this.insert_if_new(BackgroundColor(style.primary)); this.insert(BackgroundColor(style.primary));
this.insert_if_new(BorderColor(style.secondary)); this.insert(BorderColor(style.secondary));
this.insert_if_new(BorderRadius::all(Val::Px(5.0))); this.insert(BorderRadius::all(Val::Px(5.0)));
} }
}) })
} }

@ -1,16 +0,0 @@
<!doctype html>
<html lang="en">
<body style="margin: 0px;">
<script type="module">
import init from './bin.js'
init().catch((error) => {
if (!error.message.startsWith("Using exceptions for control flow, don't mind me. This isn't actually an error!")) {
throw error;
}
});
</script>
</body>
</html>

@ -1,7 +1,7 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<body>
<body style="margin: 0px;"> <canvas id="flappy-canvas"></canvas>
<script type="module"> <script type="module">
import init from './bin.js' import init from './bin.js'
@ -12,5 +12,4 @@
}); });
</script> </script>
</body> </body>
</html> </html>

Loading…
Cancel
Save