Skip to content
This repository has been archived by the owner on May 7, 2022. It is now read-only.

Tile entities #185

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/hex_tile_odd_rows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ fn load(
}

fn build_world(
mut commands: Commands,
mut game_state: ResMut<GameState>,
texture_atlases: Res<Assets<TextureAtlas>>,
asset_server: Res<AssetServer>,
Expand Down
10 changes: 9 additions & 1 deletion examples/random_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ fn build_random_world(
}

fn move_sprite(
commands: &mut Commands,
map: &mut Tilemap,
previous_position: Position,
position: Position,
Expand All @@ -331,6 +332,7 @@ fn move_sprite(
}

fn character_movement(
mut commands: Commands,
mut game_state: ResMut<GameState>,
time: Res<Time>,
keyboard_input: Res<Input<KeyCode>>,
Expand Down Expand Up @@ -412,7 +414,13 @@ fn character_movement(
}

// This is a helpful function to make it easier to do stuff!
move_sprite(&mut map, previous_position, *position, render);
move_sprite(
&mut commands,
&mut map,
previous_position,
*position,
render,
);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions examples/square_tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ fn load(
}

fn build_world(
mut commands: Commands,
mut game_state: ResMut<GameState>,
texture_atlases: Res<Assets<TextureAtlas>>,
asset_server: Res<AssetServer>,
Expand Down
10 changes: 9 additions & 1 deletion examples/stress_dwarves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ fn build_map(
}

fn move_sprite(
commands: &mut Commands,
map: &mut Tilemap,
previous_position: Position,
position: Position,
Expand All @@ -281,6 +282,7 @@ fn move_sprite(
}

fn drunk_stumbles(
mut commands: Commands,
mut state: ResMut<State>,
mut map_query: Query<&mut Tilemap>,
mut drunk_query: Query<(&mut Position, &Render)>,
Expand All @@ -297,7 +299,13 @@ fn drunk_stumbles(
if previous_position == *position {
continue;
}
move_sprite(&mut map, previous_position, *position, render);
move_sprite(
&mut commands,
&mut map,
previous_position,
*position,
render,
);
}
}
}
Expand Down
113 changes: 56 additions & 57 deletions src/chunk/layer.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
use crate::{chunk::raw_tile::RawTile, lib::*};
use crate::{lib::*, Tile};

/// Common methods for layers in a chunk.
pub(super) trait Layer: 'static {
/// Sets a raw tile for a layer at an index.
fn set_tile(&mut self, index: usize, tile: RawTile);
fn set_tile(&mut self, index: usize, tile: Entity);

/// Removes a tile for a layer at an index.
fn remove_tile(&mut self, index: usize);
fn remove_tile(&mut self, index: usize) -> Option<Entity>;

/// Gets a tile by an index.
fn get_tile(&self, index: usize) -> Option<&RawTile>;

/// Gets a tile with a mutable reference by an index.
fn get_tile_mut(&mut self, index: usize) -> Option<&mut RawTile>;
fn get_tile(&self, index: usize) -> Option<Entity>;

/// Gets all the tile indices in the layer that exist.
fn get_tile_indices(&self) -> Vec<usize>;

/// Clears a layer of all sprites.
fn clear(&mut self);
fn clear(&mut self, commands: &mut Commands);

/// Takes all the tiles in the layer and returns attributes for the renderer.
fn tiles_to_attributes(&self, dimension: Dimension3) -> (Vec<f32>, Vec<[f32; 4]>);
fn tiles_to_attributes(
&self,
tile_query: &Query<&Tile<Point3>>,
dimension: Dimension3,
) -> (Vec<f32>, Vec<[f32; 4]>);
}

/// A layer with dense sprite tiles.
Expand All @@ -32,16 +33,16 @@ pub(super) trait Layer: 'static {
#[reflect(Component, PartialEq, Serialize, Deserialize)]
pub(super) struct DenseLayer {
/// A vector of all the tiles in the chunk.
tiles: Vec<RawTile>,
tiles: Vec<Option<Entity>>,
/// A count of the tiles to keep track if layer is empty or not.
tile_count: usize,
}

impl Layer for DenseLayer {
fn set_tile(&mut self, index: usize, tile: RawTile) {
fn set_tile(&mut self, index: usize, tile: Entity) {
if let Some(inner_tile) = self.tiles.get_mut(index) {
self.tile_count += 1;
*inner_tile = tile;
*inner_tile = Some(tile);
} else {
warn!(
"tile is out of bounds at index {} and can not be set",
Expand All @@ -50,58 +51,56 @@ impl Layer for DenseLayer {
}
}

fn remove_tile(&mut self, index: usize) {
if let Some(tile) = self.tiles.get_mut(index) {
if self.tile_count != 0 {
self.tile_count -= 1;
tile.color.set_a(0.0);
}
fn remove_tile(&mut self, index: usize) -> Option<Entity> {
let maybe_entity = self.tiles.remove(index);

if maybe_entity.is_some() && self.tile_count != 0 {
self.tile_count -= 1;
}
}

fn get_tile(&self, index: usize) -> Option<&RawTile> {
self.tiles.get(index).and_then(|tile| {
if tile.color.a() == 0.0 {
None
} else {
Some(tile)
}
})
maybe_entity
}

fn get_tile_mut(&mut self, index: usize) -> Option<&mut RawTile> {
self.tiles.get_mut(index).and_then(|tile| {
if tile.color.a() == 0.0 {
None
} else {
Some(tile)
}
})
fn get_tile(&self, index: usize) -> Option<Entity> {
self.tiles.get(index).and_then(|tile| *tile)
}

fn get_tile_indices(&self) -> Vec<usize> {
let mut indices = Vec::with_capacity(self.tiles.len());
for (index, tile) in self.tiles.iter().enumerate() {
if tile.color.a() != 0.0 {
if tile.is_some() {
indices.push(index);
}
}
indices.shrink_to_fit();
indices
}

fn clear(&mut self) {
fn clear(&mut self, commands: &mut Commands) {
for entity in self.tiles.iter().flatten() {
commands.entity(*entity).despawn();
}
self.tiles.clear();
}

fn tiles_to_attributes(&self, _dimension: Dimension3) -> (Vec<f32>, Vec<[f32; 4]>) {
crate::chunk::raw_tile::dense_tiles_to_attributes(&self.tiles)
fn tiles_to_attributes(
&self,
tile_query: &Query<&Tile<Point3>>,
_dimension: Dimension3,
) -> (Vec<f32>, Vec<[f32; 4]>) {
let mut tiles: Vec<&Tile<Point3>> = Vec::with_capacity(self.tiles.len());
for entity in self.tiles.iter().flatten() {
let tile: &Tile<Point3> = tile_query.get(*entity).expect("Can't fail");
tiles.push(tile);
}

crate::chunk::dense_tiles_to_attributes(tiles)
}
}

impl DenseLayer {
/// Constructs a new dense layer with tiles.
pub fn new(tiles: Vec<RawTile>) -> DenseLayer {
pub fn new(tiles: Vec<Option<Entity>>) -> DenseLayer {
DenseLayer {
tiles,
tile_count: 0,
Expand All @@ -113,27 +112,20 @@ impl DenseLayer {
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub(super) struct SparseLayer {
/// A map of all the tiles in the chunk.
tiles: HashMap<usize, RawTile>,
tiles: HashMap<usize, Entity>,
}

impl Layer for SparseLayer {
fn set_tile(&mut self, index: usize, tile: RawTile) {
if tile.color.a() == 0.0 {
self.tiles.remove(&index);
}
fn set_tile(&mut self, index: usize, tile: Entity) {
self.tiles.insert(index, tile);
}

fn remove_tile(&mut self, index: usize) {
self.tiles.remove(&index);
fn remove_tile(&mut self, index: usize) -> Option<Entity> {
self.tiles.remove(&index)
}

fn get_tile(&self, index: usize) -> Option<&RawTile> {
self.tiles.get(&index)
}

fn get_tile_mut(&mut self, index: usize) -> Option<&mut RawTile> {
self.tiles.get_mut(&index)
fn get_tile(&self, index: usize) -> Option<Entity> {
self.tiles.get(&index).cloned()
}

fn get_tile_indices(&self) -> Vec<usize> {
Expand All @@ -144,18 +136,25 @@ impl Layer for SparseLayer {
indices
}

fn clear(&mut self) {
fn clear(&mut self, commands: &mut Commands) {
for (_, entity) in self.tiles.iter() {
commands.entity(*entity).despawn();
}
self.tiles.clear();
}

fn tiles_to_attributes(&self, dimension: Dimension3) -> (Vec<f32>, Vec<[f32; 4]>) {
crate::chunk::raw_tile::sparse_tiles_to_attributes(dimension, &self.tiles)
fn tiles_to_attributes(
&self,
tile_query: &Query<&Tile<Point3>>,
dimension: Dimension3,
) -> (Vec<f32>, Vec<[f32; 4]>) {
crate::chunk::sparse_tiles_to_attributes(tile_query, dimension, &self.tiles)
}
}

impl SparseLayer {
/// Constructs a new sparse layer with a tile hashmap.
pub fn new(tiles: HashMap<usize, RawTile>) -> SparseLayer {
pub fn new(tiles: HashMap<usize, Entity>) -> SparseLayer {
SparseLayer { tiles }
}
}
Expand Down
Loading