Read collision barriers from map file
This commit is contained in:
parent
5593bf2d36
commit
9be9f8e739
4 changed files with 64 additions and 29 deletions
23
dist/resources/map/test.json
vendored
23
dist/resources/map/test.json
vendored
|
@ -46,5 +46,28 @@
|
||||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
]
|
]
|
||||||
|
],
|
||||||
|
"collision": [
|
||||||
|
{
|
||||||
|
"type": "polygon",
|
||||||
|
"vertices": [
|
||||||
|
[1, 1],
|
||||||
|
[11, 1],
|
||||||
|
[11, 5],
|
||||||
|
[12, 5],
|
||||||
|
[12, 7],
|
||||||
|
[11, 7],
|
||||||
|
[11, 11],
|
||||||
|
[7, 11],
|
||||||
|
[7, 12],
|
||||||
|
[5, 12],
|
||||||
|
[5, 11],
|
||||||
|
[1, 11],
|
||||||
|
[1, 7],
|
||||||
|
[0, 7],
|
||||||
|
[0, 5],
|
||||||
|
[1, 5]
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { MapData } from '../model/data/map';
|
import { Collision, MapData } from '../model/data/map';
|
||||||
|
|
||||||
import { loadSimpleEntity } from '../view/entity';
|
import { loadSimpleEntity } from '../view/entity';
|
||||||
import { DirectionHandler } from '../view/input/directionhandler';
|
import { DirectionHandler } from '../view/input/directionhandler';
|
||||||
|
@ -13,19 +13,41 @@ import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class GameContext {
|
export class GameContext {
|
||||||
public static async load(renderer: Renderer): Promise<GameContext> {
|
public static async load(renderer: Renderer): Promise<GameContext> {
|
||||||
const mapView = this.loadMap(renderer);
|
|
||||||
const entity = loadSimpleEntity(renderer, 'simple_circle');
|
const entity = loadSimpleEntity(renderer, 'simple_circle');
|
||||||
|
const [mapView, collision] = await this.loadMap(renderer);
|
||||||
|
|
||||||
return new GameContext(
|
return new GameContext(
|
||||||
renderer,
|
renderer,
|
||||||
await mapView,
|
mapView,
|
||||||
await entity,
|
await entity,
|
||||||
|
collision,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async loadMap(renderer: Renderer): Promise<SpriteView> {
|
private static mkCollision(collision: Collision[]): LineSegment[] {
|
||||||
|
const ret: LineSegment[] = [];
|
||||||
|
|
||||||
|
for (const c of collision) {
|
||||||
|
switch (c.type) {
|
||||||
|
case 'polygon':
|
||||||
|
if (!c.vertices.length)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let prev = c.vertices[c.vertices.length - 1];
|
||||||
|
|
||||||
|
for (const v of c.vertices) {
|
||||||
|
ret.push(LineSegment.fromPoints(vec2.clone(prev), vec2.clone(v)));
|
||||||
|
prev = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async loadMap(renderer: Renderer): Promise<[SpriteView, LineSegment[]]> {
|
||||||
const map = new MapData(await getJSON('resources/map/test.json'));
|
const map = new MapData(await getJSON('resources/map/test.json'));
|
||||||
return loadMap(renderer, map);
|
return [await loadMap(renderer, map), this.mkCollision(map.collision)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private time: number|null = null;
|
private time: number|null = null;
|
||||||
|
@ -40,32 +62,12 @@ export class GameContext {
|
||||||
private readonly entityMovement: vec2 = vec2.create();
|
private readonly entityMovement: vec2 = vec2.create();
|
||||||
|
|
||||||
private readonly collisionRadius = 7 / 16;
|
private readonly collisionRadius = 7 / 16;
|
||||||
private readonly walls: LineSegment[] = [
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(1, 1), vec2.fromValues(11, 1)),
|
|
||||||
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(11, 1), vec2.fromValues(11, 5)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(11, 5), vec2.fromValues(12, 5)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(12, 5), vec2.fromValues(12, 7)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(12, 7), vec2.fromValues(11, 7)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(11, 7), vec2.fromValues(11, 11)),
|
|
||||||
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(11, 11), vec2.fromValues(7, 11)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(7, 11), vec2.fromValues(7, 12)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(7, 12), vec2.fromValues(5, 12)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(5, 12), vec2.fromValues(5, 11)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(5, 11), vec2.fromValues(1, 11)),
|
|
||||||
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(1, 11), vec2.fromValues(1, 7)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(1, 7), vec2.fromValues(0, 7)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(0, 7), vec2.fromValues(0, 5)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(0, 5), vec2.fromValues(1, 5)),
|
|
||||||
LineSegment.fromPoints(vec2.fromValues(1, 5), vec2.fromValues(1, 1)),
|
|
||||||
];
|
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
private readonly renderer: Renderer,
|
private readonly renderer: Renderer,
|
||||||
private readonly mapView: SpriteView,
|
private readonly mapView: SpriteView,
|
||||||
private readonly entity: SpriteView,
|
private readonly entity: SpriteView,
|
||||||
|
private readonly collision: LineSegment[],
|
||||||
) {
|
) {
|
||||||
this.input = new DirectionHandler();
|
this.input = new DirectionHandler();
|
||||||
this.input.addListener((v) => {
|
this.input.addListener((v) => {
|
||||||
|
@ -99,8 +101,8 @@ export class GameContext {
|
||||||
|
|
||||||
const move = new Movement(this.entityPos, dest);
|
const move = new Movement(this.entityPos, dest);
|
||||||
|
|
||||||
for (const w of this.walls) {
|
for (const c of this.collision) {
|
||||||
if (!w.collidesMoveCircle(dest2, move, this.collisionRadius))
|
if (!c.collidesMoveCircle(dest2, move, this.collisionRadius))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!vec2.exactEquals(dest, dest2)) {
|
if (!vec2.exactEquals(dest, dest2)) {
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
|
export interface CollisionPolygon {
|
||||||
|
readonly type: 'polygon';
|
||||||
|
readonly vertices: Array<[number, number]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Collision = CollisionPolygon;
|
||||||
|
|
||||||
export interface Input {
|
export interface Input {
|
||||||
readonly tiles: string[];
|
readonly tiles: string[];
|
||||||
readonly layers: number[][][];
|
readonly layers: number[][][];
|
||||||
|
readonly collision: Collision[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MapData {
|
export class MapData {
|
||||||
public readonly tiles: string[];
|
public readonly tiles: string[];
|
||||||
public readonly layers: number[][][];
|
public readonly layers: number[][][];
|
||||||
|
public readonly collision: Collision[];
|
||||||
|
|
||||||
public readonly width: number;
|
public readonly width: number;
|
||||||
public readonly height: number;
|
public readonly height: number;
|
||||||
|
@ -13,6 +22,7 @@ export class MapData {
|
||||||
constructor(data: Input) {
|
constructor(data: Input) {
|
||||||
this.tiles = data.tiles;
|
this.tiles = data.tiles;
|
||||||
this.layers = data.layers;
|
this.layers = data.layers;
|
||||||
|
this.collision = data.collision;
|
||||||
|
|
||||||
this.height = this.layers[0].length;
|
this.height = this.layers[0].length;
|
||||||
this.width = this.layers[0][0].length;
|
this.width = this.layers[0][0].length;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
],
|
],
|
||||||
"jsRules": {},
|
"jsRules": {},
|
||||||
"rules": {
|
"rules": {
|
||||||
"curly": [true, "as-needed"],
|
"curly": false,
|
||||||
"indent": [true, "tabs"],
|
"indent": [true, "tabs"],
|
||||||
"interface-name": false,
|
"interface-name": false,
|
||||||
"max-classes-per-file": false,
|
"max-classes-per-file": false,
|
||||||
|
|
Reference in a new issue