Small grid framework to create ecosystem models and simulations.
- The basics are explained in the introduction
- Working code can be found in examples
- Browser examples are hosted on pixcellular.github.io/pxl
- Bug, question or suggestion? Please create an issue.
- Want to contribute? :D See development and our guidelines.
With pxl we can model a world filled with entities, each entity containing specific properties and a specific set of behavioural rules.
To create a new pxl world we pass it a map in which every symbol marks an entity.
const map = [
'o ',
' o ',
' '
];
Every entity on our map can have properties:
const organisms = [
{location: new Vector(0, 0), energy: 10},
{location: new Vector(1, 1), energy: 20}
];
In the map above the o
marks two entities with two properties: a required location
property, and the energy level of an organism.
You can give any symbol any property you want.
Note: entity properties need a location
. Pxl will use it to map the symbols on the map to their properties.
All entities behave in a certain way. For the o
organism we can define a specific set of behavioural rules using the Entity.handle
function:
class MyEntity {
symbol: 'o';
props;
// Organisms behave according to specific rules:
handle = (location, world) => {
// Get a view of neighbouring cells:
const view = new pxl.Neighbours(world, location);
// Find random empty space:
const spaceDirection = view.findDirRand(e => e.symbol === ' ');
if (spaceDirection) {
// Move randomly:
view.put(spaceDirection, this);
}
// Living costs energy:
this.props.energy--;
// ... And no energy means death:
if (this.props.energy <= 0) {
// Remove entity from world:
view.remove(spaceDirection || pxl.ZERO);
}
}
}
Pxl converts the map and properties into a world with acting entities. It does this using EntityBuilder
s:
const builders = new EntityBuilderMap();
// Every entity can have its own props:
builders.add('o', {build: (props) => ({symbol: 'o', props})});
Finally, we can put all our building blocks together:
const world = new World({
map,
entityProps: organisms,
builders
});
Let's make the world go round:
while (organisms.find(e => e.energy)) {
console.log(world.turn().toMap());
}
This is a very simple example, and you probably want to give your entities more complex behaviour.
To prevent outrageously unreadable handler
functions, pxl offers a way to divide your behaviour into smaller parts using a BehaviourGraph
.
You can find an example with documented code in the herbivore example.
Instead of creating maps by hand, you might want to generate them with the PerlinMapBuilder
that uses Perlin noise to populate maps with your symbols.
You could also create your own implementation of the MapBuilder
interface.
You can find an example with documented code in the herbivore example.
Run: npm i
Run: npm t