Stubbing out shape asset loading for tetris, also fixed imports
parent
277260ecf6
commit
e07ff07e23
@ -1,44 +1,3 @@
|
|||||||
[package]
|
[workspace]
|
||||||
name = "games"
|
resolver = "3"
|
||||||
version = "0.1.0"
|
members = ["engine", "flappy", "hum", "physics", "tetris", "trees"]
|
||||||
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 = "*"
|
|
||||||
|
|||||||
@ -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 = "*"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use games::*;
|
use engine::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -1,6 +1,6 @@
|
|||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
use games::*;
|
use engine::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use games::*;
|
use engine::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use games::*;
|
use engine::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use games::*;
|
use engine::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -1,2 +1,2 @@
|
|||||||
/// Include the version of this build from an auto-generated version file
|
/// 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"
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "hum"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use games::*;
|
use engine::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -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::*;
|
use super::*;
|
||||||
|
|
||||||
pub use avian2d::prelude::*;
|
pub use avian2d::prelude::*;
|
||||||
|
|
||||||
/// 2D Physics systems, resources, events, etc.
|
/// 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 = "*"
|
||||||
Loading…
Reference in New Issue