diff options
Diffstat (limited to 'src/view/MapLoader.ts')
-rw-r--r-- | src/view/MapLoader.ts | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/view/MapLoader.ts b/src/view/MapLoader.ts new file mode 100644 index 0000000..eca8b75 --- /dev/null +++ b/src/view/MapLoader.ts @@ -0,0 +1,59 @@ +import {mapValues, mapValuesAsync, nextPowerOf2} from '../util'; + +import Renderer from './Renderer'; +import MapView from './MapView'; +import MapData from '../model/MapData'; + + +function loadImage(url: string): Promise<HTMLImageElement> { + return new Promise(function(resolve, reject) { + let img = new Image(); + img.addEventListener('load', () => { resolve(img); }); + img.addEventListener('error', () => { reject(Error('failed to load ' + url)); }); + img.src = url; + }); +} + +function loadImages(urls: Map<string, string>): Promise<Map<string, HTMLImageElement>> { + return mapValuesAsync(loadImage, urls); +} + +function loadTiles(tiles: Map<string, string>): Promise<Map<string, HTMLImageElement>> { + return loadImages(mapValues(t => `resources/sprite/tile/${t}.png`, tiles)); +} + +function mkTileTexture(gl: WebGLRenderingContext, tiles: Map<string, HTMLImageElement>): [WebGLTexture, Map<string, number>] { + let canvas = document.createElement('canvas'); + canvas.width = nextPowerOf2(tiles.size) * MapView.tileSize; + canvas.height = MapView.tileSize; + + let i = 0; + let ret: Map<string, number> = new Map(); + let ctx = canvas.getContext('2d') as CanvasRenderingContext2D; + + for (let [k, tile] of tiles) { + ctx.drawImage(tile, i * MapView.tileSize, 0); + ret.set(k, i++); + } + + let texture = gl.createTexture(); + if (!texture) + throw new Error('unable to create texture'); + + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + return [texture, ret]; +} + + +export async function loadMap(r: Renderer, mapData: MapData): Promise<MapView> { + let tiles = await loadTiles(mapData.tiles); + let [tileTexture, tileMap] = mkTileTexture(r.gl, tiles); + + return new MapView(r, mapData, tileTexture, tileMap); +} |