Skip to content

Instantly share code, notes, and snippets.

@teak1
Created February 12, 2019 04:04
Show Gist options
  • Save teak1/dd31f9f55a7c7b4919b369684bbe0c20 to your computer and use it in GitHub Desktop.
Save teak1/dd31f9f55a7c7b4919b369684bbe0c20 to your computer and use it in GitHub Desktop.
//tiled render code
//by glEnd2
/*
to use create a new Tilemap object with the path to your .json file exported from tiled.
will do the rest from there.
to get renderable canvas use Tilemap.getImage();
rendering is done at creation so that there is less overhead later on.
*/
let local = {
_(e) {
e.style.display = "none";
document.body.appendChild(e);
},
createGraphics(w, h) {
let c = document.createElement("canvas");
// document.body.appendChild(c);
c.setAttribute("width", w);
c.setAttribute("height", h);
local._(c);
return {
canvas: c,
ctx: c.getContext("2d")
};
},
loadJSON(src, cb) {
fetch(src).then(res => res.json()).then(cb);
},
loadImage(src) {
return new Promise((resolve, reject) => {
let i = new Image();
i.src = src;
local._(i);
document.body.appendChild(i);
i.addEventListener("load", () => resolve(i));
});
}
}
class Tilemap {
constructor(src) {
this.src = src;
this.raw = null;
local.loadJSON(src, result => {
this.raw = result;
this.init();
});
this.layers = [];
this.rendered = null;
this.tilesets = [];
this.black = local.createGraphics(100, 100);
// this.black.ctx.fillStyle = "black";
// this.black.ctx.fillRect(0, 0, 100, 100);
// this.black.background(0);
this.graphic = null;
this.objects = {};
}
async init() {
for (var i = 0; i < this.raw.tilesets.length; i++) {
this.tilesets[i] = await local.loadImage(this.raw.tilesets[i].image.replace(/\.\./g, ""));
}
for (var i = 0; i < this.raw.layers.length; i++) {
if (this.raw.layers[i].type == "objectgroup") {
this.objects[this.raw.layers[i].name] = this.raw.layers[i];
this.layers[i] = null;
} else {
let w = this.raw.tilewidth * this.raw.layers[i].width;
let h = this.raw.tileheight * this.raw.layers[i].height;
this.layers[i] = local.createGraphics(w, h);
}
}
this.graphic = local.createGraphics(this.raw.tilewidth * this.raw.width, this.raw.tileheight * this.raw.height);
this.render();
console.log("done!");
}
renderLayer(index) {
let tileset = this.raw.layers[index];
let surface = this.layers[index];
surface.ctx.clearRect(0, 0, Infinity, Infinity);
for (var i = 0; i < tileset.data.length; i++) {
let tw = this.raw.tilewidth;
let th = this.raw.tileheight;
let fx = (i % tileset.width) * tw;
let fy = ((i - (i % tileset.width)) / tileset.width) * th;
let img = this.getImageFromIndex(tileset.data[i]);
if (img) surface.ctx.drawImage(img.image, img.x * tw, img.y * th, tw, th, fx, fy, tw, th);
}
}
render() {
if (this.graphic) {
this.graphic.ctx.clearRect(0, 0, Infinity, Infinity);
for (var i = 0; i < this.layers.length; i++) {
if (this.layers[i]) {
this.renderLayer(i);
this.graphic.ctx.drawImage(this.layers[i].canvas, 0, 0, this.graphic.canvas.width, this.graphic.canvas.height);
}
}
} else {
return null;
}
}
getImageFromIndex(index) {
let data = this.raw.tilesets;
let ind = -1;
for (var i = 0; i < data.length; i++) {
if (index < data[i].firstgid) {
ind = i - 1;
i = Infinity;
continue;
}
}
if (ind == -1) {
return {
image: this.black.canvas,
x: 0,
y: 0
};
} else {
index -= data[ind].firstgid;
let iw = data[ind].columns;
let ix = (index % iw);
let iy = (index - (index % iw)) / iw;
return {
image: this.tilesets[ind],
x: ix,
y: iy
}
}
}
getImage() {
return this.graphic.canvas;
}
getObject(path) {
path = path.split("/");
return this.objects[path[0]];
}
}
@teak1
Copy link
Author

teak1 commented Feb 12, 2019

does run asyncish, feel free to change so that it does not block main thread,
image may not be available right away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment