initial add
This commit is contained in:
345
controller.cm
Normal file
345
controller.cm
Normal file
@@ -0,0 +1,345 @@
|
||||
var input = use('input')
|
||||
return {}
|
||||
|
||||
var downkeys = {};
|
||||
|
||||
function keyname(key)
|
||||
{
|
||||
var str = input.keyname(key);
|
||||
return str.toLowerCase();
|
||||
}
|
||||
|
||||
function modstr(mod = input.keymod()) {
|
||||
var s = "";
|
||||
if (mod.ctrl) s += "C-";
|
||||
if (mod.alt) s += "M-";
|
||||
if (mod.super) s += "S-";
|
||||
return s;
|
||||
}
|
||||
|
||||
prosperon.on('key_down', function key_down(e) {
|
||||
downkeys[e.key] = true;
|
||||
var emacs = modstr(e.mod) + keyname(e.key);
|
||||
if (e.repeat) player[0].raw_input(emacs, "rep");
|
||||
else player[0].raw_input(emacs, "pressed");
|
||||
})
|
||||
|
||||
prosperon.on('quit', function() {
|
||||
os.exit(0);
|
||||
})
|
||||
|
||||
prosperon.on('key_up', function key_up(e) {
|
||||
delete downkeys[e.key];
|
||||
var emacs = modstr(e.mod) + keyname(e.key);
|
||||
player[0].raw_input(emacs, "released");
|
||||
})
|
||||
|
||||
prosperon.on('drop_file', function (path) {
|
||||
player[0].raw_input("drop", "pressed", path);
|
||||
})
|
||||
|
||||
var mousepos = [0, 0];
|
||||
|
||||
prosperon.on('text_input', function (e) {
|
||||
player[0].raw_input("char", "pressed", e.text);
|
||||
})
|
||||
|
||||
prosperon.on('mouse_motion', function (e)
|
||||
{
|
||||
mousepos = e.pos;
|
||||
player[0].mouse_input("move", e.pos, e.d_pos);
|
||||
})
|
||||
|
||||
prosperon.on('mouse_wheel', function mousescroll(e) {
|
||||
player[0].mouse_input(modstr() + "scroll", e.scroll);
|
||||
})
|
||||
|
||||
prosperon.on('mouse_button_down', function(e) {
|
||||
player[0].mouse_input(modstr() + e.button, "pressed");
|
||||
input.mouse.buttons[e.button] = true
|
||||
})
|
||||
|
||||
prosperon.on('mouse_button_up', function(e) {
|
||||
player[0].mouse_input(modstr() + e.button, "released");
|
||||
input.mouse.buttons[e.button] = false
|
||||
})
|
||||
|
||||
input.mouse = {};
|
||||
input.mouse.screenpos = function mouse_screenpos() {
|
||||
return mousepos.slice();
|
||||
};
|
||||
input.mouse.worldpos = function mouse_worldpos() {
|
||||
return prosperon.camera.screen2world(mousepos);
|
||||
};
|
||||
input.mouse.viewpos = function mouse_viewpos()
|
||||
{
|
||||
var world = input.mouse.worldpos();
|
||||
|
||||
return mousepos.slice();
|
||||
}
|
||||
input.mouse.disabled = function mouse_disabled() {
|
||||
input.mouse_mode(1);
|
||||
};
|
||||
input.mouse.normal = function mouse_normal() {
|
||||
input.mouse_mode(0);
|
||||
};
|
||||
input.mouse.mode = function mouse_mode(m) {
|
||||
if (input.mouse.custom[m]) input.cursor_img(input.mouse.custom[m]);
|
||||
else input.mouse_cursor(m);
|
||||
};
|
||||
input.mouse.buttons = {
|
||||
0:false,
|
||||
1:false,
|
||||
2:false
|
||||
}
|
||||
|
||||
input.mouse.set_custom_cursor = function mouse_cursor(img, mode = input.mouse.cursor.default) {
|
||||
if (!img) delete input.mouse.custom[mode];
|
||||
else {
|
||||
input.cursor_img(img);
|
||||
input.mouse.custom[mode] = img;
|
||||
}
|
||||
};
|
||||
input.mouse.doc = {};
|
||||
input.mouse.doc.pos = "The screen position of the mouse.";
|
||||
input.mouse.doc.worldpos = "The position in the game world of the mouse.";
|
||||
input.mouse.disabled.doc = "Set the mouse to hidden. This locks it to the game and hides it, but still provides movement and click events.";
|
||||
input.mouse.normal.doc = "Set the mouse to show again after hiding.";
|
||||
|
||||
input.keyboard = {};
|
||||
input.keyboard.down = function (code) {
|
||||
if (typeof code == "number") return downkeys[code];
|
||||
if (typeof code == "string") return downkeys[code.toUpperCase().charCodeAt()] || downkeys[code.toLowerCase().charCodeAt()];
|
||||
return null;
|
||||
};
|
||||
|
||||
input.print_pawn_kbm = function (pawn) {
|
||||
if (!("inputs" in pawn)) return;
|
||||
var str = "";
|
||||
for (var key in pawn.inputs) {
|
||||
if (!pawn.inputs[key].doc) continue;
|
||||
str += `${key} | ${pawn.inputs[key].doc}\n`;
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
var joysticks = {};
|
||||
|
||||
joysticks["wasd"] = {
|
||||
uy: "w",
|
||||
dy: "s",
|
||||
ux: "d",
|
||||
dx: "a",
|
||||
};
|
||||
|
||||
input.procdown = function procdown() {
|
||||
for (var k in downkeys) player[0].raw_input(keyname(k), "down");
|
||||
|
||||
for (var i in joysticks) {
|
||||
var joy = joysticks[i];
|
||||
var x = joy.ux - joy.dx;
|
||||
var y = joy.uy - joy.dy;
|
||||
player[0].joy_input(i, joysticks[i]);
|
||||
}
|
||||
};
|
||||
|
||||
input.print_md_kbm = function print_md_kbm(pawn) {
|
||||
if (!("inputs" in pawn)) return;
|
||||
|
||||
var str = "";
|
||||
str += "|control|description|\n|---|---|\n";
|
||||
|
||||
for (var key in pawn.inputs) {
|
||||
str += `|${key}|${pawn.inputs[key].doc}|`;
|
||||
str += "\n";
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
|
||||
input.has_bind = function (pawn, bind) {
|
||||
return typeof pawn.inputs?.[bind] == "function";
|
||||
};
|
||||
|
||||
input.action = {
|
||||
add_new(name) {
|
||||
var action = Object.create(input.action);
|
||||
action.name = name;
|
||||
action.inputs = [];
|
||||
this.actions.push(action);
|
||||
|
||||
return action;
|
||||
},
|
||||
actions: [],
|
||||
};
|
||||
|
||||
input.tabcomplete = function tabcomplete(val, list) {
|
||||
if (!val) return val;
|
||||
list = filter(x => x.startsWith(val))
|
||||
|
||||
if (list.length == 1) {
|
||||
return list[0];
|
||||
}
|
||||
|
||||
var ret = null;
|
||||
var i = val.length;
|
||||
while (!ret && list.length != 0) {
|
||||
var char = list[0][i];
|
||||
if (
|
||||
!list.every(function (x) {
|
||||
return x[i] == char;
|
||||
})
|
||||
)
|
||||
ret = list[0].slice(0, i);
|
||||
else {
|
||||
i++;
|
||||
list = list.filter(x => x.length-1 > i)
|
||||
}
|
||||
}
|
||||
|
||||
return ret ? ret : val;
|
||||
};
|
||||
|
||||
/* May be a human player; may be an AI player */
|
||||
|
||||
/*
|
||||
'block' on a pawn's input blocks any input from reaching below for the
|
||||
*/
|
||||
|
||||
var Player = {
|
||||
players: [],
|
||||
input(fn, ...args) {
|
||||
this.pawns.forEach(x => x[fn]?.(...args));
|
||||
},
|
||||
|
||||
mouse_input(type, ...args) {
|
||||
for (var pawn of [...this.pawns].reverse()) {
|
||||
if (typeof pawn.inputs?.mouse?.[type] == "function") {
|
||||
pawn.inputs.mouse[type].call(pawn, ...args);
|
||||
pawn.inputs.post?.call(pawn);
|
||||
if (!pawn.inputs.fallthru) return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
char_input(c) {
|
||||
for (var pawn of [...this.pawns].reverse()) {
|
||||
if (typeof pawn.inputs?.char == "function") {
|
||||
pawn.inputs.char.call(pawn, c);
|
||||
pawn.inputs.post?.call(pawn);
|
||||
if (!pawn.inputs.fallthru) return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
joy_input(name, joystick) {
|
||||
for (var pawn of [...this.pawns].reverse()) {
|
||||
if (!pawn.inputs) return;
|
||||
if (!pawn.inputs.joystick) return;
|
||||
if (!pawn.inputs.joystick[name]) return;
|
||||
|
||||
var x = 0;
|
||||
if (input.keyboard.down(joystick.ux)) x++;
|
||||
if (input.keyboard.down(joystick.dx)) x--;
|
||||
var y = 0;
|
||||
if (input.keyboard.down(joystick.uy)) y++;
|
||||
if (input.keyboard.down(joystick.dy)) y--;
|
||||
|
||||
pawn.inputs.joystick[name](x, y);
|
||||
}
|
||||
},
|
||||
|
||||
raw_input(cmd, state, ...args) {
|
||||
for (var pawn of [...this.pawns].reverse()) {
|
||||
var inputs = pawn.inputs;
|
||||
|
||||
if (!inputs[cmd]) {
|
||||
if (inputs.block) return;
|
||||
continue;
|
||||
}
|
||||
|
||||
var fn = null;
|
||||
|
||||
switch (state) {
|
||||
case "pressed":
|
||||
fn = inputs[cmd];
|
||||
break;
|
||||
case "rep":
|
||||
fn = inputs[cmd].rep ? inputs[cmd] : null;
|
||||
break;
|
||||
case "released":
|
||||
fn = inputs[cmd].released;
|
||||
break;
|
||||
case "down":
|
||||
if (typeof inputs[cmd].down == "function") fn = inputs[cmd].down;
|
||||
else if (inputs[cmd].down) fn = inputs[cmd];
|
||||
}
|
||||
|
||||
var consumed = false;
|
||||
if (typeof fn == "function") {
|
||||
fn.call(pawn, ...args);
|
||||
consumed = true;
|
||||
}
|
||||
if (state == "released") inputs.release_post?.call(pawn);
|
||||
if (inputs.block) return;
|
||||
if (consumed) return;
|
||||
}
|
||||
},
|
||||
|
||||
obj_controlled(obj) {
|
||||
for (var p in Player.players) {
|
||||
if (p.pawns.has(obj)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
print_pawns() {
|
||||
[...this.pawns].reverse().forEach(x => log.console(x))
|
||||
},
|
||||
|
||||
create() {
|
||||
var n = Object.create(this);
|
||||
n.pawns = new Set()
|
||||
n.gamepads = [];
|
||||
this.players.push(n);
|
||||
this[this.players.length - 1] = n;
|
||||
return n;
|
||||
},
|
||||
|
||||
control(pawn) {
|
||||
if (!pawn)
|
||||
return
|
||||
|
||||
if (!pawn.inputs)
|
||||
throw new Error("attempted to control a pawn without any input object.");
|
||||
|
||||
this.pawns.add(pawn);
|
||||
},
|
||||
|
||||
uncontrol(pawn) {
|
||||
this.pawns.delete(pawn)
|
||||
},
|
||||
};
|
||||
|
||||
input.do_uncontrol = function input_do_uncontrol(pawn) {
|
||||
if (!pawn.inputs) return;
|
||||
Player.players.forEach(function (p) {
|
||||
p.pawns.delete(pawn)
|
||||
});
|
||||
};
|
||||
|
||||
//for (var i = 0; i < 4; i++)
|
||||
Player.create();
|
||||
|
||||
Player.control.doc = "Control a provided object, if the object has an 'inputs' object.";
|
||||
Player.uncontrol.doc = "Uncontrol a previously controlled object.";
|
||||
Player.print_pawns.doc = "Print out a list of the current pawn control stack.";
|
||||
Player.doc = {};
|
||||
Player.doc.players = "A list of current players.";
|
||||
|
||||
var player = Player;
|
||||
|
||||
input.player = Player
|
||||
|
||||
return input
|
||||
Reference in New Issue
Block a user