+function Controls(hero){
+ // processes keyboard / touch / mouse
+ // causes according player actions
+ // single player only, conrol will be assigned to server in multi player
+ var kbdmap = {
+ up: 87, altup: 38,
+ down: 83, altdown: 40,
+ left: 65, altleft: 37,
+ right: 68, altright: 39,
+ }
+ var keys = [];
+
+ window.addEventListener("keydown", e => keys[e.keyCode] = true );
+ window.addEventListener("keyup" , e => keys[e.keyCode] = false);
+ setInterval(() => input(), 33.33)
+
+ // cause player to walk, processes blocked terrain and player speed
+ // x/y are factors of speed and direction
+ // i.e. +/-1 for diagonal movement
+ // and +/-1.4 for horizontal/vertical movement
+ function translate(x, y){
+ var sx = map.info.header.tilewidth * hero.stats.speed / 33.33;
+ var sy = map.info.header.tileheight * hero.stats.speed / 33.33;
+ var dx = x * sx, hx = hero.position[0];
+ var dy = y * sy, hy = hero.position[1];
+ var f = 2.1;
+ const col = map.info.layer.find(l => l.type == "collision").data;
+
+ if (col[map.tileAt(hx + dx, hy + dy)] == 0 )
+ hero.place(hx + dx, hy + dy);
+ else if ( dy == 0 && col[map.tileAt(hx + dx / f, hy + sy / 1.5)] == 0 )
+ hero.place(hx + dx / f, hy + sy / 1.5);
+ else if ( dy == 0 && col[map.tileAt(hx + dx / f, hy - sy / 1.5)] == 0 )
+ hero.place(hx + dx / f, hy - sy / 1.5);
+ else if ( dx == 0 && col[map.tileAt(hx + sx / 1.5, hy + dy / f)] == 0 )
+ hero.place(hx + sx / 1.5, hy + dy / f);
+ else if ( dx == 0 && col[map.tileAt(hx - sx / 1.5, hy + dy / f)] == 0 )
+ hero.place(hx - sx / 1.5, hy + dy / f);
+ else player.stance();
+
+ map.center(hero.position[0], hero.position[1]);
+ events(hero.position[0], hero.position[1]);
+ }
+
+ function events(x, y) {
+ const i = map.tileAt(x,y); var ev;
+ if (map.events[i]) {
+ // intermap
+ if ( ev = map.events[i].find(e => (e.activate == "on_trigger" && e.intermap)) ){
+ ev = ev.intermap.split(/[,]/);
+ map = new Map(ev[0]);
+ hero.place( map.xOf(ev[1] * 1, ev[2] * 1), map.yOf(ev[1] * 1, ev[2] * 1) );
+ map.center( map.xOf(ev[1] * 1, ev[2] * 1), map.yOf(ev[1] * 1, ev[2] * 1) );
+ }
+ }
+ }
+
+ // process input and decide on according action
+ function input(){
+ // facing directions, indexed by OR of key press combinations
+ const dir = [ -1, 0, 4, -1, 2, 1, 3, 2, 6, 7, 5, 6, -1, 0, 4, -1 ];
+ // translation speed and direction, indexed by facing direction of movement
+ const trans = [ [-1.4,0], [-1,-1], [0,-1.4], [1,-1], [1.4,0], [1,1], [0,1.4], [-1,1] ];
+ var k = 0;
+
+ // OR of direction key presses
+ k += (keys[kbdmap.left] || keys[kbdmap.altleft]) ? 1 : 0;
+ k += (keys[kbdmap.right] || keys[kbdmap.altright]) ? 2 : 0;
+ k += (keys[kbdmap.up] || keys[kbdmap.altup]) ? 4 : 0;
+ k += (keys[kbdmap.down] || keys[kbdmap.altdown]) ? 8 : 0;
+
+ if (~dir[k]) {
+ hero.direct(dir[k]).run();
+ translate(trans[dir[k]][0], trans[dir[k]][1]);
+ } else hero.stance();
+ }
+}
+
+document.querySelector("body").setAttribute("style", "margin: 0; padding: 0;");
+canvas = document.createElement("canvas").getContext("2d");
+canvas.canvas.setAttribute("style", "display: block; border: 0; margin: 0; padding: 0;");
+document.querySelector("body").appendChild(canvas.canvas);
+
+canvas.canvas.width = window.innerWidth;
+canvas.canvas.height = window.innerHeight;
+window.addEventListener("resize", function(){
+ canvas.canvas.width = window.innerWidth;
+ canvas.canvas.height = window.innerHeight;
+});
+
+// player = new Mob("animations/enemies/zombie.txt"); player.stats = { speed: 3 };
+player = new Hero();
+map = new Map("/maps/arrival.txt");
+player.place(map.xOf(map.info.header.hero_pos[0], map.info.header.hero_pos[1]),
+ map.yOf(map.info.header.hero_pos[0], map.info.header.hero_pos[1]));
+player.direct(6).stance();