other files
This commit is contained in:
49
WEB_BUILD.md
Normal file
49
WEB_BUILD.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Building Flappy Bird for Web
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Install the WebAssembly target:
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
2. Install wasm-bindgen-cli (will be done automatically by build script):
|
||||
```bash
|
||||
cargo install wasm-bindgen-cli
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
Run the build script:
|
||||
```bash
|
||||
./build-web.sh
|
||||
```
|
||||
|
||||
This will:
|
||||
- Build the WASM binary
|
||||
- Generate JavaScript bindings
|
||||
- Copy assets to the `web/` directory
|
||||
- Copy the HTML file
|
||||
|
||||
## Running Locally
|
||||
|
||||
Serve the web directory with any HTTP server:
|
||||
|
||||
**Python:**
|
||||
```bash
|
||||
python3 -m http.server --directory web 8080
|
||||
```
|
||||
|
||||
**Alternative (if you have basic-http-server):**
|
||||
```bash
|
||||
cargo install basic-http-server
|
||||
basic-http-server web
|
||||
```
|
||||
|
||||
Then open http://localhost:8080 in your browser!
|
||||
|
||||
## Notes
|
||||
|
||||
- The game uses WebGL2 for rendering
|
||||
- All assets are included in the build
|
||||
- Image sampling is set to nearest neighbor for crisp pixel art
|
||||
6
assets/bindings.ron
Normal file
6
assets/bindings.ron
Normal file
@@ -0,0 +1,6 @@
|
||||
(
|
||||
axes: {},
|
||||
actions: {
|
||||
"flap": [[Key(Space)]],
|
||||
},
|
||||
)
|
||||
4
assets/display_config.ron
Normal file
4
assets/display_config.ron
Normal file
@@ -0,0 +1,4 @@
|
||||
(
|
||||
title: "test",
|
||||
dimensions: Some((432, 768)),
|
||||
)
|
||||
BIN
assets/screenshot1.png
Normal file
BIN
assets/screenshot1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
assets/screenshot2.png
Normal file
BIN
assets/screenshot2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/sprites/flappy.png
Normal file
BIN
assets/sprites/flappy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
169
assets/sprites/flappy.ron
Normal file
169
assets/sprites/flappy.ron
Normal file
@@ -0,0 +1,169 @@
|
||||
|
||||
List((
|
||||
texture_width: 512,
|
||||
texture_height: 512,
|
||||
sprites: [
|
||||
( // Daytime background
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 144,
|
||||
height: 256,
|
||||
),
|
||||
( // Nighttime background
|
||||
x: 146,
|
||||
y: 0,
|
||||
width: 144,
|
||||
height: 256,
|
||||
),
|
||||
( // Down Pipe
|
||||
x: 56,
|
||||
y: 323,
|
||||
width: 26,
|
||||
height: 160,
|
||||
),
|
||||
( // Up Pipe
|
||||
x: 84,
|
||||
y: 323,
|
||||
width: 26,
|
||||
height: 160,
|
||||
),
|
||||
( // Ground
|
||||
x: 292,
|
||||
y: 0,
|
||||
width: 168,
|
||||
height: 56,
|
||||
),
|
||||
( // Floppy
|
||||
x: 3,
|
||||
y: 490,
|
||||
width: 17,
|
||||
height: 13,
|
||||
),
|
||||
( // Tap Tap Dialogue
|
||||
x: 292,
|
||||
y: 91,
|
||||
width: 56,
|
||||
height: 48,
|
||||
),
|
||||
( // Play Button
|
||||
x: 354,
|
||||
y: 118,
|
||||
width: 52,
|
||||
height: 29,
|
||||
),
|
||||
( // Leaderboard button
|
||||
x: 414,
|
||||
y: 118,
|
||||
width: 52,
|
||||
height: 29,
|
||||
),
|
||||
( // Get Ready
|
||||
x: 295,
|
||||
y: 59,
|
||||
width: 91,
|
||||
height: 24,
|
||||
),
|
||||
( // Flappy Bird Text
|
||||
x: 351,
|
||||
y: 91,
|
||||
width: 90,
|
||||
height: 25,
|
||||
),
|
||||
( // Game Over
|
||||
x: 395,
|
||||
y: 58,
|
||||
width: 100,
|
||||
height: 22,
|
||||
),
|
||||
( // Number 0
|
||||
x: 314,
|
||||
y: 198,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 1
|
||||
x: 135,
|
||||
y: 455,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 2
|
||||
x: 292,
|
||||
y: 138,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 3
|
||||
x: 314,
|
||||
y: 138,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 4
|
||||
x: 336,
|
||||
y: 138,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 5
|
||||
x: 358,
|
||||
y: 138,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 6
|
||||
x: 292,
|
||||
y: 168,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 7
|
||||
x: 314,
|
||||
y: 168,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 8
|
||||
x: 336,
|
||||
y: 168,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Number 9
|
||||
x: 358,
|
||||
y: 168,
|
||||
width: 20,
|
||||
height: 28,
|
||||
),
|
||||
( // Menu Button (index 6)
|
||||
x: 462,
|
||||
y: 26,
|
||||
width: 40,
|
||||
height: 14,
|
||||
),
|
||||
( // OK Button (index 8)
|
||||
x: 462,
|
||||
y: 42,
|
||||
width: 40,
|
||||
height: 14,
|
||||
),
|
||||
( // Bird Animation 1 (index 67)
|
||||
x: 3,
|
||||
y: 491,
|
||||
width: 17,
|
||||
height: 12,
|
||||
),
|
||||
( // Bird Animation 2 (index 68)
|
||||
x: 31,
|
||||
y: 491,
|
||||
width: 17,
|
||||
height: 12,
|
||||
),
|
||||
( // Bird Animation 3 (index 69)
|
||||
x: 59,
|
||||
y: 491,
|
||||
width: 17,
|
||||
height: 12,
|
||||
)
|
||||
]
|
||||
))
|
||||
BIN
assets/sprites/logo.png
Normal file
BIN
assets/sprites/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
24
assets/sprites/logo.ron
Normal file
24
assets/sprites/logo.ron
Normal file
@@ -0,0 +1,24 @@
|
||||
(
|
||||
texture_width: 690,
|
||||
texture_height: 230,
|
||||
sprites: [
|
||||
(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 230,
|
||||
height: 230,
|
||||
),
|
||||
(
|
||||
x: 230,
|
||||
y: 0,
|
||||
width: 230,
|
||||
height: 230,
|
||||
),
|
||||
(
|
||||
x: 460,
|
||||
y: 0,
|
||||
width: 230,
|
||||
height: 230,
|
||||
)
|
||||
]
|
||||
)
|
||||
25
build-web.sh
Executable file
25
build-web.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Building for WebAssembly..."
|
||||
|
||||
# Install wasm-bindgen-cli if not present
|
||||
if ! command -v wasm-bindgen &> /dev/null; then
|
||||
echo "Installing wasm-bindgen-cli..."
|
||||
cargo install wasm-bindgen-cli
|
||||
fi
|
||||
|
||||
# Build the project
|
||||
cargo build --release --target wasm32-unknown-unknown
|
||||
|
||||
# Generate JS bindings
|
||||
wasm-bindgen --out-dir ./web --target web ./target/wasm32-unknown-unknown/release/flappy-bird-rust.wasm
|
||||
|
||||
# Copy assets and HTML
|
||||
mkdir -p web/assets
|
||||
cp -r assets/* web/assets/
|
||||
cp index.html web/
|
||||
|
||||
echo "Build complete! Files are in ./web"
|
||||
echo "To serve locally, run: python3 -m http.server --directory web 8080"
|
||||
echo "Then open http://localhost:8080"
|
||||
412
src/gameover_state.rs
Normal file
412
src/gameover_state.rs
Normal file
@@ -0,0 +1,412 @@
|
||||
use bevy::prelude::*;
|
||||
use crate::splash_state::*;
|
||||
use crate::components::*;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct GameOverScreen;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct ScoreCard {
|
||||
pub target_y: f32,
|
||||
pub animation_speed: f32,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct TinyScoreDisplay;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct TinyHighScoreDisplay;
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct DebugScoreCard {
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct ScoreCardDebugSprite;
|
||||
|
||||
pub fn setup_gameover(
|
||||
mut commands: Commands,
|
||||
sprite_handles: Res<SpriteHandles>,
|
||||
window_query: Query<&Window>,
|
||||
score: Res<Score>,
|
||||
mut high_score: ResMut<HighScore>,
|
||||
) {
|
||||
let Ok(window) = window_query.single() else {
|
||||
return;
|
||||
};
|
||||
let width = window.width();
|
||||
let height = window.height();
|
||||
|
||||
// Update high score if current score is higher
|
||||
if score.value > high_score.value {
|
||||
high_score.value = score.value;
|
||||
}
|
||||
|
||||
// Game Over sprite - positioned at 3/4 height
|
||||
let target_y = height * 0.75;
|
||||
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
image: sprite_handles.texture.clone(),
|
||||
texture_atlas: Some(TextureAtlas {
|
||||
layout: sprite_handles.layout.clone(),
|
||||
index: SPRITE_GAME_OVER,
|
||||
}),
|
||||
..default()
|
||||
},
|
||||
Transform {
|
||||
translation: Vec3::new(width * 0.5, target_y, 0.3),
|
||||
scale: Vec3::splat(3.0),
|
||||
..default()
|
||||
},
|
||||
GameOverScreen,
|
||||
));
|
||||
|
||||
// Score card - starts below screen and animates up
|
||||
let card_target_y = height * 0.4;
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
image: sprite_handles.texture.clone(),
|
||||
texture_atlas: Some(TextureAtlas {
|
||||
layout: sprite_handles.layout.clone(),
|
||||
index: SPRITE_SCORE_CARD,
|
||||
}),
|
||||
..default()
|
||||
},
|
||||
Transform {
|
||||
translation: Vec3::new(width * 0.5, -200.0, 0.2),
|
||||
scale: Vec3::splat(3.0),
|
||||
..default()
|
||||
},
|
||||
ScoreCard {
|
||||
target_y: card_target_y,
|
||||
animation_speed: 400.0,
|
||||
},
|
||||
GameOverScreen,
|
||||
));
|
||||
|
||||
// Determine medal based on score
|
||||
let medal_index = if score.value >= 40 {
|
||||
SPRITE_MEDAL_PLATINUM
|
||||
} else if score.value >= 30 {
|
||||
SPRITE_MEDAL_GOLD
|
||||
} else if score.value >= 20 {
|
||||
SPRITE_MEDAL_SILVER
|
||||
} else {
|
||||
// Everyone gets at least bronze
|
||||
SPRITE_MEDAL_BRONZE
|
||||
};
|
||||
|
||||
// Spawn medal - attached to card animation
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
image: sprite_handles.texture.clone(),
|
||||
texture_atlas: Some(TextureAtlas {
|
||||
layout: sprite_handles.layout.clone(),
|
||||
index: medal_index,
|
||||
}),
|
||||
..default()
|
||||
},
|
||||
Transform {
|
||||
translation: Vec3::new(width * 0.35 - 33.0, -200.0, 0.3),
|
||||
scale: Vec3::splat(3.0),
|
||||
..default()
|
||||
},
|
||||
ScoreCard {
|
||||
target_y: card_target_y - 10.0,
|
||||
animation_speed: 400.0,
|
||||
},
|
||||
GameOverScreen,
|
||||
));
|
||||
}
|
||||
|
||||
pub fn gameover_input(
|
||||
keyboard: Res<ButtonInput<KeyCode>>,
|
||||
mouse: Res<ButtonInput<MouseButton>>,
|
||||
touches: Res<Touches>,
|
||||
mut next_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
if keyboard.just_pressed(KeyCode::Space)
|
||||
|| mouse.just_pressed(MouseButton::Left)
|
||||
|| touches.any_just_pressed() {
|
||||
next_state.set(GameState::Ready);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn animate_score_card(
|
||||
time: Res<Time>,
|
||||
mut query: Query<(&mut Transform, &ScoreCard)>,
|
||||
) {
|
||||
for (mut transform, card) in query.iter_mut() {
|
||||
if transform.translation.y < card.target_y {
|
||||
transform.translation.y += card.animation_speed * time.delta_secs();
|
||||
// Clamp to target
|
||||
if transform.translation.y > card.target_y {
|
||||
transform.translation.y = card.target_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_tiny_score(
|
||||
mut commands: Commands,
|
||||
score: Res<Score>,
|
||||
sprite_handles: Res<SpriteHandles>,
|
||||
window_query: Query<&Window>,
|
||||
existing_digits: Query<Entity, With<TinyScoreDisplay>>,
|
||||
card_query: Query<&Transform, With<ScoreCard>>,
|
||||
) {
|
||||
// Wait for card to finish animating before showing score
|
||||
// Use iter().next() instead of single() since we have multiple ScoreCard entities
|
||||
let Some(card_transform) = card_query.iter().next() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(window) = window_query.single() else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Only render once card is near its target position
|
||||
if card_transform.translation.y < window.height() * 0.35 {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only update if score changed or digits don't exist
|
||||
if !score.is_changed() && !existing_digits.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Despawn existing score digits
|
||||
for entity in existing_digits.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
|
||||
let width = window.width();
|
||||
let height = window.height();
|
||||
let card_y = height * 0.4;
|
||||
|
||||
// Convert score to digits
|
||||
let score_string = score.value.to_string();
|
||||
let num_digits = score_string.len() as f32;
|
||||
let digit_spacing = 12.0;
|
||||
let total_width = num_digits * digit_spacing;
|
||||
let start_x = width * 0.65 - total_width / 2.0 + 30.0 + 20.0;
|
||||
|
||||
// Spawn tiny digit sprites on the score card
|
||||
for (i, digit_char) in score_string.chars().enumerate() {
|
||||
let digit = digit_char.to_digit(10).unwrap() as usize;
|
||||
let sprite_index = SPRITE_TINY_NUMBER_0 + digit;
|
||||
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
image: sprite_handles.texture.clone(),
|
||||
texture_atlas: Some(TextureAtlas {
|
||||
layout: sprite_handles.layout.clone(),
|
||||
index: sprite_index,
|
||||
}),
|
||||
..default()
|
||||
},
|
||||
Transform {
|
||||
translation: Vec3::new(start_x + (i as f32 * digit_spacing), card_y + 20.0, 0.35),
|
||||
scale: Vec3::splat(3.0),
|
||||
..default()
|
||||
},
|
||||
TinyScoreDisplay,
|
||||
GameOverScreen,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_tiny_high_score(
|
||||
mut commands: Commands,
|
||||
high_score: Res<HighScore>,
|
||||
sprite_handles: Res<SpriteHandles>,
|
||||
window_query: Query<&Window>,
|
||||
existing_digits: Query<Entity, With<TinyHighScoreDisplay>>,
|
||||
card_query: Query<&Transform, With<ScoreCard>>,
|
||||
) {
|
||||
// Wait for card to finish animating before showing high score
|
||||
// Use iter().next() instead of single() since we have multiple ScoreCard entities
|
||||
let Some(card_transform) = card_query.iter().next() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(window) = window_query.single() else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Only render once card is near its target position
|
||||
if card_transform.translation.y < window.height() * 0.35 {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only update if high score changed or digits don't exist
|
||||
if !high_score.is_changed() && !existing_digits.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Despawn existing high score digits
|
||||
for entity in existing_digits.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
|
||||
let width = window.width();
|
||||
let height = window.height();
|
||||
let card_y = height * 0.4;
|
||||
|
||||
// Convert high score to digits
|
||||
let high_score_string = high_score.value.to_string();
|
||||
let num_digits = high_score_string.len() as f32;
|
||||
let digit_spacing = 12.0;
|
||||
let total_width = num_digits * digit_spacing;
|
||||
let start_x = width * 0.65 - total_width / 2.0 + 30.0 + 20.0;
|
||||
|
||||
// Spawn tiny digit sprites on the score card below the current score
|
||||
for (i, digit_char) in high_score_string.chars().enumerate() {
|
||||
let digit = digit_char.to_digit(10).unwrap() as usize;
|
||||
let sprite_index = SPRITE_TINY_NUMBER_0 + digit;
|
||||
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
image: sprite_handles.texture.clone(),
|
||||
texture_atlas: Some(TextureAtlas {
|
||||
layout: sprite_handles.layout.clone(),
|
||||
index: sprite_index,
|
||||
}),
|
||||
..default()
|
||||
},
|
||||
Transform {
|
||||
translation: Vec3::new(start_x + (i as f32 * digit_spacing), card_y - 50.0, 0.35),
|
||||
scale: Vec3::splat(3.0),
|
||||
..default()
|
||||
},
|
||||
TinyHighScoreDisplay,
|
||||
GameOverScreen,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_scorecard_debug(
|
||||
keyboard: Res<ButtonInput<KeyCode>>,
|
||||
mut debug: ResMut<DebugScoreCard>,
|
||||
) {
|
||||
if keyboard.just_pressed(KeyCode::KeyD) {
|
||||
debug.enabled = !debug.enabled;
|
||||
println!("Score card debug: {}", if debug.enabled { "ON" } else { "OFF" });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_scorecard_debug(
|
||||
mut commands: Commands,
|
||||
debug: Res<DebugScoreCard>,
|
||||
card_query: Query<&Transform, With<ScoreCard>>,
|
||||
existing_debug: Query<Entity, With<ScoreCardDebugSprite>>,
|
||||
window_query: Query<&Window>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
) {
|
||||
// Clean up existing debug sprites
|
||||
for entity in existing_debug.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
|
||||
if !debug.enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
let Ok(window) = window_query.single() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(card_transform) = card_query.iter().next() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let width = window.width();
|
||||
let height = window.height();
|
||||
let card_y = card_transform.translation.y;
|
||||
|
||||
// Draw horizontal reference lines at different Y positions
|
||||
let reference_ys = vec![
|
||||
(card_y + 20.0, "Score line (current)"),
|
||||
(card_y, "Card center"),
|
||||
(card_y - 20.0, "Medal line (suggested)"),
|
||||
(card_y - 50.0, "High score line (current)"),
|
||||
];
|
||||
|
||||
for (y, label) in reference_ys {
|
||||
// Horizontal line
|
||||
let mesh = Mesh::from(Rectangle::new(width, 2.0));
|
||||
commands.spawn((
|
||||
Mesh2d::from(meshes.add(mesh)),
|
||||
MeshMaterial2d(materials.add(ColorMaterial::from(Color::srgba(1.0, 0.0, 0.0, 0.5)))),
|
||||
Transform {
|
||||
translation: Vec3::new(width / 2.0, y, 0.9),
|
||||
..default()
|
||||
},
|
||||
ScoreCardDebugSprite,
|
||||
));
|
||||
|
||||
// Add tick marks every 10 pixels along the horizontal line
|
||||
for tick_x in (0..(width as i32)).step_by(10) {
|
||||
let tick_mesh = Mesh::from(Rectangle::new(1.0, 8.0));
|
||||
commands.spawn((
|
||||
Mesh2d::from(meshes.add(tick_mesh)),
|
||||
MeshMaterial2d(materials.add(ColorMaterial::from(Color::srgba(1.0, 0.0, 0.0, 0.7)))),
|
||||
Transform {
|
||||
translation: Vec3::new(tick_x as f32, y, 0.91),
|
||||
..default()
|
||||
},
|
||||
ScoreCardDebugSprite,
|
||||
));
|
||||
}
|
||||
|
||||
println!("{}: y = {}", label, y);
|
||||
}
|
||||
|
||||
// Vertical reference lines for X positions
|
||||
let reference_xs = vec![
|
||||
(width * 0.35, "Medal X (current)"),
|
||||
(width * 0.5, "Center"),
|
||||
(width * 0.65, "Score area center"),
|
||||
];
|
||||
|
||||
for (x, label) in reference_xs {
|
||||
let mesh = Mesh::from(Rectangle::new(2.0, height));
|
||||
commands.spawn((
|
||||
Mesh2d::from(meshes.add(mesh)),
|
||||
MeshMaterial2d(materials.add(ColorMaterial::from(Color::srgba(0.0, 1.0, 0.0, 0.5)))),
|
||||
Transform {
|
||||
translation: Vec3::new(x, height / 2.0, 0.9),
|
||||
..default()
|
||||
},
|
||||
ScoreCardDebugSprite,
|
||||
));
|
||||
|
||||
// Add tick marks every 10 pixels along the vertical line
|
||||
for tick_y in (0..(height as i32)).step_by(10) {
|
||||
let tick_mesh = Mesh::from(Rectangle::new(8.0, 1.0));
|
||||
commands.spawn((
|
||||
Mesh2d::from(meshes.add(tick_mesh)),
|
||||
MeshMaterial2d(materials.add(ColorMaterial::from(Color::srgba(0.0, 1.0, 0.0, 0.7)))),
|
||||
Transform {
|
||||
translation: Vec3::new(x, tick_y as f32, 0.91),
|
||||
..default()
|
||||
},
|
||||
ScoreCardDebugSprite,
|
||||
));
|
||||
}
|
||||
|
||||
println!("{}: x = {}", label, x);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cleanup_gameover(
|
||||
mut commands: Commands,
|
||||
query: Query<Entity, With<GameOverScreen>>,
|
||||
) {
|
||||
for entity in query.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user