From 3b5eaf35a8d8c47fb00a28cf5656b9e8b1d7d8af Mon Sep 17 00:00:00 2001 From: Thibault Neveu Date: Fri, 8 Jun 2018 11:32:49 +0100 Subject: [PATCH] Full city: ok --- .gitignore | 6 + demo/app.js | 32 +-- demo/dist/metacar.min.js | 257 +++++++++++++++++ demo/package.json | 3 +- demo/webapp/index.html | 20 ++ demo/webapp/public/js/full_city.js | 8 + demo/webapp/public/textures/textures.json | 183 ++++++++++++ demo/webapp/public/textures/textures.png | Bin 0 -> 25109 bytes dist/metacar.min.js | 257 +++++++++++++++++ package.json | 1 + src/asset_manager.ts | 44 +-- src/bot_motion_engine.ts | 28 +- src/car.ts | 24 +- src/editor.ts | 332 ++++++++++++++++++++++ src/embedded.ts | 11 + src/embedded/level/full_city.ts | 272 ++++++++++++++++++ src/global.ts | 2 +- src/index.ts | 9 +- src/level.ts | 35 ++- src/metacar.ts | 45 ++- src/motion_engine.ts | 17 +- src/utils.ts | 33 ++- tsconfig.json | 2 +- webpack.config.js | 16 +- 24 files changed, 1535 insertions(+), 102 deletions(-) create mode 100644 .gitignore create mode 100644 demo/dist/metacar.min.js create mode 100644 demo/webapp/public/js/full_city.js create mode 100644 demo/webapp/public/textures/textures.json create mode 100644 demo/webapp/public/textures/textures.png create mode 100644 dist/metacar.min.js create mode 100644 src/editor.ts create mode 100644 src/embedded.ts create mode 100644 src/embedded/level/full_city.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2acffa --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.baseDir.ts* +node_modules/* +dist/dist-es6/* +demo/dist/dist-es6/* +demo/node_modules/ +*package-lock.json* \ No newline at end of file diff --git a/demo/app.js b/demo/app.js index f8cde0d..56a7bb0 100644 --- a/demo/app.js +++ b/demo/app.js @@ -1,49 +1,38 @@ 'use strict'; -var fs = require('fs'); -// [START app] +var fs = require('fs'); const express = require('express'); -var path = require("path"); - +var path = require("path"); function fromDir(startPath,filter){ - - //console.log('Starting from dir '+startPath+'/'); - - if (!fs.existsSync(startPath)){ - console.log("no dir ",startPath); - return []; - } - var files_list = []; var files=fs.readdirSync(startPath); for(var i=0;i=0) { + if (filename.indexOf(filter)>=0) { files_list.push(filename); }; }; return files_list; } +function get_path(file){ + return path.join(path.join(__dirname, "webapp/"), file); +} + const app = express(); app.use("/dist", express.static(path.join(__dirname, "dist/"))); app.use("/public", express.static(path.join(__dirname, "webapp/public/"))); - -function get_path(file){ - return path.join(path.join(__dirname, "webapp/"), file); -} - app.get('/', (req, res) => { res.sendFile(get_path("index.html")); }); +/** + * Create all HTML routes + * **/ const files = fromDir(path.join(__dirname, "webapp/"),'.html'); files.forEach(file => { let route = file.split("/"); @@ -61,4 +50,3 @@ app.listen(PORT, () => { console.log(`App listening on port ${PORT}`); console.log('Press Ctrl+C to quit.'); }); -// [END app] diff --git a/demo/dist/metacar.min.js b/demo/dist/metacar.min.js new file mode 100644 index 0000000..c8a11f2 --- /dev/null +++ b/demo/dist/metacar.min.js @@ -0,0 +1,257 @@ +window["metacar"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/index.ts"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./src/asset_manager.ts": +/*!******************************!*\ + !*** ./src/asset_manager.ts ***! + \******************************/ +/*! exports provided: AssetManger */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AssetManger\", function() { return AssetManger; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _car__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./car */ \"./src/car.ts\");\n/* harmony import */ var _basic_motion_engine__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./basic_motion_engine */ \"./src/basic_motion_engine.ts\");\n/* harmony import */ var _control_motion_engine__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./control_motion_engine */ \"./src/control_motion_engine.ts\");\n/* harmony import */ var _bot_motion_engine__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./bot_motion_engine */ \"./src/bot_motion_engine.ts\");\n\n\n\n\n\n\n;\nvar AssetManger = (function () {\n function AssetManger(level) {\n this.assets = [];\n this.level = level;\n this.motion = {\n \"BasicMotionEngine\": _basic_motion_engine__WEBPACK_IMPORTED_MODULE_3__[\"BasicMotionEngine\"],\n \"ControlMotionEngine\": _control_motion_engine__WEBPACK_IMPORTED_MODULE_4__[\"ControlMotionEngine\"]\n };\n }\n AssetManger.prototype.createRoadSide = function (info, textures) {\n var x = (info.mx) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n var y = (info.my) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n var area = new _global__WEBPACK_IMPORTED_MODULE_1__[\"Graphics\"]();\n area.beginFill(0xe8e8e8);\n area.drawRoundedRect(0, 0, _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] + 30, _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] + 30, undefined);\n area.x = x - 15;\n area.y = y - 15;\n area.endFill();\n this.level.addChild(area);\n };\n AssetManger.prototype.createRoad = function (info, textures) {\n var _this = this;\n var road = new _global__WEBPACK_IMPORTED_MODULE_1__[\"Sprite\"](textures[_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[info.type].image]);\n road.x = (info.mx) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n road.y = (info.my) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n road.obstacle = false;\n road.mapId = _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].ROAD;\n road.orientation = _global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[info.type].orientation;\n road.setCarPosition = function (car, line) { return _this.setCarOnRoad(road, car, line); };\n road.cars = [];\n road.mx = info.mx;\n road.my = info.my;\n this.level.addRoad(road);\n };\n AssetManger.prototype.setCarOnRoad = function (road, car, line) {\n if (line == undefined)\n line = 0;\n var carById = this.level.findCarById(road.cars[0]);\n if (road.cars.length >= 1 && carById && carById.core.line == line) {\n line = line == 0 ? 1 : 0;\n }\n if (road.cars.length >= 2) {\n car.is_valid = false;\n return;\n }\n car.line = line;\n car.x = road.x;\n car.y = road.y;\n car.x += _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2;\n car.y += _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2;\n var x_margin = 0;\n var y_margin = (_global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] * 1 / 4);\n road.orientation = (Math.floor(road.orientation / car.rotationStep) * car.rotationStep);\n var th = -road.orientation * (Math.PI);\n var x_m = (Math.cos(th) * x_margin) - (y_margin * Math.sin(th));\n var y_m = (Math.cos(th) * y_margin) + (x_margin * Math.sin(th));\n var line_side_factor = line == 0 ? 1 : -1;\n var line_side_factor_t = line == 0 ? 0 : Math.PI;\n car.x += line_side_factor * Math.round(x_m);\n car.y += line_side_factor * Math.round(y_m);\n car.mx = Math.floor(car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n car.my = Math.floor(car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n car.rotation = (th + line_side_factor_t);\n car.checkAndsetNewRoad(road);\n };\n AssetManger.prototype.createAsset = function (img, info, textures, type) {\n var asset = new _global__WEBPACK_IMPORTED_MODULE_1__[\"Sprite\"](textures[img]);\n asset.obstacle = false;\n asset.type = type;\n asset.mapId = 0;\n asset.x = info.x;\n asset.y = info.y;\n this.level.addChild(asset);\n this.assets.push(asset);\n };\n AssetManger.prototype.createMap = function (map, info, textures, roadside) {\n if (roadside === void 0) { roadside = true; }\n if (roadside) {\n for (var my = 0; my < map.length; my++) {\n for (var mx = 0; mx < map[my].length; mx++) {\n if (_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[map[my][mx]]) {\n this.createRoadSide({ mx: mx, my: my, type: map[my][mx] }, textures);\n }\n }\n }\n }\n for (var my = 0; my < map.length; my++) {\n for (var mx = 0; mx < map[my].length; mx++) {\n if (_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[map[my][mx]]) {\n this.createRoad({ mx: mx, my: my, type: map[my][mx] }, textures);\n }\n }\n }\n for (var key in _global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"]) {\n if (key != \"ROADS\" && info[key]) {\n for (var a = 0; a < info[key].length; a++) {\n this.createAsset(_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"][key].image, info[key][a], textures, key);\n }\n }\n }\n };\n AssetManger.prototype.createCars = function (map, info, textures) {\n for (var c in info.cars) {\n var options = { lidar: true, lidarInfo: { pts: 2, width: 0.5, height: 1, pos: 1 } };\n if (info.cars[c].auto) {\n options.lidar = true;\n options.motionEngine = new _bot_motion_engine__WEBPACK_IMPORTED_MODULE_5__[\"BotMotionEngine\"](this.level);\n }\n var n_car = new _car__WEBPACK_IMPORTED_MODULE_2__[\"Car\"](this.level, info.cars[c], textures, options);\n this.level.addCar(n_car);\n }\n };\n AssetManger.prototype.createAgent = function (map, info, textures) {\n var agent = new _car__WEBPACK_IMPORTED_MODULE_2__[\"Car\"](this.level, info.agent, textures, {\n image: _global__WEBPACK_IMPORTED_MODULE_1__[\"CAR_IMG\"].AGENT,\n lidar: true,\n motionEngine: new this.motion[info.agent.motion.type](this.level, info.agent.motion.options)\n });\n this.level.addChild(agent.lidar);\n this.level.addCar(agent);\n agent.core.agent = true;\n return agent;\n };\n AssetManger.prototype.addAsset = function (asset) {\n this.assets.push(asset);\n };\n AssetManger.prototype.exportMap = function (width, height, file_name) {\n var file = { \"cars\": [] };\n var map = [];\n var envs = this.level.getEnvs();\n for (var y = 0; y < height; y++) {\n var line = [];\n for (var x = 0; x < width; x++) {\n line.push(0);\n }\n map.push(line);\n }\n for (var e = 0; e < envs.length; e++) {\n var elem = envs[e];\n if (!elem.isremove) {\n if (elem.mapId == _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].CAR && !elem.agent && elem.is_valid) {\n file.cars.push({\n \"mx\": elem.mx,\n \"my\": elem.my,\n \"line\": elem.line\n });\n }\n else if (elem.mapId == _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].ROAD) {\n map[elem.my][elem.mx] = elem.arrow;\n }\n }\n }\n for (var e = 0; e < this.assets.length; e++) {\n var elem = this.assets[e];\n if (!elem.isremove) {\n if (elem.type != \"car\") {\n if (!file[elem.type])\n file[elem.type] = [];\n file[elem.type].push({\n \"x\": elem.x,\n \"y\": elem.y\n });\n }\n }\n }\n file.map = map;\n if (this.level.agent) {\n file.agent = {\n \"mx\": this.level.agent.core.mx,\n \"my\": this.level.agent.core.my,\n \"line\": this.level.agent.core.line,\n \"motion\": {\n \"type\": \"BasicMotionEngine\",\n \"options\": {\n \"rotationStep\": 0.5,\n \"actions\": [\"UP\", \"LEFT\", \"RIGHT\", \"DOWN\", \"WAIT\"]\n }\n }\n };\n }\n console.log(file);\n file = JSON.stringify(file, null, 4);\n _utils__WEBPACK_IMPORTED_MODULE_0__[\"saveAs\"](file, file_name);\n };\n return AssetManger;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/asset_manager.ts?"); + +/***/ }), + +/***/ "./src/basic_motion_engine.ts": +/*!************************************!*\ + !*** ./src/basic_motion_engine.ts ***! + \************************************/ +/*! exports provided: BasicMotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BasicMotionEngine\", function() { return BasicMotionEngine; });\n/* harmony import */ var _motion_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./motion_engine */ \"./src/motion_engine.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\n\nvar BasicMotionEngine = (function (_super) {\n __extends(BasicMotionEngine, _super);\n function BasicMotionEngine(level, options) {\n var _this = _super.call(this, level) || this;\n _this.rotationStep = options.rotationStep;\n _this.actions = options.actions;\n return _this;\n }\n BasicMotionEngine.prototype.setUp = function (car, lidar) {\n this.car = car;\n this.lidar = lidar;\n this.state = [];\n for (var y = 0; y < lidar.pts; y++) {\n var line = [];\n for (var x = 0; x < lidar.pts; x++) {\n line.push(_global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].DEFAULT);\n }\n this.state.push(line);\n }\n this.setUpKeyboard();\n this.car.v = 0;\n this.detectInteractions();\n };\n BasicMotionEngine.prototype.setUpKeyboard = function () {\n var _this = this;\n var left = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](37);\n var up = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](38);\n var right = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](39);\n var down = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](40);\n if (this.actions.indexOf(\"LEFT\") != -1)\n left.press = function () { _this.turnLeft(); };\n if (this.actions.indexOf(\"RIGHT\") != -1)\n right.press = function () { _this.turnRight(); };\n if (this.actions.indexOf(\"UP\") != -1) {\n up.press = function () { _this.moveForward(); };\n up.release = function () {\n _this.car.v = 0;\n };\n }\n if (this.actions.indexOf(\"DOWN\") != -1) {\n down.press = function () { _this.moveBackward(); };\n down.release = function () {\n _this.car.v = 0;\n };\n }\n };\n BasicMotionEngine.prototype.turnLeft = function () {\n this.car.rotation -= this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BasicMotionEngine.prototype.turnRight = function () {\n this.car.rotation += this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BasicMotionEngine.prototype.moveForward = function () {\n this.car.v = 1;\n };\n BasicMotionEngine.prototype.moveBackward = function () {\n this.car.v = -1;\n };\n BasicMotionEngine.prototype.actionStep = function (delta, action) {\n if (this.actions[action] == \"LEFT\") {\n this.turnLeft();\n }\n if (this.actions[action] == \"RIGHT\") {\n this.turnRight();\n }\n if (this.actions[action] == \"UP\") {\n this.moveForward();\n }\n if (this.actions[action] == \"DOWN\") {\n this.moveBackward();\n }\n var _a = this.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n this.car.v = 0;\n return { agent_col: agent_col, on_road: on_road };\n };\n BasicMotionEngine.prototype.actionSpace = function () {\n return Array.apply(null, { length: this.actions.length }).map(Number.call, Number);\n };\n BasicMotionEngine.prototype.step = function (delta) {\n this.car.x += this.car.v * Math.cos(this.car.rotation) * delta;\n this.car.y += this.car.v * Math.sin(this.car.rotation) * delta;\n this.car.mx = Math.floor(this.car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.my = Math.floor(this.car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.checkAndsetNewRoad();\n this.lidar.x = this.car.x;\n this.lidar.y = this.car.y;\n this.lidar.rotation = this.car.rotation;\n var _a = this.detectInteractions(), agent_col = _a.agent_col, on_road = _a.on_road;\n if (agent_col.length > 0) {\n this.car.v = 0;\n this.car.vy = 0;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n return BasicMotionEngine;\n}(_motion_engine__WEBPACK_IMPORTED_MODULE_0__[\"MotionEngine\"]));\n\n\n\n//# sourceURL=webpack://metacar/./src/basic_motion_engine.ts?"); + +/***/ }), + +/***/ "./src/bot_motion_engine.ts": +/*!**********************************!*\ + !*** ./src/bot_motion_engine.ts ***! + \**********************************/ +/*! exports provided: BotMotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BotMotionEngine\", function() { return BotMotionEngine; });\n/* harmony import */ var _motion_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./motion_engine */ \"./src/motion_engine.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\nvar BotMotionEngine = (function (_super) {\n __extends(BotMotionEngine, _super);\n function BotMotionEngine(level) {\n var _this = _super.call(this, level) || this;\n _this.map = _this.level.getMap();\n _this.mapSizeY = _this.map.length;\n _this.mapSizeX = _this.map[0].length;\n _this.rotationStep = 0.5;\n _this.rotationToNextCase = {};\n _this.rotationToNextCase[0] = { \"mx\": 1, \"my\": 0 };\n _this.rotationToNextCase[0.5] = { \"mx\": 0, \"my\": 1 };\n _this.rotationToNextCase[1.0] = { \"mx\": -1, \"my\": 0 };\n _this.rotationToNextCase[1.5] = { \"mx\": 0, \"my\": -1 };\n _this.rotationToNextCase[-0.5] = { \"mx\": 0, \"my\": -1 };\n _this.rotationToNextCase[-1.0] = { \"mx\": -1, \"my\": 0 };\n _this.rotationToNextCase[-1.5] = { \"mx\": 0, \"my\": 1 };\n return _this;\n }\n BotMotionEngine.prototype.setUp = function (car, lidar) {\n this.car = car;\n this.lidar = lidar;\n this.state = [];\n for (var y = 0; y < lidar.pts; y++) {\n var line = [];\n for (var x = 0; x < lidar.pts; x++) {\n line.push(_global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].DEFAULT);\n }\n this.state.push(line);\n }\n this.car.v = 0;\n this.detectInteractions();\n };\n BotMotionEngine.prototype.turnLeft = function () {\n this.car.rotation -= this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BotMotionEngine.prototype.turnRight = function () {\n this.car.rotation += this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BotMotionEngine.prototype.moveUp = function () {\n this.car.v = 1;\n };\n BotMotionEngine.prototype.moveDown = function () {\n this.car.v = -1;\n };\n BotMotionEngine.prototype.isRoad = function (nx, ny) {\n if (ny < 0 || ny >= this.mapSizeY || nx < 0 || nx >= this.mapSizeX || this.map[ny][nx] == 0) {\n return false;\n }\n return true;\n };\n BotMotionEngine.prototype.autoRotation = function () {\n var right_dist = _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] + (_global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 3);\n var left_dist = _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] - (_global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 3.5);\n var same_dist = _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n if (this.car.next_road) {\n var y_dist = Math.abs(((this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) - this.car.y) * this.car.next_road.outroad_np.my);\n var x_dist = Math.abs(((this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) - this.car.x) * this.car.next_road.outroad_np.mx);\n if (this.car.next_road.rotation_type == 0) {\n if (y_dist < right_dist && x_dist < right_dist) {\n this.car.haveTurned = true;\n this.car.rotation = this.car.rotation += Math.PI / 2;\n this.car.rotation = this.car.rotation % (2 * Math.PI);\n this.car.next_road = undefined;\n return;\n }\n }\n if (this.car.next_road.rotation_type == 1) {\n if (y_dist < left_dist && x_dist < left_dist) {\n this.car.haveTurned = true;\n this.car.rotation = this.car.rotation -= Math.PI / 2;\n this.car.rotation = this.car.rotation % (2 * Math.PI);\n this.car.next_road = undefined;\n return;\n }\n }\n if (this.car.next_road.rotation_type == 2) {\n if (y_dist < same_dist && x_dist < same_dist) {\n this.car.haveTurned = true;\n this.car.rotation = this.car.rotation -= Math.PI;\n this.car.rotation = this.car.rotation % (2 * Math.PI);\n if (y_dist != 0 && this.car.x < this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.x = this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.y = this.car.next_road.outroad.y;\n }\n else if (y_dist != 0 && this.car.x > this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.x = this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.y = this.car.next_road.outroad.y;\n }\n else if (x_dist != 0 && this.car.y < this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.y = this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.x = this.car.next_road.outroad.x;\n }\n else if (x_dist != 0 && this.car.y > this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.y = this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.x = this.car.next_road.outroad.x;\n }\n this.car.next_road = undefined;\n return;\n }\n }\n }\n else {\n var key = this.car.rotation / Math.PI;\n var key_r = ((this.car.rotation / Math.PI) + 0.5) % 2;\n var key_l = ((this.car.rotation / Math.PI) - 0.5) % 2;\n var is_next_pos = this.rotationToNextCase[key];\n var is_next_pos_r = this.rotationToNextCase[key_r];\n var is_next_pos_l = this.rotationToNextCase[key_l];\n var turn = false;\n var nx = this.car.mx + is_next_pos.mx;\n var ny = this.car.my + is_next_pos.my;\n if (!this.isRoad(nx, ny)) {\n turn = true;\n }\n else if (!this.car.haveTurned && !this.car.turnedRandom) {\n this.car.turnedRandom = Math.random();\n }\n else if (!this.car.haveTurned && this.car.turnedRandom < 0.33 && this.isRoad(this.car.mx + is_next_pos_r.mx, this.car.my + is_next_pos_r.my)) {\n turn = true;\n }\n else if (!this.car.haveTurned && this.car.turnedRandom > 0.66 && this.isRoad(this.car.mx + is_next_pos_l.mx, this.car.my + is_next_pos_l.my)) {\n turn = true;\n }\n if (turn) {\n var possibles_rotations = [(key + 0.5) % 2., (key - 0.5) % 2., null];\n for (var p = 0; p < possibles_rotations.length; p++) {\n var next_pos = void 0;\n if (possibles_rotations[p] != null) {\n next_pos = this.rotationToNextCase[possibles_rotations[p]];\n }\n else {\n next_pos = { \"mx\": 0, \"my\": 0 };\n }\n var px = this.car.mx + next_pos.mx;\n var py = this.car.my + next_pos.my;\n if (this.isRoad(px, py)) {\n this.car.next_road = {\n \"outroad\": { y: ny * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"], x: nx * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] },\n \"outroad_np\": is_next_pos,\n \"rotation_type\": p,\n };\n return;\n }\n }\n }\n }\n };\n BotMotionEngine.prototype.step = function (delta) {\n if (this.state.toString().indexOf(\",\" + _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].CAR.toString()) != -1) {\n this.car.v = 0;\n }\n else {\n this.car.v = 0.8;\n this.autoRotation();\n }\n this.car.x += this.car.v * Math.cos(this.car.rotation) * delta;\n this.car.y += this.car.v * Math.sin(this.car.rotation) * delta;\n this.car.mx = Math.floor(this.car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.my = Math.floor(this.car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.checkAndsetNewRoad();\n this.lidar.x = this.car.x;\n this.lidar.y = this.car.y;\n this.lidar.rotation = this.car.rotation;\n var _a = this.detectInteractions(), agent_col = _a.agent_col, on_road = _a.on_road;\n if (agent_col.length > 0) {\n this.car.v = 0;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n return BotMotionEngine;\n}(_motion_engine__WEBPACK_IMPORTED_MODULE_0__[\"MotionEngine\"]));\n\n\n\n//# sourceURL=webpack://metacar/./src/bot_motion_engine.ts?"); + +/***/ }), + +/***/ "./src/car.ts": +/*!********************!*\ + !*** ./src/car.ts ***! + \********************/ +/*! exports provided: Car */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Car\", function() { return Car; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar Global_carId = 0;\nvar Car = (function () {\n function Car(level, info, textures, options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n this.level = level;\n options.image = options.image || _global__WEBPACK_IMPORTED_MODULE_0__[\"CAR_IMG\"].DEFAULT;\n options.lidar = options.lidar || false;\n options.lidarInfo = options.lidarInfo || { pts: 5, width: 4, height: 5, pos: 0 };\n this.core = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"](textures[options.image]);\n this.info = info;\n this.core.scale.x = 0.8;\n this.core.scale.y = 0.8;\n this.core.anchor.x = 0.5;\n this.core.anchor.y = 0.5;\n this.core.road = undefined;\n this.core.carId = Global_carId;\n Global_carId += 1;\n this.core.agent = false;\n this.core.obstacle = true;\n this.core.mapId = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].CAR;\n if (options.lidar) {\n this.createLidar(options.lidarInfo);\n this.core.lidar = this.lidar;\n }\n if (options.motionEngine) {\n this.motion = options.motionEngine;\n this.motion.setUp(this.core, this.lidar);\n this.core.rotationStep = 0.5;\n }\n else {\n this.core.rotationStep = 0.5;\n }\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n this.core.x = (this.info.mx) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.y = (this.info.my) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.checkAndsetNewRoad = function (road) { return _this.checkAndsetNewRoad(road); };\n var road = this.level.getRoad(this.core.my, this.core.mx);\n this.core.line = 0;\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n }\n Car.prototype.checkAndsetNewRoad = function (n_road) {\n var current_road = this.core.road;\n if (!n_road) {\n n_road = this.level.getRoad(this.core.my, this.core.mx);\n ;\n }\n if (n_road != current_road) {\n if (current_road) {\n current_road.cars.splice(current_road.cars.indexOf(this.core.carId), 1);\n }\n this.core.road = n_road;\n this.core.haveTurned = false;\n this.turnedRandom = undefined;\n if (n_road)\n n_road.cars.push(this.core.carId);\n }\n };\n Car.prototype.reset = function () {\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n var road = this.level.getRoad(this.core.my, this.core.mx);\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n };\n Car.prototype.getState = function () {\n return this.motion.state.map(function (arr) { return arr.slice(); });\n };\n Car.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n if (action == null) {\n var _a = this.motion.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n }\n else {\n var _b = this.motion.actionStep(delta, action), agent_col = _b.agent_col, on_road = _b.on_road;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n Car.prototype.createLidar = function (lidarOptions) {\n this.lidar = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Container\"]();\n var area = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n area.pt = false;\n area.alpha = 0.5;\n area.beginFill(0x515151);\n area.drawRect(0, 0, this.core.width * lidarOptions.width, this.core.height * lidarOptions.height);\n area.endFill();\n var x_step = area.width / lidarOptions.pts;\n var y_step = area.height / lidarOptions.pts;\n for (var xs = lidarOptions.pts - 1; xs >= 0; xs--) {\n for (var ys = 0; ys < lidarOptions.pts; ys++) {\n var x = (x_step / 4) + xs * x_step;\n var y = (y_step / 4) + ys * y_step;\n var pt = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n pt.pt = true;\n pt.beginFill(0xffffff);\n pt.drawRect(x, y, 5, 5);\n pt.endFill();\n this.lidar.addChild(pt);\n }\n }\n this.lidar.pts = lidarOptions.pts;\n this.lidar.addChild(area);\n this.lidar.x = this.core.x;\n this.lidar.y = this.core.y;\n this.lidar.pivot.y = this.lidar.height / 2;\n this.lidar.pivot.x = this.core.width / 2 - (lidarOptions.pos * this.core.width);\n this.lidar.rotation = this.core.rotation;\n };\n return Car;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/car.ts?"); + +/***/ }), + +/***/ "./src/control_motion_engine.ts": +/*!**************************************!*\ + !*** ./src/control_motion_engine.ts ***! + \**************************************/ +/*! exports provided: ControlMotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ControlMotionEngine\", function() { return ControlMotionEngine; });\n/* harmony import */ var _motion_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./motion_engine */ \"./src/motion_engine.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\n\nvar ControlMotionEngine = (function (_super) {\n __extends(ControlMotionEngine, _super);\n function ControlMotionEngine(level) {\n var _this = _super.call(this, level) || this;\n _this.level = level;\n _this.actions = [\"SteeringAngle\", \"Throttle\"];\n return _this;\n }\n ControlMotionEngine.prototype.setUp = function (car, lidar) {\n this.car = car;\n this.lidar = lidar;\n this.state = [];\n for (var y = 0; y < lidar.pts; y++) {\n var line = [];\n for (var x = 0; x < lidar.pts; x++) {\n line.push(_global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].DEFAULT);\n }\n this.state.push(line);\n }\n this.setUpKeyboard();\n this.car.v = 0;\n this.car.a = 0;\n this.car.yaw_rate = 0;\n this.detectInteractions();\n };\n ControlMotionEngine.prototype.setUpKeyboard = function () {\n var _this = this;\n var left = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](37);\n var up = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](38);\n var right = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](39);\n var down = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](40);\n left.press = function () {\n _this.turn(-0.5);\n };\n left.release = function () {\n _this.turn(0);\n };\n right.press = function () {\n _this.turn(0.5);\n };\n right.release = function () {\n _this.turn(0);\n };\n up.press = function () { _this.move(1); };\n up.release = function () {\n _this.car.a = 0;\n };\n down.press = function () { _this.move(-1); };\n down.release = function () {\n _this.car.a = 0;\n };\n };\n ControlMotionEngine.prototype.turn = function (value) {\n this.car.yaw_rate = value;\n };\n ControlMotionEngine.prototype.move = function (throttle) {\n this.car.a = throttle;\n };\n ControlMotionEngine.prototype.actionStep = function (delta, actions) {\n this.car.a = Math.min(Math.max(parseInt(actions[0].toString()), -1), 1);\n this.car.yaw_rate = Math.min(Math.max(parseInt(actions[1].toString()), -1), 1);\n var _a = this.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n this.car.a = 0;\n this.car.yaw_rate = 0;\n return { agent_col: agent_col, on_road: on_road };\n };\n ControlMotionEngine.prototype.actionSpace = function () {\n return Array.apply(null, { length: this.actions.length }).map(Number.call, Number);\n };\n ControlMotionEngine.prototype.step = function (delta) {\n if (this.car.v > 0)\n this.car.v = Math.max(0, this.car.v - 0.01);\n else if (this.car.v < 0)\n this.car.v = Math.min(0, this.car.v + 0.01);\n if (this.car.a > 0)\n this.car.v = Math.min(2., this.car.v + this.car.a * 0.02);\n else\n this.car.v = Math.max(-2., this.car.v + this.car.a * 0.02);\n if (this.car.yaw_rate == 0) {\n this.car.x += this.car.v * Math.cos(this.car.rotation) * delta;\n this.car.y += this.car.v * Math.sin(this.car.rotation) * delta;\n }\n else {\n var yr = this.car.yaw_rate * 0.01 * (this.car.v + 0.001) * Math.PI;\n this.car.x += (this.car.v / yr) * (Math.sin(this.car.rotation + (yr * delta)) - Math.sin(this.car.rotation));\n this.car.y += (this.car.v / yr) * (Math.cos(this.car.rotation) - Math.cos(this.car.rotation + (yr * delta)));\n this.car.rotation += yr * delta;\n }\n this.car.mx = Math.floor(this.car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.my = Math.floor(this.car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.checkAndsetNewRoad();\n this.lidar.x = this.car.x;\n this.lidar.y = this.car.y;\n this.lidar.rotation = this.car.rotation;\n var _a = this.detectInteractions(), agent_col = _a.agent_col, on_road = _a.on_road;\n if (agent_col.length > 0) {\n this.car.v = 0;\n this.car.vy = 0;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n return ControlMotionEngine;\n}(_motion_engine__WEBPACK_IMPORTED_MODULE_0__[\"MotionEngine\"]));\n\n\n\n//# sourceURL=webpack://metacar/./src/control_motion_engine.ts?"); + +/***/ }), + +/***/ "./src/embedded.ts": +/*!*************************!*\ + !*** ./src/embedded.ts ***! + \*************************/ +/*! exports provided: embeddedUrl, embeddedContent */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"embeddedUrl\", function() { return embeddedUrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"embeddedContent\", function() { return embeddedContent; });\n/* harmony import */ var _embedded_level_full_city__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./embedded/level/full_city */ \"./src/embedded/level/full_city.ts\");\n\nvar embeddedUrl = {\n fullCity: \"embedded://level/fullCity\"\n};\nvar embeddedContent = {\n level: {\n fullCity: _embedded_level_full_city__WEBPACK_IMPORTED_MODULE_0__[\"fullCity\"]\n }\n};\n\n\n//# sourceURL=webpack://metacar/./src/embedded.ts?"); + +/***/ }), + +/***/ "./src/embedded/level/full_city.ts": +/*!*****************************************!*\ + !*** ./src/embedded/level/full_city.ts ***! + \*****************************************/ +/*! exports provided: fullCity */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"fullCity\", function() { return fullCity; });\nvar fullCity = {\n \"cars\": [\n {\n \"mx\": 2,\n \"my\": 5,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 3,\n \"my\": 4,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 3,\n \"my\": 4,\n \"line\": 1,\n \"auto\": true\n },\n {\n \"mx\": 6,\n \"my\": 3,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 6,\n \"my\": 3,\n \"line\": 1,\n \"auto\": true\n },\n {\n \"mx\": 8,\n \"my\": 2,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 8,\n \"my\": 2,\n \"line\": 1,\n \"auto\": true\n },\n {\n \"mx\": 2,\n \"my\": 7,\n \"line\": 0,\n \"auto\": true\n }\n ],\n \"house\": [\n {\n \"x\": 9,\n \"y\": 409\n },\n {\n \"x\": 146,\n \"y\": 162\n },\n {\n \"x\": 439,\n \"y\": 39\n }\n ],\n \"house2\": [\n {\n \"x\": 425,\n \"y\": 192\n },\n {\n \"x\": 431,\n \"y\": 354\n }\n ],\n \"house3\": [\n {\n \"x\": 426,\n \"y\": 281\n },\n {\n \"x\": 51,\n \"y\": 157\n },\n {\n \"x\": 553,\n \"y\": 34\n }\n ],\n \"bench\": [\n {\n \"x\": 259,\n \"y\": 206\n },\n {\n \"x\": 8,\n \"y\": 205\n }\n ],\n \"tree\": [\n {\n \"x\": 1,\n \"y\": 303\n },\n {\n \"x\": 54,\n \"y\": 357\n },\n {\n \"x\": 215,\n \"y\": 325\n },\n {\n \"x\": 230,\n \"y\": 400\n },\n {\n \"x\": 282,\n \"y\": 368\n },\n {\n \"x\": 182,\n \"y\": 433\n },\n {\n \"x\": 285,\n \"y\": 309\n },\n {\n \"x\": 576,\n \"y\": 233\n },\n {\n \"x\": 581,\n \"y\": 300\n },\n {\n \"x\": 519,\n \"y\": 388\n },\n {\n \"x\": 582,\n \"y\": 391\n },\n {\n \"x\": 256,\n \"y\": 69\n },\n {\n \"x\": 151,\n \"y\": 43\n },\n {\n \"x\": 77,\n \"y\": 77\n },\n {\n \"x\": 26,\n \"y\": 24\n },\n {\n \"x\": 189,\n \"y\": 98\n }\n ],\n \"map\": [\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↠\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↦\",\n \"↔\",\n \"↔\",\n \"↟\",\n \"↔\"\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n \"↔\",\n \"↔\",\n \"↧\",\n \"↔\",\n \"↠\",\n \"↔\",\n \"↤\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n \"↠\",\n 0,\n 0,\n 0,\n \"↠\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ]\n ]\n};\n\n\n//# sourceURL=webpack://metacar/./src/embedded/level/full_city.ts?"); + +/***/ }), + +/***/ "./src/global.ts": +/*!***********************!*\ + !*** ./src/global.ts ***! + \***********************/ +/*! exports provided: Application, Loader, Resources, Sprite, Graphics, Container, JSON_TEXTURES, LEVEL_FOLDER, ROADSIZE, CAR_IMG, MAP, ASSETS */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Application\", function() { return Application; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Loader\", function() { return Loader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Resources\", function() { return Resources; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Sprite\", function() { return Sprite; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Graphics\", function() { return Graphics; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Container\", function() { return Container; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"JSON_TEXTURES\", function() { return JSON_TEXTURES; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"LEVEL_FOLDER\", function() { return LEVEL_FOLDER; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ROADSIZE\", function() { return ROADSIZE; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CAR_IMG\", function() { return CAR_IMG; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MAP\", function() { return MAP; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ASSETS\", function() { return ASSETS; });\n/* harmony import */ var pixi_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! pixi.js */ \"pixi.js\");\n/* harmony import */ var pixi_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(pixi_js__WEBPACK_IMPORTED_MODULE_0__);\n\nvar Application = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Application\"];\nvar Loader = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"loader\"];\nvar Resources = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"loader\"].resources;\nvar Sprite = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"];\nvar Graphics = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"];\nvar Container = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Container\"];\nvar JSON_TEXTURES = \"public/textures/textures.json\";\nvar LEVEL_FOLDER = \"/level/\";\nvar ROADSIZE = 60;\nvar CAR_IMG = {\n DEFAULT: \"car.png\",\n AGENT: \"car_agent.png\"\n};\nvar MAP = {\n ROAD: -1,\n DEFAULT: 0,\n CAR: 1,\n AGENT: 1,\n};\nvar ASSETS = {\n ROADS: {\n \"↕\": {\n \"image\": \"road_u.png\",\n \"orientation\": 1.5\n },\n \"↔\": {\n \"image\": \"road_r.png\",\n \"orientation\": 0.\n },\n \"↱\": {\n \"image\": \"road_rotate_ld.png\",\n \"orientation\": 1.25\n },\n \"↰\": {\n \"image\": \"road_rotate_ul.png\",\n \"orientation\": 0.75\n },\n \"↲\": {\n \"image\": \"road_rotate_rl.png\",\n \"orientation\": 0.25\n },\n \"↳\": {\n \"image\": \"road_rotate_dl.png\",\n \"orientation\": 1.75\n },\n \"↟\": {\n \"image\": \"road_up.png\",\n \"orientation\": 1.5\n },\n \"↠\": {\n \"image\": \"road_rp.png\",\n \"orientation\": 0.\n },\n \"↤\": {\n \"image\": \"road_r2.png\",\n \"orientation\": 0.\n },\n \"↦\": {\n \"image\": \"road_l2.png\",\n \"orientation\": 1.\n },\n \"↥\": {\n \"image\": \"road_d2.png\",\n \"orientation\": 0.5\n },\n \"↧\": {\n \"image\": \"road_u2.png\",\n \"orientation\": 1.5\n },\n },\n \"house\": {\n \"image\": \"house.png\"\n },\n \"house2\": {\n \"image\": \"house2.png\"\n },\n \"house3\": {\n \"image\": \"house3.png\"\n },\n \"bench\": {\n \"image\": \"bench.png\"\n },\n \"tree\": {\n \"image\": \"tree.png\"\n }\n};\n\n\n//# sourceURL=webpack://metacar/./src/global.ts?"); + +/***/ }), + +/***/ "./src/index.ts": +/*!**********************!*\ + !*** ./src/index.ts ***! + \**********************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _metacar__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./metacar */ \"./src/metacar.ts\");\n/* harmony import */ var _embedded__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./embedded */ \"./src/embedded.ts\");\n\n\nvar metacar = {\n env: _metacar__WEBPACK_IMPORTED_MODULE_0__[\"MetaCar\"],\n level: _embedded__WEBPACK_IMPORTED_MODULE_1__[\"embeddedUrl\"]\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (metacar);\n\n\n//# sourceURL=webpack://metacar/./src/index.ts?"); + +/***/ }), + +/***/ "./src/level.ts": +/*!**********************!*\ + !*** ./src/level.ts ***! + \**********************/ +/*! exports provided: Level */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Level\", function() { return Level; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _asset_manager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./asset_manager */ \"./src/asset_manager.ts\");\n\n\nvar Level = (function () {\n function Level(levelContent, canvasId) {\n this.app = null;\n this.info = null;\n this.envs = [];\n this.map = null;\n this.agent = null;\n this.roads = {};\n this.cars = [];\n this.info = levelContent;\n this.map = this.info.map;\n this.canvasId = canvasId;\n this.am = new _asset_manager__WEBPACK_IMPORTED_MODULE_1__[\"AssetManger\"](this);\n }\n Level.prototype.load = function (loop) {\n var _this = this;\n this.loop = loop;\n return new Promise(function (resolve, reject) {\n _this.createLevel(_this.info).then(function () { return resolve(); });\n });\n };\n Level.prototype.createLevel = function (info) {\n var _this = this;\n this.app = new PIXI.Application({\n width: this.map[0].length * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"],\n height: this.map.length * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"],\n backgroundColor: 0x80bf3e\n });\n document.getElementById(this.canvasId).appendChild(this.app.view);\n return new Promise(function (resolve, reject) {\n _global__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].add([\"public/textures/textures.json\", \"public/textures/textures.png\"]).load(function () {\n _this.setup(info);\n resolve();\n });\n });\n };\n Level.prototype.setup = function (info) {\n var _this = this;\n var textures = _global__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].resources[_global__WEBPACK_IMPORTED_MODULE_0__[\"JSON_TEXTURES\"]].textures;\n this.am.createMap(this.map, info, textures);\n this.am.createCars(this.map, info, textures);\n if (info.agent)\n this.agent = this.am.createAgent(this.map, info, textures);\n this.app.ticker.add(function (delta) { return _this.loop(delta); });\n };\n Level.prototype.render = function () {\n this.app.ticker.start();\n };\n Level.prototype.reset = function () {\n this.agent.reset();\n };\n Level.prototype.setReward = function (agent_col, on_road, action) {\n var reward = -0.1;\n if (action == 0 || this.agent.core.vx == 1)\n reward += 0.5;\n if (agent_col.length > 0) {\n reward = -10;\n }\n else if (!on_road) {\n reward = -10;\n }\n return reward;\n };\n Level.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n for (var c = 0; c < this.cars.length; c++) {\n if (this.cars[c].lidar && !this.cars[c].core.agent)\n this.cars[c].step(delta);\n }\n if (this.agent) {\n var _a = this.agent.step(delta, action), agent_col = _a.agent_col, on_road = _a.on_road;\n var reward = this.setReward(agent_col, on_road, action);\n return reward;\n }\n return 0;\n };\n Level.prototype.stopRender = function () {\n this.app.ticker.stop();\n };\n Level.prototype.addChild = function (child) {\n this.app.stage.addChild(child);\n };\n Level.prototype.addRoad = function (road) {\n this.roads[[road.my.toString(), road.mx.toString()].toString()] = road;\n this.envs.push(road);\n this.app.stage.addChild(road);\n };\n Level.prototype.addCar = function (car) {\n this.cars.push(car);\n this.app.stage.addChild(car.core);\n this.envs.push(car.core);\n };\n Level.prototype.getRoad = function (my, mx) {\n return this.roads[[my.toString(), mx.toString()].toString()];\n };\n Level.prototype.getRoads = function () {\n return this.roads;\n };\n Level.prototype.findCarById = function (id) {\n return this.cars.find(function (e) { return e.car_id == id; });\n };\n Level.prototype.getEnvs = function () {\n return this.envs;\n };\n Level.prototype.getMap = function () {\n return this.map;\n };\n return Level;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/level.ts?"); + +/***/ }), + +/***/ "./src/metacar.ts": +/*!************************!*\ + !*** ./src/metacar.ts ***! + \************************/ +/*! exports provided: MetaCar */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MetaCar\", function() { return MetaCar; });\n/* harmony import */ var _level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./level */ \"./src/level.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n\n\nvar MetaCar = (function () {\n function MetaCar(canvasId, levelUrl) {\n if (!canvasId || this.levelUrl) {\n console.error(\"You must specify the canvasId and the levelUrl\");\n }\n this.isPlaying = false;\n this.canvasId = canvasId;\n this.levelUrl = levelUrl;\n }\n MetaCar.prototype.load = function (level, agent) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n _utils__WEBPACK_IMPORTED_MODULE_1__[\"loadCustomURL\"](_this.levelUrl, function (content) {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](content, _this.canvasId);\n _this.level.load(function (delta) { return _this.loop(delta); });\n resolve();\n });\n });\n };\n MetaCar.prototype.render = function () {\n this.level.render();\n };\n MetaCar.prototype.save = function (content, file_name) {\n _utils__WEBPACK_IMPORTED_MODULE_1__[\"saveAs\"](content, file_name);\n };\n MetaCar.prototype.actionSpace = function () {\n return this.level.agent.motion.actionSpace();\n };\n MetaCar.prototype.getState = function () {\n return this.level.agent.getState();\n };\n MetaCar.prototype.step = function (action) {\n return this.level.step(1, action);\n };\n MetaCar.prototype.reset = function () {\n this.level.reset();\n };\n MetaCar.prototype.randomRoadPosition = function () {\n this.level.agent.last_position = [];\n var roads = this.level.getRoads();\n var keys = Object.keys(roads);\n keys.sort(function () { return Math.random() - 0.5; });\n for (var k in keys) {\n var road = roads[keys[k]];\n if (road.cars.length == 0) {\n road.setCarPosition(this.level.agent.core);\n break;\n }\n }\n };\n MetaCar.prototype.loop = function (delta) {\n if (this.isPlaying) {\n this.agent.play(this);\n }\n else {\n this.level.step(delta);\n }\n };\n return MetaCar;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/metacar.ts?"); + +/***/ }), + +/***/ "./src/motion_engine.ts": +/*!******************************!*\ + !*** ./src/motion_engine.ts ***! + \******************************/ +/*! exports provided: MotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MotionEngine\", function() { return MotionEngine; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar MotionEngine = (function () {\n function MotionEngine(level) {\n this.level = level;\n }\n MotionEngine.prototype.boxesIntersect = function (a, b) {\n var ab = a.getBounds();\n var bb = b.getBounds();\n return ab.x + ab.width > bb.x && ab.x < bb.x + bb.width && ab.y + ab.height > bb.y && ab.y < bb.y + bb.height;\n };\n MotionEngine.prototype.detectInteractions = function () {\n var envs = this.level.getEnvs();\n var agent_col = [];\n var lidar_collisions = [];\n var on_road = false;\n for (var i = 0; i < envs.length; i++) {\n if (envs[i] != this.car && envs[i].obstacle && this.boxesIntersect(envs[i], this.car)) {\n agent_col.push(envs[i]);\n }\n else if (envs[i].mapId == _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].ROAD && this.boxesIntersect(envs[i], this.car)) {\n on_road = true;\n }\n if (this.boxesIntersect(envs[i], this.lidar)) {\n lidar_collisions.push(envs[i]);\n }\n }\n this.setState(lidar_collisions);\n return { agent_col: agent_col, on_road: on_road };\n };\n MotionEngine.prototype.setState = function (lidar_collisions) {\n var pt_id = 0;\n for (var i = 0; i < this.lidar.children.length; i++) {\n this.lidar.children[i].alpha = 0.1;\n if (this.lidar.children[i].pt) {\n var pt_y = Math.floor(pt_id / this.lidar.pts);\n var pt_x = Math.floor(pt_id % this.lidar.pts);\n this.state[pt_y][pt_x] = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].DEFAULT;\n for (var a = 0; a < lidar_collisions.length; a++) {\n if (lidar_collisions[a] != this.car) {\n var touch = this.boxesIntersect(lidar_collisions[a], this.lidar.children[i]);\n if (touch && lidar_collisions[a].obstacle) {\n this.lidar.children[i].alpha = 1.;\n }\n if (touch && (lidar_collisions[a].mapId > this.state[pt_y][pt_x] || (lidar_collisions[a].mapId == _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].ROAD && this.state[pt_y][pt_x] == _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].DEFAULT))) {\n this.state[pt_y][pt_x] = lidar_collisions[a].mapId;\n }\n }\n }\n pt_id += 1;\n }\n }\n };\n return MotionEngine;\n}());\n\n;\n\n\n//# sourceURL=webpack://metacar/./src/motion_engine.ts?"); + +/***/ }), + +/***/ "./src/utils.ts": +/*!**********************!*\ + !*** ./src/utils.ts ***! + \**********************/ +/*! exports provided: loadJSON, loadEmbeddedURL, loadLocalStorageURL, loadCustomURL, mod, argMax, mean, saveAs, shuffleArray, keyboard */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadJSON\", function() { return loadJSON; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadEmbeddedURL\", function() { return loadEmbeddedURL; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadLocalStorageURL\", function() { return loadLocalStorageURL; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadCustomURL\", function() { return loadCustomURL; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mod\", function() { return mod; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"argMax\", function() { return argMax; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mean\", function() { return mean; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"saveAs\", function() { return saveAs; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"shuffleArray\", function() { return shuffleArray; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"keyboard\", function() { return keyboard; });\n/* harmony import */ var _embedded__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./embedded */ \"./src/embedded.ts\");\n\nfunction loadJSON(url, callback) {\n var xobj = new XMLHttpRequest();\n xobj.overrideMimeType(\"application/json\");\n xobj.open('GET', url, true);\n xobj.onreadystatechange = function () {\n if (xobj.readyState == 4 && xobj.status == 200) {\n callback(xobj.responseText);\n }\n };\n xobj.send(null);\n}\nfunction loadEmbeddedURL(url, callback) {\n var split = url.split(\"//\");\n split = split[1].split(\"/\");\n callback(_embedded__WEBPACK_IMPORTED_MODULE_0__[\"embeddedContent\"][split[0]][split[1]]);\n}\nfunction loadLocalStorageURL(url, callback) {\n}\nfunction loadCustomURL(url, callback) {\n var customCall = {\n \"embedded:\": loadEmbeddedURL,\n \"http://\": loadJSON,\n \"https://\": loadJSON,\n \"localstorage://\": loadLocalStorageURL\n };\n var split = url.split(\"//\");\n customCall[split[0]](url, callback);\n}\nfunction mod(n, m) {\n return ((n % m) + m) % m;\n}\nfunction argMax(array) {\n if (array.every(function (v) { return v == -Infinity; })) {\n return Math.floor(Math.random() * array.length);\n }\n return array.map(function (x, i) { return [x, i]; }).reduce(function (r, a) { return (a[0] > r[0] ? a : r); })[1];\n}\nfunction mean(array) {\n if (array.length == 0)\n return null;\n var sum = array.reduce(function (a, b) { return a + b; });\n var avg = sum / array.length;\n return avg;\n}\nfunction saveAs(content, name) {\n var a = document.createElement(\"a\");\n document.body.appendChild(a);\n var blob = new Blob([content], { type: 'application/octet-binary' }), tmpURL = window.URL.createObjectURL(blob);\n a.href = tmpURL;\n a.download = name;\n a.click();\n window.URL.revokeObjectURL(tmpURL);\n a.href = \"\";\n}\nfunction shuffleArray(array) {\n for (var i = array.length - 1; i > 0; i--) {\n var j = Math.floor(Math.random() * (i + 1));\n var temp = array[i];\n array[i] = array[j];\n array[j] = temp;\n }\n return array;\n}\nfunction keyboard(keyCode) {\n var key = {};\n key.code = keyCode;\n key.isDown = false;\n key.isUp = true;\n key.press = undefined;\n key.release = undefined;\n key.downHandler = function (event) {\n if (event.keyCode === key.code) {\n if (key.isUp && key.press)\n key.press();\n key.isDown = true;\n key.isUp = false;\n }\n event.preventDefault();\n };\n key.upHandler = function (event) {\n if (event.keyCode === key.code) {\n if (key.isDown && key.release)\n key.release();\n key.isDown = false;\n key.isUp = true;\n }\n event.preventDefault();\n };\n window.addEventListener(\"keydown\", key.downHandler.bind(key), false);\n window.addEventListener(\"keyup\", key.upHandler.bind(key), false);\n return key;\n}\n\n\n//# sourceURL=webpack://metacar/./src/utils.ts?"); + +/***/ }), + +/***/ "pixi.js": +/*!***********************!*\ + !*** external "PIXI" ***! + \***********************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("(function() { module.exports = window[\"PIXI\"]; }());\n\n//# sourceURL=webpack://metacar/external_%22PIXI%22?"); + +/***/ }) + +/******/ })["default"]; \ No newline at end of file diff --git a/demo/package.json b/demo/package.json index f8eec2a..94c086d 100644 --- a/demo/package.json +++ b/demo/package.json @@ -9,6 +9,7 @@ "author": "Thibault Neveu", "license": "ISC", "dependencies": { - "express": "^4.16.3" + "express": "^4.16.3", + "pixi.js": "^4.8.1" } } diff --git a/demo/webapp/index.html b/demo/webapp/index.html index ef6037b..df876a0 100644 --- a/demo/webapp/index.html +++ b/demo/webapp/index.html @@ -5,6 +5,26 @@ Hello World + +
+ +
+ + + + + + + +
+
+ +
+ + + + + diff --git a/demo/webapp/public/js/full_city.js b/demo/webapp/public/js/full_city.js new file mode 100644 index 0000000..3eae13e --- /dev/null +++ b/demo/webapp/public/js/full_city.js @@ -0,0 +1,8 @@ +// Get the url of the desired level +let levelUrl = metacar.level.fullCity; +// Create the environement (canvasID, levelUrl) +var env = new metacar.env("canvas", levelUrl); +env.load().then(() => { + // The level is loaded + +}); \ No newline at end of file diff --git a/demo/webapp/public/textures/textures.json b/demo/webapp/public/textures/textures.json new file mode 100644 index 0000000..965c7c8 --- /dev/null +++ b/demo/webapp/public/textures/textures.json @@ -0,0 +1,183 @@ +{"frames": { + +"bench.png": +{ + "frame": {"x":0,"y":0,"w":31,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":31,"h":16}, + "sourceSize": {"w":31,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +"car.png": +{ + "frame": {"x":31,"y":0,"w":42,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":24}, + "sourceSize": {"w":42,"h":24}, + "pivot": {"x":0.5,"y":0.5} +}, +"car_agent.png": +{ + "frame": {"x":73,"y":0,"w":42,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":42,"h":24}, + "sourceSize": {"w":42,"h":24}, + "pivot": {"x":0.5,"y":0.5} +}, +"house.png": +{ + "frame": {"x":0,"y":469,"w":88,"h":62}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":88,"h":62}, + "sourceSize": {"w":88,"h":62}, + "pivot": {"x":0.5,"y":0.5} +}, +"house2.png": +{ + "frame": {"x":0,"y":264,"w":60,"h":85}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":85}, + "sourceSize": {"w":60,"h":85}, + "pivot": {"x":0.5,"y":0.5} +}, +"house3.png": +{ + "frame": {"x":0,"y":531,"w":89,"h":67}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":89,"h":67}, + "sourceSize": {"w":89,"h":67}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_d2.png": +{ + "frame": {"x":0,"y":349,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_l2.png": +{ + "frame": {"x":60,"y":264,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_r.png": +{ + "frame": {"x":0,"y":409,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_r2.png": +{ + "frame": {"x":60,"y":409,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_rotate_dl.png": +{ + "frame": {"x":60,"y":349,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_rotate_ld.png": +{ + "frame": {"x":60,"y":204,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_rotate_rl.png": +{ + "frame": {"x":0,"y":84,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_rotate_ul.png": +{ + "frame": {"x":48,"y":24,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_rp.png": +{ + "frame": {"x":60,"y":84,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_u.png": +{ + "frame": {"x":0,"y":204,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_u2.png": +{ + "frame": {"x":0,"y":144,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"road_up.png": +{ + "frame": {"x":60,"y":144,"w":60,"h":60}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":60}, + "sourceSize": {"w":60,"h":60}, + "pivot": {"x":0.5,"y":0.5} +}, +"tree.png": +{ + "frame": {"x":0,"y":24,"w":48,"h":46}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":46}, + "sourceSize": {"w":48,"h":46}, + "pivot": {"x":0.5,"y":0.5} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "textures.png", + "format": "RGBA8888", + "size": {"w":120,"h":598}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:8bfcaef7ab9440b3c4c801d035ca0e1a:71d4ef3f85e164cd8a50ee71cd767fd7:cf827d152df04949dfee256cd0c8efd8$" +} +} diff --git a/demo/webapp/public/textures/textures.png b/demo/webapp/public/textures/textures.png new file mode 100644 index 0000000000000000000000000000000000000000..aa715b13b438d91e2eb6be8b4a820c107d434cf3 GIT binary patch literal 25109 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 IM6N<$g4j2;MgRZ+ literal 0 HcmV?d00001 diff --git a/dist/metacar.min.js b/dist/metacar.min.js new file mode 100644 index 0000000..c8a11f2 --- /dev/null +++ b/dist/metacar.min.js @@ -0,0 +1,257 @@ +window["metacar"] = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/index.ts"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./src/asset_manager.ts": +/*!******************************!*\ + !*** ./src/asset_manager.ts ***! + \******************************/ +/*! exports provided: AssetManger */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AssetManger\", function() { return AssetManger; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _car__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./car */ \"./src/car.ts\");\n/* harmony import */ var _basic_motion_engine__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./basic_motion_engine */ \"./src/basic_motion_engine.ts\");\n/* harmony import */ var _control_motion_engine__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./control_motion_engine */ \"./src/control_motion_engine.ts\");\n/* harmony import */ var _bot_motion_engine__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./bot_motion_engine */ \"./src/bot_motion_engine.ts\");\n\n\n\n\n\n\n;\nvar AssetManger = (function () {\n function AssetManger(level) {\n this.assets = [];\n this.level = level;\n this.motion = {\n \"BasicMotionEngine\": _basic_motion_engine__WEBPACK_IMPORTED_MODULE_3__[\"BasicMotionEngine\"],\n \"ControlMotionEngine\": _control_motion_engine__WEBPACK_IMPORTED_MODULE_4__[\"ControlMotionEngine\"]\n };\n }\n AssetManger.prototype.createRoadSide = function (info, textures) {\n var x = (info.mx) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n var y = (info.my) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n var area = new _global__WEBPACK_IMPORTED_MODULE_1__[\"Graphics\"]();\n area.beginFill(0xe8e8e8);\n area.drawRoundedRect(0, 0, _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] + 30, _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] + 30, undefined);\n area.x = x - 15;\n area.y = y - 15;\n area.endFill();\n this.level.addChild(area);\n };\n AssetManger.prototype.createRoad = function (info, textures) {\n var _this = this;\n var road = new _global__WEBPACK_IMPORTED_MODULE_1__[\"Sprite\"](textures[_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[info.type].image]);\n road.x = (info.mx) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n road.y = (info.my) * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n road.obstacle = false;\n road.mapId = _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].ROAD;\n road.orientation = _global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[info.type].orientation;\n road.setCarPosition = function (car, line) { return _this.setCarOnRoad(road, car, line); };\n road.cars = [];\n road.mx = info.mx;\n road.my = info.my;\n this.level.addRoad(road);\n };\n AssetManger.prototype.setCarOnRoad = function (road, car, line) {\n if (line == undefined)\n line = 0;\n var carById = this.level.findCarById(road.cars[0]);\n if (road.cars.length >= 1 && carById && carById.core.line == line) {\n line = line == 0 ? 1 : 0;\n }\n if (road.cars.length >= 2) {\n car.is_valid = false;\n return;\n }\n car.line = line;\n car.x = road.x;\n car.y = road.y;\n car.x += _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2;\n car.y += _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2;\n var x_margin = 0;\n var y_margin = (_global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] * 1 / 4);\n road.orientation = (Math.floor(road.orientation / car.rotationStep) * car.rotationStep);\n var th = -road.orientation * (Math.PI);\n var x_m = (Math.cos(th) * x_margin) - (y_margin * Math.sin(th));\n var y_m = (Math.cos(th) * y_margin) + (x_margin * Math.sin(th));\n var line_side_factor = line == 0 ? 1 : -1;\n var line_side_factor_t = line == 0 ? 0 : Math.PI;\n car.x += line_side_factor * Math.round(x_m);\n car.y += line_side_factor * Math.round(y_m);\n car.mx = Math.floor(car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n car.my = Math.floor(car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n car.rotation = (th + line_side_factor_t);\n car.checkAndsetNewRoad(road);\n };\n AssetManger.prototype.createAsset = function (img, info, textures, type) {\n var asset = new _global__WEBPACK_IMPORTED_MODULE_1__[\"Sprite\"](textures[img]);\n asset.obstacle = false;\n asset.type = type;\n asset.mapId = 0;\n asset.x = info.x;\n asset.y = info.y;\n this.level.addChild(asset);\n this.assets.push(asset);\n };\n AssetManger.prototype.createMap = function (map, info, textures, roadside) {\n if (roadside === void 0) { roadside = true; }\n if (roadside) {\n for (var my = 0; my < map.length; my++) {\n for (var mx = 0; mx < map[my].length; mx++) {\n if (_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[map[my][mx]]) {\n this.createRoadSide({ mx: mx, my: my, type: map[my][mx] }, textures);\n }\n }\n }\n }\n for (var my = 0; my < map.length; my++) {\n for (var mx = 0; mx < map[my].length; mx++) {\n if (_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"].ROADS[map[my][mx]]) {\n this.createRoad({ mx: mx, my: my, type: map[my][mx] }, textures);\n }\n }\n }\n for (var key in _global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"]) {\n if (key != \"ROADS\" && info[key]) {\n for (var a = 0; a < info[key].length; a++) {\n this.createAsset(_global__WEBPACK_IMPORTED_MODULE_1__[\"ASSETS\"][key].image, info[key][a], textures, key);\n }\n }\n }\n };\n AssetManger.prototype.createCars = function (map, info, textures) {\n for (var c in info.cars) {\n var options = { lidar: true, lidarInfo: { pts: 2, width: 0.5, height: 1, pos: 1 } };\n if (info.cars[c].auto) {\n options.lidar = true;\n options.motionEngine = new _bot_motion_engine__WEBPACK_IMPORTED_MODULE_5__[\"BotMotionEngine\"](this.level);\n }\n var n_car = new _car__WEBPACK_IMPORTED_MODULE_2__[\"Car\"](this.level, info.cars[c], textures, options);\n this.level.addCar(n_car);\n }\n };\n AssetManger.prototype.createAgent = function (map, info, textures) {\n var agent = new _car__WEBPACK_IMPORTED_MODULE_2__[\"Car\"](this.level, info.agent, textures, {\n image: _global__WEBPACK_IMPORTED_MODULE_1__[\"CAR_IMG\"].AGENT,\n lidar: true,\n motionEngine: new this.motion[info.agent.motion.type](this.level, info.agent.motion.options)\n });\n this.level.addChild(agent.lidar);\n this.level.addCar(agent);\n agent.core.agent = true;\n return agent;\n };\n AssetManger.prototype.addAsset = function (asset) {\n this.assets.push(asset);\n };\n AssetManger.prototype.exportMap = function (width, height, file_name) {\n var file = { \"cars\": [] };\n var map = [];\n var envs = this.level.getEnvs();\n for (var y = 0; y < height; y++) {\n var line = [];\n for (var x = 0; x < width; x++) {\n line.push(0);\n }\n map.push(line);\n }\n for (var e = 0; e < envs.length; e++) {\n var elem = envs[e];\n if (!elem.isremove) {\n if (elem.mapId == _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].CAR && !elem.agent && elem.is_valid) {\n file.cars.push({\n \"mx\": elem.mx,\n \"my\": elem.my,\n \"line\": elem.line\n });\n }\n else if (elem.mapId == _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].ROAD) {\n map[elem.my][elem.mx] = elem.arrow;\n }\n }\n }\n for (var e = 0; e < this.assets.length; e++) {\n var elem = this.assets[e];\n if (!elem.isremove) {\n if (elem.type != \"car\") {\n if (!file[elem.type])\n file[elem.type] = [];\n file[elem.type].push({\n \"x\": elem.x,\n \"y\": elem.y\n });\n }\n }\n }\n file.map = map;\n if (this.level.agent) {\n file.agent = {\n \"mx\": this.level.agent.core.mx,\n \"my\": this.level.agent.core.my,\n \"line\": this.level.agent.core.line,\n \"motion\": {\n \"type\": \"BasicMotionEngine\",\n \"options\": {\n \"rotationStep\": 0.5,\n \"actions\": [\"UP\", \"LEFT\", \"RIGHT\", \"DOWN\", \"WAIT\"]\n }\n }\n };\n }\n console.log(file);\n file = JSON.stringify(file, null, 4);\n _utils__WEBPACK_IMPORTED_MODULE_0__[\"saveAs\"](file, file_name);\n };\n return AssetManger;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/asset_manager.ts?"); + +/***/ }), + +/***/ "./src/basic_motion_engine.ts": +/*!************************************!*\ + !*** ./src/basic_motion_engine.ts ***! + \************************************/ +/*! exports provided: BasicMotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BasicMotionEngine\", function() { return BasicMotionEngine; });\n/* harmony import */ var _motion_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./motion_engine */ \"./src/motion_engine.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\n\nvar BasicMotionEngine = (function (_super) {\n __extends(BasicMotionEngine, _super);\n function BasicMotionEngine(level, options) {\n var _this = _super.call(this, level) || this;\n _this.rotationStep = options.rotationStep;\n _this.actions = options.actions;\n return _this;\n }\n BasicMotionEngine.prototype.setUp = function (car, lidar) {\n this.car = car;\n this.lidar = lidar;\n this.state = [];\n for (var y = 0; y < lidar.pts; y++) {\n var line = [];\n for (var x = 0; x < lidar.pts; x++) {\n line.push(_global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].DEFAULT);\n }\n this.state.push(line);\n }\n this.setUpKeyboard();\n this.car.v = 0;\n this.detectInteractions();\n };\n BasicMotionEngine.prototype.setUpKeyboard = function () {\n var _this = this;\n var left = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](37);\n var up = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](38);\n var right = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](39);\n var down = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](40);\n if (this.actions.indexOf(\"LEFT\") != -1)\n left.press = function () { _this.turnLeft(); };\n if (this.actions.indexOf(\"RIGHT\") != -1)\n right.press = function () { _this.turnRight(); };\n if (this.actions.indexOf(\"UP\") != -1) {\n up.press = function () { _this.moveForward(); };\n up.release = function () {\n _this.car.v = 0;\n };\n }\n if (this.actions.indexOf(\"DOWN\") != -1) {\n down.press = function () { _this.moveBackward(); };\n down.release = function () {\n _this.car.v = 0;\n };\n }\n };\n BasicMotionEngine.prototype.turnLeft = function () {\n this.car.rotation -= this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BasicMotionEngine.prototype.turnRight = function () {\n this.car.rotation += this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BasicMotionEngine.prototype.moveForward = function () {\n this.car.v = 1;\n };\n BasicMotionEngine.prototype.moveBackward = function () {\n this.car.v = -1;\n };\n BasicMotionEngine.prototype.actionStep = function (delta, action) {\n if (this.actions[action] == \"LEFT\") {\n this.turnLeft();\n }\n if (this.actions[action] == \"RIGHT\") {\n this.turnRight();\n }\n if (this.actions[action] == \"UP\") {\n this.moveForward();\n }\n if (this.actions[action] == \"DOWN\") {\n this.moveBackward();\n }\n var _a = this.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n this.car.v = 0;\n return { agent_col: agent_col, on_road: on_road };\n };\n BasicMotionEngine.prototype.actionSpace = function () {\n return Array.apply(null, { length: this.actions.length }).map(Number.call, Number);\n };\n BasicMotionEngine.prototype.step = function (delta) {\n this.car.x += this.car.v * Math.cos(this.car.rotation) * delta;\n this.car.y += this.car.v * Math.sin(this.car.rotation) * delta;\n this.car.mx = Math.floor(this.car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.my = Math.floor(this.car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.checkAndsetNewRoad();\n this.lidar.x = this.car.x;\n this.lidar.y = this.car.y;\n this.lidar.rotation = this.car.rotation;\n var _a = this.detectInteractions(), agent_col = _a.agent_col, on_road = _a.on_road;\n if (agent_col.length > 0) {\n this.car.v = 0;\n this.car.vy = 0;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n return BasicMotionEngine;\n}(_motion_engine__WEBPACK_IMPORTED_MODULE_0__[\"MotionEngine\"]));\n\n\n\n//# sourceURL=webpack://metacar/./src/basic_motion_engine.ts?"); + +/***/ }), + +/***/ "./src/bot_motion_engine.ts": +/*!**********************************!*\ + !*** ./src/bot_motion_engine.ts ***! + \**********************************/ +/*! exports provided: BotMotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BotMotionEngine\", function() { return BotMotionEngine; });\n/* harmony import */ var _motion_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./motion_engine */ \"./src/motion_engine.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\nvar BotMotionEngine = (function (_super) {\n __extends(BotMotionEngine, _super);\n function BotMotionEngine(level) {\n var _this = _super.call(this, level) || this;\n _this.map = _this.level.getMap();\n _this.mapSizeY = _this.map.length;\n _this.mapSizeX = _this.map[0].length;\n _this.rotationStep = 0.5;\n _this.rotationToNextCase = {};\n _this.rotationToNextCase[0] = { \"mx\": 1, \"my\": 0 };\n _this.rotationToNextCase[0.5] = { \"mx\": 0, \"my\": 1 };\n _this.rotationToNextCase[1.0] = { \"mx\": -1, \"my\": 0 };\n _this.rotationToNextCase[1.5] = { \"mx\": 0, \"my\": -1 };\n _this.rotationToNextCase[-0.5] = { \"mx\": 0, \"my\": -1 };\n _this.rotationToNextCase[-1.0] = { \"mx\": -1, \"my\": 0 };\n _this.rotationToNextCase[-1.5] = { \"mx\": 0, \"my\": 1 };\n return _this;\n }\n BotMotionEngine.prototype.setUp = function (car, lidar) {\n this.car = car;\n this.lidar = lidar;\n this.state = [];\n for (var y = 0; y < lidar.pts; y++) {\n var line = [];\n for (var x = 0; x < lidar.pts; x++) {\n line.push(_global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].DEFAULT);\n }\n this.state.push(line);\n }\n this.car.v = 0;\n this.detectInteractions();\n };\n BotMotionEngine.prototype.turnLeft = function () {\n this.car.rotation -= this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BotMotionEngine.prototype.turnRight = function () {\n this.car.rotation += this.rotationStep * Math.PI;\n this.lidar.rotation = this.car.rotation;\n };\n BotMotionEngine.prototype.moveUp = function () {\n this.car.v = 1;\n };\n BotMotionEngine.prototype.moveDown = function () {\n this.car.v = -1;\n };\n BotMotionEngine.prototype.isRoad = function (nx, ny) {\n if (ny < 0 || ny >= this.mapSizeY || nx < 0 || nx >= this.mapSizeX || this.map[ny][nx] == 0) {\n return false;\n }\n return true;\n };\n BotMotionEngine.prototype.autoRotation = function () {\n var right_dist = _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] + (_global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 3);\n var left_dist = _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] - (_global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 3.5);\n var same_dist = _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"];\n if (this.car.next_road) {\n var y_dist = Math.abs(((this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) - this.car.y) * this.car.next_road.outroad_np.my);\n var x_dist = Math.abs(((this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) - this.car.x) * this.car.next_road.outroad_np.mx);\n if (this.car.next_road.rotation_type == 0) {\n if (y_dist < right_dist && x_dist < right_dist) {\n this.car.haveTurned = true;\n this.car.rotation = this.car.rotation += Math.PI / 2;\n this.car.rotation = this.car.rotation % (2 * Math.PI);\n this.car.next_road = undefined;\n return;\n }\n }\n if (this.car.next_road.rotation_type == 1) {\n if (y_dist < left_dist && x_dist < left_dist) {\n this.car.haveTurned = true;\n this.car.rotation = this.car.rotation -= Math.PI / 2;\n this.car.rotation = this.car.rotation % (2 * Math.PI);\n this.car.next_road = undefined;\n return;\n }\n }\n if (this.car.next_road.rotation_type == 2) {\n if (y_dist < same_dist && x_dist < same_dist) {\n this.car.haveTurned = true;\n this.car.rotation = this.car.rotation -= Math.PI;\n this.car.rotation = this.car.rotation % (2 * Math.PI);\n if (y_dist != 0 && this.car.x < this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.x = this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.y = this.car.next_road.outroad.y;\n }\n else if (y_dist != 0 && this.car.x > this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.x = this.car.next_road.outroad.x + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.y = this.car.next_road.outroad.y;\n }\n else if (x_dist != 0 && this.car.y < this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.y = this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.x = this.car.next_road.outroad.x;\n }\n else if (x_dist != 0 && this.car.y > this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2) {\n this.car.y = this.car.next_road.outroad.y + _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 2 - _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] / 4;\n this.car.x = this.car.next_road.outroad.x;\n }\n this.car.next_road = undefined;\n return;\n }\n }\n }\n else {\n var key = this.car.rotation / Math.PI;\n var key_r = ((this.car.rotation / Math.PI) + 0.5) % 2;\n var key_l = ((this.car.rotation / Math.PI) - 0.5) % 2;\n var is_next_pos = this.rotationToNextCase[key];\n var is_next_pos_r = this.rotationToNextCase[key_r];\n var is_next_pos_l = this.rotationToNextCase[key_l];\n var turn = false;\n var nx = this.car.mx + is_next_pos.mx;\n var ny = this.car.my + is_next_pos.my;\n if (!this.isRoad(nx, ny)) {\n turn = true;\n }\n else if (!this.car.haveTurned && !this.car.turnedRandom) {\n this.car.turnedRandom = Math.random();\n }\n else if (!this.car.haveTurned && this.car.turnedRandom < 0.33 && this.isRoad(this.car.mx + is_next_pos_r.mx, this.car.my + is_next_pos_r.my)) {\n turn = true;\n }\n else if (!this.car.haveTurned && this.car.turnedRandom > 0.66 && this.isRoad(this.car.mx + is_next_pos_l.mx, this.car.my + is_next_pos_l.my)) {\n turn = true;\n }\n if (turn) {\n var possibles_rotations = [(key + 0.5) % 2., (key - 0.5) % 2., null];\n for (var p = 0; p < possibles_rotations.length; p++) {\n var next_pos = void 0;\n if (possibles_rotations[p] != null) {\n next_pos = this.rotationToNextCase[possibles_rotations[p]];\n }\n else {\n next_pos = { \"mx\": 0, \"my\": 0 };\n }\n var px = this.car.mx + next_pos.mx;\n var py = this.car.my + next_pos.my;\n if (this.isRoad(px, py)) {\n this.car.next_road = {\n \"outroad\": { y: ny * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"], x: nx * _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"] },\n \"outroad_np\": is_next_pos,\n \"rotation_type\": p,\n };\n return;\n }\n }\n }\n }\n };\n BotMotionEngine.prototype.step = function (delta) {\n if (this.state.toString().indexOf(\",\" + _global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].CAR.toString()) != -1) {\n this.car.v = 0;\n }\n else {\n this.car.v = 0.8;\n this.autoRotation();\n }\n this.car.x += this.car.v * Math.cos(this.car.rotation) * delta;\n this.car.y += this.car.v * Math.sin(this.car.rotation) * delta;\n this.car.mx = Math.floor(this.car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.my = Math.floor(this.car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.checkAndsetNewRoad();\n this.lidar.x = this.car.x;\n this.lidar.y = this.car.y;\n this.lidar.rotation = this.car.rotation;\n var _a = this.detectInteractions(), agent_col = _a.agent_col, on_road = _a.on_road;\n if (agent_col.length > 0) {\n this.car.v = 0;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n return BotMotionEngine;\n}(_motion_engine__WEBPACK_IMPORTED_MODULE_0__[\"MotionEngine\"]));\n\n\n\n//# sourceURL=webpack://metacar/./src/bot_motion_engine.ts?"); + +/***/ }), + +/***/ "./src/car.ts": +/*!********************!*\ + !*** ./src/car.ts ***! + \********************/ +/*! exports provided: Car */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Car\", function() { return Car; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar Global_carId = 0;\nvar Car = (function () {\n function Car(level, info, textures, options) {\n if (options === void 0) { options = {}; }\n var _this = this;\n this.level = level;\n options.image = options.image || _global__WEBPACK_IMPORTED_MODULE_0__[\"CAR_IMG\"].DEFAULT;\n options.lidar = options.lidar || false;\n options.lidarInfo = options.lidarInfo || { pts: 5, width: 4, height: 5, pos: 0 };\n this.core = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"](textures[options.image]);\n this.info = info;\n this.core.scale.x = 0.8;\n this.core.scale.y = 0.8;\n this.core.anchor.x = 0.5;\n this.core.anchor.y = 0.5;\n this.core.road = undefined;\n this.core.carId = Global_carId;\n Global_carId += 1;\n this.core.agent = false;\n this.core.obstacle = true;\n this.core.mapId = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].CAR;\n if (options.lidar) {\n this.createLidar(options.lidarInfo);\n this.core.lidar = this.lidar;\n }\n if (options.motionEngine) {\n this.motion = options.motionEngine;\n this.motion.setUp(this.core, this.lidar);\n this.core.rotationStep = 0.5;\n }\n else {\n this.core.rotationStep = 0.5;\n }\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n this.core.x = (this.info.mx) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.y = (this.info.my) * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"];\n this.core.checkAndsetNewRoad = function (road) { return _this.checkAndsetNewRoad(road); };\n var road = this.level.getRoad(this.core.my, this.core.mx);\n this.core.line = 0;\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n }\n Car.prototype.checkAndsetNewRoad = function (n_road) {\n var current_road = this.core.road;\n if (!n_road) {\n n_road = this.level.getRoad(this.core.my, this.core.mx);\n ;\n }\n if (n_road != current_road) {\n if (current_road) {\n current_road.cars.splice(current_road.cars.indexOf(this.core.carId), 1);\n }\n this.core.road = n_road;\n this.core.haveTurned = false;\n this.turnedRandom = undefined;\n if (n_road)\n n_road.cars.push(this.core.carId);\n }\n };\n Car.prototype.reset = function () {\n this.core.mx = this.info.mx;\n this.core.my = this.info.my;\n var road = this.level.getRoad(this.core.my, this.core.mx);\n if (road) {\n road.setCarPosition(this.core, this.info.line);\n }\n };\n Car.prototype.getState = function () {\n return this.motion.state.map(function (arr) { return arr.slice(); });\n };\n Car.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n if (action == null) {\n var _a = this.motion.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n }\n else {\n var _b = this.motion.actionStep(delta, action), agent_col = _b.agent_col, on_road = _b.on_road;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n Car.prototype.createLidar = function (lidarOptions) {\n this.lidar = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Container\"]();\n var area = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n area.pt = false;\n area.alpha = 0.5;\n area.beginFill(0x515151);\n area.drawRect(0, 0, this.core.width * lidarOptions.width, this.core.height * lidarOptions.height);\n area.endFill();\n var x_step = area.width / lidarOptions.pts;\n var y_step = area.height / lidarOptions.pts;\n for (var xs = lidarOptions.pts - 1; xs >= 0; xs--) {\n for (var ys = 0; ys < lidarOptions.pts; ys++) {\n var x = (x_step / 4) + xs * x_step;\n var y = (y_step / 4) + ys * y_step;\n var pt = new _global__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"]();\n pt.pt = true;\n pt.beginFill(0xffffff);\n pt.drawRect(x, y, 5, 5);\n pt.endFill();\n this.lidar.addChild(pt);\n }\n }\n this.lidar.pts = lidarOptions.pts;\n this.lidar.addChild(area);\n this.lidar.x = this.core.x;\n this.lidar.y = this.core.y;\n this.lidar.pivot.y = this.lidar.height / 2;\n this.lidar.pivot.x = this.core.width / 2 - (lidarOptions.pos * this.core.width);\n this.lidar.rotation = this.core.rotation;\n };\n return Car;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/car.ts?"); + +/***/ }), + +/***/ "./src/control_motion_engine.ts": +/*!**************************************!*\ + !*** ./src/control_motion_engine.ts ***! + \**************************************/ +/*! exports provided: ControlMotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ControlMotionEngine\", function() { return ControlMotionEngine; });\n/* harmony import */ var _motion_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./motion_engine */ \"./src/motion_engine.ts\");\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\n\nvar ControlMotionEngine = (function (_super) {\n __extends(ControlMotionEngine, _super);\n function ControlMotionEngine(level) {\n var _this = _super.call(this, level) || this;\n _this.level = level;\n _this.actions = [\"SteeringAngle\", \"Throttle\"];\n return _this;\n }\n ControlMotionEngine.prototype.setUp = function (car, lidar) {\n this.car = car;\n this.lidar = lidar;\n this.state = [];\n for (var y = 0; y < lidar.pts; y++) {\n var line = [];\n for (var x = 0; x < lidar.pts; x++) {\n line.push(_global__WEBPACK_IMPORTED_MODULE_1__[\"MAP\"].DEFAULT);\n }\n this.state.push(line);\n }\n this.setUpKeyboard();\n this.car.v = 0;\n this.car.a = 0;\n this.car.yaw_rate = 0;\n this.detectInteractions();\n };\n ControlMotionEngine.prototype.setUpKeyboard = function () {\n var _this = this;\n var left = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](37);\n var up = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](38);\n var right = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](39);\n var down = _utils__WEBPACK_IMPORTED_MODULE_2__[\"keyboard\"](40);\n left.press = function () {\n _this.turn(-0.5);\n };\n left.release = function () {\n _this.turn(0);\n };\n right.press = function () {\n _this.turn(0.5);\n };\n right.release = function () {\n _this.turn(0);\n };\n up.press = function () { _this.move(1); };\n up.release = function () {\n _this.car.a = 0;\n };\n down.press = function () { _this.move(-1); };\n down.release = function () {\n _this.car.a = 0;\n };\n };\n ControlMotionEngine.prototype.turn = function (value) {\n this.car.yaw_rate = value;\n };\n ControlMotionEngine.prototype.move = function (throttle) {\n this.car.a = throttle;\n };\n ControlMotionEngine.prototype.actionStep = function (delta, actions) {\n this.car.a = Math.min(Math.max(parseInt(actions[0].toString()), -1), 1);\n this.car.yaw_rate = Math.min(Math.max(parseInt(actions[1].toString()), -1), 1);\n var _a = this.step(delta), agent_col = _a.agent_col, on_road = _a.on_road;\n this.car.a = 0;\n this.car.yaw_rate = 0;\n return { agent_col: agent_col, on_road: on_road };\n };\n ControlMotionEngine.prototype.actionSpace = function () {\n return Array.apply(null, { length: this.actions.length }).map(Number.call, Number);\n };\n ControlMotionEngine.prototype.step = function (delta) {\n if (this.car.v > 0)\n this.car.v = Math.max(0, this.car.v - 0.01);\n else if (this.car.v < 0)\n this.car.v = Math.min(0, this.car.v + 0.01);\n if (this.car.a > 0)\n this.car.v = Math.min(2., this.car.v + this.car.a * 0.02);\n else\n this.car.v = Math.max(-2., this.car.v + this.car.a * 0.02);\n if (this.car.yaw_rate == 0) {\n this.car.x += this.car.v * Math.cos(this.car.rotation) * delta;\n this.car.y += this.car.v * Math.sin(this.car.rotation) * delta;\n }\n else {\n var yr = this.car.yaw_rate * 0.01 * (this.car.v + 0.001) * Math.PI;\n this.car.x += (this.car.v / yr) * (Math.sin(this.car.rotation + (yr * delta)) - Math.sin(this.car.rotation));\n this.car.y += (this.car.v / yr) * (Math.cos(this.car.rotation) - Math.cos(this.car.rotation + (yr * delta)));\n this.car.rotation += yr * delta;\n }\n this.car.mx = Math.floor(this.car.x / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.my = Math.floor(this.car.y / _global__WEBPACK_IMPORTED_MODULE_1__[\"ROADSIZE\"]);\n this.car.checkAndsetNewRoad();\n this.lidar.x = this.car.x;\n this.lidar.y = this.car.y;\n this.lidar.rotation = this.car.rotation;\n var _a = this.detectInteractions(), agent_col = _a.agent_col, on_road = _a.on_road;\n if (agent_col.length > 0) {\n this.car.v = 0;\n this.car.vy = 0;\n }\n return { agent_col: agent_col, on_road: on_road };\n };\n return ControlMotionEngine;\n}(_motion_engine__WEBPACK_IMPORTED_MODULE_0__[\"MotionEngine\"]));\n\n\n\n//# sourceURL=webpack://metacar/./src/control_motion_engine.ts?"); + +/***/ }), + +/***/ "./src/embedded.ts": +/*!*************************!*\ + !*** ./src/embedded.ts ***! + \*************************/ +/*! exports provided: embeddedUrl, embeddedContent */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"embeddedUrl\", function() { return embeddedUrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"embeddedContent\", function() { return embeddedContent; });\n/* harmony import */ var _embedded_level_full_city__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./embedded/level/full_city */ \"./src/embedded/level/full_city.ts\");\n\nvar embeddedUrl = {\n fullCity: \"embedded://level/fullCity\"\n};\nvar embeddedContent = {\n level: {\n fullCity: _embedded_level_full_city__WEBPACK_IMPORTED_MODULE_0__[\"fullCity\"]\n }\n};\n\n\n//# sourceURL=webpack://metacar/./src/embedded.ts?"); + +/***/ }), + +/***/ "./src/embedded/level/full_city.ts": +/*!*****************************************!*\ + !*** ./src/embedded/level/full_city.ts ***! + \*****************************************/ +/*! exports provided: fullCity */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"fullCity\", function() { return fullCity; });\nvar fullCity = {\n \"cars\": [\n {\n \"mx\": 2,\n \"my\": 5,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 3,\n \"my\": 4,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 3,\n \"my\": 4,\n \"line\": 1,\n \"auto\": true\n },\n {\n \"mx\": 6,\n \"my\": 3,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 6,\n \"my\": 3,\n \"line\": 1,\n \"auto\": true\n },\n {\n \"mx\": 8,\n \"my\": 2,\n \"line\": 0,\n \"auto\": true\n },\n {\n \"mx\": 8,\n \"my\": 2,\n \"line\": 1,\n \"auto\": true\n },\n {\n \"mx\": 2,\n \"my\": 7,\n \"line\": 0,\n \"auto\": true\n }\n ],\n \"house\": [\n {\n \"x\": 9,\n \"y\": 409\n },\n {\n \"x\": 146,\n \"y\": 162\n },\n {\n \"x\": 439,\n \"y\": 39\n }\n ],\n \"house2\": [\n {\n \"x\": 425,\n \"y\": 192\n },\n {\n \"x\": 431,\n \"y\": 354\n }\n ],\n \"house3\": [\n {\n \"x\": 426,\n \"y\": 281\n },\n {\n \"x\": 51,\n \"y\": 157\n },\n {\n \"x\": 553,\n \"y\": 34\n }\n ],\n \"bench\": [\n {\n \"x\": 259,\n \"y\": 206\n },\n {\n \"x\": 8,\n \"y\": 205\n }\n ],\n \"tree\": [\n {\n \"x\": 1,\n \"y\": 303\n },\n {\n \"x\": 54,\n \"y\": 357\n },\n {\n \"x\": 215,\n \"y\": 325\n },\n {\n \"x\": 230,\n \"y\": 400\n },\n {\n \"x\": 282,\n \"y\": 368\n },\n {\n \"x\": 182,\n \"y\": 433\n },\n {\n \"x\": 285,\n \"y\": 309\n },\n {\n \"x\": 576,\n \"y\": 233\n },\n {\n \"x\": 581,\n \"y\": 300\n },\n {\n \"x\": 519,\n \"y\": 388\n },\n {\n \"x\": 582,\n \"y\": 391\n },\n {\n \"x\": 256,\n \"y\": 69\n },\n {\n \"x\": 151,\n \"y\": 43\n },\n {\n \"x\": 77,\n \"y\": 77\n },\n {\n \"x\": 26,\n \"y\": 24\n },\n {\n \"x\": 189,\n \"y\": 98\n }\n ],\n \"map\": [\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↠\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↦\",\n \"↔\",\n \"↔\",\n \"↟\",\n \"↔\"\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n \"↔\",\n \"↔\",\n \"↧\",\n \"↔\",\n \"↠\",\n \"↔\",\n \"↤\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n \"↠\",\n 0,\n 0,\n 0,\n \"↠\",\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n \"↕\",\n 0,\n 0,\n 0,\n 0\n ]\n ]\n};\n\n\n//# sourceURL=webpack://metacar/./src/embedded/level/full_city.ts?"); + +/***/ }), + +/***/ "./src/global.ts": +/*!***********************!*\ + !*** ./src/global.ts ***! + \***********************/ +/*! exports provided: Application, Loader, Resources, Sprite, Graphics, Container, JSON_TEXTURES, LEVEL_FOLDER, ROADSIZE, CAR_IMG, MAP, ASSETS */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Application\", function() { return Application; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Loader\", function() { return Loader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Resources\", function() { return Resources; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Sprite\", function() { return Sprite; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Graphics\", function() { return Graphics; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Container\", function() { return Container; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"JSON_TEXTURES\", function() { return JSON_TEXTURES; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"LEVEL_FOLDER\", function() { return LEVEL_FOLDER; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ROADSIZE\", function() { return ROADSIZE; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CAR_IMG\", function() { return CAR_IMG; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MAP\", function() { return MAP; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ASSETS\", function() { return ASSETS; });\n/* harmony import */ var pixi_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! pixi.js */ \"pixi.js\");\n/* harmony import */ var pixi_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(pixi_js__WEBPACK_IMPORTED_MODULE_0__);\n\nvar Application = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Application\"];\nvar Loader = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"loader\"];\nvar Resources = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"loader\"].resources;\nvar Sprite = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"];\nvar Graphics = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Graphics\"];\nvar Container = pixi_js__WEBPACK_IMPORTED_MODULE_0__[\"Container\"];\nvar JSON_TEXTURES = \"public/textures/textures.json\";\nvar LEVEL_FOLDER = \"/level/\";\nvar ROADSIZE = 60;\nvar CAR_IMG = {\n DEFAULT: \"car.png\",\n AGENT: \"car_agent.png\"\n};\nvar MAP = {\n ROAD: -1,\n DEFAULT: 0,\n CAR: 1,\n AGENT: 1,\n};\nvar ASSETS = {\n ROADS: {\n \"↕\": {\n \"image\": \"road_u.png\",\n \"orientation\": 1.5\n },\n \"↔\": {\n \"image\": \"road_r.png\",\n \"orientation\": 0.\n },\n \"↱\": {\n \"image\": \"road_rotate_ld.png\",\n \"orientation\": 1.25\n },\n \"↰\": {\n \"image\": \"road_rotate_ul.png\",\n \"orientation\": 0.75\n },\n \"↲\": {\n \"image\": \"road_rotate_rl.png\",\n \"orientation\": 0.25\n },\n \"↳\": {\n \"image\": \"road_rotate_dl.png\",\n \"orientation\": 1.75\n },\n \"↟\": {\n \"image\": \"road_up.png\",\n \"orientation\": 1.5\n },\n \"↠\": {\n \"image\": \"road_rp.png\",\n \"orientation\": 0.\n },\n \"↤\": {\n \"image\": \"road_r2.png\",\n \"orientation\": 0.\n },\n \"↦\": {\n \"image\": \"road_l2.png\",\n \"orientation\": 1.\n },\n \"↥\": {\n \"image\": \"road_d2.png\",\n \"orientation\": 0.5\n },\n \"↧\": {\n \"image\": \"road_u2.png\",\n \"orientation\": 1.5\n },\n },\n \"house\": {\n \"image\": \"house.png\"\n },\n \"house2\": {\n \"image\": \"house2.png\"\n },\n \"house3\": {\n \"image\": \"house3.png\"\n },\n \"bench\": {\n \"image\": \"bench.png\"\n },\n \"tree\": {\n \"image\": \"tree.png\"\n }\n};\n\n\n//# sourceURL=webpack://metacar/./src/global.ts?"); + +/***/ }), + +/***/ "./src/index.ts": +/*!**********************!*\ + !*** ./src/index.ts ***! + \**********************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _metacar__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./metacar */ \"./src/metacar.ts\");\n/* harmony import */ var _embedded__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./embedded */ \"./src/embedded.ts\");\n\n\nvar metacar = {\n env: _metacar__WEBPACK_IMPORTED_MODULE_0__[\"MetaCar\"],\n level: _embedded__WEBPACK_IMPORTED_MODULE_1__[\"embeddedUrl\"]\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (metacar);\n\n\n//# sourceURL=webpack://metacar/./src/index.ts?"); + +/***/ }), + +/***/ "./src/level.ts": +/*!**********************!*\ + !*** ./src/level.ts ***! + \**********************/ +/*! exports provided: Level */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Level\", function() { return Level; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n/* harmony import */ var _asset_manager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./asset_manager */ \"./src/asset_manager.ts\");\n\n\nvar Level = (function () {\n function Level(levelContent, canvasId) {\n this.app = null;\n this.info = null;\n this.envs = [];\n this.map = null;\n this.agent = null;\n this.roads = {};\n this.cars = [];\n this.info = levelContent;\n this.map = this.info.map;\n this.canvasId = canvasId;\n this.am = new _asset_manager__WEBPACK_IMPORTED_MODULE_1__[\"AssetManger\"](this);\n }\n Level.prototype.load = function (loop) {\n var _this = this;\n this.loop = loop;\n return new Promise(function (resolve, reject) {\n _this.createLevel(_this.info).then(function () { return resolve(); });\n });\n };\n Level.prototype.createLevel = function (info) {\n var _this = this;\n this.app = new PIXI.Application({\n width: this.map[0].length * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"],\n height: this.map.length * _global__WEBPACK_IMPORTED_MODULE_0__[\"ROADSIZE\"],\n backgroundColor: 0x80bf3e\n });\n document.getElementById(this.canvasId).appendChild(this.app.view);\n return new Promise(function (resolve, reject) {\n _global__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].add([\"public/textures/textures.json\", \"public/textures/textures.png\"]).load(function () {\n _this.setup(info);\n resolve();\n });\n });\n };\n Level.prototype.setup = function (info) {\n var _this = this;\n var textures = _global__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].resources[_global__WEBPACK_IMPORTED_MODULE_0__[\"JSON_TEXTURES\"]].textures;\n this.am.createMap(this.map, info, textures);\n this.am.createCars(this.map, info, textures);\n if (info.agent)\n this.agent = this.am.createAgent(this.map, info, textures);\n this.app.ticker.add(function (delta) { return _this.loop(delta); });\n };\n Level.prototype.render = function () {\n this.app.ticker.start();\n };\n Level.prototype.reset = function () {\n this.agent.reset();\n };\n Level.prototype.setReward = function (agent_col, on_road, action) {\n var reward = -0.1;\n if (action == 0 || this.agent.core.vx == 1)\n reward += 0.5;\n if (agent_col.length > 0) {\n reward = -10;\n }\n else if (!on_road) {\n reward = -10;\n }\n return reward;\n };\n Level.prototype.step = function (delta, action) {\n if (action === void 0) { action = null; }\n for (var c = 0; c < this.cars.length; c++) {\n if (this.cars[c].lidar && !this.cars[c].core.agent)\n this.cars[c].step(delta);\n }\n if (this.agent) {\n var _a = this.agent.step(delta, action), agent_col = _a.agent_col, on_road = _a.on_road;\n var reward = this.setReward(agent_col, on_road, action);\n return reward;\n }\n return 0;\n };\n Level.prototype.stopRender = function () {\n this.app.ticker.stop();\n };\n Level.prototype.addChild = function (child) {\n this.app.stage.addChild(child);\n };\n Level.prototype.addRoad = function (road) {\n this.roads[[road.my.toString(), road.mx.toString()].toString()] = road;\n this.envs.push(road);\n this.app.stage.addChild(road);\n };\n Level.prototype.addCar = function (car) {\n this.cars.push(car);\n this.app.stage.addChild(car.core);\n this.envs.push(car.core);\n };\n Level.prototype.getRoad = function (my, mx) {\n return this.roads[[my.toString(), mx.toString()].toString()];\n };\n Level.prototype.getRoads = function () {\n return this.roads;\n };\n Level.prototype.findCarById = function (id) {\n return this.cars.find(function (e) { return e.car_id == id; });\n };\n Level.prototype.getEnvs = function () {\n return this.envs;\n };\n Level.prototype.getMap = function () {\n return this.map;\n };\n return Level;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/level.ts?"); + +/***/ }), + +/***/ "./src/metacar.ts": +/*!************************!*\ + !*** ./src/metacar.ts ***! + \************************/ +/*! exports provided: MetaCar */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MetaCar\", function() { return MetaCar; });\n/* harmony import */ var _level__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./level */ \"./src/level.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ \"./src/utils.ts\");\n\n\nvar MetaCar = (function () {\n function MetaCar(canvasId, levelUrl) {\n if (!canvasId || this.levelUrl) {\n console.error(\"You must specify the canvasId and the levelUrl\");\n }\n this.isPlaying = false;\n this.canvasId = canvasId;\n this.levelUrl = levelUrl;\n }\n MetaCar.prototype.load = function (level, agent) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n _utils__WEBPACK_IMPORTED_MODULE_1__[\"loadCustomURL\"](_this.levelUrl, function (content) {\n _this.level = new _level__WEBPACK_IMPORTED_MODULE_0__[\"Level\"](content, _this.canvasId);\n _this.level.load(function (delta) { return _this.loop(delta); });\n resolve();\n });\n });\n };\n MetaCar.prototype.render = function () {\n this.level.render();\n };\n MetaCar.prototype.save = function (content, file_name) {\n _utils__WEBPACK_IMPORTED_MODULE_1__[\"saveAs\"](content, file_name);\n };\n MetaCar.prototype.actionSpace = function () {\n return this.level.agent.motion.actionSpace();\n };\n MetaCar.prototype.getState = function () {\n return this.level.agent.getState();\n };\n MetaCar.prototype.step = function (action) {\n return this.level.step(1, action);\n };\n MetaCar.prototype.reset = function () {\n this.level.reset();\n };\n MetaCar.prototype.randomRoadPosition = function () {\n this.level.agent.last_position = [];\n var roads = this.level.getRoads();\n var keys = Object.keys(roads);\n keys.sort(function () { return Math.random() - 0.5; });\n for (var k in keys) {\n var road = roads[keys[k]];\n if (road.cars.length == 0) {\n road.setCarPosition(this.level.agent.core);\n break;\n }\n }\n };\n MetaCar.prototype.loop = function (delta) {\n if (this.isPlaying) {\n this.agent.play(this);\n }\n else {\n this.level.step(delta);\n }\n };\n return MetaCar;\n}());\n\n\n\n//# sourceURL=webpack://metacar/./src/metacar.ts?"); + +/***/ }), + +/***/ "./src/motion_engine.ts": +/*!******************************!*\ + !*** ./src/motion_engine.ts ***! + \******************************/ +/*! exports provided: MotionEngine */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MotionEngine\", function() { return MotionEngine; });\n/* harmony import */ var _global__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./global */ \"./src/global.ts\");\n\nvar MotionEngine = (function () {\n function MotionEngine(level) {\n this.level = level;\n }\n MotionEngine.prototype.boxesIntersect = function (a, b) {\n var ab = a.getBounds();\n var bb = b.getBounds();\n return ab.x + ab.width > bb.x && ab.x < bb.x + bb.width && ab.y + ab.height > bb.y && ab.y < bb.y + bb.height;\n };\n MotionEngine.prototype.detectInteractions = function () {\n var envs = this.level.getEnvs();\n var agent_col = [];\n var lidar_collisions = [];\n var on_road = false;\n for (var i = 0; i < envs.length; i++) {\n if (envs[i] != this.car && envs[i].obstacle && this.boxesIntersect(envs[i], this.car)) {\n agent_col.push(envs[i]);\n }\n else if (envs[i].mapId == _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].ROAD && this.boxesIntersect(envs[i], this.car)) {\n on_road = true;\n }\n if (this.boxesIntersect(envs[i], this.lidar)) {\n lidar_collisions.push(envs[i]);\n }\n }\n this.setState(lidar_collisions);\n return { agent_col: agent_col, on_road: on_road };\n };\n MotionEngine.prototype.setState = function (lidar_collisions) {\n var pt_id = 0;\n for (var i = 0; i < this.lidar.children.length; i++) {\n this.lidar.children[i].alpha = 0.1;\n if (this.lidar.children[i].pt) {\n var pt_y = Math.floor(pt_id / this.lidar.pts);\n var pt_x = Math.floor(pt_id % this.lidar.pts);\n this.state[pt_y][pt_x] = _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].DEFAULT;\n for (var a = 0; a < lidar_collisions.length; a++) {\n if (lidar_collisions[a] != this.car) {\n var touch = this.boxesIntersect(lidar_collisions[a], this.lidar.children[i]);\n if (touch && lidar_collisions[a].obstacle) {\n this.lidar.children[i].alpha = 1.;\n }\n if (touch && (lidar_collisions[a].mapId > this.state[pt_y][pt_x] || (lidar_collisions[a].mapId == _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].ROAD && this.state[pt_y][pt_x] == _global__WEBPACK_IMPORTED_MODULE_0__[\"MAP\"].DEFAULT))) {\n this.state[pt_y][pt_x] = lidar_collisions[a].mapId;\n }\n }\n }\n pt_id += 1;\n }\n }\n };\n return MotionEngine;\n}());\n\n;\n\n\n//# sourceURL=webpack://metacar/./src/motion_engine.ts?"); + +/***/ }), + +/***/ "./src/utils.ts": +/*!**********************!*\ + !*** ./src/utils.ts ***! + \**********************/ +/*! exports provided: loadJSON, loadEmbeddedURL, loadLocalStorageURL, loadCustomURL, mod, argMax, mean, saveAs, shuffleArray, keyboard */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadJSON\", function() { return loadJSON; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadEmbeddedURL\", function() { return loadEmbeddedURL; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadLocalStorageURL\", function() { return loadLocalStorageURL; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"loadCustomURL\", function() { return loadCustomURL; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mod\", function() { return mod; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"argMax\", function() { return argMax; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mean\", function() { return mean; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"saveAs\", function() { return saveAs; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"shuffleArray\", function() { return shuffleArray; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"keyboard\", function() { return keyboard; });\n/* harmony import */ var _embedded__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./embedded */ \"./src/embedded.ts\");\n\nfunction loadJSON(url, callback) {\n var xobj = new XMLHttpRequest();\n xobj.overrideMimeType(\"application/json\");\n xobj.open('GET', url, true);\n xobj.onreadystatechange = function () {\n if (xobj.readyState == 4 && xobj.status == 200) {\n callback(xobj.responseText);\n }\n };\n xobj.send(null);\n}\nfunction loadEmbeddedURL(url, callback) {\n var split = url.split(\"//\");\n split = split[1].split(\"/\");\n callback(_embedded__WEBPACK_IMPORTED_MODULE_0__[\"embeddedContent\"][split[0]][split[1]]);\n}\nfunction loadLocalStorageURL(url, callback) {\n}\nfunction loadCustomURL(url, callback) {\n var customCall = {\n \"embedded:\": loadEmbeddedURL,\n \"http://\": loadJSON,\n \"https://\": loadJSON,\n \"localstorage://\": loadLocalStorageURL\n };\n var split = url.split(\"//\");\n customCall[split[0]](url, callback);\n}\nfunction mod(n, m) {\n return ((n % m) + m) % m;\n}\nfunction argMax(array) {\n if (array.every(function (v) { return v == -Infinity; })) {\n return Math.floor(Math.random() * array.length);\n }\n return array.map(function (x, i) { return [x, i]; }).reduce(function (r, a) { return (a[0] > r[0] ? a : r); })[1];\n}\nfunction mean(array) {\n if (array.length == 0)\n return null;\n var sum = array.reduce(function (a, b) { return a + b; });\n var avg = sum / array.length;\n return avg;\n}\nfunction saveAs(content, name) {\n var a = document.createElement(\"a\");\n document.body.appendChild(a);\n var blob = new Blob([content], { type: 'application/octet-binary' }), tmpURL = window.URL.createObjectURL(blob);\n a.href = tmpURL;\n a.download = name;\n a.click();\n window.URL.revokeObjectURL(tmpURL);\n a.href = \"\";\n}\nfunction shuffleArray(array) {\n for (var i = array.length - 1; i > 0; i--) {\n var j = Math.floor(Math.random() * (i + 1));\n var temp = array[i];\n array[i] = array[j];\n array[j] = temp;\n }\n return array;\n}\nfunction keyboard(keyCode) {\n var key = {};\n key.code = keyCode;\n key.isDown = false;\n key.isUp = true;\n key.press = undefined;\n key.release = undefined;\n key.downHandler = function (event) {\n if (event.keyCode === key.code) {\n if (key.isUp && key.press)\n key.press();\n key.isDown = true;\n key.isUp = false;\n }\n event.preventDefault();\n };\n key.upHandler = function (event) {\n if (event.keyCode === key.code) {\n if (key.isDown && key.release)\n key.release();\n key.isDown = false;\n key.isUp = true;\n }\n event.preventDefault();\n };\n window.addEventListener(\"keydown\", key.downHandler.bind(key), false);\n window.addEventListener(\"keyup\", key.upHandler.bind(key), false);\n return key;\n}\n\n\n//# sourceURL=webpack://metacar/./src/utils.ts?"); + +/***/ }), + +/***/ "pixi.js": +/*!***********************!*\ + !*** external "PIXI" ***! + \***********************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("(function() { module.exports = window[\"PIXI\"]; }());\n\n//# sourceURL=webpack://metacar/external_%22PIXI%22?"); + +/***/ }) + +/******/ })["default"]; \ No newline at end of file diff --git a/package.json b/package.json index 15f9a03..c1a7d3b 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "scripts": { "build": "./node_modules/.bin/webpack-cli --mode production", + "build-dev": "./node_modules/.bin/webpack-cli --mode development", "watch": "./node_modules/.bin/webpack-cli --watch --mode development" } } diff --git a/src/asset_manager.ts b/src/asset_manager.ts index 61df32c..5ccbb2b 100644 --- a/src/asset_manager.ts +++ b/src/asset_manager.ts @@ -14,6 +14,7 @@ import {CarOptions, Car} from "./car"; import {BasicMotionEngine} from "./basic_motion_engine"; import {ControlMotionEngine} from "./control_motion_engine"; import {BotMotionEngine} from "./bot_motion_engine"; +import { Editor } from "./editor"; export interface AssetInfo { readonly mx?: number; @@ -38,6 +39,7 @@ export interface RoadSprite extends PIXI.Sprite { // (x, y position) Relatif to the map mx?: number; my?: number; + isremove?: boolean; } export interface SimpleSprite extends PIXI.Sprite { @@ -45,17 +47,18 @@ export interface SimpleSprite extends PIXI.Sprite { // name of the asset (not the name of the image) type?: string; mapId?: number; + isremove?: boolean; } export class AssetManger { - private level: Level; + 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 - private assets: SimpleSprite[] = []; + public assets: SimpleSprite[] = []; - constructor(level: Level) { + constructor(level: Level|Editor) { this.level = level; this.motion = { "BasicMotionEngine": BasicMotionEngine, @@ -111,7 +114,8 @@ export class AssetManger { */ if (line == undefined) line = 0; - if (road.cars.length >= 1 && this.level.findCarById(road.cars[0]).core.line == line){ + let carById = this.level.findCarById(road.cars[0]); + if (road.cars.length >= 1 && carById && carById.core.line == line){ line = line == 0 ? 1:0; } if (road.cars.length >= 2){ @@ -129,10 +133,10 @@ export class AssetManger { let y_margin = (ROADSIZE*1/4); // transform to map x coordinate // transform to map y coordinate - road.orientation = (Math.floor(road.orientation / car.rotation_step)*car.rotation_step); - let theta = -road.orientation*(Math.PI); - let x_m = (Math.cos(theta) * x_margin) - (y_margin * Math.sin(theta)); - let y_m = (Math.cos(theta) * y_margin) + (x_margin * Math.sin(theta)); + road.orientation = (Math.floor(road.orientation / car.rotationStep)*car.rotationStep); + let th = -road.orientation*(Math.PI); // theta + let x_m = (Math.cos(th) * x_margin) - (y_margin * Math.sin(th)); + let y_m = (Math.cos(th) * y_margin) + (x_margin * Math.sin(th)); let line_side_factor = line == 0 ? 1:-1; let line_side_factor_t = line == 0 ? 0:Math.PI; @@ -143,7 +147,7 @@ export class AssetManger { car.mx = Math.floor(car.x / ROADSIZE); car.my = Math.floor(car.y / ROADSIZE); // Car rotation - car.rotation = (theta+line_side_factor_t); + car.rotation = (th+line_side_factor_t); // Set the new road of the car car.checkAndsetNewRoad(road); } @@ -169,7 +173,7 @@ export class AssetManger { this.assets.push(asset); } - createMap(map: (string|number)[][], info: LevelInfo, textures: PIXI.Texture, roadside:boolean=true){ + createMap(map: (string|number)[][], info: LevelInfo, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary), roadside:boolean=true){ /* Method used to create the map with all assets (except the cars) @map (2dim Array) @@ -204,7 +208,7 @@ export class AssetManger { } } - createCars(map: (string|number)[][], info: LevelInfo, textures: PIXI.Texture){ + createCars(map: (string|number)[][], info: any, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary)){ /* Method used to create all the cars @map (2dim Array) @@ -213,7 +217,7 @@ export class AssetManger { */ // Go through all the bot cars on the map for (let c in info.cars){ - let options: CarOptions = {lidar: false, lidarInfo: {pts: 2, width: 0.5, height: 1, pos: 1}}; + let options: CarOptions = {lidar: true, lidarInfo: {pts: 2, width: 0.5, height: 1, pos: 1}}; if (info.cars[c].auto){ options.lidar = true; options.motionEngine = new BotMotionEngine(this.level); @@ -221,10 +225,11 @@ export class AssetManger { let n_car = new Car(this.level, info.cars[c], textures, options); // Append the car to the canvas this.level.addCar(n_car); + //this.level.addChild(n_car.lidar); } } - createAgent(map: (string|number)[][], info: LevelInfo, textures: PIXI.Texture){ + createAgent(map: (string|number)[][], info: any, textures: (PIXI.Texture|PIXI.loaders.TextureDictionary)){ /* Method used to create the agent's car. @map (2dim Array) @@ -244,6 +249,10 @@ export class AssetManger { return agent; } + addAsset(asset: any){ + this.assets.push(asset); + } + exportMap(width: number, height: number, file_name: string){ /* Export the map @@ -251,8 +260,9 @@ export class AssetManger { @height (Integer) Height of the new map @file_name (String) name of the file to export */ - var file = {"cars": []}; + var file: any = {"cars": []}; let map = []; + let envs = this.level.getEnvs(); for (var y = 0; y < height; y++) { let line = []; for (var x = 0; x < width; x++) { @@ -260,8 +270,8 @@ export class AssetManger { } map.push(line); } - for (var e = 0; e < this.level.envs.length; e++) { - let elem = this.level.envs[e]; + for (var e = 0; e < envs.length; e++) { + let elem = envs[e]; if (!elem.isremove){ // Add the cars if (elem.mapId == MAP.CAR && !elem.agent && elem.is_valid){ @@ -300,7 +310,7 @@ export class AssetManger { "motion": { "type": "BasicMotionEngine", "options":{ - "rotation_step": 0.5, + "rotationStep": 0.5, "actions": ["UP", "LEFT", "RIGHT", "DOWN", "WAIT"] } } diff --git a/src/bot_motion_engine.ts b/src/bot_motion_engine.ts index 13fd653..dd93a3a 100644 --- a/src/bot_motion_engine.ts +++ b/src/bot_motion_engine.ts @@ -4,6 +4,7 @@ import {Level} from "./level"; import { MAP, ROADSIZE } from "./global"; +import { Editor } from "./editor"; export class BotMotionEngine extends MotionEngine { /* @@ -18,7 +19,7 @@ export class BotMotionEngine extends MotionEngine { private map: (string|number)[][]; private rotationToNextCase: any; - constructor(level: Level) { + constructor(level: Level|Editor) { super(level); this.map = this. level.getMap(); @@ -35,7 +36,7 @@ export class BotMotionEngine extends MotionEngine { this.rotationToNextCase[-0.5] = {"mx": 0, "my": -1}; this.rotationToNextCase[-1.0] = {"mx": -1, "my": 0}; this.rotationToNextCase[-1.5] = {"mx": 0, "my": 1}; - // this.rotationToNextCase[null] = {"mx": 0, "my": 0}; + //this.rotationToNextCase[undefined] = {"mx": 0, "my": 0}; } setUp(car: any, lidar: any){ @@ -93,7 +94,7 @@ export class BotMotionEngine extends MotionEngine { Method used to check is there a road is present at this potion on the map */ - if (ny < 0 || ny >= this.mapSizeY || nx < 0 || nx >= this.mapSizeX || this.level.map[ny][nx] == 0){ + if (ny < 0 || ny >= this.mapSizeY || nx < 0 || nx >= this.mapSizeX || this.map[ny][nx] == 0){ return false; } return true; @@ -114,7 +115,7 @@ export class BotMotionEngine extends MotionEngine { if (this.car.next_road.rotation_type == 0){ // Turn right if (y_dist < right_dist && x_dist < right_dist){ - this.car.have_turned = true; + this.car.haveTurned = true; this.car.rotation = this.car.rotation += Math.PI/2; this.car.rotation = this.car.rotation % (2*Math.PI); this.car.next_road = undefined; @@ -124,7 +125,7 @@ export class BotMotionEngine extends MotionEngine { if (this.car.next_road.rotation_type == 1){ // Turn left if (y_dist < left_dist && x_dist < left_dist){ - this.car.have_turned = true; + this.car.haveTurned = true; this.car.rotation = this.car.rotation -= Math.PI/2; this.car.rotation = this.car.rotation % (2*Math.PI); this.car.next_road = undefined; @@ -134,7 +135,7 @@ export class BotMotionEngine extends MotionEngine { if (this.car.next_road.rotation_type == 2){ // Rotation if (y_dist < same_dist && x_dist < same_dist){ - this.car.have_turned = true; + this.car.haveTurned = true; this.car.rotation = this.car.rotation -= Math.PI; this.car.rotation = this.car.rotation % (2*Math.PI); @@ -176,19 +177,24 @@ export class BotMotionEngine extends MotionEngine { if (!this.isRoad(nx, ny)){ turn = true; } - else if (!this.car.have_turned && !this.car.turn_random){ - this.car.turn_random = Math.random(); + else if (!this.car.haveTurned && !this.car.turnedRandom){ + this.car.turnedRandom = Math.random(); } - else if(!this.car.have_turned && this.car.turn_random < 0.33 && this.isRoad(this.car.mx + is_next_pos_r.mx, this.car.my + is_next_pos_r.my)){ + else if(!this.car.haveTurned && this.car.turnedRandom < 0.33 && this.isRoad(this.car.mx + is_next_pos_r.mx, this.car.my + is_next_pos_r.my)){ turn = true; } - else if(!this.car.have_turned && this.car.turn_random > 0.66 && this.isRoad(this.car.mx + is_next_pos_l.mx, this.car.my + is_next_pos_l.my)){ + else if(!this.car.haveTurned && this.car.turnedRandom > 0.66 && this.isRoad(this.car.mx + is_next_pos_l.mx, this.car.my + is_next_pos_l.my)){ turn = true; } if (turn){ let possibles_rotations = [(key+0.5) % 2., (key-0.5) % 2., null]; for (let p = 0; p < possibles_rotations.length; p++){ - let next_pos = this.rotationToNextCase[possibles_rotations[p]]; + let next_pos; + if (possibles_rotations[p] != null){ + next_pos = this.rotationToNextCase[possibles_rotations[p]]; + } else{ + next_pos = {"mx": 0, "my": 0}; + } let px = this.car.mx + next_pos.mx; let py = this.car.my + next_pos.my; if (this.isRoad(px, py)){ diff --git a/src/car.ts b/src/car.ts index 6563c07..c0f85d4 100644 --- a/src/car.ts +++ b/src/car.ts @@ -4,7 +4,8 @@ This class create the agent and the associated sensor (lidar) */ -import {Level, LevelInfo} from "./level"; +import {Level} from "./level"; +import {Editor} from "./editor"; import { CAR_IMG, Sprite, MAP, ROADSIZE, Container, Graphics @@ -49,17 +50,22 @@ export interface CarSprite extends PIXI.Sprite { agent?: boolean; } +export interface LidarChild extends PIXI.Graphics { + // Is a lidar point + pt?: boolean; +} + export class Car { - public level: Level; + public level: Level|Editor; public core: CarSprite; public lidar: any; private info: CarInfo; private motion: any; - private turnedRandom: any; + public turnedRandom: any; - constructor(level: Level, info: CarInfo, textures: any, options:CarOptions={}) { + constructor(level: Level|Editor, info: CarInfo, textures: any, options:CarOptions={}) { /* @level (Level class) @info: (CarInfo) Info from the json file about the car @@ -200,9 +206,9 @@ export class Car { @height: Height of the lidar (in proportion to the car) */ this.lidar = new Container(); - // Area of the lidar - let area = new Graphics(); + let area: LidarChild = new Graphics(); + area.pt = false; area.alpha = 0.5; area.beginFill(0x515151); area.drawRect(0, 0, this.core.width*lidarOptions.width, this.core.height*lidarOptions.height); @@ -216,8 +222,8 @@ export class Car { let x = (x_step/4) + xs * x_step; let y = (y_step/4) + ys * y_step; - - let pt = new Graphics(); + let pt: LidarChild = new Graphics(); + pt.pt = true; pt.beginFill(0xffffff); pt.drawRect(x, y, 5, 5); pt.endFill(); @@ -227,8 +233,10 @@ export class Car { this.lidar.pts = lidarOptions.pts; this.lidar.addChild(area); + this.lidar.x = this.core.x; this.lidar.y = this.core.y; + this.lidar.pivot.y = this.lidar.height/2; this.lidar.pivot.x = this.core.width/2 - (lidarOptions.pos*this.core.width); this.lidar.rotation = this.core.rotation; diff --git a/src/editor.ts b/src/editor.ts new file mode 100644 index 0000000..351dc6a --- /dev/null +++ b/src/editor.ts @@ -0,0 +1,332 @@ +import { LevelInfo, Roads } from "./level"; +import { AssetManger, RoadSprite } from "./asset_manager"; +import { Car} from "./car"; +import {Loader, Sprite, JSON_TEXTURES, ROADSIZE, MAP, LEVEL_FOLDER} from "./global"; +import * as U from "./utils"; + +/* + @Level class + This is the core of game, the class is used create all the differents + services in the game (assets, map, agents...). +*/ + +export class Editor { + + public app: PIXI.Application = null; // The pixi app. + // Informations on the level + private levelName: string; + private info: LevelInfo = null; + private envs: any[] = [] // Used to list all elements the car can crash with + public am: AssetManger; + public map: (string|number)[][] = null; // Use the roads positions of the level + public agent: any = null; // (@Car class) for the agent + // Object to store all the roads assets + // Each road is accesible as follow this.roads[[my, mx]] + // with my and mx the (x, y) position relative to the map (not pixel). + private cars: Car[] = []; // Array used to store all the cars assets + private loop: any = null; // Loop method called for each render + // Current selector items by the editor + public selectedItems: any = null; + private canvasId: string; // Id of the target canvas + private roads: Roads = {}; + + constructor(levelName: string, canvasId: string) { + /* + @levelName (String) Name of the level to load (.json) + */ + this.levelName = levelName; + this.canvasId = canvasId; + this.am = new AssetManger(this); + } + + selectedItem(item: any){ + /* + Method to select an items. + Once an item is selected, the item stick to the current + mouse position + @items (Object) + @img (String) + @type (String) + */ + if(this.selectedItems){ + this.app.stage.removeChild(this.selectedItems); + } + let textures = Loader.resources[JSON_TEXTURES].textures; + this.selectedItems = new Sprite(textures[item.image]); + this.selectedItems.type = item.type; + this.selectedItems.image = item.image; + this.selectedItems.data = item.data; + // The road is not an obstacle + this.selectedItems.x = 0; + this.selectedItems.y = 0; + this.app.stage.addChild(this.selectedItems); + } + + removeItem(item: any){ + if (item.lidar){ + this.app.stage.removeChild(item.lidar); + } + if (item.map_id == MAP.CAR){ + item.road.cars.splice(item.road.cars.indexOf(item.car_id), 1); + } + if (item.agent) + this.agent = undefined; + this.app.stage.removeChild(item); + item.isremove = true; + } + + setCurrentItem(){ + this.am.addAsset(this.selectedItems); + let textures = Loader.resources[JSON_TEXTURES].textures; + var that = this; + if (this.selectedItems.type == "road"){ + this.am.createRoad({ + mx: Math.floor(this.selectedItems.x / ROADSIZE), + my: Math.floor(this.selectedItems.y / ROADSIZE), + type: this.selectedItems.data + }, textures); + this.envs[this.envs.length - 1].interactive = true; + 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:[{ + "mx": Math.floor(this.selectedItems.x / ROADSIZE), + "my": Math.floor(this.selectedItems.y / ROADSIZE), + "rotation": 0, + "line": 0, + }]}, textures); + this.envs[this.envs.length - 1].interactive = true; + 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:{ + "mx": Math.floor(this.selectedItems.x / ROADSIZE), + "my": Math.floor(this.selectedItems.y / ROADSIZE), + "rotation": 0, + "line": 0, + "motion": { + "type": "BasicMotionEngine", + "options":{ + "rotation_step": 0.5, + "actions": ["UP", "LEFT", "RIGHT", "DOWN", "WAIT"] + } + } + }}, textures); + this.envs[this.envs.length - 1].interactive = true; + this.envs[this.envs.length - 1].on("rightclick", function(this: any) {that.removeItem(this)}); + } + else if (this.selectedItems.type == "asset"){ + this.am.createAsset(this.selectedItems.image, {x: this.selectedItems.x, y: this.selectedItems.y} ,textures, this.selectedItems.data); + this.am.assets[this.am.assets.length - 1].interactive = true; + this.am.assets[this.am.assets.length - 1].on("rightclick", function(this: any) {that.removeItem(this)}); + } + this.app.stage.removeChild(this.selectedItems); + this.selectedItems = null; + } + + load(loop: any){ + /* + Load the map from the file given in the constructor of the class + @loop (Method) This method will be call for each render + */ + this.loop = loop; + return new Promise((resolve, reject) => { + // Load the level + U.loadJSON(LEVEL_FOLDER + this.levelName, (response: any) => { + // Parse JSON string into object + this.info = JSON.parse(response); + this.createLevel(this.info).then(() => resolve()); + }); + }); + } + + createLevel(info: LevelInfo){ + /* + Create the level + @info (Object) Level's json. + */ + this.map = info.map; // Store the map to let it accessible faster later on. + //Create the Pixi Application + this.app = new PIXI.Application({ + width: this.map[0].length * ROADSIZE, + height: this.map.length * ROADSIZE, + backgroundColor: 0x80bf3e + } + ); + // Append the app to the body + document.getElementById(this.canvasId).appendChild(this.app.view); + + return new Promise((resolve, reject) => { + Loader.add(["textures/textures.json", "textures/textures.png"]).load(() => { + this.setup(info); // Set up the level (Add assets) + resolve(); + }); + }); + } + + setup(info: any){ + /* + Setup all the element of the map + @info (Object) Level's json. + */ + // Load the textures file + 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); + if (info.agent) + this.agent = this.am.createAgent(this.map, info, textures); + + var that = this; + for (var i = 0; i < this.envs.length; i++) { + this.envs[i].interactive = true; + this.envs[i].on("rightclick", function(this: any) {that.removeItem(this)}); + } + for (var i = 0; i < this.am.assets.length; i++) { + this.am.assets[i].interactive = true; + this.am.assets[i].on("rightclick", function(this: any) {that.removeItem(this)}); + } + + // Set up the main loop + this.app.ticker.add(delta => this.loop(delta)); + } + + resize(width: number, height: number){ + /* + Resize the map + */ + this.app.renderer.resize(width * ROADSIZE, height * ROADSIZE); + } + + addChild(child: any){ + /** + * Add child to the app + */ + this.app.stage.addChild(child); + } + + addCar(car: Car){ + /** + * Add car to the level + */ + this.cars.push(car); + this.app.stage.addChild(car.core); + this.envs.push(car.core); + } + + getMap(): (string|number)[][] { + return this.map; + } + + getEnvs(): any[] { + /** + * Return the list of envs + * / + */ + return this.envs; + } + + addRoad(road: RoadSprite){ + /* + Add road using the mx and my positions + */ + this.roads[[road.my.toString(), road.mx.toString()].toString()] = road; + this.envs.push(road); + this.app.stage.addChild(road); + } + + findCarById(id: number){ + /* + Find car by @id + */ + return this.cars.find((e: any) => {return e.car_id == id}); + } + + getRoad(my: number, mx: number){ + return this.roads[[my.toString(), mx.toString()].toString()]; + } + + getRoads(){ + return this.roads; + } +} + +/* +function createEditor(id: string){ + + // Get the DOM element to change the width/height of the map + const height_input = document.getElementById("height_input"); + const width_input = document.getElementById("width_input"); + var width = parseInt((width_input).value); + var height = parseInt((height_input).value); + + // Create the editor class + let file = window.location.hash || "template.json"; + file = file.slice(1, file.length) + console.log(file); + var editor = new Editor(file, "string"); + + // For the first init retrieve the widht and height of the map + var fist_init = false; + function init(){ + width = editor.map[0].length; + height = editor.map.length; + (width_input).value = width.toString(); + (height_input).value = height.toString(); + } + + function load(){ + if (!fist_init){ + fist_init = true; + init(); + } + let mouse_position = editor.app.renderer.plugins.interaction.mouse.global; + if (editor.selectedItems && editor.selectedItems.type == "asset"){ + editor.selectedItems.x = mouse_position.x; + editor.selectedItems.y = mouse_position.y; + } + else if (editor.selectedItems) { + editor.selectedItems.x = Math.floor(mouse_position.x/ROADSIZE) * ROADSIZE; + editor.selectedItems.y = Math.floor(mouse_position.y/ROADSIZE) * ROADSIZE; + } + } + + // Game loop + editor.load((delta: any) => { + load(); + }); + + var classname = document.getElementsByClassName("img_item"); + for (var i = 0; i < classname.length; i++) { + classname[i].addEventListener('click', function(this: any){ + editor.selectedItem({image : this.getAttribute('data-img'), type: this.getAttribute('data-type'), data: this.getAttribute("data-data")}); + }, false); + } + + width_input.onchange = () => { + width = parseInt((width_input).value); + editor.resize(width, height); + } + + height_input.onchange = () => { + height = parseInt((height_input).value); + editor.resize(width, height); + } + + document.getElementById("saveMap").onclick = () => { + editor.am.exportMap(width, height, file); + }; + + document.getElementById("canvas").addEventListener("click", () => { + if (editor.selectedItems){ + editor.setCurrentItem(); + } + }); + + document.getElementById("loadMap").addEventListener("click", () => { + window.location.href = "/editor.html#"+prompt("What is the name of the level ? (The file should be located in your level folder)"); + location.reload(); + }); + + document.getElementById("canvas").addEventListener('contextmenu', event => event.preventDefault()); +}*/ \ No newline at end of file diff --git a/src/embedded.ts b/src/embedded.ts new file mode 100644 index 0000000..2426558 --- /dev/null +++ b/src/embedded.ts @@ -0,0 +1,11 @@ +import {fullCity} from "./embedded/level/full_city"; + +export const embeddedUrl: any = { + fullCity: "embedded://level/fullCity" +} + +export const embeddedContent: any = { + level: { + fullCity: fullCity + } +} \ No newline at end of file diff --git a/src/embedded/level/full_city.ts b/src/embedded/level/full_city.ts new file mode 100644 index 0000000..71c3029 --- /dev/null +++ b/src/embedded/level/full_city.ts @@ -0,0 +1,272 @@ +export const fullCity: any = { + "cars": [ + { + "mx": 2, + "my": 5, + "line": 0, + "auto": true + }, + { + "mx": 3, + "my": 4, + "line": 0, + "auto": true + }, + { + "mx": 3, + "my": 4, + "line": 1, + "auto": true + }, + { + "mx": 6, + "my": 3, + "line": 0, + "auto": true + }, + { + "mx": 6, + "my": 3, + "line": 1, + "auto": true + }, + { + "mx": 8, + "my": 2, + "line": 0, + "auto": true + }, + { + "mx": 8, + "my": 2, + "line": 1, + "auto": true + }, + { + "mx": 2, + "my": 7, + "line": 0, + "auto": true + } + ], + "house": [ + { + "x": 9, + "y": 409 + }, + { + "x": 146, + "y": 162 + }, + { + "x": 439, + "y": 39 + } + ], + "house2": [ + { + "x": 425, + "y": 192 + }, + { + "x": 431, + "y": 354 + } + ], + "house3": [ + { + "x": 426, + "y": 281 + }, + { + "x": 51, + "y": 157 + }, + { + "x": 553, + "y": 34 + } + ], + "bench": [ + { + "x": 259, + "y": 206 + }, + { + "x": 8, + "y": 205 + } + ], + "tree": [ + { + "x": 1, + "y": 303 + }, + { + "x": 54, + "y": 357 + }, + { + "x": 215, + "y": 325 + }, + { + "x": 230, + "y": 400 + }, + { + "x": 282, + "y": 368 + }, + { + "x": 182, + "y": 433 + }, + { + "x": 285, + "y": 309 + }, + { + "x": 576, + "y": 233 + }, + { + "x": 581, + "y": 300 + }, + { + "x": 519, + "y": 388 + }, + { + "x": 582, + "y": 391 + }, + { + "x": 256, + "y": 69 + }, + { + "x": 151, + "y": 43 + }, + { + "x": 77, + "y": 77 + }, + { + "x": 26, + "y": 24 + }, + { + "x": 189, + "y": 98 + } + ], + "map": [ + [ + 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, + 0 + ], + [ + 0, + 0, + "↠", + 0, + 0, + 0, + "↠", + 0, + 0, + 0, + 0 + ], + [ + 0, + 0, + "↕", + 0, + 0, + 0, + "↕", + 0, + 0, + 0, + 0 + ] + ] +} diff --git a/src/global.ts b/src/global.ts index f4edba2..bb68890 100644 --- a/src/global.ts +++ b/src/global.ts @@ -13,7 +13,7 @@ export const Graphics = PIXI.Graphics; export const Container = PIXI.Container; // Textures files -export const JSON_TEXTURES = "textures/textures.json"; +export const JSON_TEXTURES = "public/textures/textures.json"; // Level foler export const LEVEL_FOLDER = "/level/"; diff --git a/src/index.ts b/src/index.ts index 1cdfc07..77b4bfe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,9 @@ import {MetaCar} from "./metacar"; -export default MetaCar; \ No newline at end of file +import {embeddedUrl} from "./embedded"; + +const metacar = { + env: MetaCar, + level: embeddedUrl +} + +export default metacar; \ No newline at end of file diff --git a/src/level.ts b/src/level.ts index 0e84bb8..8d48093 100644 --- a/src/level.ts +++ b/src/level.ts @@ -8,9 +8,9 @@ import * as U from "./utils"; import { LEVEL_FOLDER, ROADSIZE, Loader, JSON_TEXTURES } from "./global"; -import {AssetManger, RoadSprite, SimpleSprite, AssetInfo, } from "./asset_manager"; +import {AssetManger, RoadSprite} from "./asset_manager"; -import {Car} from "./car"; +import {Car, CarSprite} from "./car"; export interface LevelInfo { map: (string|number)[][]; @@ -24,26 +24,27 @@ export interface Roads { export class Level { - private app: any = null; // The pixi app. - private name: string = null; // Name fo the level + public app: any = null; // The pixi app. private info: LevelInfo = null; // Information of the loaded level private envs: any[] = [] // Used to list all elements the car can crash with private map: (string|number)[][] = null; // Use the roads positions of the level - private agent: any = null; // (@Car class) for the agent + public agent: any = null; // (@Car class) for the agent // Object to store all the roads assets // Each road is accesible as follow this.roads[[my, mx]] // with my and mx the (x, y) position relative to the map (not pixel). - private roads: Roads; - private cars: any; // Array used to store all the cars assets + private roads: Roads = {}; + private cars: Car[] = []; // Array used to store all the cars assets private loop: any; // Loop method called for each render private am: AssetManger; // The AssetManger is used to set most of the elements on the map private canvasId: string; // Id of the target canvas - constructor(levelName: string, canvasId: string) { + constructor(levelContent: LevelInfo, canvasId: string) { /* - @levelName: Name of the level to load (.json) + @levelContent: Content of the level + @canvasID: HTML canvas id */ - this.name = levelName; + this.info = levelContent; + this.map = this.info.map; this.canvasId = canvasId; this.am = new AssetManger(this); } @@ -55,13 +56,7 @@ export class Level { */ this.loop = loop; return new Promise((resolve, reject) => { - // Load the level - U.loadJSON(LEVEL_FOLDER + this.name, (response: string) => { - // Parse JSON string into object - this.info = JSON.parse(response); - this.map = this.info.map; // Store the map to let it accessible faster later on. - this.createLevel(this.info).then(() => resolve()); - }); + this.createLevel(this.info).then(() => resolve()); }); } @@ -81,7 +76,7 @@ export class Level { document.getElementById(this.canvasId).appendChild(this.app.view); return new Promise((resolve, reject) => { - Loader.add(["textures/textures.json", "textures/textures.png"]).load(() => { + Loader.add(["public/textures/textures.json", "public/textures/textures.png"]).load(() => { this.setup(info); // Set up the level (Add assets) resolve(); }); @@ -193,6 +188,10 @@ export class Level { getRoad(my: number, mx: number){ return this.roads[[my.toString(), mx.toString()].toString()]; } + + getRoads(){ + return this.roads; + } findCarById(id: number){ /* diff --git a/src/metacar.ts b/src/metacar.ts index 971317b..88fd91f 100644 --- a/src/metacar.ts +++ b/src/metacar.ts @@ -2,26 +2,52 @@ Main class of the project */ -import {Level} from "./level"; +import {Level, LevelInfo} from "./level"; +import * as U from "./utils"; export class MetaCar { private isPlaying: boolean; private agent: any; private level: Level; + private canvasId: string; + private levelUrl: string; - constructor() { + constructor(canvasId: string, levelUrl: string) { + /** + * @canvasId: HTML canvas ID to used + * @level: URL or Local storage URL. + * localstorage://level-name + * embedded:// + * http(s):// + */ + if (!canvasId || this.levelUrl){ + console.error("You must specify the canvasId and the levelUrl"); + } + this.isPlaying = false; + this.canvasId = canvasId; + this.levelUrl = levelUrl; } - load(level: string, agent: any){ + load(level: string, agent: any): Promise{ /* Load the environement @level (String) Name of the json level to load @agent (Agent class) */ - this.isPlaying = false; + + return new Promise((resolve, reject) => { + U.loadCustomURL(this.levelUrl, (content: LevelInfo) => { + this.level = new Level(content, this.canvasId); + this.level.load((delta: number) => this.loop(delta)); + resolve(); + }); + }); + + /* + this.agent = agent; - this.level = new Level(level); + this.level = new Level(level, "canvas"); this.level.load((delta: number) => this.loop(delta)); document.getElementById("train").addEventListener("click", () => { @@ -45,6 +71,7 @@ export class MetaCar { document.getElementById("dumpFile").addEventListener("change", (e) => { //readDump(e, (content) => this.agent.restore(this, content)); }); + */ } render(){ @@ -59,7 +86,7 @@ export class MetaCar { /* Save the agent */ - saveAs(content, file_name); + U.saveAs(content, file_name); } actionSpace(){ @@ -97,10 +124,11 @@ export class MetaCar { This position */ this.level.agent.last_position = []; - let keys = Object.keys(this.level.roads); + let roads = this.level.getRoads(); + let keys = Object.keys(roads); keys.sort(function() {return Math.random()-0.5;}); for (let k in keys){ - let road = this.level.roads[keys[k]]; + let road = roads[keys[k]]; if (road.cars.length == 0){ road.setCarPosition(this.level.agent.core); break; @@ -115,7 +143,6 @@ export class MetaCar { else { this.level.step(delta); } - document.getElementById("rewardDisplay").innerHTML = this.level.last_reward; } } diff --git a/src/motion_engine.ts b/src/motion_engine.ts index 351574e..0ff9efc 100644 --- a/src/motion_engine.ts +++ b/src/motion_engine.ts @@ -8,6 +8,7 @@ import {Level} from "./level"; import { MAP } from "./global"; +import { Editor } from "./editor"; export interface MotionOption{ readonly rotationStep?: number; @@ -16,12 +17,12 @@ export interface MotionOption{ export class MotionEngine { - protected level: Level; + protected level: Level|Editor; protected car: any; protected lidar: any; protected state: any; - constructor(level: Level) { + constructor(level: Level|Editor) { this.level = level; } @@ -53,7 +54,7 @@ export class MotionEngine { if (envs[i] != this.car && envs[i].obstacle && this.boxesIntersect(envs[i], this.car)){ agent_col.push(envs[i]); } - else if (envs[i].map_id == MAP.ROAD && this.boxesIntersect(envs[i], this.car)){ + else if (envs[i].mapId == MAP.ROAD && this.boxesIntersect(envs[i], this.car)){ on_road = true; } if (this.boxesIntersect(envs[i], this.lidar)){ @@ -70,16 +71,14 @@ export class MotionEngine { Set up the current state of the agent @lidar_collisions List with all possible lidar collisions */ - let state = []; - let f = 0.1; let pt_id = 0; for (var i = 0; i < this.lidar.children.length; i++) { this.lidar.children[i].alpha = 0.1; if (this.lidar.children[i].pt){ // If this is a lidar point - let pt_y = Math.round(pt_id/this.lidar.pts); - let pt_x = Math.round(pt_id%this.lidar.pts); + let pt_y = Math.floor(pt_id/this.lidar.pts); + let pt_x = Math.floor(pt_id%this.lidar.pts); this.state[pt_y][pt_x] = MAP.DEFAULT; for (var a = 0; a < lidar_collisions.length; a++) { @@ -89,11 +88,11 @@ export class MotionEngine { // If this is an obstacle this.lidar.children[i].alpha = 1.; } - if (touch && (lidar_collisions[a].map_id > this.state[pt_y][pt_x] || (lidar_collisions[a].map_id == MAP.ROAD && this.state[pt_y][pt_x]==MAP.DEFAULT))){ + if (touch && (lidar_collisions[a].mapId > this.state[pt_y][pt_x] || (lidar_collisions[a].mapId == MAP.ROAD && this.state[pt_y][pt_x]==MAP.DEFAULT))){ // Add this interaction to the state // If this interaction is more important than the one befor // we kept the more important one - this.state[pt_y][pt_x] = lidar_collisions[a].map_id; + this.state[pt_y][pt_x] = lidar_collisions[a].mapId; } } } diff --git a/src/utils.ts b/src/utils.ts index c263f75..6a995ef 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,5 @@ +import {embeddedContent} from "./embedded"; + /* File with some usefull methods */ @@ -19,6 +21,33 @@ export function loadJSON(url: string, callback: any) { xobj.send(null); } +export function loadEmbeddedURL(url: string, callback: any):void { + let split = url.split("//"); + split = split[1].split("/"); + 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 + * localstorage://level-name + * http(s):// + * embedded::// + @callback function onece the content is loaded + */ + const customCall: any = { + "embedded:": loadEmbeddedURL, + "http://": loadJSON, + "https://": loadJSON, + "localstorage://": loadLocalStorageURL + } + const split = url.split("//"); + customCall[split[0]](url, callback); +} + export function mod(n: number, m:number) { return ((n % m) + m) % m; } @@ -33,7 +62,7 @@ export function argMax(array: number[]) { return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1]; } -export function mean(array: number){ +export function mean(array: number[]){ /** * Return the mean of the array */ @@ -44,7 +73,7 @@ export function mean(array: number){ return avg; } -function saveAs(content: string, name: string) { +export function saveAs(content: string, name: string) { var a = document.createElement("a"); //a.style = "display: none"; document.body.appendChild(a); diff --git a/tsconfig.json b/tsconfig.json index cb7eb6b..1d7e967 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "target": "es5", "lib": ["es2015", "dom"], "outDir": "./dist-es6", - "noUnusedLocals": true, + "noUnusedLocals": false, "noImplicitReturns": true, "noImplicitThis": true, "alwaysStrict": true, diff --git a/webpack.config.js b/webpack.config.js index 2b334da..80ab419 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,4 +1,5 @@ const path = require('path'); +var webpack = require('webpack') var config = { entry: './src/index', @@ -7,26 +8,37 @@ var config = { { test: /\.ts$/, use: 'ts-loader', - }, + } ], }, resolve: { extensions: [ '.ts', ], - } + }, + externals: [ + // Don't bundle pixi.js, assume it'll be included in the HTML via a script + // tag, and made available in the global variable PIXI. + {"pixi.js": "PIXI"} + ] }; var packageConfig = Object.assign({}, config, { output: { filename: 'metacar.min.js', path: path.resolve(__dirname, './dist'), + library: 'metacar', + libraryTarget: 'window', + libraryExport: 'default' } }); var demoConfig = Object.assign({}, config,{ output: { filename: 'metacar.min.js', path: path.resolve(__dirname, './demo/dist'), + library: 'metacar', + libraryTarget: 'window', + libraryExport: 'default' } });