mirror of
https://gitlab.com/skysthelimit.dev/selenite.git
synced 2025-06-16 02:22:07 -05:00
308 lines
8.9 KiB
JavaScript
308 lines
8.9 KiB
JavaScript
/* Triggers.js */
|
|
// Keeps track of triggers, which mainly consist of key presses,
|
|
// and messages, which would be from an index.html UI
|
|
|
|
function resetTriggers() {
|
|
// Make the controls object
|
|
window.controls = new Controls({
|
|
left: [37, 65, "AXIS_LEFT", "DPAD_LEFT"], // a, left
|
|
right: [39, 68, "AXIS_RIGHT", "DPAD_RIGHT"], // d, right
|
|
up: [38, 87, 32, "FACE_1", "DPAD_UP", "LEFT_BOTTOM_SHOULDER"], // w, up
|
|
down: [40, 83, "AXIS_DOWN", "DPAD_DOWN"], // s, down
|
|
sprint: [16, 17, "FACE_1"], // shift, ctrl
|
|
pause: [80, "START_FORWARD"], // p
|
|
mute: [77], // m
|
|
q: [81] // q
|
|
});
|
|
|
|
// Gamepad.js support for joysticks and controllers
|
|
window.gamepad = new Gamepad();
|
|
gamepad.bind(Gamepad.Event.BUTTON_DOWN, ControlsPipe("keydown", true));
|
|
gamepad.bind(Gamepad.Event.BUTTON_UP, ControlsPipe("keyup", false));
|
|
gamepad.bind(Gamepad.Event.AXIS_CHANGED, function(event) {
|
|
var value = event.value,
|
|
value_abs = abs(value);
|
|
|
|
// Don't allow tremors
|
|
if(value_abs < 0.1) return;
|
|
|
|
// Depending on the axis used...
|
|
switch(event.axis) {
|
|
// Left stick, vertical
|
|
case "LEFT_STICK_Y":
|
|
case "RIGHT_STICK_Y":
|
|
// If it actually has a direction, either go up or down
|
|
if(value_abs > 0.5) {
|
|
keydown(value > 0 ? "DPAD_DOWN" : "DPAD_UP");
|
|
}
|
|
// It doesn't have a direction, so they're both unpressed
|
|
else {
|
|
keyup("DPAD_UP");
|
|
keyup("DPAD_DOWN");
|
|
}
|
|
break;
|
|
// Left stick, horizontal
|
|
case "LEFT_STICK_X":
|
|
case "RIGHT_STICK_X":
|
|
// If it actually has a direction, either go left or right
|
|
if(value_abs > 0.5) {
|
|
keydown(value < 0 ? "DPAD_LEFT" : "DPAD_RIGHT");
|
|
}
|
|
// It doesn't have a direction, so they're both unpressed
|
|
else {
|
|
keyup("DPAD_UP");
|
|
keyup("DPAD_DOWN");
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
|
|
gamepad.init();
|
|
|
|
// Set the key events on the body
|
|
proliferate(body, {
|
|
onkeydown: ControlsPipe("keydown", true),
|
|
onkeyup: ControlsPipe("keyup", false),
|
|
oncontextmenu: contextmenu,
|
|
onmousedown: mousedown
|
|
});
|
|
|
|
// Set UI triggers
|
|
setMessageTriggers();
|
|
}
|
|
|
|
// Hash table for onkeydown and onkeyup
|
|
function Controls(pipes, gamepadPipes) {
|
|
// Pipes is a listing of which actions are piped to by which character codes
|
|
this.pipes = pipes;
|
|
|
|
// Actions are piped to the corresponding keydown or keyup via the corresponding ControlsPipe
|
|
var keydown = this.keydown = {
|
|
// Left
|
|
left: function(keys) {
|
|
keys.run = -1;
|
|
keys.left_down = true;
|
|
},
|
|
// Right
|
|
right: function(keys) {
|
|
keys.run = 1;
|
|
keys.right_down = true; // independent of changes to mario.keys.run
|
|
},
|
|
// Up / Jump
|
|
up: function(keys) {
|
|
keys.up = true;
|
|
if(mario.canjump &&/* !mario.crouching &&*/ (mario.resting || map.underwater)) {
|
|
keys.jump = 1;
|
|
mario.canjump = keys.jumplev = 0;
|
|
// To do: can mario make a jumping sound during the spring, and during the pipe cutscenes?
|
|
if(mario.power > 1) play("Jump Super");
|
|
else play("Jump Small");
|
|
if(map.underwater) setTimeout(function() {
|
|
mario.jumping = keys.jump = false;
|
|
}, timer * 14);
|
|
}
|
|
},
|
|
// Down / Crouch
|
|
down: function(keys) {
|
|
keys.crouch = true;
|
|
},
|
|
// Sprint / Fire
|
|
sprint: function(keys) {
|
|
if(mario.power == 3 && keys.sprint == 0 && !keys.crouch)
|
|
mario.fire();
|
|
keys.sprint = 1;
|
|
},
|
|
// Pause
|
|
pause: function(keys) {
|
|
if(!paused && !(window.editing && !editor.playing))
|
|
setTimeout(function() { pause(true); }, 140);
|
|
},
|
|
// Mute / Unmute
|
|
mute: function(keys) {
|
|
toggleMute();
|
|
},
|
|
// qqqqqqq
|
|
q: function(keys) {
|
|
if(++qcount > 28) maxlulz();
|
|
switch(qcount) {
|
|
case 7: lulz(); break;
|
|
case 14: superlulz(); break;
|
|
case 21: hyperlulz(); break;
|
|
}
|
|
}
|
|
};
|
|
var keyup = this.keyup = {
|
|
// Left
|
|
left: function(keys) {
|
|
keys.run = 0;
|
|
keys.left_down = false;
|
|
},
|
|
// Right
|
|
right: function(keys) {
|
|
keys.run = 0;
|
|
keys.right_down = false;
|
|
},
|
|
// Up
|
|
up: function(keys) {
|
|
if(!map.underwater) keys.jump = keys.up = 0;
|
|
mario.canjump = true;
|
|
},
|
|
// Down
|
|
down: function(keys) {
|
|
keys.crouch = 0;
|
|
removeCrouch();
|
|
},
|
|
// Spring
|
|
sprint: function(keys) {
|
|
keys.sprint = 0;
|
|
},
|
|
// Pause (if held down)
|
|
pause: function(keys) {
|
|
unpause(true);
|
|
},
|
|
}
|
|
|
|
var tag, codes, code, i;
|
|
// Map each character code in pipes to the corresponding key event
|
|
// For each tag ("up", "down"...)
|
|
for(tag in pipes) {
|
|
// For each array of character codes, like 38 (up) or 40 (down)
|
|
codes = pipes[tag];
|
|
for(i in codes) {
|
|
code = codes[i];
|
|
// That code redirects to the equivalent tag (38 -> "up")
|
|
keydown[code] = keydown[tag];
|
|
keyup[code] = keyup[tag];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generates a pipe to the given name
|
|
// For example, ControlsPipe("keydown") pipes to Controls.keydown
|
|
function ControlsPipe(name, strict) {
|
|
var responses = controls[name];
|
|
return function(event) {
|
|
if((strict && ((mario && mario.dead) || window.paused)) || window.nokeys) return;
|
|
|
|
// Allow this to be used as keyup(37) or keyup({which: 37})
|
|
if(typeof(event) != "number" || event.which || event.control)
|
|
event = event.which || event.control;
|
|
|
|
// If there is a known response to this character code, do it
|
|
if(responses[event])
|
|
responses[event](mario.keys);
|
|
// Otherwise only complain if verbosity[name] is true
|
|
else mlog(name, "Could not", name, event);
|
|
|
|
// Record this in the history
|
|
window.gamehistory[gamecount] = [keydown, event];
|
|
};
|
|
}
|
|
|
|
function keydown(event) {
|
|
if((mario && mario.dead) || window.paused || window.nokeys) return;
|
|
var responses = controls["keydown"];
|
|
// Allow this to be used as keyup(37) or keyup({which: 37})
|
|
if(typeof(event) === "object" || event.which)
|
|
event = event.which;
|
|
if(responses[event])
|
|
responses[event](mario.keys);
|
|
|
|
window.gamehistory[gamecount] = [keydown, event];
|
|
}
|
|
|
|
function keyup(event) {
|
|
if(window.nokeys) return;
|
|
var responses = controls["keyup"];
|
|
// Allow this to be used as keyup(37) or keyup({which: 37})
|
|
if(typeof(event) === "object" || event.which)
|
|
event = event.which;
|
|
if(responses[event])
|
|
responses[event](mario.keys);
|
|
|
|
window.gamehistory[gamecount] = [keyup, event];
|
|
}
|
|
|
|
function contextmenu(event) {
|
|
if(event.preventDefault)
|
|
event.preventDefault();
|
|
}
|
|
|
|
function mousedown(event) {
|
|
// Right click
|
|
if(event.which == 3) {
|
|
if(paused) unpause();
|
|
else if((!window.editor) || (!editing && !editor.playing)) pause(true);
|
|
if(event.preventDefault)
|
|
event.preventDefault()
|
|
}
|
|
}
|
|
|
|
function scriptKeys(oldhistory) {
|
|
var i, entry;
|
|
for(i in oldhistory) {
|
|
entry = oldhistory[i];
|
|
TimeHandler.addEvent(entry[0], i, entry[1]);
|
|
TimeHandler.addEvent(function() { alert(entry[0].name + ", " + entry[1]) }, i);
|
|
}
|
|
}
|
|
|
|
|
|
function lulz(options, timer) {
|
|
mario.star = true;
|
|
options = options || [Goomba];
|
|
timer = timer || 7;
|
|
TimeHandler.addEvent(function() {
|
|
if(characters.length > 210) return;
|
|
var lul = new Thing(options[randInt(options.length)], randBoolJS(), randBoolJS());
|
|
lul.yvel = random() * -unitsizet4;
|
|
lul.xvel = lul.speed = random() * unitsizet2 * randSign();
|
|
addThing(lul, (32 * random() + 128) * unitsize, (88 * random()) * unitsize);
|
|
}, timer, Infinity);
|
|
}
|
|
function superlulz() {
|
|
lulz([Goomba, Koopa, Beetle, HammerBro, Lakitu, Podoboo, Blooper]);
|
|
}
|
|
function hyperlulz() {
|
|
lulz([Bowser], 21);
|
|
}
|
|
function maxlulz() {
|
|
// Sigh....
|
|
// window.palette = arrayShuffle(window.palette, 1);
|
|
// clearAllSprites(true);
|
|
TimeHandler.addEvent(function(arr) {
|
|
setAreaSetting(arr[randInt(arr.length)]);
|
|
}, 7, Infinity, ["Overworld", "Underworld", "Underwater", "Sky", "Castle"]);
|
|
}
|
|
|
|
|
|
|
|
/* Triggers (from a UI)
|
|
*/
|
|
function setMessageTriggers() {
|
|
// Commands will be sent in by these codes
|
|
var command_codes = {
|
|
setMap: triggerSetMap,
|
|
startEditor: function() { loadEditor(); }
|
|
};
|
|
|
|
// When a message is received, send it to the appropriate command code
|
|
window.addEventListener("message", function(event) {
|
|
var data = event.data,
|
|
type = data.type;
|
|
// If the type is known, do it
|
|
if(command_codes[type])
|
|
command_codes[type](data);
|
|
// Otherwise complain
|
|
else {
|
|
console.log("Unknown event type received:", type, ".\n", data);
|
|
}
|
|
});
|
|
}
|
|
|
|
// The UI has requested a map change
|
|
function triggerSetMap(data) {
|
|
clearMarioStats();
|
|
setMap.apply(this, data.map || []);
|
|
setLives(3);
|
|
} |