Awesome
About
Pixi-tilemap allows a developer to create tilemaps based on PIXI.js and https://github.com/pixijs/pixi-tilemap
Example Usage
Completed demo: https://alanhollis.com/pixi-tilemap-tutorial/
Creating a basic tile map
<!doctype html>
<html>
<head>
<script src="https://pixijs.download/release/pixi.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@pixi/tilemap@latest/dist/pixi-tilemap.umd.js"></script>
</head>
<body>
<script>
var resolutionX = 800;
var resolutionY = 600;
var tileSizeX = 128;
var tileSizeY = 128;
var app = new PIXI.Application(resolutionX, resolutionY);
document.body.appendChild(app.view);
PIXI.loader
.add([
"imgs/imgGround.png"
])
.load(setup);
function setup() {
var groundTiles = new PIXI.tilemap.CompositeRectTileLayer(0, PIXI.utils.TextureCache['imgs/imgGround.png']);
app.stage.addChild(groundTiles);
for (var i = 0; i <= parseInt(resolutionX / tileSizeX); i++) {
for (var j = 0; j <= parseInt(resolutionX / tileSizeX); j++) {
groundTiles.addFrame('imgs/imgGround.png', i * tileSizeX, j * tileSizeY);
}
}
}
</script>
</body>
</html>
Pivoting the tile map around a player to give a movement effect
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.4.3/pixi.min.js"></script>
<script src="https://cdn.rawgit.com/pixijs/pixi-tilemap/master/bin/pixi-tilemap.js"></script>
</head>
<body>
<script>
var resolutionX = 800;
var resolutionY = 600;
var tileSizeX = 128;
var tileSizeY = 128;
var app = new PIXI.Application(resolutionX, resolutionY);
document.body.appendChild(app.view);
var groundTiles;
var playerTankSprite;
var playerOffsetX = (resolutionX / 2 - 24);
var playerOffsetY = (resolutionY / 2 - 24);
var player = {
x: 0,
y: 0
};
const loader = PIXI.Loader.shared;
loader
.add([
"imgs/imgGround.png",
"imgs/imgTanks.png",
"imgs/imgBuildings.png"
])
.load(setup);
function setup() {
// Create our tile map based on the ground texture
groundTiles = new PIXI.tilemap.CompositeRectTileLayer(0, PIXI.utils.TextureCache['imgs/imgGround.png']);
groundTiles.position.set(playerOffsetX + player.x, playerOffsetY + player.y);
drawTiles();
app.stage.addChild(groundTiles);
// Place a tank in the middle of the texture the tank sprite never moves
// Instead we move the tile map around the player in out game loop
var tankTexture = new PIXI.Texture(
PIXI.utils.TextureCache['imgs/imgTanks.png'],
new PIXI.Rectangle(0 * 48, 0, 48, 48)
);
playerTankSprite = new PIXI.Sprite(tankTexture);
playerTankSprite.x = playerOffsetX;
playerTankSprite.y = playerOffsetY;
app.stage.addChild(playerTankSprite);
gameLoop();
}
function drawTiles() {
// The +5 gives us a buffer around the current player
var numberOfTiles = parseInt(resolutionX / tileSizeX) + 5;
for (var i = -numberOfTiles; i <= numberOfTiles; i++) {
for (var j = -numberOfTiles; j <= numberOfTiles; j++) {
groundTiles.addFrame('imgs/imgGround.png', i * tileSizeX, j * tileSizeY);
}
}
}
function gameLoop() {
// Make it look like the tank is driving forwards by moving the tiles
player.y -= 4;
groundTiles.pivot.set(player.x, player.y);
requestAnimationFrame(gameLoop);
}
</script>
</body>
</html>
Redrawing the tile map to give the illusion of constant movement
Change the draw tiles function and the gampe loop function as follows
function drawTiles() {
var numberOfTiles = parseInt(resolutionX / tileSizeX) + 10;
// We need to calculate this in order to prevent the tile looking "jumpy" when it's redrawn
var groundOffsetX = player.x % 128; // Number of tank tiles on x axis
var groundOffsetY = player.y % 128; // Number of tank tiles on y axis
for (var i = -numberOfTiles; i <= numberOfTiles; i++) {
for (var j = -numberOfTiles; j <= numberOfTiles; j++) {
groundTiles.addFrame('imgs/imgGround.png', i * tileSizeX, j * tileSizeY);
}
}
groundTiles.position.set(playerOffsetX + player.x - groundOffsetX, playerOffsetY + player.y - groundOffsetY);
}
function gameLoop() {
if (player.y % (10 * tileSizeY ) === -0) {
drawTiles();
}
// Make it look like the tank is driving forwards by moving the tiles
player.y -= 4;
groundTiles.pivot.set(player.x, player.y);
requestAnimationFrame(gameLoop);
}
Add another image to the tile map
function drawTiles() {
var numberOfTiles = parseInt(resolutionX / tileSizeX) + 10;
// We need to calculate this in order to prevent the tile looking "jumpy" when it's redrawn
var groundOffsetX = player.x % 128; // Number of tank tiles on x axis
var groundOffsetY = player.y % 128; // Number of tank tiles on y axis
for (var i = -numberOfTiles; i <= numberOfTiles; i++) {
for (var j = -numberOfTiles; j <= numberOfTiles; j++) {
groundTiles.addFrame('imgs/imgGround.png', i * tileSizeX, j * tileSizeY);
}
}
// We'll use these later to animate the building
var animateX = 1;
var animateY = 0;
/**
* We'll draw the building off the players viewport to start to give it the impression we're driving past
* @type {number}
*/
var buildingTexture = new PIXI.Texture(
PIXI.utils.TextureCache['imgs/imgBuildings.png'],
new PIXI.Rectangle(0, 0, 144, 144, 144)
);
groundTiles.addFrame(buildingTexture, (2 * 128), (4 * 128) * -1, animateX, animateY);
groundTiles.position.set(playerOffsetX + player.x - groundOffsetX, playerOffsetY + player.y - groundOffsetY);
}
Add animation to the building
var tick = new Date().getTime();
var tileAnim = 0;
var tileAnimationTick = 0;
function gameLoop() {
tick = new Date().getTime();
if (player.y % (10 * tileSizeY ) === -0) {
console.log("redrawing");
drawTiles();
}
// Make it look like the tank is driving forwards by moving the tiles
player.y -= 4;
groundTiles.pivot.set(player.x, player.y);
app.renderer.plugins.tilemap.tileAnim[0] = tileAnim * 144;
if (tick > tileAnimationTick) {
tileAnimationTick = tick + 300;
tileAnim = tileAnim + 1;
if (tileAnim >= 3) {
tileAnim = 0;
}
}
requestAnimationFrame(gameLoop);
}
Complete code with stats
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.4.3/pixi.min.js"></script>
<script src="https://cdn.rawgit.com/pixijs/pixi-tilemap/master/bin/pixi-tilemap.js"></script>
<script src="//rawgit.com/mrdoob/stats.js/master/build/stats.min.js"></script>
</head>
<body>
<script>
var resolutionX = 800;
var resolutionY = 600;
var tileSizeX = 128;
var tileSizeY = 128;
var stats = new Stats();
stats.showPanel(0);
document.body.appendChild(stats.dom);
var app = new PIXI.Application(resolutionX, resolutionY);
document.body.appendChild(app.view);
var groundTiles;
var playerTankSprite;
var playerOffsetX = (resolutionX / 2 - 24);
var playerOffsetY = (resolutionY / 2 - 24);
var player = {
x: 0,
y: 0
};
PIXI.loader
.add([
"imgs/imgGround.png",
"imgs/imgTanks.png",
"imgs/imgBuildings.png"
])
.load(setup);
function setup() {
// Create our tile map based on the ground texture
groundTiles = new PIXI.tilemap.CompositeRectTileLayer(0, PIXI.utils.TextureCache['imgs/imgGround.png']);
drawTiles();
app.stage.addChild(groundTiles);
// Place a tank in the middle of the texture the tank sprite never moves
// Instead we move the tile map around the player in out game loop
var tankTexture = new PIXI.Texture(
PIXI.utils.TextureCache['imgs/imgTanks.png'],
new PIXI.Rectangle(0 * 48, 0, 48, 48)
);
playerTankSprite = new PIXI.Sprite(tankTexture);
playerTankSprite.x = playerOffsetX;
playerTankSprite.y = playerOffsetY;
app.stage.addChild(playerTankSprite);
gameLoop();
}
function drawTiles() {
var numberOfTiles = parseInt(resolutionX / tileSizeX) + 10;
// We need to calculate this in order to prevent the tile looking "jumpy" when it's redrawn
var groundOffsetX = player.x % 128; // Number of tank tiles on x axis
var groundOffsetY = player.y % 128; // Number of tank tiles on y axis
for (var i = -numberOfTiles; i <= numberOfTiles; i++) {
for (var j = -numberOfTiles; j <= numberOfTiles; j++) {
groundTiles.addFrame('imgs/imgGround.png', i * tileSizeX, j * tileSizeY);
}
}
// We'll use these later to animate the building
var animateX = 1;
var animateY = 0;
/**
* We'll draw the building off the players viewport to start to give it the impression we're driving past
* @type {number}
*/
var buildingTexture = new PIXI.Texture(
PIXI.utils.TextureCache['imgs/imgBuildings.png'],
new PIXI.Rectangle(0, 0, 144, 144, 144)
);
groundTiles.addFrame(buildingTexture, (2 * 128), (4 * 128) * -1, animateX, animateY);
groundTiles.position.set(playerOffsetX + player.x - groundOffsetX, playerOffsetY + player.y - groundOffsetY);
}
var tick = new Date().getTime();
var tileAnim = 0;
var tileAnimationTick = 0;
function gameLoop() {
stats.begin();
tick = new Date().getTime();
if (player.y % (10 * tileSizeY ) === -0) {
console.log("redrawing");
drawTiles();
}
// Make it look like the tank is driving forwards by moving the tiles
player.y -= 4;
groundTiles.pivot.set(player.x, player.y);
app.renderer.plugins.tilemap.tileAnim[0] = tileAnim * 144;
if (tick > tileAnimationTick) {
tileAnimationTick = tick + 300;
tileAnim = tileAnim + 1;
if (tileAnim >= 3) {
tileAnim = 0;
}
}
stats.end();
requestAnimationFrame(gameLoop);
}
</script>
</body>
</html>