Skip to content
Snippets Groups Projects
Verified Commit 2ccb8053 authored by Louis's avatar Louis :fire:
Browse files

Import scaffolding

parent 12a6ff3a
No related branches found
No related tags found
No related merge requests found
Showing
with 3540 additions and 0 deletions
# Add the contents of this file to `config.toml` to enable "fast build" configuration. Please read the notes below.
# NOTE: For maximum performance, build using a nightly compiler
# If you are using rust stable, remove the "-Zshare-generics=y" below.
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"]
# NOTE: you must manually install https://github.com/michaeleisel/zld on mac. you can easily do this with the "brew" package manager:
# `brew install michaeleisel/zld/zld`
[target.x86_64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/zld", "-Zshare-generics=y"]
[target.aarch64-apple-darwin]
rustflags = ["-C", "link-arg=-fuse-ld=/opt/homebrew/bin/zld", "-Zshare-generics=y"]
[target.x86_64-pc-windows-msvc]
linker = "rust-lld.exe"
rustflags = ["-Zshare-generics=n"]
# Optional: Uncommenting the following improves compile times, but reduces the amount of debug info to 'line number tables only'
# In most cases the gains are negligible, but if you are on macos and have slow compile times you should see significant gains.
#[profile.dev]
#debug = 1
[target.wasm32-unknown-unknown]
runner = "wasm-server-runner"
\ No newline at end of file
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
......@@ -4,3 +4,7 @@
# These are backup files generated by rustfmt
**/*.rs.bk
.idea/
.vscode/
dist/
\ No newline at end of file
Cargo.lock 0 → 100644
This diff is collapsed.
[workspace]
resolver = "2"
members = [
"game_core",
]
[profile.release]
debug = 0
opt-level = 3
Makefile 0 → 100644
linux-deps:
sudo apt-get install -yyq clang pkg-config libx11-dev libasound-dev libudev-dev lld
wayland-deps:
sudo apt-get install -yyq libwayland-dev libxkbcommon-dev
cargo-deps:
rustup target install wasm32-unknown-unknown
cargo install -f wasm-server-runner
setup-x11: linux-deps cargo-deps
setup-wayland: linux-deps wayland-deps cargo-deps
run:
RUSTFLAGS="-Awarnings" \
cargo run --release --features "bevy/dynamic" -p game_core
run-web:
cd game_core && trunk serve --release
check:
cargo check --release --features "bevy/dynamic" -p game_core
\ No newline at end of file
README 0 → 100644
# Bevy 2D Template
## Usage
Write some code, ya dig?
This project is set up for a multi-crate bevy game, but will work equally well
if just using a single crate for your game. `game_core` is the location of your
entry point, assets are placed at the root of the workspace in the `assets` folder.
Update the splash screen by replacing `assets/splash.png` - it is scaled by
default to fill the shortest screen side; you can include empty space in your
splash image as a simple way of changing the padding.
## Commands
- Linux:
- Run `make x11-setup` or `make wayland-setup` depending on the target platform
- Run `make run` to play
- Run `make check` to run Cargo Check
- Web:
- Run `make cargo-deps` to install wasm tools
- Run `make run-web` to launch the dev server
- Run `make check` to run Cargo Check
- Run `make web` to build the release version of the web project
## Includes
- Workspace configuration w/ assets dir
- Splash screen
assets/splash.png

131 B

File added
(function () {
// An array of all contexts to resume on the page
const audioContextList = [];
// An array of various user interaction events we should listen for
const userInputEventNames = [
'click',
'contextmenu',
'auxclick',
'dblclick',
'mousedown',
'mouseup',
'pointerup',
'touchend',
'keydown',
'keyup',
];
// A proxy object to intercept AudioContexts and
// add them to the array for tracking and resuming later
self.AudioContext = new Proxy(self.AudioContext, {
construct(target, args) {
const result = new target(...args);
audioContextList.push(result);
return result;
},
});
// To resume all AudioContexts being tracked
function resumeAllContexts(event) {
let count = 0;
audioContextList.forEach(context => {
if (context.state !== 'running') {
context.resume();
} else {
count++;
}
});
// If all the AudioContexts have now resumed then we
// unbind all the event listeners from the page to prevent
// unnecessary resume attempts
if (count == audioContextList.length) {
userInputEventNames.forEach(eventName => {
document.removeEventListener(eventName, resumeAllContexts);
});
}
}
// We bind the resume function for each user interaction
// event on the page
userInputEventNames.forEach(eventName => {
document.addEventListener(eventName, resumeAllContexts);
});
})();
\ No newline at end of file
/target
[package]
name = "game_core"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
iyes_loopless = "0.6.1"
fastrand = "1.7.0"
anyhow = "1.0.58"
log = "0.4.17"
thiserror = "1.0.31"
serde = "1.0.139"
serde_json = "1.0.82"
micro_bevy_musicbox = { git = "https://lab.lcr.gr/microhacks/micro-bevy-musicbox.git", rev="a6c8ae0127de2a0f2fd20ce7189625471663cd4a"}
[dependencies.bevy]
version = "0.7"
default-features = false
features = [
"render",
"bevy_winit",
"png",
"hdr",
"x11",
]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Bevy 2D Template</title> <!-- TODO: Set game name -->
<link data-trunk rel="copy-dir" href="../assets"/>
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
<!-- <link data-trunk rel="copy-dir" href="credits"/>-->
<!-- <link data-trunk rel="copy-file" href="build/windows/icon.ico"/>-->
<!-- <link rel="icon" href="icon.ico">-->
<!-- <link data-trunk rel="inline" href="build/web/styles.css"/>-->
</head>
<body>
<link data-trunk rel="inline" href="../build/web/audio.js"/>
</body>
</html>
\ No newline at end of file
use std::marker::PhantomData;
use bevy::asset::LoadState;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use bevy::reflect::TypeUuid;
use micro_bevy_musicbox::prelude::AudioSource;
use crate::assets::{AssetHandles, FixedAssetNameMapping, SpriteSheetConfig};
#[derive(SystemParam)]
pub struct AssetTypeLoader<'w, 's> {
pub handles: ResMut<'w, AssetHandles>,
pub asset_server: Res<'w, AssetServer>,
pub atlas: ResMut<'w, Assets<TextureAtlas>>,
#[system_param(ignore)]
marker: PhantomData<&'s usize>,
}
impl<'w, 's> AssetTypeLoader<'w, 's> {
fn load_list<
T: Sync + Send + TypeUuid + 'static,
Loader: Fn(&mut AssetTypeLoader, String, String) -> Handle<T>,
>(
&mut self,
files: &[FixedAssetNameMapping],
load: Loader,
) -> Vec<Handle<T>> {
files
.iter()
.map(|(path, key)| load(self, path.to_string(), key.to_string()))
.collect()
}
pub fn load_images(&mut self, assets: &[FixedAssetNameMapping]) -> Vec<Handle<Image>> {
self.load_list(assets, |loader, path, key| {
let handle: Handle<Image> = loader.asset_server.load(&path);
loader.handles.images.insert(key, handle.clone());
handle
})
}
pub fn load_spritesheet(
&mut self,
config: &SpriteSheetConfig,
assets: &[FixedAssetNameMapping],
) -> Vec<Handle<Image>> {
self.load_list(assets, |loader, path, key| {
let handle: Handle<Image> = loader.asset_server.load(&path);
loader
.handles
.images
.insert(key.to_string(), handle.clone());
let atlas = TextureAtlas::from_grid(
handle.clone(),
Vec2::new(config.tile_width as f32, config.tile_height as f32),
config.columns,
config.rows,
);
let atlas_handle = loader.atlas.add(atlas);
loader.handles.atlas.insert(key, atlas_handle);
handle
})
}
pub fn load_audio(&mut self, assets: &[FixedAssetNameMapping]) -> Vec<Handle<AudioSource>> {
self.load_list(assets, |loader, path, key| {
let handle: Handle<AudioSource> = loader.asset_server.load(&path);
loader.handles.sounds.insert(key, handle.clone());
handle
})
}
pub fn get_all_load_state(&self) -> Vec<LoadState> {
let image_state = self
.asset_server
.get_group_load_state(self.handles.images.values().map(|f| f.id));
let atlas_state = self
.asset_server
.get_group_load_state(self.handles.images.values().map(|f| f.id));
vec![image_state, atlas_state]
}
}
mod loader;
mod resources;
mod startup;
use bevy::app::Plugin;
use iyes_loopless::condition::ConditionSet;
use iyes_loopless::prelude::AppLooplessStateExt;
pub use loader::AssetTypeLoader;
pub use resources::{AssetHandles, AssetNameMapping, FixedAssetNameMapping, SpriteSheetConfig};
use crate::system::flow::AppState;
use crate::App;
pub struct AssetsPlugin;
impl Plugin for AssetsPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<AssetHandles>()
.add_enter_system(AppState::Preload, startup::start_preload_resources)
.add_enter_system(AppState::Preload, startup::start_load_resources)
.add_system_set(
ConditionSet::new()
.run_in_state(AppState::Setup)
.with_system(startup::check_load_resources)
.into(),
);
}
}
use bevy::prelude::*;
use bevy::utils::HashMap;
use micro_bevy_musicbox::prelude::AudioSource;
use micro_bevy_musicbox::utilities::SuppliesAudio;
#[derive(Copy, Clone, Debug)]
pub struct SpriteSheetConfig {
pub tile_width: usize,
pub tile_height: usize,
pub columns: usize,
pub rows: usize,
}
impl SpriteSheetConfig {
pub fn squares(tile_wh: usize, columns: usize, rows: usize) -> Self {
Self {
tile_width: tile_wh,
tile_height: tile_wh,
columns,
rows,
}
}
pub fn rectangles(tile_width: usize, tile_height: usize, columns: usize, rows: usize) -> Self {
Self {
tile_width,
tile_height,
columns,
rows,
}
}
}
#[derive(Default)]
pub struct AssetHandles {
pub(crate) images: HashMap<String, Handle<Image>>,
pub(crate) atlas: HashMap<String, Handle<TextureAtlas>>,
pub(crate) sounds: HashMap<String, Handle<AudioSource>>,
}
impl SuppliesAudio for AssetHandles {
fn get_audio_track<T: ToString>(&self, name: T) -> Option<Handle<AudioSource>> {
self.sounds.get(&name.to_string()).map(Handle::clone_weak)
}
}
pub type AssetNameMapping = (String, String);
pub type FixedAssetNameMapping = (&'static str, &'static str);
use bevy::asset::LoadState;
use bevy::prelude::*;
use iyes_loopless::prelude::NextState;
use crate::assets::AssetTypeLoader;
use crate::system::flow::AppState;
pub fn start_preload_resources(mut commands: Commands) {
// TODO: Add preload commands here
commands.insert_resource(NextState(AppState::Setup))
}
pub fn start_load_resources(mut loader: AssetTypeLoader) {
loader.load_images(&[("splash.png", "splash")]);
loader.load_audio(&[("splash_sting.mp3", "splash_sting")]);
}
pub fn check_load_resources(mut commands: Commands, loader: AssetTypeLoader) {
let load_states = loader.get_all_load_state();
if load_states.iter().all(|state| *state == LoadState::Loaded) {
log::info!("Assets loaded successfully");
commands.insert_resource(NextState(AppState::Splash))
}
}
use bevy::asset::AssetServerSettings;
use bevy::prelude::*;
use bevy::window::PresentMode;
use crate::system::camera::{spawn_orthographic_camera, spawn_ui_camera};
pub mod assets;
pub mod splash_screen;
pub mod system;
#[cfg(target_arch = "wasm32")]
pub fn get_asset_path_string() -> String {
String::from("assets")
}
#[cfg(not(target_arch = "wasm32"))]
pub fn get_asset_path_string() -> String {
std::env::current_dir()
.unwrap()
.join("assets")
.to_str()
.unwrap()
.to_string()
}
pub struct DefaultResourcesPlugin;
impl Plugin for DefaultResourcesPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(WindowDescriptor {
width: 1280.0,
height: 720.0,
resizable: true,
title: String::from("Bevy 2D Template"),
present_mode: PresentMode::Mailbox,
..Default::default()
})
.insert_resource(Msaa { samples: 1 })
.insert_resource(ClearColor(Color::hex("040720").unwrap()))
.insert_resource(AssetServerSettings {
asset_folder: get_asset_path_string(),
watch_for_changes: false,
})
.add_startup_system(spawn_orthographic_camera)
.add_startup_system(spawn_ui_camera);
}
}
use bevy::prelude::*;
use game_core::system::flow::AppState;
use game_core::DefaultResourcesPlugin;
use iyes_loopless::prelude::AppLooplessStateExt;
use micro_bevy_musicbox::CombinedAudioPlugins;
fn main() {
App::new()
.add_loopless_state(AppState::Preload)
.add_plugin(DefaultResourcesPlugin)
.add_plugins(DefaultPlugins)
.add_plugin(game_core::assets::AssetsPlugin)
.add_plugins(CombinedAudioPlugins)
.add_plugin(game_core::splash_screen::SplashScreenPlugin)
.run();
}
use bevy::prelude::*;
#[derive(Clone)]
pub enum SplashAnimationType {
FadeColour { from: Color, to: Color },
Wait,
}
#[derive(Component, Clone)]
pub struct SplashAnimation {
pub duration: f32,
pub anim: SplashAnimationType,
pub then: Option<Box<SplashAnimation>>,
}
#[derive(Component, Clone)]
pub struct SplashAnimationTimer(pub f32);
#[derive(Bundle)]
pub struct SplashAnimationBundle {
animation: SplashAnimation,
timer: SplashAnimationTimer,
}
impl SplashAnimationBundle {
pub fn from_animation(animation: SplashAnimation) -> Self {
Self {
animation,
timer: SplashAnimationTimer(0.0),
}
}
}
impl SplashAnimation {
pub fn fade(
from: Color,
to: Color,
duration: f32,
then: Option<Box<SplashAnimation>>,
) -> SplashAnimation {
SplashAnimation {
anim: SplashAnimationType::FadeColour { from, to },
duration,
then,
}
}
pub fn wait(duration: f32, then: Option<Box<SplashAnimation>>) -> SplashAnimation {
SplashAnimation {
anim: SplashAnimationType::Wait,
duration,
then,
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment