Add loader for simple (single-sprint) entities, use direction input
This commit is contained in:
parent
69be8d2ef8
commit
31c131289c
5 changed files with 80 additions and 9 deletions
BIN
dist/resources/sprite/entity/simple_square.png
vendored
Normal file
BIN
dist/resources/sprite/entity/simple_square.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 155 B |
46
src/index.ts
46
src/index.ts
|
@ -1,17 +1,63 @@
|
||||||
import MapData from './model/data/MapData';
|
import MapData from './model/data/MapData';
|
||||||
|
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
import { getJSON } from './util';
|
import { getJSON } from './util';
|
||||||
|
import { loadSimpleEntity } from './view/entity';
|
||||||
|
import DirectionHandler from './view/input/DirectionHandler';
|
||||||
import { loadMap } from './view/map';
|
import { loadMap } from './view/map';
|
||||||
import Renderer from './view/renderer/Renderer';
|
import Renderer from './view/renderer/Renderer';
|
||||||
|
|
||||||
|
const entityCenter = vec2.create();
|
||||||
|
const entityTranslation = vec2.create();
|
||||||
|
const entityMovement = vec2.create();
|
||||||
|
|
||||||
window.onload = async () => {
|
window.onload = async () => {
|
||||||
const canvas = document.getElementById('rpgedit') as HTMLCanvasElement;
|
const canvas = document.getElementById('rpgedit') as HTMLCanvasElement;
|
||||||
if (!canvas)
|
if (!canvas)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const input = new DirectionHandler();
|
||||||
|
input.addListener((v) => {
|
||||||
|
if (vec2.sqrLen(v) > 0)
|
||||||
|
vec2.normalize(entityMovement, v);
|
||||||
|
else
|
||||||
|
vec2.copy(entityMovement, [0, 0]);
|
||||||
|
});
|
||||||
|
|
||||||
const renderer = new Renderer(canvas);
|
const renderer = new Renderer(canvas);
|
||||||
|
|
||||||
const map = new MapData(await getJSON('resources/map/test.json'));
|
const map = new MapData(await getJSON('resources/map/test.json'));
|
||||||
const mapView = await loadMap(renderer, map);
|
const mapView = await loadMap(renderer, map);
|
||||||
|
|
||||||
|
const entity = await loadSimpleEntity(renderer, 'simple_square');
|
||||||
|
|
||||||
|
let prevTime: number|null = null;
|
||||||
|
|
||||||
|
const render = (time: number) => {
|
||||||
|
const res = 64;
|
||||||
|
|
||||||
|
let diff = 0;
|
||||||
|
if (prevTime !== null)
|
||||||
|
diff = time - prevTime;
|
||||||
|
prevTime = time;
|
||||||
|
|
||||||
|
vec2.scaleAndAdd(entityCenter, entityCenter, entityMovement, diff / 100);
|
||||||
|
vec2.scale(entityCenter, entityCenter, res);
|
||||||
|
vec2.round(entityCenter, entityCenter);
|
||||||
|
vec2.scale(entityCenter, entityCenter, 1 / res);
|
||||||
|
|
||||||
|
renderer.setCenter(entityCenter);
|
||||||
|
renderer.clear();
|
||||||
|
|
||||||
mapView.render();
|
mapView.render();
|
||||||
|
|
||||||
|
vec2.sub(entityTranslation, entityCenter, [0.5, 0.5]);
|
||||||
|
renderer.setTranslation(entityTranslation);
|
||||||
|
entity.render();
|
||||||
|
|
||||||
|
window.requestAnimationFrame(render);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.requestAnimationFrame(render);
|
||||||
};
|
};
|
||||||
|
|
15
src/view/entity.ts
Normal file
15
src/view/entity.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import Renderer from './renderer/Renderer';
|
||||||
|
import { SpriteCoords, SpriteView, SpriteViewBuilder } from './sprite';
|
||||||
|
import { loadImage, mkTexture } from './util/image';
|
||||||
|
|
||||||
|
export async function loadSimpleEntity(r: Renderer, sprite: string): Promise<SpriteView> {
|
||||||
|
const tile = await loadImage(`resources/sprite/entity/${sprite}.png`);
|
||||||
|
const texture = mkTexture(r.getContext(), tile);
|
||||||
|
|
||||||
|
const builder = new SpriteViewBuilder(r, texture);
|
||||||
|
|
||||||
|
const coords: SpriteCoords = [0, 0, 1, 1];
|
||||||
|
builder.addSprite(coords, coords);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
import {mat4} from 'gl-matrix';
|
import { mat4, vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
import Shaders from './Shaders';
|
import Shaders from './Shaders';
|
||||||
|
|
||||||
export default class Renderer {
|
export default class Renderer {
|
||||||
private readonly gl: WebGLRenderingContext;
|
private readonly gl: WebGLRenderingContext;
|
||||||
private readonly shaders: Shaders;
|
private readonly shaders: Shaders;
|
||||||
|
|
||||||
|
private readonly center: vec2 = vec2.create();
|
||||||
|
private readonly translation: vec2 = vec2.create();
|
||||||
private readonly viewport: mat4 = mat4.create();
|
private readonly viewport: mat4 = mat4.create();
|
||||||
|
|
||||||
constructor(private readonly canvas: HTMLCanvasElement) {
|
constructor(private readonly canvas: HTMLCanvasElement) {
|
||||||
|
@ -45,8 +48,19 @@ export default class Renderer {
|
||||||
return this.shaders.samplerLoc;
|
return this.shaders.samplerLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTranslation(v: Float32List) {
|
public setCenter(v: vec2|number[]) {
|
||||||
this.gl.uniform2fv(this.shaders.translateLoc, v);
|
vec2.copy(this.center, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTranslation(v: vec2|number[]) {
|
||||||
|
vec2.sub(this.translation, v, this.center);
|
||||||
|
this.gl.uniform2fv(this.shaders.translateLoc, this.translation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(): void {
|
||||||
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
this.setTranslation([0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private mkContext(): WebGLRenderingContext {
|
private mkContext(): WebGLRenderingContext {
|
||||||
|
@ -64,12 +78,10 @@ export default class Renderer {
|
||||||
const h = this.canvas.height;
|
const h = this.canvas.height;
|
||||||
|
|
||||||
this.gl.viewport(0, 0, w, h);
|
this.gl.viewport(0, 0, w, h);
|
||||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
this.clear();
|
||||||
|
|
||||||
mat4.identity(this.viewport);
|
mat4.identity(this.viewport);
|
||||||
mat4.scale(this.viewport, this.viewport, [2 * 64 / w, -2 * 64 / h, 1.0]);
|
mat4.scale(this.viewport, this.viewport, [2 * 64 / w, -2 * 64 / h, 1.0]);
|
||||||
this.gl.uniformMatrix4fv(this.shaders.viewportLoc, false, this.viewport);
|
this.gl.uniformMatrix4fv(this.shaders.viewportLoc, false, this.viewport);
|
||||||
|
|
||||||
this.setTranslation([-5, -5]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,6 @@ export class SpriteView {
|
||||||
public render(): void {
|
public render(): void {
|
||||||
const gl = this.r.getContext();
|
const gl = this.r.getContext();
|
||||||
|
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
gl.activeTexture(gl.TEXTURE0);
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
||||||
gl.uniform1i(this.r.getSamplerLoc(), 0);
|
gl.uniform1i(this.r.getSamplerLoc(), 0);
|
||||||
|
|
Reference in a new issue