175 lines
5.0 KiB
JavaScript
175 lines
5.0 KiB
JavaScript
|
|
DWE.Tiled = {}
|
|
|
|
DWE.Tiled.Map = class {
|
|
constructor (file) {
|
|
this.file = file
|
|
let fname = file.split('/')
|
|
this.name = fname[fname.length - 1]
|
|
this.dir = fname.slice(0, -1).join('/')
|
|
this.loaded = false
|
|
|
|
this.tileMaps = []
|
|
this.layers = {}
|
|
this.tileWidth = 0
|
|
this.tileHeight = 0
|
|
this.scale = 1
|
|
|
|
this.loadTiledMap()
|
|
}
|
|
|
|
done () {
|
|
if (this['onready'])
|
|
this.onready.apply(this, [this])
|
|
|
|
this.loaded = true
|
|
}
|
|
|
|
error (e) {
|
|
if (this['onerror'])
|
|
this.onerror.apply(this, [e])
|
|
else
|
|
console.error(e)
|
|
|
|
this.loaded = false
|
|
}
|
|
|
|
loadTiledMap () {
|
|
DWE.File.loadJson(this.file).then((mapData) => {
|
|
// Currently, only allow orthogonal and right-down options.
|
|
if (mapData.orientation !== 'orthogonal' || mapData.renderorder !== 'right-down')
|
|
return this.error(new Error('Currently, DWE Libs only allows orthogonal orientation and right-down render order.'))
|
|
|
|
var map = this
|
|
|
|
// Load map layers
|
|
function loadMapLayers () {
|
|
var width = mapData.width
|
|
var height = mapData.height
|
|
|
|
for (let i in mapData.layers) {
|
|
let layer = mapData.layers[i]
|
|
let lw = layer.width || width
|
|
let lh = layer.height || height
|
|
let tiles = []
|
|
|
|
if (layer.type != 'tilelayer' || !layer.visible) continue
|
|
|
|
for(let i = 0; i < lw; i++) {
|
|
for(let j = 0; j < lh; j++) {
|
|
let value = layer.data[(j * lw) + i]
|
|
if (value == 0) continue
|
|
|
|
tiles.push({
|
|
x: i,
|
|
y: j,
|
|
tile: value
|
|
})
|
|
}
|
|
}
|
|
|
|
map.layers[layer.name] = {
|
|
tiles, x: parseInt(layer.x), y: parseInt(layer.y)
|
|
}
|
|
}
|
|
|
|
map.width = width
|
|
map.height = height
|
|
|
|
map.tileWidth = mapData.tilewidth
|
|
map.tileHeight = mapData.tileheight
|
|
|
|
map.done()
|
|
}
|
|
|
|
// Load tile maps
|
|
function loadNextTileMap(index) {
|
|
if (index === mapData.tilesets.length) return loadMapLayers()
|
|
var xtile = mapData.tilesets[index]
|
|
var path = map.dir + '/' + xtile.source
|
|
|
|
DWE.File.httpGET(path).then(function (data) {
|
|
var parser = new DOMParser()
|
|
var doc = parser.parseFromString(data, 'application/xml')
|
|
var tilesets = doc.getElementsByTagName('tileset')
|
|
|
|
for (let i in tilesets) {
|
|
let d = tilesets[i]
|
|
if (!(d instanceof Element)) continue
|
|
|
|
let tw = parseInt(d.getAttribute('tilewidth'))
|
|
let th = parseInt(d.getAttribute('tileheight'))
|
|
let imgfile = d.getElementsByTagName('image')[0]
|
|
|
|
if (imgfile) {
|
|
let img = new DWE.Image.TileMap(map.dir + '/' + imgfile.getAttribute('source'), tw, th)
|
|
|
|
img.offset = xtile.firstgid
|
|
img.tileCount = parseInt(d.getAttribute('tilecount'))
|
|
map.tileMaps.push(img)
|
|
|
|
img.onready = function () {
|
|
loadNextTileMap(index + 1)
|
|
}
|
|
}
|
|
}
|
|
}, function (e) {
|
|
map.error.apply(map, [e])
|
|
})
|
|
}
|
|
|
|
loadNextTileMap(0)
|
|
}, function (e) {
|
|
map.error.apply(map, [e])
|
|
})
|
|
}
|
|
|
|
drawLayer (ctx, origin, viewport, name) {
|
|
if (!this.layers[name]) return null
|
|
var layer = this.layers[name]
|
|
|
|
for (let i in this.tileMaps) {
|
|
let tileMap = this.tileMaps[i]
|
|
|
|
for (let j in layer.tiles) {
|
|
let tile = layer.tiles[j]
|
|
let tcount = tileMap.tileCount || tileMap.tiles.length
|
|
|
|
if (tile.tile >= tileMap.offset && tile.tile <= tcount) {
|
|
tileMap.draw(ctx, tile.tile - tileMap.offset, ((tile.x * this.tileWidth * this.scale) + origin.x + layer.x) + viewport.x,
|
|
((tile.y * this.tileHeight * this.scale) + origin.y + layer.y) + viewport.y, this.tileWidth * this.scale,
|
|
this.tileHeight * this.scale)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// object: Object that collides (i.e. a player, monster)
|
|
// name: Name of the layer (generally "static")
|
|
// effectiveRange: Range around object where tiles are tested for collisions
|
|
collideLayer (object, origin, viewport, name, effectiveRange) {
|
|
if (!this.layers[name]) return null
|
|
var layer = this.layers[name]
|
|
var collisions = null
|
|
var posAbs = new DWE.Math.Box2((object.x * this.scale) + origin.x + layer.x - viewport.x,
|
|
(object.y * this.scale) + origin.y + layer.y - viewport.y, object.width, object.height)
|
|
|
|
for (let i in layer.tiles) {
|
|
let tile = layer.tiles[i]
|
|
let tilePosAbs = new DWE.Math.Box2((tile.x * this.tileWidth * this.scale) + origin.x + layer.x + viewport.x,
|
|
(tile.y * this.tileHeight * this.scale) + origin.y + layer.y + viewport.y, this.tileWidth, this.tileHeight)
|
|
if (tilePosAbs.distance(posAbs) > effectiveRange) continue
|
|
if (posAbs.intersectsBox(tilePosAbs)) {
|
|
if (!collisions) collisions = []
|
|
collisions.push(tilePosAbs.subtract(posAbs).normalize())
|
|
}
|
|
}
|
|
|
|
return collisions
|
|
}
|
|
|
|
setScale (scale) {
|
|
this.scale = scale
|
|
}
|
|
}
|