Stubbing out shape asset loading for tetris, also fixed imports

main
Elijah Voigt 4 days ago
parent 277260ecf6
commit e07ff07e23

72
Cargo.lock generated

@ -2299,6 +2299,20 @@ dependencies = [
"syn",
]
[[package]]
name = "engine"
version = "0.1.0"
dependencies = [
"bevy",
"chrono",
"itertools 0.14.0",
"lipsum",
"rand 0.9.2",
"serde",
"thiserror 2.0.12",
"walkdir",
]
[[package]]
name = "equivalent"
version = "1.0.2"
@ -2376,6 +2390,14 @@ version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "flappy"
version = "0.1.0"
dependencies = [
"engine",
"physics",
]
[[package]]
name = "flate2"
version = "1.1.2"
@ -2497,24 +2519,6 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "games"
version = "0.1.0"
dependencies = [
"avian2d",
"avian3d",
"bevy",
"chrono",
"indoc",
"itertools 0.14.0",
"lipsum",
"rand 0.9.2",
"serde",
"thiserror 2.0.12",
"toml",
"walkdir",
]
[[package]]
name = "gethostname"
version = "0.4.3"
@ -2903,6 +2907,10 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "hum"
version = "0.1.0"
[[package]]
name = "iana-time-zone"
version = "0.1.63"
@ -4041,6 +4049,15 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "physics"
version = "0.1.0"
dependencies = [
"avian2d",
"avian3d",
"engine",
]
[[package]]
name = "pin-project"
version = "1.1.10"
@ -4857,6 +4874,17 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "tetris"
version = "0.1.0"
dependencies = [
"bevy",
"engine",
"serde",
"thiserror 1.0.69",
"toml",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@ -5098,6 +5126,14 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "trees"
version = "0.1.0"
dependencies = [
"engine",
"indoc",
]
[[package]]
name = "ttf-parser"
version = "0.20.0"

@ -1,44 +1,3 @@
[package]
name = "games"
version = "0.1.0"
edition = "2024"
[[example]]
name = "demo_parallax2d"
path = "examples/demos/parallax2d.rs"
[[example]]
name = "demo_parallax3d"
path = "examples/demos/parallax3d.rs"
[features]
hide_debug = []
[dependencies]
itertools = "*"
thiserror = "2.0.12"
toml = "0.9.8"
[dependencies.serde]
version = "1.0.219"
features = ["derive"]
[dependencies.avian3d]
version = "0.4.1"
[dependencies.avian2d]
version = "0.4.1"
[dependencies.bevy]
version = "0.17.2"
features = ["wayland", "dynamic_linking", "track_location", "experimental_bevy_feathers", "experimental_bevy_ui_widgets"]
[dev-dependencies]
lipsum = "*"
rand = "*"
itertools = "*"
indoc = "*"
[build-dependencies]
walkdir = "*"
chrono = "*"
[workspace]
resolver = "3"
members = ["engine", "flappy", "hum", "physics", "tetris", "trees"]

@ -0,0 +1,28 @@
[package]
name = "engine"
version = "0.1.0"
edition = "2024"
[features]
hide_debug = []
[dependencies.bevy]
version = "0.17.2"
features = ["wayland", "dynamic_linking", "track_location", "experimental_bevy_feathers", "experimental_bevy_ui_widgets"]
[dependencies.serde]
version = "1.0.219"
features = ["derive"]
[dependencies]
itertools = "0.14.0"
thiserror = "2.0.12"
[dev-dependencies]
lipsum = "*"
rand = "*"
itertools = "*"
[build-dependencies]
walkdir = "*"
chrono = "*"

@ -3,22 +3,23 @@
use bevy::{
color::palettes,
feathers::{
FeathersPlugins,
controls::{
button, checkbox, color_slider, color_swatch, radio, slider, toggle_switch,
ButtonProps, ButtonVariant, ColorChannel, ColorSlider, ColorSliderProps, ColorSwatch,
SliderBaseColor, SliderProps,
SliderBaseColor, SliderProps, button, checkbox, color_slider, color_swatch, radio,
slider, toggle_switch,
},
dark_theme::create_dark_theme,
rounded_corners::RoundedCorners,
theme::{ThemeBackgroundColor, ThemedText, UiTheme},
tokens, FeathersPlugins,
tokens,
},
input_focus::tab_navigation::TabGroup,
prelude::*,
ui::{Checked, InteractionDisabled},
ui_widgets::{
checkbox_self_update, observe, slider_self_update, Activate, RadioButton, RadioGroup,
SliderPrecision, SliderStep, SliderValue, ValueChange,
Activate, RadioButton, RadioGroup, SliderPrecision, SliderStep, SliderValue, ValueChange,
checkbox_self_update, observe, slider_self_update,
},
};

@ -1,4 +1,4 @@
use games::*;
use engine::*;
fn main() {
App::new()

@ -1,6 +1,6 @@
use std::f32::consts::PI;
use games::*;
use engine::*;
fn main() {
App::new()

@ -1,4 +1,4 @@
use games::*;
use engine::*;
fn main() {
App::new()

@ -1,4 +1,4 @@
use games::*;
use engine::*;
fn main() {
App::new()

@ -3,7 +3,7 @@
//! This example illustrates scrolling in Bevy UI.
use bevy::picking::hover::HoverMap;
use games::*;
use engine::*;
use lipsum::*;
use rand::*;

@ -1,4 +1,4 @@
use games::*;
use engine::*;
fn main() {
App::new()

@ -6,8 +6,6 @@ mod base_game;
mod debug;
mod loading;
mod parallax;
pub mod physics2d;
pub mod physics3d;
mod scheduling;
mod ui;
mod version;
@ -24,6 +22,7 @@ pub use bevy::{
},
camera::{primitives::*, visibility::*, *},
color::palettes::css::*,
feathers::controls::*,
gizmos::{aabb::AabbGizmoPlugin, light::LightGizmoPlugin},
input::{
ButtonState,
@ -40,10 +39,9 @@ pub use bevy::{
render::render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
sprite_render::*,
time::common_conditions::*,
window::{WindowResized, WindowResolution},
ui_widgets::{Button, *},
ui::*,
feathers::controls::*,
ui_widgets::{Button, *},
window::{WindowResized, WindowResolution},
};
pub use itertools::Itertools;
pub use serde::Deserialize;

@ -1,2 +1,2 @@
/// Include the version of this build from an auto-generated version file
pub const VERSION: &str = include_str!("../VERSION");
pub const VERSION: &str = include_str!("../../VERSION");

@ -0,0 +1,10 @@
[package]
name = "flappy"
version = "0.1.0"
edition = "2024"
[dependencies.engine]
path = "../engine"
[dependencies.physics]
path = "../physics"

@ -4,8 +4,8 @@
use bevy::image::{ImageLoaderSettings, ImageSampler};
use bevy::platform::time::Instant;
use bevy::render::view::ColorGrading;
use games::physics2d::*;
use games::*;
use engine::*;
use physics::physics2d::*;
use std::hash::BuildHasher;
fn main() {

@ -0,0 +1,6 @@
[package]
name = "hum"
version = "0.1.0"
edition = "2024"
[dependencies]

@ -1,4 +1,4 @@
use games::*;
use engine::*;
fn main() {
App::new()

@ -1,5 +1,11 @@
VERSION := `git rev-parse --short HEAD`
check:
cargo check -p tetris
play:
cargo run -p tetris
bindgen profile name:
mkdir -p ./dist/{{name}}

@ -0,0 +1,14 @@
[package]
name = "physics"
version = "0.1.0"
edition = "2024"
[dependencies.engine]
path = "../engine"
[dependencies.avian3d]
version = "0.4.1"
[dependencies.avian2d]
version = "0.4.1"

@ -0,0 +1,2 @@
pub mod physics2d;
pub mod physics3d;

@ -1,4 +1,5 @@
use super::*;
pub use avian2d::prelude::*;
/// 2D Physics systems, resources, events, etc.

@ -1,53 +0,0 @@
use super::*;
/// Create tetris game with camera that renders to subset of viewport
///
/// Focus on a single piece and making it really tight mechanically
/// A single piece with movement, rotation, jump-to-end, line clearing, etc.
///
/// Once done, make pieces a data input so we can add arbitrary metadata to them
pub struct BlocksPlugin;
impl Plugin for BlocksPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, init_blocks);
}
}
/// Shape asset
/// Stores shape data in an asset file, likely toml
#[derive(Asset, TypePath, Debug, Deserialize)]
struct ShapeAsset {
layout: Vec<Vec<u8>>
}
#[derive(Default)]
struct ShapeAssetLoader;
impl AssetLoader for ShapeAssetLoader {
type Asset = ShapeAsset;
type Settings = ();
type Error = ();
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &(),
_load_context: &mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await.unwrap_or(());
let shape_asset = toml::from_slice::<ShapeAsset>(bytes.into()).unwrap_or(());
Ok(shape_asset)
}
fn extension(&self) -> &[str] {
&["shape.toml"]
}
}
/// Initialize camera and block game area
fn init_blocks(
mut commands: Commands,
) {
commands.spawn((Camera2d, Camera::default()));
}

@ -1,16 +0,0 @@
mod blocks;
mod debug;
mod fighter;
use games::*;
use blocks::*;
use debug::*;
use fighter::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, BlocksPlugin, FighterPlugin))
.run();
}

@ -0,0 +1,19 @@
[package]
name = "tetris"
version = "0.1.0"
edition = "2024"
[dependencies.serde]
version = "1.0.219"
features = ["derive"]
[dependencies.engine]
path = "../engine"
[dependencies]
toml = "0.9.8"
thiserror = "*"
[dependencies.bevy]
version = "0.17.2"
features = ["wayland", "dynamic_linking", "track_location", "experimental_bevy_feathers", "experimental_bevy_ui_widgets"]

@ -0,0 +1,4 @@
layout = [
[0,1,0],
[1,1,1],
]

@ -0,0 +1,90 @@
use super::*;
/// Create tetris game with camera that renders to subset of viewport
///
/// Focus on a single piece and making it really tight mechanically
/// A single piece with movement, rotation, jump-to-end, line clearing, etc.
///
/// Once done, make pieces a data input so we can add arbitrary metadata to them
pub struct BlocksPlugin;
impl Plugin for BlocksPlugin {
fn build(&self, app: &mut App) {
app.init_asset::<ShapeAsset>()
.init_asset_loader::<ShapeAssetLoader>()
.add_systems(OnEnter(LoadState::Loading), load_assets)
.add_systems(OnEnter(GameState::Setup), (setup_camera, setup_blocks))
.add_observer(add_shape);
}
}
/// Shape asset
/// Stores shape data in an asset file, likely toml
#[derive(Asset, TypePath, Debug, Deserialize)]
struct ShapeAsset {
layout: Vec<Vec<u8>>,
}
impl ShapeAsset {
fn into_bundle(&self) -> impl Bundle {
()
}
}
#[derive(Default)]
struct ShapeAssetLoader;
#[derive(Debug, Error)]
enum ShapeAssetError {
#[error("Failed to read file {0}")]
Io(#[from] std::io::Error),
#[error("Failed to parse file {0}")]
Parse(#[from] toml::de::Error),
}
impl AssetLoader for ShapeAssetLoader {
type Asset = ShapeAsset;
type Settings = ();
type Error = ShapeAssetError;
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &(),
_load_context: &mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let shape_asset = toml::from_slice::<ShapeAsset>(bytes.as_slice())?;
Ok(shape_asset)
}
fn extensions(&self) -> &[&str] {
&["shape.toml"]
}
}
/// Initialize camera and block game area
fn load_assets(server: Res<AssetServer>, mut all_assets: ResMut<AllAssets>) {
all_assets.handles.push(server.load::<ShapeAsset>("t.shape.toml").untyped());
}
fn setup_camera(mut commands: Commands) {
commands.spawn((Camera2d, Camera::default()));
}
fn setup_blocks(mut commands: Commands) {
error!("Setup blocks");
error!("Once all steps are setup, move on to Run");
}
/// Event handler for transforming a handle component into a thing
fn add_shape(
event: On<Add, AssetComponent<ShapeAsset>>,
query: Query<&AssetComponent<ShapeAsset>>,
mut commands: Commands,
shapes: Res<Assets<ShapeAsset>>,
) {
let asset_component = query.get(event.entity).unwrap();
let shape = shapes.get(asset_component.handle.id()).unwrap();
commands.entity(event.entity).insert(shape.into_bundle());
}

@ -0,0 +1,69 @@
mod blocks;
mod debug;
mod fighter;
use engine::*;
use serde::Deserialize;
use thiserror::Error;
use blocks::*;
use debug::*;
use fighter::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, BlocksPlugin, FighterPlugin))
.init_state::<GameState>()
.init_resource::<AllAssets>()
.add_systems(Update, load.run_if(in_state(LoadState::Loading)))
.run();
}
#[derive(Default, Resource)]
struct AllAssets {
handles: Vec<UntypedHandle>,
}
/// Reports if the game is loading assets
#[derive(States, Default, Clone, Eq, Debug, PartialEq, Hash)]
enum LoadState {
#[default]
Loading,
Loaded,
}
/// Tracks if the game is in debug mode
#[derive(States, Default, Clone, Eq, Debug, PartialEq, Hash)]
enum DebugState {
#[default]
Off,
On,
}
/// Tracks what state the main game loop is in
#[derive(States, Default, Clone, Eq, Debug, PartialEq, Hash)]
enum GameState {
#[default]
Setup,
Run,
}
fn load(mut next: ResMut<NextState<GameState>>, server: Res<AssetServer>, assets: Res<AllAssets>) {
for asset in assets.handles.iter() {
let state = server.get_load_state(asset.id());
println!("{:?}", state);
}
next.set(GameState::Setup);
}
/// A wrapper around a handle for assigning an arbitrary Handle<T> to an entity
#[derive(Debug, Component)]
struct AssetComponent<T: Asset> {
handle: Handle<T>,
}
impl<T: Asset> AssetComponent<T> {
fn new(handle: Handle<T>) -> Self {
Self { handle }
}
}

@ -0,0 +1,10 @@
[package]
name = "trees"
version = "0.1.0"
edition = "2024"
[dependencies.engine]
path = "../engine"
[dev-dependencies]
indoc = "*"

@ -8,7 +8,7 @@ mod mono;
use bevy::{picking::hover::HoverMap, platform::hash::RandomState};
use debug::*;
use games::*;
use engine::*;
use mono::*;
use std::hash::BuildHasher;
Loading…
Cancel
Save