Giter VIP home page Giter VIP logo

grid-forge's Introduction

grid-forge

Generic abstraction for grid maps.

I've found it pretty frustrating that every engine of framework have their own way of handling grid maps. This made any attempts at generic solutions for common problems not easily applicable.

grid-forge tries to solve this problem, providing a generic abstraction for grid maps - currently only 2D rectangular grids are supported, 3D grids are planned as well, and possibly support for other shapes in the future.

Basic functionality

Data hold for each tile in the grid is very flexible, and can be anything that is needed. Just implement a TileData marker trait and you are good to go.

use grid_forge::TileData;

enum TileColor {
    Blue,
    Green,
}

struct TwoColoredTile {
    color: TileColor,
}

impl TileData for TwoColoredTile {}

Such data can then be placed inside of the GridMap2D, and used hovewer you want. Outside of the grid, the data is always contained within one of the TileContainer implementors:

  • GridTile<T> - container owning the data for a tile.
  • GridRef<T> - reference to the data for a tile.
  • GridRefMut<T> - mutable reference to the data for a tile.
let size = GridSize::new_xy(100, 100);
let mut map = GridMap2D::<TwoColoredTile>::new(size);
let mut rng = thread_rng();

for pos in map.size().get_all_possible_positions() {
    let color = if rng.gen_bool(0.5) {
        TileColor::Blue
    } else {
        TileColor::Green
    };
    let tile = GridTile::new(pos, TwoColoredTile { color });
    map.insert_tile(tile);
}

It can be then retrieved from the GridMap in such a container, holding alongside your data the position of the tile.

Its tends to be useful when you would want to pass the data further through the function - information about its position is often crucial.

let pos = GridPosition::new_xy(10, 10);
let tile: GridRef<TwoColoredTile> = map.get_tile_at_position(&pos);

assert_eq!(tile.grid_position(), pos);

let mut tile: GridRefMut<TwoColoredTile> = map.get_mut_tile_at_position(&pos);
assert_eq!(tile.grid_position(), pos);

tile.as_mut().color = TileColor::Blue;

Identifiable tile data

There are often times when you want to use a finite set of tiles, which share some common baseline properties - and often holding all of these properties inside of the grid is not desirable.

For this reason, there is a IdentifiableTileData trait - holding an unique identifier for each tile type.

struct TwoColoredTile {
    tile_type_id: u64,
    color: TileColor,
}

impl IdentifiableTileData for TwoColoredTile {
    fn tile_type_id(&self) -> u64 {
        self.tile_type_id
    }
}

This allows for storing additional data specific to each tile type in some other container (e.g. one implementing provided IdentTileCollection trait) and also easily creating new tile instance of specific type.

impl ConstructableViaIdentifierTile for TwoColoredTile {
    fn tile_new(tile_type_id: u64) -> Self {
        if tile_type_id == 0 {
            Self { tile_type_id, color: TileColor::Blue }
        } else {
            Self { tile_type_id, color: TileColor::Green }
        }
    }
}

IdentifiableTileData is used by some built-in tile types used by different more specialized functionalities.

Visual representation of tiles

There are some basic visualization methods provided within the grid-forge, lying under the #[vis] feature flag. These are most useful for loading and saving 2D grid maps from/to image files, and use image crate under the hood.

VisTileData make it easy to generate visual representation of the tile data dynamically, eg. by using some other characteristics of the tile.

struct TwoColoredTile {
    color: TileColor,
}

// Each tile will be represented by 10x10 RGB pixels.
impl<DefaultVisPixel, 10, 10> VisTileData for TwoColoredTile {
    fn vis_pixels(&self) -> [[DefaultVisPixel; 1]; 1] {
      let pixel = match self.color {
          TileColor::Blue => [[DefaultVisPixel::new([0, 0, 255])]],
          TileColor::Green => [[DefaultVisPixel::new([0, 255, 0])]],
      }
      vec![vec![pixel; 10]; 10]
    }
}

There are also options associated with VisCollection struct, which holds visual representation of each IdentifiableTileData tile type - making it kind of naive and basic resource system.

Procedural generation

There is a whole procedural generation module, at the moment containing two kind of generators:

  • basic Random Walk algorithm - see gen_walker example.
  • collapsible tile generation (Model Synthesis/Wave function collapse) - see gen_collapse_overlap and gen_collapse_singular examples.

Godot integration

godot module contains a collection of structs allowing for easy roundtrips between Godot's and grid-forge data structures, using IdentifiableTileData trait to synchronize the data between the two sources.

For Rust-Godot communication it uses GDExtension godot-rust crate.

See example_godot crate for an example of simple Godot App using the grid-forge for loading the map from image file and procedural generation, rendering it in Godot's TileMap class.

grid-forge's People

Contributors

statismike avatar

Watchers

 avatar

grid-forge's Issues

Generalize resolver

Current implementations of Model Synthesis and WFC algorithms are not really adhering strictly to the rules of nether.

  • they are both acting on tile-to-tile basis, without overlapping
  • they are both selecting next collapse candidate on basis of entrophy
  • their only difference is currently how they are selecting valid options for next tile: either concrete tile ID (WFC) or calculated border candidates (MS)

At least these elements should be abstracted:

  • NextCollapsePositionStrategy
  • CollapseWindowStrategy

VisTile + IdentifiableTile - cache for pixels

Currently, the basic VisTile holds all pixels inside its definitions for it to be retrieved from the object. Option to retrieve the pixels from external source, which will save pixels for every IdentifiableTile and then add the pixels to final visual representation.

`Subscriber` for Godot example

Make the current godot feature example more interesting by introducing the GodotSubscriber, which will propagate changes made be collapsible algorithms during the map creation.

The show-off should be toggleable, as it would need some intended delay - the example app should illustrate the process, but also present accurate speed of the algorithms.

Seperate the `PositionQueue` and `EntrophyQueue` resolvers solution.

The #11 have introduced massive speedups of EntrophyQueue, but also made the PositionQueue much more fallible. The implementations for both should be separated, reintroducing the previous version of choosing possible options for PositionQueue (with all nifty speedups introduced by that PR) to make it more viable again.

Launch `GridMap` into 3D!

Currently GridMap2D implementation, as the name suggests supports only 2D maps. Most work-intensive generative algorithms (resting in collapse module) are already prepared for launching into third dimension, but the overhaul in other functionalities would be significant.

  • GridPosition is abstracted enough so the full-time inclusion of y coordinate shouldn't be too significant (probably the current Option<u32> implementation will be enough).
  • GridDir and dependent elements need to be adjusted. A possibilty of Dimensionality trait type for overhauled GridMap is there, though I would like to keep the current trait-complexity in check.
  • GridSize as above.

One of the solutions would be to remodel GridMap2D to use ndarray instead of grid under-the-hood.

Methods for joining gridmaps

Generate final gridmap using some pregenerated gridmaps.

Will be useful for inserting one GridMap into another, with options either to

  • overwrite
  • keep existing tiles
  • conditionally do both above

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.