By placing the tiles in a square texture, the dimensions are bounded by the square root of the dimension in the old solution. This way we can fit a significantly higher number of tiles into it without using up all the accuracy of the coordinates.
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import MapState from '../model/state/MapState';
|
|
import {TileMap} from './MapLoader';
|
|
import Renderer from './renderer/Renderer';
|
|
|
|
export default class MapView {
|
|
public static readonly tileSize: number = 32;
|
|
|
|
private redrawPending: boolean = false;
|
|
|
|
private readonly vertexBuffer: WebGLBuffer;
|
|
private readonly textureBuffer: WebGLBuffer;
|
|
|
|
constructor(
|
|
private readonly r: Renderer,
|
|
private readonly map: MapState,
|
|
private readonly tileMap: TileMap,
|
|
) {
|
|
const vertexData: number[] = [];
|
|
const textureData: number[] = [];
|
|
|
|
for (let x = 0; x < map.data.width; x++)
|
|
for (let y = 0; y < map.data.height; y++)
|
|
this.addTile(vertexData, textureData, x, y, map.data.layers[0][y][x]);
|
|
|
|
const gl = r.getContext();
|
|
|
|
this.vertexBuffer = r.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW);
|
|
|
|
this.textureBuffer = r.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.textureBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureData), gl.STATIC_DRAW);
|
|
}
|
|
|
|
public draw(): void {
|
|
const gl = this.r.getContext();
|
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
gl.bindTexture(gl.TEXTURE_2D, this.tileMap.texture);
|
|
gl.uniform1i(this.r.getSamplerLoc(), 0);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
gl.vertexAttribPointer(this.r.getVertexPosLoc(), 2, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.textureBuffer);
|
|
gl.vertexAttribPointer(this.r.getTextureCoordLoc(), 2, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.drawArrays(gl.TRIANGLES, 0, 6 * this.map.data.width * this.map.data.height);
|
|
}
|
|
|
|
private pushTile(buf: number[], coords: [number, number, number, number]) {
|
|
const [x1, y1, x2, y2] = coords;
|
|
|
|
buf.push(x1); buf.push(y1);
|
|
buf.push(x2); buf.push(y1);
|
|
buf.push(x1); buf.push(y2);
|
|
|
|
buf.push(x1); buf.push(y2);
|
|
buf.push(x2); buf.push(y1);
|
|
buf.push(x2); buf.push(y2);
|
|
}
|
|
|
|
private addTile(vertexData: number[], textureData: number[], x: number, y: number, tile: string) {
|
|
const tilePos = this.tileMap.tiles.get(tile);
|
|
if (!tilePos)
|
|
throw new Error('invalid tile specifier in map data');
|
|
|
|
this.pushTile(vertexData, [x, y, x + 1, y + 1]);
|
|
this.pushTile(textureData, tilePos);
|
|
}
|
|
}
|