Skip to content

Commit

Permalink
map v2 (#8)
Browse files Browse the repository at this point in the history
allow
* player start and goal
* object layer (as example stone tile can now be placed on every base layer)
  • Loading branch information
LuckyTurtleDev committed May 12, 2023
1 parent 3cb7aa3 commit f2edb11
Show file tree
Hide file tree
Showing 21 changed files with 308 additions and 29 deletions.
2 changes: 2 additions & 0 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub fn include_map(input: TokenStream) -> TokenStream {
{
use m3_map::Map;
use m3_map::tiles::MapBaseTile;
use m3_map::Player;
use m3_map::tiles::ObjectTile;
// include the bytes so that the compiler knows to recompile when the
// map or tilesets changes
const _: &[u8] = ::core::include_bytes!(#path);
Expand Down
128 changes: 123 additions & 5 deletions map/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
use self_rust_tokenize::SelfRustTokenize;
use std::path::Path;
use std::{iter, path::Path};
use thiserror::Error;
use tiled::{LayerType, Loader};

pub mod tiles;
use tiles::{InvalidTileID, MapBaseTile};
use tiles::{InvalidTileID, MapBaseTile, ObjectTile, PlayerTile, Tile};

#[derive(Clone, Debug, SelfRustTokenize)]
pub struct Player {
pub start: (u8, u8),
pub goal: Option<(u8, u8)>
}

#[derive(Clone, Debug, SelfRustTokenize)]
pub struct Map {
pub width: u8,
pub height: u8,
pub base_layer: Vec<Vec<MapBaseTile>>
pub base_layer: Vec<Vec<MapBaseTile>>,
pub object_layer: Vec<Vec<Option<ObjectTile>>>,
pub global_goal: Option<(u8, u8)>,
pub player_1: Player,
pub player_2: Option<Player>,
pub player_3: Option<Player>,
pub player_4: Option<Player>
}

#[derive(Error, Debug)]
Expand All @@ -28,15 +40,24 @@ pub enum MapError {
#[error("Map is to hight. Max size is 255x255 tiles")]
ToHight,
#[error("{0}")]
InvalidTileId(#[from] InvalidTileID)
InvalidTileId(#[from] InvalidTileID),
#[error("Map needs at least one player")]
NoPlayer
}

impl Map {
// this is ugly. Should i refactor this?
pub fn from_tmx(path: impl AsRef<Path>) -> Result<Self, MapError> {
let map = Loader::new().load_tmx_map(path)?;
let width: u8 = map.width.try_into().map_err(|_| MapError::ToWidth)?;
let height: u8 = map.height.try_into().map_err(|_| MapError::ToHight)?;
let mut base_layer = Vec::with_capacity(height as usize);
let mut object_layer = Vec::with_capacity(height as usize);
let mut global_goal = None;
let mut player_1 = None;
let mut player_2 = None;
let mut player_3 = None;
let mut player_4 = None;
for (i, layer) in map.layers().enumerate() {
match i {
0 => match layer.layer_type() {
Expand All @@ -55,13 +76,79 @@ impl Map {
},
_ => return Err(MapError::WrongLayer(i, "TileLayer".to_owned()))
},
1 => match layer.layer_type() {
LayerType::Tiles(tile_layer) => {
for x in 0..width {
let mut column = Vec::with_capacity(width as usize);
for y in 0..height {
let tile = match tile_layer.get_tile(x.into(), y.into()) {
Some(tile) => Some(ObjectTile::try_from(tile.id())?),
None => None
};
column.push(tile);
}
object_layer.push(column);
}
},
_ => return Err(MapError::WrongLayer(i, "TileLayer".to_owned()))
},
2 => match layer.layer_type() {
LayerType::Tiles(tile_layer) => {
for x in 0..width {
for y in 0..height {
if let Some(tile) =
tile_layer.get_tile(x.into(), y.into())
{
let tile = PlayerTile::try_from(tile.id())?;
match tile {
PlayerTile::Car1 => {
player_1 = Some(Player {
start: (x, y),
goal: None
})
},
PlayerTile::Car2 => {
player_2 = Some(Player {
start: (x, y),
goal: None
})
},
PlayerTile::Car3 => {
player_3 = Some(Player {
start: (x, y),
goal: None
})
},
PlayerTile::Car4 => {
player_4 = Some(Player {
start: (x, y),
goal: None
})
},
PlayerTile::GlobalGoal => {
global_goal = Some((x, y))
},
}
}
}
}
},
_ => return Err(MapError::WrongLayer(i, "TileLayer".to_owned()))
},
_ => return Err(MapError::ToManyLayers)
}
}
let player_1 = player_1.ok_or(MapError::NoPlayer)?;
Ok(Map {
width,
height,
base_layer
base_layer,
object_layer,
global_goal,
player_1,
player_2,
player_3,
player_4
})
}

Expand All @@ -74,4 +161,35 @@ impl Map {
.map(move |(y, item)| (x as u8, y as u8, item))
})
}

/// return an iterator over all ObjectTiles and its x and y postion
pub fn iter_object_layer(&self) -> impl Iterator<Item = (u8, u8, ObjectTile)> + '_ {
self.object_layer.iter().enumerate().flat_map(|(x, y_vec)| {
y_vec
.iter()
.enumerate()
.filter_map(move |(y, item)| item.map(|item| (x as u8, y as u8, item)))
})
}

/// return an iterator over all player goals tiles and its x and y postion
pub fn iter_player_goals(&self) -> impl Iterator<Item = (u8, u8, PlayerTile)> + '_ {
iter::once(self.global_goal)
.flat_map(|goal| goal.map(|(x, y)| (x, y, PlayerTile::GlobalGoal)))
}

/// return an iterator over all static Tiles and its x and y postion.
/// starting from the lowest layer
pub fn iter_all(&self) -> impl Iterator<Item = (u8, u8, Tile)> + '_ {
let base = self
.iter_base_layer()
.map(|(x, y, tile)| (x, y, Tile::MapBaseTile(tile.to_owned())));
let objects = self
.iter_object_layer()
.map(|(x, y, tile)| (x, y, Tile::MapObjectTile(tile.to_owned())));
let goals = self
.iter_player_goals()
.map(|(x, y, tile)| (x, y, Tile::PlayerTile(tile)));
base.chain(objects).chain(goals)
}
}
4 changes: 2 additions & 2 deletions map/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ pub struct Opt {

fn main() {
let opt = Opt::parse();
let result = Map::from_tmx(&opt.file);
let result = Map::from_tmx(opt.file);
match result {
Err(err) => {
eprintln!("ERROR: {err}");
std::process::exit(1);
},
Ok(map) => println!("{map:#?}")
Ok(map) => println!("{map:#?}\nmap is valid")
}
}
60 changes: 53 additions & 7 deletions map/src/tiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ use num_enum::TryFromPrimitive;
use self_rust_tokenize::SelfRustTokenize;
use thiserror::Error;

pub enum Tile {
MapBaseTile(MapBaseTile),
MapObjectTile(ObjectTile),
PlayerTile(PlayerTile)
}

#[derive(Debug, Copy, Clone, Error)]
pub enum InvalidTileID {
#[error("invalid tiel id {0}")]
InvalidId(u32)
}

///Store all Tiles, with can be used at the map background
#[derive(
Clone, Copy, Debug, Default, Eq, SelfRustTokenize, PartialEq, TryFromPrimitive,
Expand All @@ -10,19 +22,53 @@ use thiserror::Error;
pub enum MapBaseTile {
//numbers must match them from the Tiled tilesets
#[default]
Grass = 0,
Grass = 0
}

impl TryFrom<u32> for MapBaseTile {
type Error = InvalidTileID;
fn try_from(value: u32) -> Result<MapBaseTile, Self::Error> {
let value_u8: u8 = value
.try_into()
.map_err(|_| Self::Error::InvalidId(value))?;
Self::try_from_primitive(value_u8).map_err(|_| Self::Error::InvalidId(value))
}
}

///Store all Tiles, with can be place the layer above the background
#[derive(Clone, Copy, Debug, Eq, SelfRustTokenize, PartialEq, TryFromPrimitive)]
#[repr(u8)]
pub enum ObjectTile {
//numbers must match them from the Tiled tilesets
Stone = 1
}

#[derive(Debug, Copy, Clone, Error)]
pub enum InvalidTileID {
#[error("invalid tiel id {0}")]
InvalidId(u32)
impl TryFrom<u32> for ObjectTile {
type Error = InvalidTileID;
fn try_from(value: u32) -> Result<ObjectTile, Self::Error> {
let value_u8: u8 = value
.try_into()
.map_err(|_| Self::Error::InvalidId(value))?;
Self::try_from_primitive(value_u8).map_err(|_| Self::Error::InvalidId(value))
}
}

impl TryFrom<u32> for MapBaseTile {
///Store all Tiles, with can be place the layer above the background
#[derive(Clone, Copy, Debug, Eq, SelfRustTokenize, PartialEq, TryFromPrimitive)]
#[repr(u8)]
pub enum PlayerTile {
//numbers must match them from the Tiled tilesets
Car1 = 0,
Car2 = 1,
Car3 = 2,
Car4 = 3,
//goal, which can be used by all players
GlobalGoal = 4
}

impl TryFrom<u32> for PlayerTile {
type Error = InvalidTileID;
fn try_from(value: u32) -> Result<MapBaseTile, Self::Error> {
fn try_from(value: u32) -> Result<PlayerTile, Self::Error> {
let value_u8: u8 = value
.try_into()
.map_err(|_| Self::Error::InvalidId(value))?;
Expand Down
5 changes: 1 addition & 4 deletions pc/assets/img/BaseTiles/BaseTiles.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.1" name="BaseTiles" tilewidth="256" tileheight="256" tilecount="2" columns="0">
<tileset version="1.10" tiledversion="1.10.1" name="BaseTiles" tilewidth="256" tileheight="256" tilecount="1" columns="0">
<grid orientation="orthogonal" width="1" height="1"/>
<tile id="0">
<image width="256" height="256" source="grass.png"/>
</tile>
<tile id="1">
<image width="256" height="256" source="stone.png"/>
</tile>
</tileset>
Binary file removed pc/assets/img/BaseTiles/Grass mit Rand.png
Binary file not shown.
Binary file removed pc/assets/img/BaseTiles/Grass mit Rand2.png
Binary file not shown.
Binary file modified pc/assets/img/BaseTiles/grass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed pc/assets/img/BaseTiles/stone.png
Binary file not shown.
7 changes: 7 additions & 0 deletions pc/assets/img/ObjectTiles/ObjectTiles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.1" name="ObjectTiles" tilewidth="256" tileheight="256" tilecount="1" columns="0">
<grid orientation="orthogonal" width="1" height="1"/>
<tile id="1">
<image width="256" height="256" source="stone.png"/>
</tile>
</tileset>
File renamed without changes
19 changes: 19 additions & 0 deletions pc/assets/img/Player/Player.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.1" name="Player" tilewidth="256" tileheight="256" tilecount="5" columns="0">
<grid orientation="orthogonal" width="1" height="1"/>
<tile id="0">
<image width="256" height="256" source="player1_car.png"/>
</tile>
<tile id="1">
<image width="256" height="256" source="player2_car.png"/>
</tile>
<tile id="2">
<image width="256" height="256" source="player3_car.png"/>
</tile>
<tile id="3">
<image width="256" height="256" source="player4_car.png"/>
</tile>
<tile id="4">
<image width="256" height="256" source="goal.png"/>
</tile>
</tileset>
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Binary file removed pc/assets/img/player1_car.png
Binary file not shown.
40 changes: 34 additions & 6 deletions pc/assets/level/001.tmx
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="16" height="9" tilewidth="256" tileheight="256" infinite="0" nextlayerid="2" nextobjectid="1">
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="16" height="9" tilewidth="256" tileheight="256" infinite="0" nextlayerid="4" nextobjectid="1">
<tileset firstgid="1" source="../img/BaseTiles/BaseTiles.tsx"/>
<layer id="1" name="Tile Layer 1" width="16" height="9">
<tileset firstgid="2" source="../img/ObjectTiles/ObjectTiles.tsx"/>
<tileset firstgid="4" source="../img/Player/Player.tsx"/>
<layer id="1" name="Base" width="16" height="9">
<data encoding="csv">
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
</data>
</layer>
<layer id="2" name="Objects" width="16" height="9">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,
0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,3,0,0,3,3,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Player" width="16" height="9">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,
0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,4,0,0,0,0,0,0,0,0,0,0,7,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
</map>
4 changes: 2 additions & 2 deletions pc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use tetra::{
Context, ContextBuilder, State
};
type Vec2 = vek::vec::repr_c::vec2::Vec2<f32>;
use log::info;
use m3_macro::include_map;
use m3_map::Map;
use once_cell::sync::Lazy;
use tetra::{
graphics::{DrawParams, Texture},
time::get_delta_time
};
use log::{info};

mod tiles;
use tiles::Textures;
Expand Down Expand Up @@ -60,7 +60,7 @@ impl State for GameState {
(window_size.0 / map.width as i32) as f32,
(window_size.1 / map.height as i32) as f32
);
for (x, y, tile) in map.iter_base_layer() {
for (x, y, tile) in map.iter_all() {
let texture = tile.texture(&self.textures);
texture.draw(
ctx,
Expand Down
Loading

0 comments on commit f2edb11

Please sign in to comment.