API issues

This commit is contained in:
Thibault Neveu
2018-06-16 16:57:43 +01:00
parent 700dd87d46
commit d582567d37
27 changed files with 245 additions and 751 deletions
+2 -1
View File
@@ -5,4 +5,5 @@ demo/dist/dist-es6/*
demo/node_modules/
*package-lock.json*
docs
dist-es6
dist-es6
demo/docs
+5
View File
@@ -0,0 +1,5 @@
demo
docs
node_modules
package-lock.json
img
+1
View File
@@ -27,6 +27,7 @@ app.use(cors());
app.use("/dist", express.static(path.join(__dirname, "dist/")));
app.use("/public", express.static(path.join(__dirname, "webapp/public/")));
app.use("/docs", express.static(path.join(__dirname, "docs/")));
app.get('/', (req, res) => {
res.sendFile(get_path("index.html"));
+1 -329
View File
File diff suppressed because one or more lines are too long
+8
View File
@@ -25,6 +25,14 @@
</div>
<div class="body_container">
<h3>Editor</h3><br>
<p>
<b>Left click </b>on one item to select it. Then Left click on the map to set the item.<br>
<b>Right click</b> is used to remove an item.
</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.7.1/pixi.min.js"></script>
<script src="/dist/metacar.min.js"></script>
+11 -10
View File
@@ -25,15 +25,14 @@
<div class="body_container">
<h2>Metacar</h2>
<h3>A reinforcement learning environement for self driving cars in the browser.</h3>
<h3>A reinforcement learning environment for self-driving cars in the browser.</h3>
<pre><code data-language="javascript"> const env = new metacar.env("canvas", metacar.level.fullCity);<br> env.load();</code></pre>
<p>
Learn how to start with metacar by reading the <a href="https://github.com/thibo73800/metacar">documentation</a>.
</p>
<br><br><br>
<h3>Checkout examples of algorithm create with <b>metacar</b></h3>
<h3>Check out examples of algorithm create with <b>metacar</b></h3>
<br><br><br>
<div class="level_link_box" style="height: 300px;">
@@ -42,9 +41,9 @@
<br><a href="/level0.html">Q-learning with table</a>
</h4>
<p>
In this example the goal is to give a simple working exemple
of reinforcement learning algorithm using the metacar environement.
You can checkout <a href="/level0.html">the demo</a> or take a look at the <a href="#">medium tutorial</a>.
In this example, the goal is to demonstrate a simple working example of reinforcement learning
algorithm using the metacar environment. You can check out
<a href="/level0.html">the demo</a> or take a look at the <a href="#">medium tutorial</a>.
</p>
</div>
@@ -54,8 +53,9 @@
<br><a href="/level1.html">Policy Monte carlo</a>
</h4>
<p>
In this example, I give an example of policy gradient algorithm based on monte carlo
exploration. The neural network is build using <a href="tensorflow.js">tensorflow.js</a>. Checkout <a href="/level1.html"> the demo</a>
Example of policy gradient algorithm based on Monte Carlo exploration.
The neural network is build using <a href="http://js.tensorflow.org">tensorflow.js</a>. Check out <a href="/level1.html"> the demo</a>.
<br><br>
</p>
</div>
@@ -66,8 +66,9 @@
<br><a href="/editor.html">Create your own level!</a>
</h4>
<p>
Metacar let's you edit your own level using <a href="/editor.html">the editor</a>.
<br>Also, youre more than welcome to <a href="https://github.com/thibo73800/metacar">contributing</a>.
Metacar lets you edit your own level using the <a href="/editor.html">the editor</a>.
Also, youre more than welcome to <a href="https://github.com/thibo73800/metacar">contribute</a> to the project.
</p>
</div>
+10 -1
View File
@@ -27,7 +27,16 @@
<h3>Current state (Lidar points)</h3><br>
<div id="realtime_viewer" style="float: left"></div>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
<b>Q-learning</b> algorithm with table. <br><br>
Click on <b>"Load trained agent"</b> to load the model. Then click on <b>"Play"</b>
to see the result. <br><br>
The left window gives you an overview of what's the autonomous vehicle (in red) see.<br><br>
The algorithm is implemented <a a href="https://github.com/thibo73800/metacar/blob/master/demo/webapp/public/js/q_table_agent.js">here</a> using <a href="https://github.com/thibo73800/metacar">the metacar environement.</a>
You can see below the content of the Q-table once the model is loaded.
</p>
</div>
+8 -1
View File
@@ -26,7 +26,14 @@
<h3>Current state (Lidar points)</h3><br>
<div id="realtime_viewer" style="float: left"></div>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
<b>Policy Gradient</b> algorithm based on Monte Carlo exploration. <br><br>
Click on <b>"Load trained agent"</b> to load the model. Then click on <b>"Play"</b>
to see the result. <br><br>
The left window gives you an overview of what's the autonomous vehicle (in red) see.<br><br>
The algorithm is implemented <a a href="https://github.com/thibo73800/metacar/blob/master/demo/webapp/public/js/policy_agent.js">here</a> using <a href="https://github.com/thibo73800/metacar">the metacar environement.</a>
</p>
</div>
+2 -4
View File
@@ -35,11 +35,9 @@ env.load().then(() => {
});
env.addEvent("save", () => agent.save());
env.addEvent("load", (content) => {
loadJSON("http://localhost:3000/public/models/qtable/qtable.json", (content) => {
agent.restore(content);
loadJSON("https://meta-project/public/models/qtable/qtable.json", (content) => {
agent.restore(content);
displayQTable("q_table", agent.stateList, agent, ["Top", "Left", "Right"]);
});
});
env.addEvent("custom", () => {
});
});
+4 -3
View File
@@ -3,8 +3,6 @@ let levelUrl = metacar.level.level1;
// Create the environement (canvasID, levelUrl)
var env = new metacar.env("canvas", levelUrl);
env.setAgentMotion(metacar.motion.BasicMotion, {rotationStep: 0.1});
// Create the Policy agent
var agent = new PolicyAgent(env);
@@ -31,5 +29,8 @@ env.load().then(() => {
console.log("On reset env!");
});
env.addEvent("save", () => agent.save());
env.addEvent("load", () => agent.restore());
env.addEvent("load", () => {
document.getElementById("metacar_canvas_button_train").style.display = "none";
agent.restore()
});
});
+6 -4
View File
@@ -22,7 +22,7 @@ class PolicyAgent {
Build the Value function
@weights (Object) Weights for the layer
*/
const LEARNING_RATE = 0.01;
const LEARNING_RATE = 0.005;
const value_optimizer = tf.train.adam(LEARNING_RATE);
/*
-----------------------
@@ -59,7 +59,7 @@ class PolicyAgent {
Build the policy network
@weights (Object) Weights for the layer
*/
const LEARNING_RATE = 0.01;
const LEARNING_RATE = 0.005;
this.policy_optimizer = tf.train.adam(LEARNING_RATE);
/*
-----------------------
@@ -175,8 +175,10 @@ class PolicyAgent {
/*
Restore the weights of the network
*/
this.valueModel = await tf.loadModel('https://metacar-project.com/public/models/policy/value-model-policy-agent.json');
this.policyModel = await tf.loadModel("https://metacar-project.com/public/models/policy/policy-model-policy-agent.json");
//this.valueModel = await tf.loadModel('https://metacar-project.com/public/models/policy/value-model-policy-agent.json');
//this.policyModel = await tf.loadModel("https://metacar-project.com/public/models/policy/policy-model-policy-agent.json");
this.valueModel = await tf.loadModel('http://localhost:3000/public/models/policy/value-model-policy-agent.json');
this.policyModel = await tf.loadModel("http://localhost:3000/public/models/policy/policy-model-policy-agent.json");
}
play(){
+148
View File
@@ -0,0 +1,148 @@
{
"cars": [],
"house": [
{
"x": 263,
"y": 108
},
{
"x": 112,
"y": 258
}
],
"house3": [
{
"x": 262,
"y": 16
}
],
"bench": [
{
"x": 135,
"y": 34
}
],
"tree": [
{
"x": 124,
"y": 134
},
{
"x": 260,
"y": 211
},
{
"x": 19,
"y": 54
},
{
"x": 17,
"y": 92
},
{
"x": 23,
"y": 132
},
{
"x": 71,
"y": 129
},
{
"x": 54,
"y": 46
},
{
"x": 107,
"y": 29
},
{
"x": 54,
"y": 78
}
],
"asset": [
{
"x": 19,
"y": 54
},
{
"x": 17,
"y": 92
},
{
"x": 23,
"y": 132
},
{
"x": 71,
"y": 129
},
{
"x": 54,
"y": 46
},
{
"x": 107,
"y": 29
},
{
"x": 54,
"y": 78
}
],
"map": [
[
0,
0,
0,
0,
0
],
[
0,
"↱",
"↔",
"↰",
0
],
[
0,
"↕",
0,
"↕",
0
],
[
0,
"↳",
"↠",
"↲",
0
],
[
0,
0,
0,
0,
0
]
],
"agent": {
"mx": 2,
"my": 1,
"line": 1,
"motion": {
"type": "BasicMotionEngine",
"options": {
"rotationStep": 0.5,
"actions": [
"UP",
"LEFT",
"RIGHT",
"DOWN",
"WAIT"
]
}
}
}
}
@@ -0,0 +1 @@
{"-1,-1,-1,-1":[38.41559993476102,37.65002795012376,37.38483694531514],"0,0,-1,-1":[37.62498572562567,37.80332356260869,37.3046709762896],"0,0,0,0":[34.070528769574345,34.641914478399805,33.874618288072924],"0,0,-1,0":[37.49471434416808,37.72852866958,36.31603666094973],"0,-1,-1,-1":[38.07277667405897,37.41500326267591,37.87683622071364],"-1,0,-1,-1":[38.051726923441535,37.90970644063301,37.293556977524595],"0,0,0,-1":[37.28014175378364,36.78736188762118,37.57500486223731],"0,-1,0,-1":[35.51195704245981,35.42196427040668,37.84970557040712],"-1,0,-1,0":[36.803399265972836,37.93584887730367,36.343739000290775],"-1,-1,0,-1":[17.326632163377663,23.714711979348117,37.54300608700161],"-1,-1,-1,0":[33.45157506696106,37.89368395744174,33.56173243769651],"-1,-1,0,0":[3.8973901965290025,7.788651280752156,22.37450751169544],"0,-1,0,0":[1.488747275090645,19.456561890876525,7.225236475305854],"-1,0,0,0":[1.998090897118808,7.814518157457918,26.485809153258685]}
+1 -329
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -1,6 +1,7 @@
{
"name": "metacar",
"version": "0.0.1",
"description": "A reinforcement learning environment for self-driving cars in the browser.",
"version": "0.0.3",
"main": "dist/metacar.min.js",
"author": "Thibault Neveu",
"license": "MIT",
+4 -11
View File
@@ -12,10 +12,8 @@ import {
import {CarOptions, Car, LidarInfoI} from "./car";
import {BasicMotionEngine} from "./basic_motion_engine";
import {ControlMotionEngine} from "./control_motion_engine";
import {BotMotionEngine} from "./bot_motion_engine";
import { Editor } from "./editor";
import { MotionEngine } from "./motion_engine";
export interface AssetInfo {
readonly mx?: number;
@@ -56,7 +54,6 @@ export class AssetManger {
private level: Level|Editor;
// Used to list the differents MotionEngine possible to add on the car
private motion: any;
// List of all items on the map
public assets: SimpleSprite[] = [];
private agentMotionEngine: any = BasicMotionEngine;
@@ -65,10 +62,6 @@ export class AssetManger {
constructor(level: Level|Editor) {
this.level = level;
this.motion = {
"BasicMotionEngine": BasicMotionEngine,
"ControlMotionEngine": ControlMotionEngine
}
}
/**
@@ -92,7 +85,7 @@ export class AssetManger {
this.agentMotionOptions = options;
}
createRoadSide(info: AssetInfo, textures: any){
createRoadSide(info: AssetInfo){
/*
@textures: (Pixi textures)
*/
@@ -208,7 +201,7 @@ export class AssetManger {
for (let my = 0; my < map.length; my++) {
for (let mx = 0; mx < map[my].length; mx++) {
if (ASSETS.ROADS[map[my][mx]]){
this.createRoadSide({mx, my, type: map[my][mx]}, textures);
this.createRoadSide({mx, my, type: map[my][mx]});
}
}
}
@@ -231,7 +224,7 @@ export class AssetManger {
}
}
createCars(map: (string|number)[][], info: any, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary)){
createCars(info: any, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary)){
/*
Method used to create all the cars
@map (2dim Array)
@@ -250,7 +243,7 @@ export class AssetManger {
}
}
createAgent(map: (string|number)[][], info: any, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary), displayLidar:boolean=true){
createAgent(info: any, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary), displayLidar:boolean=true){
/*
Method used to create the agent's car.
@map (2dim Array)
-1
View File
@@ -182,7 +182,6 @@ export class BotMotionEngine extends MotionEngine {
let turn = false;
let nx = this.car.mx + is_next_pos.mx;
let ny = this.car.my + is_next_pos.my;
let current_road = this.level.getRoad(this.car.my, this.car.mx);
if (!this.isRoad(nx, ny)) {
turn = true;
this.car.optionalTurn = false;
-1
View File
@@ -11,7 +11,6 @@ import {
CAR_IMG, Sprite, MAP, ROADSIZE, Container, Graphics
} from "./global";
import { RoadSprite } from "./asset_manager";
import { stat } from "fs";
var Global_carId = 0;
+7 -20
View File
@@ -1,9 +1,6 @@
import { LevelInfo, Roads } from "./level";
import { AssetManger, RoadSprite } from "./asset_manager";
import { Car} from "./car";
import { LevelInfo } from "./level";
import { AssetManger } from "./asset_manager";
import {Loader, Sprite, JSON_TEXTURES, ROADSIZE, MAP} from "./global";
import * as U from "./utils";
import {UIEvent} from "./ui_event";
import { World } from "./world";
/*
@@ -16,7 +13,6 @@ export class Editor extends World {
// Current selector items by the editor
private selectedItems: any = null;
private event: UIEvent;
constructor(levelContent: LevelInfo, canvasId: string) {
/*
@@ -40,9 +36,9 @@ export class Editor extends World {
let textures = Loader.resources[JSON_TEXTURES].textures;
// Load all elements of the car
this.am.createMap(this.map, info, textures, false);
this.am.createCars(this.map, info, textures);
this.am.createCars(info, textures);
if (info.agent)
this.agent = this.am.createAgent(this.map, info, textures, false);
this.agent = this.am.createAgent(info, textures, false);
var that = this;
for (var i = 0; i < this.envs.length; i++) {
@@ -124,7 +120,7 @@ export class Editor extends World {
this.envs[this.envs.length - 1].on("rightclick", function(this: any) {that.removeItem(this)});
}
else if (this.selectedItems.type == "car"){
this.am.createCars(this.map, {cars:[{
this.am.createCars({cars:[{
"mx": Math.floor(this.selectedItems.x / ROADSIZE),
"my": Math.floor(this.selectedItems.y / ROADSIZE),
"rotation": 0,
@@ -134,7 +130,7 @@ export class Editor extends World {
this.envs[this.envs.length - 1].on("rightclick", function(this: any) {that.removeItem(this)});
}
else if (this.selectedItems.type == "agent" && this.agent == undefined){
this.agent = this.am.createAgent(this.map, {agent:{
this.agent = this.am.createAgent({agent:{
"mx": Math.floor(this.selectedItems.x / ROADSIZE),
"my": Math.floor(this.selectedItems.y / ROADSIZE),
"rotation": 0,
@@ -158,13 +154,4 @@ export class Editor extends World {
this.app.stage.removeChild(this.selectedItems);
this.selectedItems = null;
}
}
/*
function createEditor(id: string){
document.getElementById("saveMap").onclick = () => {
editor.am.exportMap(width, height, file);
};
}*/
}
+4 -5
View File
@@ -3,13 +3,12 @@
services in the game (assets, map, agents...).
*/
import * as U from "./utils";
import {
ROADSIZE, Loader, JSON_TEXTURES
Loader, JSON_TEXTURES
} from "./global";
import {AssetManger, RoadSprite} from "./asset_manager";
import {Car, CarSprite, LidarChild, LidarInfoI} from "./car";
import {LidarInfoI} from "./car";
import {World} from "./world";
import { BasicMotionEngine, BasicMotionOptions } from "./basic_motion_engine";
import { ControlMotionEngine } from "./control_motion_engine";
@@ -90,9 +89,9 @@ export class Level extends World {
let textures = Loader.resources[JSON_TEXTURES].textures;
// Load all elements of the car
this.am.createMap(this.map, info, textures);
this.am.createCars(this.map, info, textures);
this.am.createCars(info, textures);
if (info.agent)
this.agent = this.am.createAgent(this.map, info, textures);
this.agent = this.am.createAgent(info, textures);
// Set up the main loop
this.app.ticker.add((delta: number) => this.loop(delta));
}
+2 -3
View File
@@ -3,7 +3,7 @@
*/
import {Level, LevelInfo} from "./level";
import {actionSpaceDescription, MotionEngine} from "./motion_engine";
import {actionSpaceDescription} from "./motion_engine";
import {UIEvent} from "./ui_event";
import * as U from "./utils";
import { BasicMotionEngine, BasicMotionOptions } from "./basic_motion_engine";
@@ -20,7 +20,6 @@ export interface eventLoadOptions {
export class MetaCar {
private agent: any;
private level: Level;
private canvasId: string;
private levelToLoad: string|Object;
@@ -245,7 +244,7 @@ export class MetaCar {
*/
public load(): Promise<void>{
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
if (typeof this.levelToLoad == "string"){
U.loadCustomURL(<string>this.levelToLoad, (content: LevelInfo) => {
this.level = new Level(content, this.canvasId);
+6 -9
View File
@@ -1,13 +1,11 @@
import { Level, LevelInfo } from "./level";
import { LevelInfo } from "./level";
import { UIEvent, eventEditorLoadOptions } from "./ui_event";
import * as U from "./utils";
import { Editor } from "./editor";
import { ROADSIZE } from "./global";
import { eventLoadOptions } from "./metacar";
export class MetaCarEditor {
private agent: any;
private level: Editor;
private canvasId: string;
private levelToLoad: string|Object;
@@ -28,17 +26,17 @@ export class MetaCarEditor {
this.levelToLoad = levelToLoad;
}
public load(level: string, agent: any): Promise<void>{
public load(): Promise<void>{
/*
Load the environement
@level (String) Name of the json level to load
@agent (Agent class)
*/
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
if (typeof this.levelToLoad == "string"){
U.loadCustomURL(<string>this.levelToLoad, (content: LevelInfo) => {
this.level = new Editor(content, this.canvasId);
this.level.load((delta: number) => this.loop(delta));
this.level.load(() => this.loop());
this.event = new UIEvent(this.level, this.canvasId);
this.event.createEditorElementsEvents();
@@ -50,7 +48,7 @@ export class MetaCarEditor {
}
else{
this.level = new Editor(<LevelInfo>this.levelToLoad, this.canvasId);
this.level.load((delta: number) => this.loop(delta));
this.level.load(() => this.loop());
this.event = new UIEvent(this.level, this.canvasId);
this.event.createEditorElementsEvents();
@@ -88,11 +86,10 @@ export class MetaCarEditor {
this.event.onCustomEvent(eventName, fc);
return;
}
const event = this.eventList[index];
this.eventCallback[index](fc, options);
}
private loop(delta: number): void{
private loop(): void{
let mousePos = this.level.getMousePosition();
let selectedItem = (<Editor>this.level).getSelectedItems();
if (selectedItem && selectedItem.type == "asset"){
+7 -9
View File
@@ -34,7 +34,7 @@ export class MotionEngine {
this.level = level;
}
protected boxesIntersect(a: any, b: any, reduce: boolean) {
protected boxesIntersect(a: any, b: any) {
/*
Chack if a the two elements intersect each others
@a (Pixi sprite)
@@ -51,9 +51,9 @@ export class MotionEngine {
* @object The object
*/
protected carIntersect(car1: CarSprite, object: CarSprite){
const nb = this.car.lidar.collisionPts.length;
const nb = car1.lidar.collisionPts.length;
for (let c=0; c < nb; c++){
if (this.boxesIntersect(this.car.lidar.collisionPts[c], object, false)){
if (this.boxesIntersect(car1.lidar.collisionPts[c], object)){
return true;
}
}
@@ -66,10 +66,10 @@ export class MotionEngine {
* @object The object
*/
protected carCaptorInObject(car1: CarSprite, object: CarSprite): number{
const size = this.car.lidar.collisionPts.length;
const size = car1.lidar.collisionPts.length;
let nb = 0;
for (let c=0; c < size; c++){
if (this.boxesIntersect(this.car.lidar.collisionPts[c], object, false)){
if (this.boxesIntersect(car1.lidar.collisionPts[c], object)){
nb += 1;
}
}
@@ -91,19 +91,17 @@ export class MotionEngine {
let agentCollisions = [];
let lidar_collisions = [];
let onRoadCnt = 0;
let checkNb = 0;
let onRoad = false;
for (let i = 0; i < envs.length; i++) {
if (envs[i] != this.car && Math.abs(envs[i].mx - this.car.mx) < 2 && Math.abs(envs[i].my - this.car.my) < 2){
checkNb += 1;
if (all && envs[i].obstacle && this.carIntersect(this.car, envs[i])){
agentCollisions.push(envs[i]);
}
else if (all && envs[i].mapId == MAP.ROAD){
onRoadCnt += this.carCaptorInObject(this.car, envs[i]);
}
if (this.boxesIntersect(envs[i], this.lidar, false)){
if (this.boxesIntersect(envs[i], this.lidar)){
lidar_collisions.push(envs[i]);
}
}
@@ -131,7 +129,7 @@ export class MotionEngine {
for (var a = 0; a < lidar_collisions.length; a++) {
if (lidar_collisions[a] != this.car){
let touch = this.boxesIntersect(lidar_collisions[a], this.lidar.lidarPts[i], false);
let touch = this.boxesIntersect(lidar_collisions[a], this.lidar.lidarPts[i]);
if (touch && lidar_collisions[a].obstacle){
// If this is an obstacle
this.lidar.lidarPts[i].alpha = 1.;
-1
View File
@@ -18,7 +18,6 @@ export class UIEvent {
private playing: boolean;
private canvasId: string;
private buttonsContainer: HTMLDivElement;
private selectedItems: boolean = false;
private level: Level|Editor;
private editorWidth: number;
private editorHeight: number;
-3
View File
@@ -27,9 +27,6 @@ export function loadEmbeddedURL(url: string, callback: any):void {
callback(embeddedContent[split[0]][split[1]]);
}
export function loadLocalStorageURL(url: string, callback: any):void{
}
export function loadCustomURL(url: string, callback: any):void {
/**
* @url: CustomURL to load
+4 -4
View File
@@ -1,6 +1,6 @@
import { LevelInfo, Roads } from "./level";
import { AssetManger, RoadSprite } from "./asset_manager";
import { Car, CarSprite } from "./car";
import { Car } from "./car";
import { ROADSIZE, Loader, JSON_TEXTURES, JSON_IMAGE } from "./global";
export class World {
@@ -36,7 +36,7 @@ export class World {
@loop (Method) This method will be call for each render
*/
this.loop = loop;
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
this.createLevel(this.info).then(() => resolve());
});
}
@@ -57,7 +57,7 @@ export class World {
// Append the app to the body
document.getElementById(this.canvasId).appendChild(this.app.view);
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
Loader.add([JSON_TEXTURES, JSON_IMAGE], {crossOrigin: true}).load(() => {
this._setup(info); // Set up the level (Add assets)
resolve();
@@ -66,7 +66,7 @@ export class World {
}
protected _setup(info: LevelInfo){
console.warn("This method should be implemented.");
console.warn("This method should be implemented.", info);
}
public getRoads(): Roads {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"mode": "modules",
"out": "docs",
"out": "demo/docs",
"src": "src/index.ts",
"theme": "default",
"ignoreCompilerErrors": "true",