- block/voxel/cube -> mostly interchangeable. The minecrafty blocks you see on the screen.
- chunk: is a piece of the world that contains voxels
- AABB: bounding volume
- voxeljs: not 100% consistent yet, 'voxel.js' also acceptable, but definitely not 'VoxelJS'.
- dims: short for 'dimensions'. Perhaps obvious to some.
x
,z
: horizontal planey
: vertical plane
voxeljs uses various forms to represent positions:
{x: Number, y: Number, z: Number}
[x, y, z]
and- Three.js's
Vector3
. Vector3 is rad and has a bunch of operations that allow you to combine vectors in various ways. Wish this was the only way they represented positions, but perhaps it's not a good idea for performance reasons. ??
// returns 0 or 1 depending whether block at that position exists and is 'on'
game.getVoxel(pos)
game.setVoxel(pos, 0) // off
game.setVoxel(pos, 1) // on
game.setVoxel(pos, 2) // on, with another material
game.controls.yawObject.position
Flat world is a nicer way to start (at least you can't fall off the edge). This places the player just above the ground.
var game = createGame({
generate: function(i,j,k) {
return j < 1 ? 1 : 0;
},
startingPosition: [0, 75, 0],
texturePath: texturePath // etc
})
Default block size is 25, accessible via game.cubeSize
:
game.cubeSize // => 25
Default 'player size' is a 1/2 block long/wide and 1.5 blocks high:
game.playerAABB().width() // => 12.5
game.playerAABB().height() // => 37.5
See implementation of Game.prototype.playerAABB
for more details.
Game instance can fire the following, non-exhaustive, list of events:
Captures mouse activity
Called every game tick. Callback is passed delta
.
Called every tick when an item is colliding with the player. Callback is passed the item that is colliding.
Detects collisions between an item and other items, or voxels.
game.getCollisions(item.mesh.position, item)
This will give you back a 'collisions object' whose keys are positions on the object and values are arrays of the positions of faces that are colliding.
For example, here we have 4 faces colliding with the bottom of our object:
{
back: Array[0]
bottom: Array[4]
down: Array[1]
forward: Array[0]
left: Array[0]
middle: Array[0]
right: Array[0]
top: Array[0]
up: Array[0]
}
Loading textures creates multiple "materials".
var material = game.loadTextures([ 'obsidian', 'dirt' ]);
Both of these textures come with 6 materials, one for each side of a cube, giving a total of 12 materials. By default, faces 1 to 6 are assigned materials 1 to 6. You can assign materials to faces in however you want. For example, we could load materials 7 to 12 (e.g. the dirt materials) like so:
mesh.geometry.faces.forEach(function (face, index) {
face.materialIndex = index + 6; // obsidian texture indices 0 - 5, dirt 6 - 11.
});
- Items are non-voxel objects you can add to your game. e.g. Monsters/Players, Powerups, etc.
- Items currently implement their own physics, which is calculated every 'tick' by running an items' item.tick function. It's not very sophisticated.
- Items .mesh property is the thing that's actually processed by the THREE.js engine. Other properties of item are used in voxel.js to update the mesh, e.g. item.velocity.y is used every tick to calculate the next position the mesh should be in.
- Using the current item physics system, setting item.resting to false will force an item to recalculate it's position.
// texture for item
var material = game.loadTextures([ 'obsidian' ]);
var mesh = new game.THREE.Mesh(
new game.THREE.CubeGeometry(10, 30, 10), // width, height, depth
material
);
// move item to some location
mesh.translateX(87.5);
mesh.translateY(420);
mesh.translateZ(12.5);
// if these item dimensions don't match the mesh's dimensions,
// the object's physics will not operate correctly.
var item = {
mesh: mesh,
width: 10,
height: 100,
depth: 10,
collisionRadius: 20, // padding around object dimensions box for collisions
velocity: { x: 0, y: 0, z: 0 } // initial velocity
};
game.items.length // => 0
game.addItem(item)
// use `game.removeItem(item)` to remove
game.items.length // => 1
on second look, most of this stuff is in the readme haha. TLDR.