Commit 253eb0f6 authored by Florian Blasius's avatar Florian Blasius 🤘
Browse files

Reimplement tile map loading and drawing with ron.

parent b3a967db
This diff is collapsed.
title = "OrbAdventure"
stage = "examples/adventure/stage.toml"
target_fps = 60
ui_css = "examples/adventure/ui.css"
width = 800
height = 600
\ No newline at end of file
This diff is collapsed.
sheet = "examples/adventure/tile_sheet.png"
tile_size = 16
blocked_tiles = [1, 86, 87, 88, 89, 90, 126, 127, 128, 129, 130, 166, 167, 169, 170, 521, 522, 523, 561, 563, 601, 602, 603, 685, 686]
use std::cell::{Cell, RefCell};
use orbtk::{CloneCell, Rect};
use sprite::Sprite;
use TomlLoader;
static LAYER_KEY: &str = "layer";
static SPRITE_KEY: &str = "sprite";
static SCRIPT_KEY: &str = "script";
#[derive(Clone)]
pub struct Entity {
layer: i32,
rect: Cell<Rect>,
sprite: RefCell<Option<Sprite>>,
script: RefCell<String>,
}
impl Entity {
pub fn from_toml(path: &str) -> Self {
let value = super::load_toml_value(path).unwrap();
Entity {
layer: value[LAYER_KEY]
.as_integer()
.expect("property layer not found") as i32,
rect: Cell::new(Rect::from_toml_value(&value)),
sprite: RefCell::new(Some(Sprite::from_toml_value(&value[SPRITE_KEY]))),
script: RefCell::new(String::from(super::read_file_as_string(
value[SCRIPT_KEY]
.as_str()
.expect("property script not found"),
))),
}
}
pub fn layer(&self) -> i32 {
self.layer
}
pub fn rect(&self) -> &Cell<Rect> {
&self.rect
}
pub fn sprite(&self) -> &RefCell<Option<Sprite>> {
&self.sprite
}
pub fn script(&self) -> &RefCell<String> {
&self.script
}
}
// use std::cell::{Cell, RefCell};
// use orbtk::{CloneCell, Rect};
// use sprite::Sprite;
// use TomlLoader;
// static LAYER_KEY: &str = "layer";
// static SPRITE_KEY: &str = "sprite";
// static SCRIPT_KEY: &str = "script";
// #[derive(Clone)]
// pub struct Entity {
// layer: i32,
// rect: Cell<Rect>,
// sprite: RefCell<Option<Sprite>>,
// script: RefCell<String>,
// }
// impl Entity {
// pub fn from_toml(path: &str) -> Self {
// let value = super::load_toml_value(path).unwrap();
// Entity {
// layer: value[LAYER_KEY]
// .as_integer()
// .expect("property layer not found") as i32,
// rect: Cell::new(Rect::from_toml_value(&value)),
// sprite: RefCell::new(Some(Sprite::from_toml_value(&value[SPRITE_KEY]))),
// script: RefCell::new(String::from(super::read_file_as_string(
// value[SCRIPT_KEY]
// .as_str()
// .expect("property script not found"),
// ))),
// }
// }
// pub fn layer(&self) -> i32 {
// self.layer
// }
// pub fn rect(&self) -> &Cell<Rect> {
// &self.rect
// }
// pub fn sprite(&self) -> &RefCell<Option<Sprite>> {
// &self.sprite
// }
// pub fn script(&self) -> &RefCell<String> {
// &self.script
// }
// }
// use std::sync::Arc;
// use std::cell::RefCell;
use std::sync::Arc;
// use toml;
// use std::io::Read;
use std::fs::File;
// use ron::value::Value;
use ron;
use ron::de::from_reader;
use orbtk::{Rect, Window, WindowBuilder};
use orbtk::{Rect, Window};
// use orbtk::{Place, Rect, Window};
use super::{ScriptEngine};
use super::{ScriptEngine, SceneConfig, Scene};
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename = "Game")]
pub struct Config {
pub struct GameConfig {
pub title: String,
pub width: u32,
pub height: u32,
pub target_fps: u32,
pub theme: String,
pub scene: SceneConfig,
}
pub struct Game {
window: Window,
target_fps: u32,
script_engine: ScriptEngine,
scene: Arc<Scene>,
}
impl Game {
pub fn from_config(config: &Config) -> Game {
pub fn from_config(config: &GameConfig) -> Game {
// todo: load theme css
let window_builder = WindowBuilder::new(Rect::new(0, 0, config.width, config.height), &config.title);
let window = window_builder.build();
let scene = Scene::from_config(&config.scene);
window.add(&scene);
Game {
window: Window::new(Rect::new(0, 0, config.width, config.height), &config.title),
window,
target_fps: config.target_fps,
script_engine: ScriptEngine::new(),
scene: scene,
}
}
......
......@@ -3,7 +3,7 @@ use std::fs::File;
use ron;
use ron::de::from_reader;
use game::{Config, Game};
use game::{GameConfig, Game};
pub struct GameBuilder {
path: String,
......@@ -18,7 +18,7 @@ impl GameBuilder {
pub fn build(&self) -> Result<Game, String> {
if let Ok(file) = File::open(&self.path) {
let config: ron::de::Result<Config> = from_reader(file);
let config: ron::de::Result<GameConfig> = from_reader(file);
if let Ok(config) = config {
return Ok(Game::from_config(&config))
} else {
......
......@@ -47,41 +47,22 @@ static HEIGHT_KEY: &str = "height";
// }
// pub use self::camera::*;
// pub use self::entity::*;
pub use self::camera::*;
pub use self::entity::*;
pub use self::game_builder::*;
pub use self::game::*;
// pub use self::tile_map::*;
pub use self::tile_map::*;
pub use self::scene::*;
pub use self::script_engine::ScriptEngine;
// pub use self::sprite::Sprite;
// pub use self::stage::*;
// mod camera;
// mod entity;
mod camera;
mod entity;
mod game_builder;
mod game;
// mod tile_map;
pub mod tile_map;
pub mod scene;
mod script_engine;
// mod sprite;
// mod stage;
pub fn read_file_as_string(path: &str) -> String {
let mut file = File::open(path).expect("file not found");
let mut contents = String::new();
file.read_to_string(&mut contents).expect("cannot read file");
contents
}
pub fn load_ron_value(path: &str) -> ron::de::Result<Value> {
ron::value::Value::from_str(&read_file_as_string(path)[..])
}
// pub fn load_toml_value(path: &str) -> Result<Value, String> {
// let contents = read_file_as_string(path);
// if let Ok(value) = contents.parse::<toml::Value>() {
// return Result::Ok(value)
// }
// Result::Err(String::from(format!("Could not parse file; {}", path)))
// }
\ No newline at end of file
// mod stage;
\ No newline at end of file
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::sync::Arc;
use std::cmp;
use std::collections::HashMap;
use std::fmt::Display;
use orbclient::Renderer;
use orbtk::{Event, Place, Point, Rect, Widget};
use orbtk::theme::Theme;
use orbimage::Image;
use orbtk::{Point, Rect, Renderer, Widget, Place, Event};
use orbtk::theme::Theme;
use Camera;
use Entity;
use TileMap;
use ScriptEngine;
static MAP_KEY: &str = "map";
static ENTITIES_KEY: &str = "entities";
use tile_map::{TileMap, TileMapConfig};
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename = "Scene")]
pub struct SceneConfig {
pub x: i32,
pub y: i32,
pub map: TileMapConfig,
}
#[derive(Clone)]
pub struct Stage {
pub struct Scene {
rect: Cell<Rect>,
entities: HashMap<i32, RefCell<Vec<Entity>>>,
// entities: HashMap<i32, RefCell<Vec<Entity>>>,
tile_map: RefCell<Option<TileMap>>,
camera: RefCell<Camera>,
}
impl Stage {
pub fn from_toml(path: &str) -> Arc<Self> {
let value = super::load_toml_value(path).unwrap();
let mut entities: HashMap<i32, RefCell<Vec<Entity>>> = HashMap::new();
let entities_values = value[ENTITIES_KEY]
.as_array()
.expect("property entities not found");
for entity in entities_values.iter() {
let entity = Entity::from_toml(entity.as_str().expect("could not read path"));
let layer = entity.layer();
if let Some(vec) = entities.get(&layer) {
let mut vec = vec.borrow_mut();
vec.push(entity);
continue;
}
let mut vec = vec![];
vec.push(entity);
entities.insert(layer, RefCell::new(vec));
}
// todo handle Result of tilemap and use None for error (not found)
Arc::new(Stage {
tile_map: RefCell::new(Some(TileMap::from_toml_value(&value[MAP_KEY]))),
rect: Cell::new(Rect::new(0, 0, 0, 0)),
entities: entities,
impl Scene {
pub fn from_config(config: &SceneConfig) -> Arc<Self> {
Arc::new(Scene {
rect: Cell::new(Rect::new(config.x, config.y, 800, 600)),
tile_map: RefCell::new(Some(TileMap::from_config(&config.map))),
// todo: real camera values
camera: RefCell::new(Camera::new(
Rect::new(0, 0, 800, 600),
Point::new(1000, 1000),
......@@ -108,36 +86,36 @@ impl Stage {
let layer = i as i32;
if let Some(entities) = self.entities.get(&layer) {
for entity in &*entities.borrow() {
self.draw_entity(renderer, entity);
}
}
// if let Some(entities) = self.entities.get(&layer) {
// for entity in &*entities.borrow() {
// self.draw_entity(renderer, entity);
// }
// }
}
}
}
fn draw_entity(&self, renderer: &mut Renderer, entity: &Entity) {
let rect = entity.rect().get();
if let Some(ref sprite) = *entity.sprite().borrow() {
let sheet = sprite.sheet();
let animation_rect = sprite.current_animation_rect();
if let Some(ref sheet) = *sheet.borrow() {
Stage::draw_image_part(
renderer,
sheet,
rect.x,
rect.y,
animation_rect.x as u32,
animation_rect.y as u32,
animation_rect.width,
animation_rect.height,
);
}
}
}
// fn draw_entity(&self, renderer: &mut Renderer, entity: &Entity) {
// let rect = entity.rect().get();
// if let Some(ref sprite) = *entity.sprite().borrow() {
// let sheet = sprite.sheet();
// let animation_rect = sprite.current_animation_rect();
// if let Some(ref sheet) = *sheet.borrow() {
// Scene::draw_image_part(
// renderer,
// sheet,
// rect.x,
// rect.y,
// animation_rect.x as u32,
// animation_rect.y as u32,
// animation_rect.width,
// animation_rect.height,
// );
// }
// }
// }
fn draw_tile_map_layer(
&self,
......@@ -176,7 +154,7 @@ impl Stage {
let tile_c = tile as f32 % tile_column_count as f32;
let tile_r = (tile as f32 / tile_column_count as f32).floor();
Stage::draw_image_part(
Scene::draw_image_part(
renderer,
image,
(((c - start_column) as f32) * tile_map.tile_size() as f32
......@@ -224,7 +202,7 @@ impl Stage {
}
}
impl Widget for Stage {
impl Widget for Scene {
fn rect(&self) -> &Cell<Rect> {
&self.rect
}
......@@ -242,4 +220,4 @@ impl Widget for Stage {
}
}
impl Place for Stage {}
impl Place for Scene {}
use std::cell::{Cell, RefCell};
use toml::Value;
use orbimage::Image;
static LAYER_COUNT_KEY: &str = "layer_count";
static ROW_COUNT_KEY: &str = "row_count";
static COLUMN_COUNT_KEY: &str = "column_count";
static TILE_SIZE_KEY: &str = "tile_size";
static BLOCKED_TILES_KEY: &str = "blocked_tiles";
static LAYERS_KEY: &str = "layers";
static TILE_SET_KEY: &str = "tile_set";
static SHEET_KEY: &str = "sheet";
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename = "TileSet")]
pub struct TileSetConfig {
sheet: String,
blocked_tiles: Vec<i32>,
tile_size: u32,
}
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename = "Layer")]
pub struct LayerConfig {
tiles: Vec<i32>,
}
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename = "TileMap")]
pub struct TileMapConfig {
pub layer_count: usize,
pub row_count: usize,
pub column_count: usize,
pub layers: Vec<LayerConfig>,
pub tile_set: TileSetConfig,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Layer {
......@@ -19,8 +32,16 @@ pub struct Layer {
}
impl Layer {
pub fn new() -> Self {
Layer { tiles: Vec::new() }
pub fn from_config(config: &LayerConfig) -> Self {
let mut tiles = vec![];
for tile in config.tiles.clone() {
tiles.push(Cell::new(tile));
}
Layer {
tiles,
}
}
pub fn push(&mut self, tile: i32) {
......@@ -28,7 +49,7 @@ impl Layer {
}
}
#[derive(Clone, Default)]
#[derive(Clone)]
pub struct TileMap {
layer_count: usize,
row_count: usize,
......@@ -40,58 +61,29 @@ pub struct TileMap {
}
impl TileMap {
pub fn from_toml_value(value: &Value) -> Self {
let tile_set = super::load_toml_value(value[TILE_SET_KEY].as_str().expect("property tile_set not found")).unwrap();
let blocked_tiles = {
let toml = tile_set[BLOCKED_TILES_KEY].as_array().expect("property blocked_tiles not found").to_vec();
let mut blocked_tiles: Vec<i32> = vec![];
pub fn from_config(config: &TileMapConfig) -> TileMap {
let mut layers = vec![];
for t in &toml {
blocked_tiles.push(t.as_integer().expect("cannot parse blocked tiles value") as i32);
}
blocked_tiles
};
let layers = {
let toml = value[LAYERS_KEY].as_array().expect("property layers not found").to_vec();
let mut layers: Vec<Layer> = vec![];
for l in &toml {
let mut layer = Layer::new();
for (_key, v) in l.as_table().expect("layers not found") {
for t in v.as_array().expect("layer not found") {
layer.push(t.as_integer().expect("cannot parse tile") as i32);
}
}
layers.push(layer);
}
for layer in config.layers.clone() {
layers.push(Layer::from_config(&layer));
}
layers
};
println!("{}", config.tile_set.sheet);
let mut sheet = None;
if let Ok(image) = Image::from_path(tile_set[SHEET_KEY].as_str().expect("property sheet not found")) {
sheet = Some(image)
}
TileMap {
layer_count: value[LAYER_COUNT_KEY].as_integer().expect("property layer_count not found") as usize,
row_count: value[ROW_COUNT_KEY].as_integer().expect("property row_count not found") as usize,
column_count: value[COLUMN_COUNT_KEY].as_integer().expect("property column_count not found") as usize,
tile_size: tile_set[TILE_SIZE_KEY].as_integer().expect("property tile_size not found") as u32,
blocked_tiles,
layers,
sheet: RefCell::new(sheet)
if let Ok(image) = Image::from_path(&config.tile_set.sheet) {
sheet = Some(image)
}
}
pub fn new() -> TileMap {
TileMap {
..Default::default()
layer_count: config.layer_count,
row_count: config.row_count,
column_count: config.column_count,
tile_size: config.tile_set.tile_size,
blocked_tiles: config.tile_set.blocked_tiles.clone(),
layers,
sheet: RefCell::new(sheet),
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment