mirror of
https://github.com/wassname/metacar.git
synced 2026-09-09 11:26:47 +08:00
Add event API + level1
This commit is contained in:
Vendored
+17
-5
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hello World</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="canvas" id="canvas"></div>
|
||||
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.7.1/pixi.min.js"></script>
|
||||
<script src="/dist/metacar.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/public/js/level1.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
// Get the url of the desired level
|
||||
let levelUrl = metacar.level.level1;
|
||||
// Create the environement (canvasID, levelUrl)
|
||||
var env = new metacar.env("canvas", levelUrl);
|
||||
env.load().then(() => {
|
||||
// The level is loaded. Add listernes
|
||||
env.addEvent("train", () => {
|
||||
console.log("On train!");
|
||||
});
|
||||
env.addEvent("play", () => {
|
||||
console.log("On play!");
|
||||
});
|
||||
env.addEvent("stop", () => {
|
||||
console.log("On sotp!");
|
||||
});
|
||||
env.addEvent("reset_env", () => {
|
||||
console.log("On reset env!");
|
||||
});
|
||||
env.addEvent("reset_agent", () => {
|
||||
console.log("On reset agent");
|
||||
})
|
||||
env.addEvent("save", () => {
|
||||
console.log("On save");
|
||||
});
|
||||
env.addEvent("load", (content) => {
|
||||
console.log("content", content);
|
||||
});
|
||||
});
|
||||
Vendored
+17
-5
File diff suppressed because one or more lines are too long
@@ -77,15 +77,15 @@ export class BasicMotionEngine extends MotionEngine {
|
||||
}
|
||||
}
|
||||
|
||||
turnLeft(){
|
||||
turnLeft():void {
|
||||
/*
|
||||
Turn left
|
||||
*/
|
||||
this.car.rotation -= this.rotationStep*Math.PI;
|
||||
this.lidar.rotation = this.car.rotation;
|
||||
this.car.rotation -= this.rotationStep*Math.PI
|
||||
this.lidar.rotation = this.car.rotation;
|
||||
}
|
||||
|
||||
turnRight(){
|
||||
turnRight():void {
|
||||
/*
|
||||
Turn right
|
||||
*/
|
||||
@@ -93,14 +93,14 @@ export class BasicMotionEngine extends MotionEngine {
|
||||
this.lidar.rotation = this.car.rotation;
|
||||
}
|
||||
|
||||
moveForward(){
|
||||
moveForward():void {
|
||||
/*
|
||||
Move forward
|
||||
*/
|
||||
this.car.v = 1;
|
||||
}
|
||||
|
||||
moveBackward(){
|
||||
moveBackward():void {
|
||||
/*
|
||||
Move backward
|
||||
*/
|
||||
|
||||
+5
-2
@@ -1,11 +1,14 @@
|
||||
import {fullCity} from "./embedded/level/full_city";
|
||||
import {level1} from "./embedded/level/level_1";
|
||||
|
||||
export const embeddedUrl: any = {
|
||||
fullCity: "embedded://level/fullCity"
|
||||
fullCity: "embedded://level/fullCity",
|
||||
level1: "embedded://level/level1"
|
||||
}
|
||||
|
||||
export const embeddedContent: any = {
|
||||
level: {
|
||||
fullCity: fullCity
|
||||
fullCity: fullCity,
|
||||
level1: level1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
export const level1: any = {
|
||||
"cars": [
|
||||
{
|
||||
"mx": 5,
|
||||
"my": 3,
|
||||
"line": 0,
|
||||
"auto": true
|
||||
},
|
||||
{
|
||||
"mx": 5,
|
||||
"my": 3,
|
||||
"line": 1,
|
||||
"auto": true
|
||||
},
|
||||
{
|
||||
"mx": 5,
|
||||
"my": 1,
|
||||
"line": 0,
|
||||
"auto": true
|
||||
}
|
||||
],
|
||||
"tree": [
|
||||
{
|
||||
"x": 120,
|
||||
"y": 50
|
||||
},
|
||||
{
|
||||
"x": 86.5,
|
||||
"y": 85
|
||||
},
|
||||
{
|
||||
"x": 94.5,
|
||||
"y": 135
|
||||
},
|
||||
{
|
||||
"x": 30.5,
|
||||
"y": 128
|
||||
},
|
||||
{
|
||||
"x": 72.5,
|
||||
"y": 190
|
||||
},
|
||||
{
|
||||
"x": 23.5,
|
||||
"y": 232
|
||||
},
|
||||
{
|
||||
"x": 110.5,
|
||||
"y": 242
|
||||
},
|
||||
{
|
||||
"x": 43.5,
|
||||
"y": 33
|
||||
},
|
||||
{
|
||||
"x": 18.5,
|
||||
"y": 178
|
||||
},
|
||||
{
|
||||
"x": 305.5,
|
||||
"y": 125
|
||||
},
|
||||
{
|
||||
"x": 360.5,
|
||||
"y": 122
|
||||
}
|
||||
],
|
||||
"asset": [
|
||||
{
|
||||
"x": 252.5,
|
||||
"y": 142
|
||||
},
|
||||
{
|
||||
"x": 86.5,
|
||||
"y": 85
|
||||
},
|
||||
{
|
||||
"x": 94.5,
|
||||
"y": 135
|
||||
},
|
||||
{
|
||||
"x": 30.5,
|
||||
"y": 128
|
||||
},
|
||||
{
|
||||
"x": 252.5,
|
||||
"y": 26
|
||||
},
|
||||
{
|
||||
"x": 195.5,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 307.5,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 72.5,
|
||||
"y": 190
|
||||
},
|
||||
{
|
||||
"x": 23.5,
|
||||
"y": 232
|
||||
},
|
||||
{
|
||||
"x": 110.5,
|
||||
"y": 242
|
||||
},
|
||||
{
|
||||
"x": 43.5,
|
||||
"y": 33
|
||||
},
|
||||
{
|
||||
"x": 35.5,
|
||||
"y": 185
|
||||
},
|
||||
{
|
||||
"x": 18.5,
|
||||
"y": 178
|
||||
},
|
||||
{
|
||||
"x": 289.5,
|
||||
"y": 126
|
||||
},
|
||||
{
|
||||
"x": 337.5,
|
||||
"y": 126
|
||||
},
|
||||
{
|
||||
"x": 305.5,
|
||||
"y": 125
|
||||
},
|
||||
{
|
||||
"x": 360.5,
|
||||
"y": 122
|
||||
},
|
||||
{
|
||||
"x": 492.5,
|
||||
"y": 56
|
||||
},
|
||||
{
|
||||
"x": 503.5,
|
||||
"y": 136
|
||||
},
|
||||
{
|
||||
"x": 504.5,
|
||||
"y": 58
|
||||
}
|
||||
],
|
||||
"bench": [
|
||||
{
|
||||
"x": 252.5,
|
||||
"y": 142
|
||||
},
|
||||
{
|
||||
"x": 252.5,
|
||||
"y": 26
|
||||
}
|
||||
],
|
||||
"road": [
|
||||
{
|
||||
"x": 240,
|
||||
"y": 60
|
||||
},
|
||||
{
|
||||
"x": 240,
|
||||
"y": 60
|
||||
},
|
||||
{
|
||||
"x": 480,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 480,
|
||||
"y": 60
|
||||
},
|
||||
{
|
||||
"x": 480,
|
||||
"y": 120
|
||||
},
|
||||
{
|
||||
"x": 480,
|
||||
"y": 180
|
||||
},
|
||||
{
|
||||
"x": 480,
|
||||
"y": 240
|
||||
},
|
||||
{
|
||||
"x": 300,
|
||||
"y": 180
|
||||
},
|
||||
{
|
||||
"x": 300,
|
||||
"y": 180
|
||||
},
|
||||
{
|
||||
"x": 360,
|
||||
"y": 180
|
||||
},
|
||||
{
|
||||
"x": 420,
|
||||
"y": 180
|
||||
},
|
||||
{
|
||||
"x": 420,
|
||||
"y": 120
|
||||
},
|
||||
{
|
||||
"x": 420,
|
||||
"y": 60
|
||||
},
|
||||
{
|
||||
"x": 360,
|
||||
"y": 60
|
||||
},
|
||||
{
|
||||
"x": 300,
|
||||
"y": 60
|
||||
},
|
||||
{
|
||||
"x": 420,
|
||||
"y": 120
|
||||
}
|
||||
],
|
||||
"house3": [
|
||||
{
|
||||
"x": 503.5,
|
||||
"y": 136
|
||||
}
|
||||
],
|
||||
"house": [
|
||||
{
|
||||
"x": 504.5,
|
||||
"y": 58
|
||||
}
|
||||
],
|
||||
"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
|
||||
]
|
||||
],
|
||||
"agent": {
|
||||
"mx": 4,
|
||||
"my": 3,
|
||||
"line": 0,
|
||||
"motion": {
|
||||
"type": "BasicMotionEngine",
|
||||
"options": {
|
||||
"rotationStep": 0.5,
|
||||
"actions": [
|
||||
"UP",
|
||||
"LEFT",
|
||||
"RIGHT"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-8
@@ -60,6 +60,15 @@ export class Level {
|
||||
});
|
||||
}
|
||||
|
||||
render(val: boolean){
|
||||
if (val){
|
||||
this.app.ticker.start();
|
||||
}
|
||||
else{
|
||||
this.app.ticker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
createLevel(info: LevelInfo){
|
||||
/*
|
||||
Create the level
|
||||
@@ -98,14 +107,6 @@ export class Level {
|
||||
this.app.ticker.add((delta: number) => this.loop(delta));
|
||||
}
|
||||
|
||||
render(){
|
||||
/*
|
||||
If the rendering has been stopped, this Method
|
||||
restart the rendering.
|
||||
*/
|
||||
this.app.ticker.start();
|
||||
}
|
||||
|
||||
reset(){
|
||||
/*
|
||||
Reset the game.
|
||||
|
||||
+134
-5
@@ -5,6 +5,10 @@
|
||||
import {Level, LevelInfo} from "./level";
|
||||
import * as U from "./utils";
|
||||
|
||||
export interface eventLoadOptions {
|
||||
computer: boolean;
|
||||
}
|
||||
|
||||
export class MetaCar {
|
||||
|
||||
private isPlaying: boolean;
|
||||
@@ -12,6 +16,9 @@ export class MetaCar {
|
||||
private level: Level;
|
||||
private canvasId: string;
|
||||
private levelUrl: string;
|
||||
private eventList: string[] = ["train", "play", "stop", "reset_env", "reset_agent", "save", "load"]
|
||||
private eventCallback: any[];
|
||||
private buttonsContainer: HTMLDivElement;
|
||||
|
||||
constructor(canvasId: string, levelUrl: string) {
|
||||
/**
|
||||
@@ -27,6 +34,23 @@ export class MetaCar {
|
||||
this.isPlaying = false;
|
||||
this.canvasId = canvasId;
|
||||
this.levelUrl = levelUrl;
|
||||
this.eventCallback = [
|
||||
(fc: any) => this.onTrain(fc),
|
||||
(fc: any) => this.onPlay(fc),
|
||||
(fc:any) => this.onStop(fc),
|
||||
(fc: any) => this.onResetEnv(fc),
|
||||
(fc: any) => this.onResetAgent(fc),
|
||||
(fc: any) => this.onSave(fc),
|
||||
(fc: any, opt: eventLoadOptions) => this.onLoad(fc, opt)
|
||||
];
|
||||
|
||||
// Insert the event div
|
||||
var canvas = document.getElementById(canvasId);
|
||||
var buttons = document.createElement('div'); // create new textarea
|
||||
buttons.classList.add("metacar_buttons_container");
|
||||
buttons.id = "metacar_"+ canvasId + "_buttons_container";
|
||||
canvas.parentNode.insertBefore(buttons, canvas.nextSibling);
|
||||
this.buttonsContainer = buttons;
|
||||
}
|
||||
|
||||
load(level: string, agent: any): Promise<void>{
|
||||
@@ -56,8 +80,8 @@ export class MetaCar {
|
||||
});
|
||||
document.getElementById("stop").addEventListener("click", () => {
|
||||
this.isPlaying = false;
|
||||
this.agent.stop();
|
||||
this.level.render();
|
||||
this.agent.stop();
|
||||
});
|
||||
document.getElementById("reset").addEventListener("click", () => {
|
||||
this.level.reset();
|
||||
@@ -74,12 +98,117 @@ export class MetaCar {
|
||||
*/
|
||||
}
|
||||
|
||||
render(){
|
||||
private _createButton(parent: HTMLDivElement, name: string): HTMLButtonElement{
|
||||
var button = document.createElement('button'); // create new textarea
|
||||
button.classList.add("metacar_button_train");
|
||||
button.id = "metacar_"+ this.canvasId + "_button_" + name;
|
||||
// Uppercase first letter and replace _
|
||||
name = name.replace(/_/g , " ");
|
||||
button.innerHTML = name.charAt(0).toUpperCase() + name.slice(1);;
|
||||
parent.appendChild(button);
|
||||
return button
|
||||
}
|
||||
|
||||
onTrain(fc: any){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "train");
|
||||
// Listen the event
|
||||
button.addEventListener("click", () => {
|
||||
this.render(false);
|
||||
if (fc) fc();
|
||||
});
|
||||
}
|
||||
|
||||
onPlay(fc: any){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "play");
|
||||
// Listen the event
|
||||
button.addEventListener("click", () => {
|
||||
if (fc) fc();
|
||||
});
|
||||
}
|
||||
|
||||
onStop(fc: any){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "stop");
|
||||
// Listen the event
|
||||
button.addEventListener("click", () => {
|
||||
if (fc) fc();
|
||||
});
|
||||
}
|
||||
|
||||
onResetEnv(fc: any){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "reset_env");
|
||||
button.addEventListener("click", () => {
|
||||
if (fc) fc();
|
||||
});
|
||||
}
|
||||
|
||||
onResetAgent(fc: any){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "reset_agent");
|
||||
button.addEventListener("click", () => {
|
||||
if (fc) fc();
|
||||
});
|
||||
}
|
||||
|
||||
onSave(fc: any){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "save");
|
||||
button.addEventListener("click", () => {
|
||||
if (fc) fc();
|
||||
});
|
||||
}
|
||||
|
||||
onLoad(fc: any, options: eventLoadOptions){
|
||||
// Create the button
|
||||
const button = this._createButton(this.buttonsContainer, "load_trained_agent");
|
||||
// Create the fake input input file
|
||||
var input_file = document.createElement('input'); // create new textarea
|
||||
input_file.type = "file";
|
||||
input_file.accept = "*/*";
|
||||
input_file.style.display = "none";
|
||||
input_file.classList.add("metacar_button_input_file");
|
||||
input_file.id = "metacar_"+ this.canvasId + "_button_input_file";
|
||||
this.buttonsContainer.appendChild(input_file);
|
||||
|
||||
input_file.addEventListener("change", (dump) => {
|
||||
console.log("New file to handle");
|
||||
U.readDump(dump, (content: any) => {
|
||||
if (fc) fc(content);
|
||||
});
|
||||
});
|
||||
|
||||
button.addEventListener("click", () => {
|
||||
input_file.click();
|
||||
});
|
||||
}
|
||||
|
||||
addEvent(eventName: string, fc: any, options?: eventLoadOptions):void {
|
||||
/**
|
||||
* eventName: Name of the event to listen
|
||||
* fc: Function to call each time this event is raise
|
||||
*/
|
||||
const index = this.eventList.indexOf(eventName);
|
||||
if (index == -1){
|
||||
console.error("The environement does not support this event. Only the following are\
|
||||
avaible:" + this.eventList);
|
||||
}
|
||||
const event = this.eventList[index];
|
||||
if (event != "load"){
|
||||
this.eventCallback[index](fc);
|
||||
}
|
||||
else{
|
||||
this.eventCallback[index](fc, options);
|
||||
}
|
||||
}
|
||||
|
||||
render(val: boolean){
|
||||
/*
|
||||
Render the environement
|
||||
again
|
||||
Choose whether to render the environement.
|
||||
*/
|
||||
this.level.render();
|
||||
this.level.render(val);
|
||||
}
|
||||
|
||||
save(content: any, file_name: string){
|
||||
|
||||
+7
-9
@@ -122,18 +122,16 @@ function readBuffer(buffer) {
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function readDump(e, callback) {
|
||||
var input = e.target;
|
||||
export function readDump(dump: any, callback: any) {
|
||||
var input = dump.target;
|
||||
var file = input.files[0];
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.readAsText(file, "UTF-8");
|
||||
reader.onload = (evt) => {
|
||||
reader.onload = (evt:any) => {
|
||||
callback(evt.target.result);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
export function shuffleArray(array: number[]) {
|
||||
/**
|
||||
@@ -174,7 +172,7 @@ export function keyboard(keyCode: any ) {
|
||||
key.isDown = true;
|
||||
key.isUp = false;
|
||||
}
|
||||
event.preventDefault();
|
||||
//event.preventDefault();
|
||||
};
|
||||
|
||||
key.upHandler = (event: any) => {
|
||||
@@ -183,9 +181,9 @@ export function keyboard(keyCode: any ) {
|
||||
key.isDown = false;
|
||||
key.isUp = true;
|
||||
}
|
||||
event.preventDefault();
|
||||
//event.preventDefault();
|
||||
};
|
||||
|
||||
|
||||
//Attach event listeners
|
||||
window.addEventListener(
|
||||
"keydown", key.downHandler.bind(key), false
|
||||
|
||||
Reference in New Issue
Block a user