This commit is contained in:
parent
2cd4588b13
commit
809b1d7c5c
10 changed files with 512 additions and 4 deletions
54
Cargo.lock
generated
54
Cargo.lock
generated
|
@ -566,6 +566,17 @@ dependencies = [
|
|||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ecs_tilemap"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d880047f5deaf5166ffc08238125a4ccbd2837f781ca6525fa200fcf5785ba3b"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_encase_derive"
|
||||
version = "0.14.1"
|
||||
|
@ -3560,6 +3571,18 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiled"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad408d366c0e1e7e4e504cabc14c77fdda77176d93b3c6abe5b3b31885df3ad0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"flate2",
|
||||
"xml-rs",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.8.0"
|
||||
|
@ -4514,9 +4537,12 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bevy",
|
||||
"bevy_asset_loader",
|
||||
"bevy_ecs_tilemap",
|
||||
"bevy_kira_audio",
|
||||
"image",
|
||||
"log",
|
||||
"thiserror",
|
||||
"tiled",
|
||||
"webbrowser",
|
||||
"winit",
|
||||
]
|
||||
|
@ -4541,3 +4567,31 @@ dependencies = [
|
|||
"quote",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.13+zstd.1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
|
|
@ -70,3 +70,6 @@ log = { version = "0.4", features = [
|
|||
"max_level_debug",
|
||||
"release_max_level_warn",
|
||||
] }
|
||||
thiserror = "1.0.63"
|
||||
bevy_ecs_tilemap = { version = "0.14.0" }
|
||||
tiled = { version = "0.12.0", features = ["wasm"] }
|
||||
|
|
30
assets/maps/test.tmx
Normal file
30
assets/maps/test.tmx
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-up" width="30" height="20" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||
<tileset firstgid="1" name="test" tilewidth="32" tileheight="32" tilecount="6" columns="3">
|
||||
<image source="../textures/grass_tiles.png" width="96" height="64"/>
|
||||
</tileset>
|
||||
<layer id="1" name="Tile Layer 1" width="30" height="20">
|
||||
<data encoding="csv">
|
||||
1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,1,1,1,3,3,3,1,1,1,
|
||||
1,3,1,1,1,3,3,1,1,1,1,1,1,1,3,3,3,3,3,3,1,1,3,3,3,1,3,3,1,1,
|
||||
1,3,1,3,3,3,1,1,1,1,3,3,1,1,1,3,1,1,1,1,1,1,3,3,1,1,1,3,1,1,
|
||||
1,1,4,3,1,1,1,1,6,1,3,3,1,1,1,1,1,1,1,1,3,3,3,3,3,4,4,3,3,1,
|
||||
1,1,3,3,4,4,4,4,4,1,1,1,1,1,1,3,1,1,6,1,1,1,1,1,1,4,4,4,3,1,
|
||||
1,1,3,1,1,1,1,1,4,1,1,1,1,3,3,3,1,1,1,1,1,1,4,4,1,4,4,3,4,1,
|
||||
1,3,3,1,1,1,1,1,4,1,3,3,3,3,1,1,3,1,5,5,1,1,5,4,1,1,4,3,4,4,
|
||||
1,4,1,1,1,6,1,4,4,1,3,3,1,1,6,1,3,1,5,5,1,3,3,3,4,1,1,3,1,4,
|
||||
1,4,4,1,1,1,3,3,1,1,3,3,1,1,1,1,3,3,1,5,5,3,5,1,3,4,4,3,1,4,
|
||||
1,3,4,1,1,3,3,3,1,1,1,3,3,3,3,3,3,3,3,1,5,3,5,5,3,3,4,3,3,4,
|
||||
1,3,3,1,1,3,4,1,3,1,1,1,3,1,1,1,3,3,3,3,1,3,1,5,1,3,3,4,4,1,
|
||||
1,4,3,1,1,1,1,1,3,3,1,1,3,3,5,5,3,1,1,3,3,3,1,1,1,1,3,1,1,1,
|
||||
1,1,3,1,1,1,6,1,1,3,1,1,1,3,3,3,1,1,1,1,6,3,3,1,1,1,3,1,1,1,
|
||||
1,1,4,3,1,1,1,1,1,1,5,5,5,5,1,3,3,1,1,1,3,1,3,1,1,1,3,1,3,3,
|
||||
1,1,1,3,3,1,1,1,1,1,5,5,5,1,1,1,3,3,1,1,4,1,3,3,1,1,1,1,3,1,
|
||||
3,3,1,4,3,1,1,6,1,1,1,3,3,3,3,3,1,1,1,1,4,1,1,3,1,1,1,1,3,1,
|
||||
1,3,1,1,3,3,1,1,3,3,3,3,1,1,1,1,1,1,1,1,4,4,4,1,1,1,1,3,3,1,
|
||||
1,3,3,1,1,1,3,3,3,1,1,1,1,1,1,1,6,1,1,3,3,3,4,4,1,1,1,3,1,1,
|
||||
1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,1,3,3,3,4,1,1,3,1,1,
|
||||
1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,3,3,1,1
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
BIN
assets/textures/grass_tiles.png
(Stored with Git LFS)
Normal file
BIN
assets/textures/grass_tiles.png
(Stored with Git LFS)
Normal file
Binary file not shown.
14
src/lib.rs
14
src/lib.rs
|
@ -5,9 +5,13 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
|
||||
use bevy::prelude::*;
|
||||
use bevy_ecs_tilemap::TilemapPlugin;
|
||||
use map::MapPlugin;
|
||||
use player::PlayerPlugin;
|
||||
|
||||
mod loaders;
|
||||
mod loading;
|
||||
mod map;
|
||||
mod menu;
|
||||
mod player;
|
||||
|
||||
|
@ -25,8 +29,14 @@ pub struct YunoPlugin;
|
|||
|
||||
impl Plugin for YunoPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_state::<GameState>()
|
||||
.add_plugins((LoadingPlugin, MenuPlugin, PlayerPlugin));
|
||||
app.init_state::<GameState>().add_plugins((
|
||||
TilemapPlugin,
|
||||
loaders::tiled::TiledMapPlugin,
|
||||
MapPlugin,
|
||||
LoadingPlugin,
|
||||
MenuPlugin,
|
||||
PlayerPlugin,
|
||||
));
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
|
1
src/loaders/mod.rs
Normal file
1
src/loaders/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub(crate) mod tiled;
|
381
src/loaders/tiled.rs
Normal file
381
src/loaders/tiled.rs
Normal file
|
@ -0,0 +1,381 @@
|
|||
// How to use this:
|
||||
// You should copy/paste this into your project and use it much like examples/tiles.rs uses this
|
||||
// file. When you do so you will need to adjust the code based on whether you're using the
|
||||
// 'atlas` feature in bevy_ecs_tilemap. The bevy_ecs_tilemap uses this as an example of how to
|
||||
// use both single image tilesets and image collection tilesets. Since your project won't have
|
||||
// the 'atlas' feature defined in your Cargo config, the expressions prefixed by the #[cfg(...)]
|
||||
// macro will not compile in your project as-is. If your project depends on the bevy_ecs_tilemap
|
||||
// 'atlas' feature then move all of the expressions prefixed by #[cfg(not(feature = "atlas"))].
|
||||
// Otherwise remove all of the expressions prefixed by #[cfg(feature = "atlas")].
|
||||
//
|
||||
// Functional limitations:
|
||||
// * When the 'atlas' feature is enabled tilesets using a collection of images will be skipped.
|
||||
// * Only finite tile layers are loaded. Infinite tile layers and object layers will be skipped.
|
||||
|
||||
use std::io::{Cursor, ErrorKind};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bevy::{
|
||||
asset::{io::Reader, AssetLoader, AssetPath, AsyncReadExt},
|
||||
log,
|
||||
prelude::{
|
||||
Added, Asset, AssetApp, AssetEvent, AssetId, Assets, Bundle, Commands, Component,
|
||||
DespawnRecursiveExt, Entity, EventReader, GlobalTransform, Handle, Image, Plugin, Query,
|
||||
Res, Transform, Update,
|
||||
},
|
||||
reflect::TypePath,
|
||||
utils::HashMap,
|
||||
};
|
||||
use bevy_ecs_tilemap::prelude::*;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TiledMapPlugin;
|
||||
|
||||
impl Plugin for TiledMapPlugin {
|
||||
fn build(&self, app: &mut bevy::prelude::App) {
|
||||
app.init_asset::<TiledMap>()
|
||||
.register_asset_loader(TiledLoader)
|
||||
.add_systems(Update, process_loaded_maps);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(TypePath, Asset)]
|
||||
pub struct TiledMap {
|
||||
pub map: tiled::Map,
|
||||
|
||||
pub tilemap_textures: HashMap<usize, TilemapTexture>,
|
||||
|
||||
// The offset into the tileset_images for each tile id within each tileset.
|
||||
pub tile_image_offsets: HashMap<(usize, tiled::TileId), u32>,
|
||||
}
|
||||
|
||||
// Stores a list of tiled layers.
|
||||
#[derive(Component, Default)]
|
||||
pub struct TiledLayersStorage {
|
||||
pub storage: HashMap<u32, Entity>,
|
||||
}
|
||||
|
||||
#[derive(Default, Bundle)]
|
||||
pub struct TiledMapBundle {
|
||||
pub tiled_map: Handle<TiledMap>,
|
||||
pub storage: TiledLayersStorage,
|
||||
pub transform: Transform,
|
||||
pub global_transform: GlobalTransform,
|
||||
pub render_settings: TilemapRenderSettings,
|
||||
}
|
||||
|
||||
struct BytesResourceReader {
|
||||
bytes: Arc<[u8]>,
|
||||
}
|
||||
|
||||
impl BytesResourceReader {
|
||||
fn new(bytes: &[u8]) -> Self {
|
||||
Self {
|
||||
bytes: Arc::from(bytes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl tiled::ResourceReader for BytesResourceReader {
|
||||
type Resource = Cursor<Arc<[u8]>>;
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn read_from(&mut self, _path: &Path) -> std::result::Result<Self::Resource, Self::Error> {
|
||||
// In this case, the path is ignored because the byte data is already provided.
|
||||
Ok(Cursor::new(self.bytes.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TiledLoader;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum TiledAssetLoaderError {
|
||||
/// An [IO](std::io) Error
|
||||
#[error("Could not load Tiled file: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
impl AssetLoader for TiledLoader {
|
||||
type Asset = TiledMap;
|
||||
type Settings = ();
|
||||
type Error = TiledAssetLoaderError;
|
||||
|
||||
async fn load<'a>(
|
||||
&'a self,
|
||||
reader: &'a mut Reader<'_>,
|
||||
_settings: &'a Self::Settings,
|
||||
load_context: &'a mut bevy::asset::LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
let mut bytes = Vec::new();
|
||||
reader.read_to_end(&mut bytes).await?;
|
||||
|
||||
let mut loader = tiled::Loader::with_cache_and_reader(
|
||||
tiled::DefaultResourceCache::new(),
|
||||
BytesResourceReader::new(&bytes),
|
||||
);
|
||||
let map = loader.load_tmx_map(load_context.path()).map_err(|e| {
|
||||
std::io::Error::new(ErrorKind::Other, format!("Could not load TMX map: {e}"))
|
||||
})?;
|
||||
|
||||
let mut tilemap_textures = HashMap::default();
|
||||
let mut tile_image_offsets = HashMap::default();
|
||||
|
||||
for (tileset_index, tileset) in map.tilesets().iter().enumerate() {
|
||||
let tilemap_texture = match &tileset.image {
|
||||
None => {
|
||||
{
|
||||
let mut tile_images: Vec<Handle<Image>> = Vec::new();
|
||||
for (tile_id, tile) in tileset.tiles() {
|
||||
if let Some(img) = &tile.image {
|
||||
// The load context path is the TMX file itself. If the file is at the root of the
|
||||
// assets/ directory structure then the tmx_dir will be empty, which is fine.
|
||||
let tmx_dir = load_context
|
||||
.path()
|
||||
.parent()
|
||||
.expect("The asset load context was empty.");
|
||||
let tile_path = tmx_dir.join(&img.source);
|
||||
let asset_path = AssetPath::from(tile_path);
|
||||
log::info!("Loading tile image from {asset_path:?} as image ({tileset_index}, {tile_id})");
|
||||
let texture: Handle<Image> = load_context.load(asset_path.clone());
|
||||
tile_image_offsets
|
||||
.insert((tileset_index, tile_id), tile_images.len() as u32);
|
||||
tile_images.push(texture.clone());
|
||||
}
|
||||
}
|
||||
|
||||
TilemapTexture::Vector(tile_images)
|
||||
}
|
||||
}
|
||||
Some(img) => {
|
||||
// The load context path is the TMX file itself. If the file is at the root of the
|
||||
// assets/ directory structure then the tmx_dir will be empty, which is fine.
|
||||
let texture: Handle<Image> = load_context.load(img.source.clone());
|
||||
|
||||
TilemapTexture::Single(texture.clone())
|
||||
}
|
||||
};
|
||||
|
||||
tilemap_textures.insert(tileset_index, tilemap_texture);
|
||||
}
|
||||
|
||||
let asset_map = TiledMap {
|
||||
map,
|
||||
tilemap_textures,
|
||||
tile_image_offsets,
|
||||
};
|
||||
|
||||
log::info!("Loaded map: {}", load_context.path().display());
|
||||
Ok(asset_map)
|
||||
}
|
||||
|
||||
fn extensions(&self) -> &[&str] {
|
||||
static EXTENSIONS: &[&str] = &["tmx"];
|
||||
EXTENSIONS
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_loaded_maps(
|
||||
mut commands: Commands,
|
||||
mut map_events: EventReader<AssetEvent<TiledMap>>,
|
||||
maps: Res<Assets<TiledMap>>,
|
||||
tile_storage_query: Query<(Entity, &TileStorage)>,
|
||||
mut map_query: Query<(
|
||||
&Handle<TiledMap>,
|
||||
&mut TiledLayersStorage,
|
||||
&TilemapRenderSettings,
|
||||
)>,
|
||||
new_maps: Query<&Handle<TiledMap>, Added<Handle<TiledMap>>>,
|
||||
) {
|
||||
let mut changed_maps = Vec::<AssetId<TiledMap>>::default();
|
||||
for event in map_events.read() {
|
||||
match event {
|
||||
AssetEvent::Added { id } => {
|
||||
log::info!("Map added!");
|
||||
changed_maps.push(*id);
|
||||
}
|
||||
AssetEvent::Modified { id } => {
|
||||
log::info!("Map changed!");
|
||||
changed_maps.push(*id);
|
||||
}
|
||||
AssetEvent::Removed { id } => {
|
||||
log::info!("Map removed!");
|
||||
// if mesh was modified and removed in the same update, ignore the modification
|
||||
// events are ordered so future modification events are ok
|
||||
changed_maps.retain(|changed_handle| changed_handle == id);
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
// If we have new map entities add them to the changed_maps list.
|
||||
for new_map_handle in new_maps.iter() {
|
||||
changed_maps.push(new_map_handle.id());
|
||||
}
|
||||
|
||||
for changed_map in changed_maps.iter() {
|
||||
for (map_handle, mut layer_storage, render_settings) in map_query.iter_mut() {
|
||||
// only deal with currently changed map
|
||||
if map_handle.id() != *changed_map {
|
||||
continue;
|
||||
}
|
||||
if let Some(tiled_map) = maps.get(map_handle) {
|
||||
// TODO: Create a RemoveMap component..
|
||||
for layer_entity in layer_storage.storage.values() {
|
||||
if let Ok((_, layer_tile_storage)) = tile_storage_query.get(*layer_entity) {
|
||||
for tile in layer_tile_storage.iter().flatten() {
|
||||
commands.entity(*tile).despawn_recursive()
|
||||
}
|
||||
}
|
||||
// commands.entity(*layer_entity).despawn_recursive();
|
||||
}
|
||||
|
||||
// The TilemapBundle requires that all tile images come exclusively from a single
|
||||
// tiled texture or from a Vec of independent per-tile images. Furthermore, all of
|
||||
// the per-tile images must be the same size. Since Tiled allows tiles of mixed
|
||||
// tilesets on each layer and allows differently-sized tile images in each tileset,
|
||||
// this means we need to load each combination of tileset and layer separately.
|
||||
for (tileset_index, tileset) in tiled_map.map.tilesets().iter().enumerate() {
|
||||
let Some(tilemap_texture) = tiled_map.tilemap_textures.get(&tileset_index)
|
||||
else {
|
||||
log::warn!("Skipped creating layer with missing tilemap textures.");
|
||||
continue;
|
||||
};
|
||||
|
||||
let tile_size = TilemapTileSize {
|
||||
x: tileset.tile_width as f32,
|
||||
y: tileset.tile_height as f32,
|
||||
};
|
||||
|
||||
let tile_spacing = TilemapSpacing {
|
||||
x: tileset.spacing as f32,
|
||||
y: tileset.spacing as f32,
|
||||
};
|
||||
|
||||
// Once materials have been created/added we need to then create the layers.
|
||||
for (layer_index, layer) in tiled_map.map.layers().enumerate() {
|
||||
let offset_x = layer.offset_x;
|
||||
let offset_y = layer.offset_y;
|
||||
|
||||
let tiled::LayerType::Tiles(tile_layer) = layer.layer_type() else {
|
||||
log::info!(
|
||||
"Skipping layer {} because only tile layers are supported.",
|
||||
layer.id()
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
||||
let tiled::TileLayer::Finite(layer_data) = tile_layer else {
|
||||
log::info!(
|
||||
"Skipping layer {} because only finite layers are supported.",
|
||||
layer.id()
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
||||
let map_size = TilemapSize {
|
||||
x: tiled_map.map.width,
|
||||
y: tiled_map.map.height,
|
||||
};
|
||||
|
||||
let grid_size = TilemapGridSize {
|
||||
x: tiled_map.map.tile_width as f32,
|
||||
y: tiled_map.map.tile_height as f32,
|
||||
};
|
||||
|
||||
let map_type = match tiled_map.map.orientation {
|
||||
tiled::Orientation::Hexagonal => {
|
||||
TilemapType::Hexagon(HexCoordSystem::Row)
|
||||
}
|
||||
tiled::Orientation::Isometric => {
|
||||
TilemapType::Isometric(IsoCoordSystem::Diamond)
|
||||
}
|
||||
tiled::Orientation::Staggered => {
|
||||
TilemapType::Isometric(IsoCoordSystem::Staggered)
|
||||
}
|
||||
tiled::Orientation::Orthogonal => TilemapType::Square,
|
||||
};
|
||||
|
||||
let mut tile_storage = TileStorage::empty(map_size);
|
||||
let layer_entity = commands.spawn_empty().id();
|
||||
|
||||
for x in 0..map_size.x {
|
||||
for y in 0..map_size.y {
|
||||
// Transform TMX coords into bevy coords.
|
||||
let mapped_y = tiled_map.map.height - 1 - y;
|
||||
|
||||
let mapped_x = x as i32;
|
||||
let mapped_y = mapped_y as i32;
|
||||
|
||||
let layer_tile = match layer_data.get_tile(mapped_x, mapped_y) {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if tileset_index != layer_tile.tileset_index() {
|
||||
continue;
|
||||
}
|
||||
let layer_tile_data =
|
||||
match layer_data.get_tile_data(mapped_x, mapped_y) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let texture_index = match tilemap_texture {
|
||||
TilemapTexture::Single(_) => layer_tile.id(),
|
||||
TilemapTexture::Vector(_) =>
|
||||
*tiled_map.tile_image_offsets.get(&(tileset_index, layer_tile.id()))
|
||||
.expect("The offset into to image vector should have been saved during the initial load."),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let tile_pos = TilePos { x, y };
|
||||
let tile_entity = commands
|
||||
.spawn(TileBundle {
|
||||
position: tile_pos,
|
||||
tilemap_id: TilemapId(layer_entity),
|
||||
texture_index: TileTextureIndex(texture_index),
|
||||
flip: TileFlip {
|
||||
x: layer_tile_data.flip_h,
|
||||
y: layer_tile_data.flip_v,
|
||||
d: layer_tile_data.flip_d,
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.id();
|
||||
tile_storage.set(&tile_pos, tile_entity);
|
||||
}
|
||||
}
|
||||
|
||||
commands.entity(layer_entity).insert(TilemapBundle {
|
||||
grid_size,
|
||||
size: map_size,
|
||||
storage: tile_storage,
|
||||
texture: tilemap_texture.clone(),
|
||||
tile_size,
|
||||
spacing: tile_spacing,
|
||||
transform: get_tilemap_center_transform(
|
||||
&map_size,
|
||||
&grid_size,
|
||||
&map_type,
|
||||
layer_index as f32,
|
||||
) * Transform::from_xyz(offset_x, -offset_y, 0.0),
|
||||
map_type,
|
||||
render_settings: *render_settings,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
layer_storage
|
||||
.storage
|
||||
.insert(layer_index as u32, layer_entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ use bevy_asset_loader::{
|
|||
loading_state::{config::ConfigureLoadingState, LoadingState, LoadingStateAppExt},
|
||||
};
|
||||
|
||||
use crate::GameState;
|
||||
use crate::{loaders::tiled::TiledMap, GameState};
|
||||
|
||||
pub struct LoadingPlugin;
|
||||
|
||||
|
@ -13,6 +13,7 @@ impl Plugin for LoadingPlugin {
|
|||
app.add_loading_state(
|
||||
LoadingState::new(GameState::Loading)
|
||||
.continue_to_state(GameState::Menu)
|
||||
.load_collection::<MapAssets>()
|
||||
.load_collection::<TextureAssets>(),
|
||||
);
|
||||
}
|
||||
|
@ -38,3 +39,9 @@ pub struct TextureAssets {
|
|||
#[asset(path = "textures/forgejo.png")]
|
||||
pub forgejo: Handle<Image>,
|
||||
}
|
||||
|
||||
#[derive(AssetCollection, Resource)]
|
||||
pub struct MapAssets {
|
||||
#[asset(path = "maps/test.tmx")]
|
||||
pub map: Handle<TiledMap>,
|
||||
}
|
||||
|
|
18
src/map.rs
Normal file
18
src/map.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
use crate::{loaders::tiled::TiledMapBundle, loading::MapAssets, GameState};
|
||||
|
||||
pub struct MapPlugin;
|
||||
|
||||
impl Plugin for MapPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(OnEnter(GameState::Playing), setup);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands, maps: Res<MapAssets>) {
|
||||
commands.spawn(TiledMapBundle {
|
||||
tiled_map: maps.map.clone(),
|
||||
..default()
|
||||
});
|
||||
}
|
|
@ -47,7 +47,7 @@ impl AnimationConfig {
|
|||
|
||||
fn spawn(mut commands: Commands, textures: Res<TextureAssets>) {
|
||||
let mut camera = Camera2dBundle::default();
|
||||
camera.projection.scale *= 0.25;
|
||||
camera.projection.scale *= 0.5;
|
||||
commands.spawn(camera);
|
||||
|
||||
let animation_config = AnimationConfig::new(0, 3, 10);
|
||||
|
@ -55,6 +55,7 @@ fn spawn(mut commands: Commands, textures: Res<TextureAssets>) {
|
|||
commands.spawn((
|
||||
SpriteBundle {
|
||||
texture: textures.witch.clone(),
|
||||
transform: Transform::from_xyz(0.0, 0.0, 100.0),
|
||||
..default()
|
||||
},
|
||||
TextureAtlas::from(textures.witch_layout.clone()),
|
||||
|
|
Loading…
Reference in a new issue