【超级玛丽】是一个基于HTML5
和JavaScript
开发的经典电子游戏。玩家需要控制主角马里奥在各种关卡中跳跃、奔跑、消灭敌人,以完成游戏目标。玩家通过浏览器可以体验经典的超级玛丽关卡和冒险。
运行效果:方向键控制马里奥的左右移动、跳跃、奔跑;
CTRL
键发射子弹
HTML
源码-mario.html
:<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>Full Screen Mario</title>
<link href="mario.css" rel="stylesheet">
<link href="Fonts/stylesheet.css" rel="stylesheet">
<script src="data.js"></script>
<script src="editor.js"></script>
<script src="events.js"></script>
<script src="generator.js"></script>
<script src="library.js"></script>
<script src="load.js"></script>
<script src="maps.js"></script>
<script src="mario.js"></script>
<script src="quadrants.js"></script>
<script src="sounds.js"></script>
<script src="sprites.js"></script>
<script src="things.js"></script>
<script src="toned.js"></script>
<script src="triggers.js"></script>
<script src="upkeep.js"></script>
<script src="utility.js"></script>
<script src="gamepad.js"></script>
</head>
<body onload="FullScreenMario()">
</body>
</html>
CSS
源码-mario.css
:html { background: black; }
html, body, .text, .display {
border: 0;
margin: 0;
padding: 0;
color: #fafafa;
text-align: center;
vertical-align: middle;
font-family: 'Press Start';
z-index: 84;
-webkit-font-smoothing: none;
-webkit-user-select: none;
}
body {
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
position: absolute;
left: 0;
}
.display {
position: fixed;
font-size: 21px;
}
.indisplay {
margin: 7px 14px 0 14px;
text-align: center;
z-index: 14;
}
.indisplay.counter, .indisplay.seed {
position: fixed;
padding: 3px 7px;
bottom: 0;
background: rgba(0,0,0,.49);
}
.indisplay.counter { right: 0; }
.indisplay.seed{ left: 0; }
.text {
position: absolute;
z-index: 14;
text-align: left;
line-height: 210%;
vertical-align: middle;
}
.text * {
margin: 0;
}
.score {
width: 35px;
height: 14px;
font-size: 21px;
z-index: 14;
}
.editor #data_display {
display: none;
}
#sidebar {
background: black;
position: fixed;
right: -322px;
width: 343px;
height: 100%;
z-index: 96;
border-left: 2px solid #ccc;
transition: right 280ms;
}
#sidebar:hover , #sidebar.expanded { right: 0; }
#sidebar * {
font-family: 'Press Start';
line-height: 140%;
color: #ddd;
}
#sidebar #sectionselect {
font-size: 1.4em;
}
#sidebar h1 {
font-size: 1.4em;
padding-bottom: 14px;
border-bottom: 2px solid #999;
}
#sidebar .group {
padding: 7px;
width: 100%;
min-height: 70px;
line-height: 175%;
}
#sidebar .group select , #sidebar .group input{
padding-bottom: 3px;
height: 21px;
border: 1px solid #333;
border-radius: 3px;
background-color: black;
}
#sidebar #options {
font-size: 17px;
}
#sidebar .options.big {
padding-top: 3px;
height: 28px;
text-align: center;
font-size: 21px;
}
#sidebar #options h3.title {
margin-top: -21px;
padding-right: 105px;
border-bottom: 1px solid #777;
text-align: right;
font-size: 19px;
}
#sidebar #options input, #sidebar #options select {
margin-top: -14px;
padding: 3px;
max-width: 175px;
min-height: 24px;
background: black;
border: 1px solid #333;
text-align: left;
}
#sidebar #options .auto {
padding: 3px 7px;
text-align: left;
}
#sidebar #options input[type=Number] {
max-width: 63px;
}
#sidebar #options .optspan {
margin-right: 3px;
font-size: 14px;
color: #aaa;
}
#sidebar #options .optspan + input {
margin-top: -3px;
}
#options tr td:first-of-type {
text-align: right;
}
#options tr td:last-of-type {
text-align: left;
}
#controls {
position: absolute;
bottom: 0;
right: 3px;
transition: 70ms opacity;
}
.control {
float: right;
width: 64px;
height: 64px;
border: 2px solid #aaa;
cursor: pointer;
transition: 49ms opacity;
opacity: .7;
}
.control:hover, .control.enabled { opacity: 1; }
.controltext {
padding-top: 21px;
font-size: 11px;
opacity: .49;
}
#bottombar {
position: absolute;
bottom: 68px;
background: #111;
transition: all 280ms, visibility 0;
opacity: .7;
}
#bottombar:hover {
opacity: 1;
}
#bottombar .holder {
float: left;
width: 64px;
height: 64px;
border: 2px solid white;
cursor: pointer;
overflow: hidden;
}
#bottombar canvas {
position: static;
max-height: 100%;
}
#maplines {
position: fixed;
height: 100%;
width: 100%;
opacity: .49;
border-left: 2px dashed #ddd;
cursor: crosshair;
}
.mapline {
position: fixed;
padding: 1px;
width: 100%;
border-top: 2px dashed #eee;
text-align: left;
cursor: crosshair;
}
#erasing canvas, .erasing #maplines, .erasing .mapline, .erasing #follower {
cursor: url(Theme/EraserTip.gif), pointer;
}
#follower {
cursor: crosshair;
}
.scroller {
position: fixed;
width: 64px;
height: 128px;
opacity: .21;
z-index: 7;
cursor: none;
background: url('Theme/Hand.gif') center center no-repeat;
}
.scroller:hover { opacity: .84; }
.scroller.off {
display: none;
visibility: hidden;
z-index: -35;
}
.flipped {
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";
}
#input_window {
position: fixed;
height: 100%;
padding-top: 42px;
background: rgba(7,21,0,.84);
box-shadow: 0 0 210px rgba(0,0,1,.7) inset;
z-index: 98;
}
#input_window textarea {
margin-top: 35px;
padding: 7px 21px 14px 28px;
width: 100%;
height: 50%;
background-color: rgba(14, 14, 14, .77);
background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAGZmZv///yH5BAEAAAEALAAAAAABAAEAAAICRAEAOw==);
background-repeat: repeat-y;
background-position: 21px;
border-width: 1px 0 1px 0;
color: white;
vertical-align: top;
font-family: "Courier New", "Courier", monospace;
}
#input_window textarea:focus {
outline: 0;
border-color: gold;
}
#input_window .window_button {
float: right;
margin: 0 21px 0 0;
padding: 11px;
padding-bottom: 7px;
border: 3px solid rgba(175,175,175,.7);
border-top: 0;
border-bottom-right-radius: 7px;
border-bottom-left-radius: 7px;
cursor: pointer;
}
#window_submit {
margin-right: 4%;
background: rgba(14,70,14,.84);
font-size: 21px;
}
#window_cancel {
margin-right: 14px;
background: rgba(70,14,14,.84);
}
JS
源码mario.js
function FullScreenMario() {
var time_start = Date.now();
ensureLocalStorage();
TonedJS(true);
window.body = document.body;
window.bodystyle = body.style;
window.verbosity = {Maps: false,
Sounds: false,
};
if(Function.prototype.name === undefined && Object.defineProperty !== undefined) {
Object.defineProperty(Function.prototype, 'name', {
get: function() {
var funcNameRegex = /function\s([^(]{1,})\(/,
results = (funcNameRegex).exec((this).toString());
return (results && results.length > 1) ? results[1].trim() : "";
},
set: function(value) {}
});
}
window.requestAnimationFrame = window.requestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(func) { setTimeout(func, timer); };
window.cancelAnimationFrame = window.cancelAnimationFrame
|| window.webkitCancelRequestAnimationFrame
|| window.mozCancelRequestAnimationFrame
|| window.oCancelRequestAnimationFrame
|| window.msCancelRequestAnimationFrame
|| clearTimeout;
window.Uint8ClampedArray = window.Uint8ClampedArray
|| window.Uint8Array
|| Array;
window.Uint8ArrayName = Uint8ClampedArray.name || "Uint8Array"; // ie
resetMeasurements();
resetLibrary();
resetCanvas();
resetMaps();
resetScenery();
resetTriggers();
resetSeed();
resetSounds();
window.gameon = true;
setMap(1,1);
startLoadingSounds();
log("It took " + (Date.now() - time_start) + " milliseconds to start.");
}
function ensureLocalStorage() {
var ls_ok = false;
try {
if(!window.hasOwnProperty("localStorage"))
window.localStorage = { crappy: true };
if(window.localStorage) ls_ok = true;
}
catch(err) {
ls_ok = false;
}
if(!ls_ok) {
var nope = document.body.innerText = "It seems your browser does not allow localStorage!";
throw nope;
}
}
function resetMeasurements() {
resetUnitsize(4);
resetTimer(1000 / 60);
window.jumplev1 = 32;
window.jumplev2 = 64;
window.ceillev = 88;
window.ceilmax = 104;
window.castlev = -48;
window.paused = true;
resetGameScreen();
if(!window.parentwindow) window.parentwindow = false;
}
function resetUnitsize(num) {
window.unitsize = num;
for(var i = 2; i <= 64; ++i) {
window["unitsizet" + i] = unitsize * i;
window["unitsized" + i] = unitsize / i;
}
window.scale = unitsized2;
window.gravity = round(12 * unitsize) / 100;
}
function resetTimer(num) {
num = roundDigit(num, .001);
window.timer = window.timernorm = num;
window.timert2 = num * 2;
window.timerd2 = num / 2;
window.fps = window.fps_target = roundDigit(1000 / num, .001);
window.time_prev = Date.now();
}
function resetGameScreen() {
window.gamescreen = new getGameScreen();
}
function getGameScreen() {
resetGameScreenPosition(this);
this.middlex = (this.left + this.right) / 2;
window.botmax = this.height - ceilmax;
if(botmax < unitsize) {
body.innerHTML = "<div><br>Your screen isn't high enough. Make it taller, then refresh.</div>";
}
this.deathheight = this.bottom + 48;
}
function resetGameScreenPosition(me) {
me = me || window.gamescreen;
me.left = me.top = 0;
me.bottom = innerHeight;
me.right = innerWidth;
me.height = innerHeight / unitsize;
me.width = innerWidth / unitsize;
me.unitheight = innerHeight;
me.unitwidth = innerWidth;
}
function resetGameState(nocount) {
clearAllTimeouts();
resetData();
window.nokeys = window.spawning = window.spawnon =
window.notime = window.editing = window.qcount = window.lastscroll = 0;
window.paused = window.gameon = true;
if(!nocount) window.gamecount = 0;
resetQuadrants();
window.gamehistory = [];
window.gamehistory = [];
pauseAllSounds();
sounds = {};
}
function scrollWindow(x, y) {
x = x || 0; y = y || 0;
var xinv = -x, yinv = -y;
gamescreen.left += x; gamescreen.right += x;
gamescreen.top += y; gamescreen.bottom += y;
shiftAll(characters, xinv, yinv);
shiftAll(solids, xinv, yinv);
shiftAll(scenery, xinv, yinv);
shiftAll(quads, xinv, yinv);
shiftElements(texts, xinv, yinv);
updateQuads(xinv);
if(window.playediting) scrollEditor(x, y);
}
function shiftAll(stuff, x, y) {
for(var i = stuff.length - 1; i >= 0; --i)
shiftBoth(stuff[i], x, y);
}
function shiftElements(stuff, x, y) {
for(var i = stuff.length - 1, elem; i >= 0; --i) {
elem = stuff[i];
elementShiftLeft(elem, x);
elementShiftTop(elem, y);
}
}
function scrollMario(x, y, see) {
var saveleft = mario.left,
savetop = mario.top;
y = y || 0;
scrollWindow(x,y);
setLeft(mario, saveleft, see);
setTop(mario, savetop + y * unitsize, see);
updateQuads();
}
function mlog(type) {
if(verbosity[type]) {
log.apply(console, arguments);
}
}
data.js
function resetData() {
var check;
if(check = document.getElementById("data_display"))
body.removeChild(check);
if(!window.data) {
window.data = new Data();
}
}
function Data() {
this.mariopower = 1;
this.traveled = this.traveledold = 0;
this.scorelevs = [100, 200, 400, 500, 800, 1000, 2000, 4000, 5000, 8000];
this.score = new DataObject(0, 6, "SCORE");
this.time = new DataObject(350, 3, "TIME");
this.world = new DataObject(0, 0, "WORLD");
this.coins = new DataObject(0, 0, "COINS");
this.lives = new DataObject(3, 1, "LIVES");
this.time.dir = -1;
this.scoreold = 0;
}
function DataObject(amount, length, name) {
this.amount = amount;
this.length = length;
this.name = name;
this.element = createElement("td", {className: "indisplay"});
}
function setDataDisplay() {
var display = createElement("table", {
id: "data_display",
className: "display",
style: {
width: (gamescreen.right + 14) + "px"
}}),
elems = ["score", "coins", "world", "time", "lives"];
body.appendChild(display);
data.display = display;
for(var i in elems) {
display.appendChild(data[elems[i]].element);
updateDataElement(data[elems[i]]);
}
body.appendChild(data.display);
}
function clearDataDisplay() {
body.removeChild(data_display);
}
function startDataTime() {
addEventInterval(updateDataTime, 25, Infinity, data.time);
}
function updateDataTime(me) {
if(me.dir != 1) {
if(me.amount == 100) playCurrentThemeHurry();
else if(me.amount <= 0) killMario(mario, true);
}
if(!notime) {
map.time = me.amount += me.dir;
updateDataElement(me);
}
}
function updateDataElement(me) {
var text = me.name + "<br />" + (me.amount == "Infinity" ? "Inf" : me.amount);
me.element.innerHTML = text;
me.element.style.width = "";
}
function score(me, amount, appears) {
if(amount <= 0) return;
if(arguments.length == 1) return score(mario, me);
localStorage.highscore = max(localStorage.highscore, data.score.amount += amount);
if(appears) {
var text = addText(amount, me.left, me.top);
text.yvel = -unitsized4;
addEvent(killScore, 49, text);
}
while(data.score > 10000) {
gainLife();
data.score.amount = data.score.amount % 10000;
}
updateDataElement(data.score);
}
function killScore(text) {
body.removeChild(text);
killNormal(text);
deleteThing(text, texts, texts.indexOf(text));
}
function findScore(lev) {
if(lev < data.scorelevs.length) return data.scorelevs[lev];
gainLife();
return -1;
}
function gainLife(num, nosound) {
data.lives.amount += typeof(num) == "number" ? num : 1;
if(!nosound) play("Gain Life");
updateDataElement(data.lives);
}
function setLives(num) {
data.lives.amount = Number(num);
updateDataElement(data.lives);
}
function storeMarioStats() {
data.mariopower = mario.power;
}
function clearMarioStats() {
data.mariopower = mario.power = 1;
}
events.js
function addEvent(func, count) {
if(!(func instanceof Function)) return false;
count = count || 1;
var args = arrayMake(arguments);
args.splice(0, 2);
var contents = {
func: func,
count: gamecount + count,
args: args,
timeout: count,
repeat: true
};
insertSortedEvent(events, contents, contents.count);
return contents;
}
function addEventInterval(func, count, reptimes) {
if(!(func instanceof Function)) return false;
count = count || 1;
var args = arrayMake(arguments);
args.splice(0, 3);
var contents = {
func: func,
count: gamecount + count,
args: args,
timeout: count,
repeat: reptimes
};
contents.func.event = contents;
insertSortedEvent(events, contents, contents.count);
return contents;
}
function addEventIntervalSynched(func, count, reptimes, me, settings) {
var calctime = count * settings.length,
entry = ceil(gamecount / calctime) * calctime,
scope = this,
addfunc = function(scope, args, me) {
me.startcount = gamecount;
return addEventInterval.apply(scope, args);
};
if(entry == gamecount) {
return addfunc(scope, arguments, me);
}
else {
var dt = entry - gamecount;
addEvent(addfunc, dt, scope, arguments, me);
}
}
function handleEvents() {
++gamecount;
var events_current = events[gamecount],
event, repfunc,
len, i;
if(!events_current) return;
for(i = 0, len = events_current.length; i < len; ++i) {
event = events_current[i];
if(event.repeat && !event.func.apply(null, event.args)) {
if(event.count_changer) event.count_changer(event);
if(event.repeat instanceof Function) {
repfunc = event.repeat.bind(event);
if(repfunc()) {
event.count += event.timeout;
insertSortedEvent(events, event, event.count);
}
}
else {
if(--event.repeat != 0) {
event.count += event.timeout;
insertSortedEvent(events, event, event.count);
}
}
}
}
delete events[gamecount];
}
function insertSortedEvent(events, contents, count) {
if(!events[count]) events[count] = [];
events[count].push(contents);
}
function clearEvent(event) {
if(!event) return;
event.repeat = false;
}
function clearEventInterval(event) {
if(!event) return;
event.repeat = false;
}
function addSpriteCycle(me, settings, name, timing) {
if(!me.cycles) me.cycles = {};
clearClassCycle(me, name);
var cycle = me.cycles[name || 0] = setSpriteCycle(me, settings, typeof(timing) == "function" ? 0 : timing);
if(cycle.event && typeof(timing) == "function") cycle.event.count_changer = timing;
cycleClass(me, settings);
return cycle;
}
function addSpriteCycleSynched(me, settings, name, timing) {
if(!me.cycles) me.cycles = {}
settings = settings || ["one", "two"];
var cycle = me.cycles[name || 0] = setSpriteCycle(me, settings, timing, true);
clearClassCycle(me, name);
cycleClass(me, settings);
return cycle;
}
function setSpriteCycle(me, settings, timing, synched) {
settings.loc = -1;
settings.oldclass = "761deadsoldiers";
me.onadding = function() {
if(synched) settings.event = addEventIntervalSynched(cycleClass, timing || 9, Infinity, me, settings);
else settings.event = addEventInterval(cycleClass, timing || 9, Infinity, me, settings);
}
if(me.placed) me.onadding();
return settings;
}
function clearClassCycles(me, names) {
names = names.split(" ");
for(var i = names.length - 1; i >= 0; --i)
clearClassCycle(me, names[i]);
}
function clearClassCycle(me, name) {
if(!characterIsAlive(me) || !me.cycles[name]) return;
me.cycles[name][0] = false;
me.cycles[name].length = 1;
delete me.cycles[name];
}
function clearAllCycles(me) {
for(var i in me.cycles)
clearClassCycle(me, i);
}
function cycleClass(me, settings) {
if(!me || !settings || !settings.length) return true;
if(settings.oldclass != "") removeClass(me, settings.oldclass);
settings.loc = ++settings.loc % settings.length;
var current = settings[settings.loc];
if(current) {
var name = current instanceof Function ? current(me, settings) : current;
if(typeof(name) == "string") {
settings.oldclass = name;
addClass(me, name);
return false;
}
else return (name === false);
}
else {
return (current === false);
}
}
function addSpriteCycleManual(me, settings, name, timing) {
if(!me.cycles) me.cycles = {}
me.cycles[name || 0] = setSpriteCycleManual(me, settings, timing);
}
function setSpriteCycleManual(me, settings, timing) {
settings.loc = -1;
settings.oldclass = "761deadsoldiers";
timing = (timing || 9) * timer;
var interval = setInterval(function() {
if(cycleClass(me, settings))
clearInterval(interval);
}, timing);
return settings;
}
function removeSpriteCycle(me, name) {
}
function scrollTime(dx) {
dx = dx || 21;
mario.nofall = mario.nocollide = nokeys = true;
addEventInterval(scrollMario, 1, Infinity, dx);
mario.oldtop = mario.top;
mario.siny = -Math.PI;
addEventInterval(function() {
setTop(mario, mario.oldtop - Math.sin(mario.siny -= .125) * unitsizet8);
}, 1, Infinity);
addEventInterval(function() {
shiftVert(mario, -1.4);
mario.oldtop -= 1.4;
}, 1, 49);
addEventInterval(function() {
if(map.has_lakitu) killFlip(map.has_lakitu);
}, 70);
}
gamepad.js
(function(exports) {
'use strict';
var nullFunction = function() {};
var nullPlatform = {
getType: function() {
return 'null';
},
isSupported: function() {
return false;
},
update: nullFunction
};
var AnimFrameUpdateStrategy = function(requestAnimationFrame) {
var that = this;
var win = window;
this.update = nullFunction;
this.requestAnimationFrame = requestAnimationFrame || win.requestAnimationFrame ||
win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame;
this.tickFunction = function() {
that.update();
that.startTicker();
};
this.startTicker = function() {
that.requestAnimationFrame.apply(win, [that.tickFunction]);
};
};
AnimFrameUpdateStrategy.prototype.start = function(updateFunction) {
this.update = updateFunction || nullFunction;
this.startTicker();
};
var ManualUpdateStrategy = function() {
};
ManualUpdateStrategy.prototype.update = nullFunction;
ManualUpdateStrategy.prototype.start = function(updateFunction) {
this.update = updateFunction || nullFunction;
};
var WebKitPlatform = function(listener, gamepadGetter) {
this.listener = listener;
this.gamepadGetter = gamepadGetter;
this.knownGamepads = [];
};
WebKitPlatform.factory = function(listener) {
var platform = nullPlatform;
var navigator = window && window.navigator;
if (navigator) {
if (typeof(navigator.webkitGamepads) !== 'undefined') {
platform = new WebKitPlatform(listener, function() {
return navigator.webkitGamepads;
});
} else if (typeof(navigator.webkitGetGamepads) !== 'undefined') {
platform = new WebKitPlatform(listener, function() {
return navigator.webkitGetGamepads();
});
}
}
return platform;
};
WebKitPlatform.getType = function() {
return 'WebKit';
},
WebKitPlatform.prototype.getType = function() {
return WebKitPlatform.getType();
},
WebKitPlatform.prototype.isSupported = function() {
return true;
};
WebKitPlatform.prototype.update = function() {
var that = this;
var gamepads = Array.prototype.slice.call(this.gamepadGetter(), 0);
var gamepad;
var i;
for (i = this.knownGamepads.length - 1; i >= 0; i--) {
gamepad = this.knownGamepads[i];
if (gamepads.indexOf(gamepad) < 0) {
this.knownGamepads.splice(i, 1);
this.listener._disconnect(gamepad);
}
}
for (i = 0; i < gamepads.length; i++) {
gamepad = gamepads[i];
if (gamepad && (that.knownGamepads.indexOf(gamepad) < 0)) {
that.knownGamepads.push(gamepad);
that.listener._connect(gamepad);
}
}
};
var FirefoxPlatform = function(listener) {
this.listener = listener;
window.addEventListener('gamepadconnected', function(e) {
listener._connect(e.gamepad);
});
window.addEventListener('gamepaddisconnected', function(e) {
listener._disconnect(e.gamepad);
});
};
FirefoxPlatform.factory = function(listener) {
var platform = nullPlatform;
if (window && (typeof(window.addEventListener) !== 'undefined')) {
platform = new FirefoxPlatform(listener);
}
return platform;
};
FirefoxPlatform.getType = function() {
return 'Firefox';
},
FirefoxPlatform.prototype.getType = function() {
return FirefoxPlatform.getType();
},
FirefoxPlatform.prototype.isSupported = function() {
return true;
};
FirefoxPlatform.prototype.update = nullFunction;
var Gamepad = function(updateStrategy) {
this.updateStrategy = updateStrategy || new AnimFrameUpdateStrategy();
this.gamepads = [];
this.listeners = {};
this.platform = nullPlatform;
this.deadzone = 0.03;
this.maximizeThreshold = 0.97;
};
Gamepad.UpdateStrategies = {
AnimFrameUpdateStrategy: AnimFrameUpdateStrategy,
ManualUpdateStrategy: ManualUpdateStrategy
};
Gamepad.PlatformFactories = [WebKitPlatform.factory, FirefoxPlatform.factory];
Gamepad.Type = {
PLAYSTATION: 'playstation',
LOGITECH: 'logitech',
XBOX: 'xbox',
UNKNOWN: 'unknown'
};
Gamepad.Event = {
CONNECTED: 'connected',
UNSUPPORTED: 'unsupported',
DISCONNECTED: 'disconnected',
TICK: 'tick',
BUTTON_DOWN: 'button-down',
BUTTON_UP: 'button-up',
AXIS_CHANGED: 'axis-changed'
};
Gamepad.StandardButtons = [
'FACE_1', 'FACE_2', 'FACE_3', 'FACE_4',
'LEFT_TOP_SHOULDER', 'RIGHT_TOP_SHOULDER', 'LEFT_BOTTOM_SHOULDER', 'RIGHT_BOTTOM_SHOULDER',
'SELECT_BACK', 'START_FORWARD', 'LEFT_STICK', 'RIGHT_STICK',
'DPAD_UP', 'DPAD_DOWN', 'DPAD_LEFT', 'DPAD_RIGHT',
'HOME'
];
Gamepad.StandardAxes = ['LEFT_STICK_X', 'LEFT_STICK_Y', 'RIGHT_STICK_X', 'RIGHT_STICK_Y'];
var getControlName = function(names, index, extraPrefix) {
return (index < names.length) ? names[index] : extraPrefix + (index - names.length + 1);
};
Gamepad.StandardMapping = {
env: {},
buttons: {
byButton: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
},
axes: {
byAxis: [0, 1, 2, 3]
}
};
Gamepad.Mappings = [
{
env: {
platform: FirefoxPlatform.getType(),
type: Gamepad.Type.PLAYSTATION
},
buttons: {
byButton: [14, 13, 15, 12, 10, 11, 8, 9, 0, 3, 1, 2, 4, 6, 7, 5, 16]
},
axes: {
byAxis: [0, 1, 2, 3]
}
},
{
env: {
platform: WebKitPlatform.getType(),
type: Gamepad.Type.LOGITECH
},
buttons: { // TODO: This can't be right - LEFT/RIGHT_STICK have same mappings as HOME/DPAD_UP
byButton: [1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 10]
},
axes: {
byAxis: [0, 1, 2, 3]
}
},
{
env: {
platform: FirefoxPlatform.getType(),
type: Gamepad.Type.LOGITECH
},
buttons: {
byButton: [0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 11, 12, 13, 14, 10],
byAxis: [-1, -1, -1, -1, -1, -1, [2, 0, 1],
[2, 0, -1]
]
},
axes: {
byAxis: [0, 1, 3, 4]
}
}
];
Gamepad.prototype.init = function() {
var platform = Gamepad.resolvePlatform(this);
var that = this;
this.platform = platform;
this.updateStrategy.start(function() {
that._update();
});
return platform.isSupported();
};
Gamepad.prototype.bind = function(event, listener) {
if (typeof(this.listeners[event]) === 'undefined') {
this.listeners[event] = [];
}
this.listeners[event].push(listener);
return this;
};
Gamepad.prototype.unbind = function(type, listener) {
if (typeof(type) === 'undefined') {
this.listeners = {};
return;
}
if (typeof(listener) === 'undefined') {
this.listeners[type] = [];
return;
}
if (typeof(this.listeners[type]) === 'undefined') {
return false;
}
for (var i = 0; i < this.listeners[type].length; i++) {
if (this.listeners[type][i] === listener) {
this.listeners[type].splice(i, 1);
return true;
}
}
return false;
};
Gamepad.prototype.count = function() {
return this.gamepads.length;
};
Gamepad.prototype._fire = function(event, data) {
if (typeof(this.listeners[event]) === 'undefined') {
return;
}
for (var i = 0; i < this.listeners[event].length; i++) {
this.listeners[event][i].apply(this.listeners[event][i], [data]);
}
};
Gamepad.getNullPlatform = function() {
return Object.create(nullPlatform);
};
Gamepad.resolvePlatform = function(listener) {
var platform = nullPlatform;
var i;
for (i = 0; !platform.isSupported() && (i < Gamepad.PlatformFactories.length); i++) {
platform = Gamepad.PlatformFactories[i](listener);
}
return platform;
};
Gamepad.prototype._connect = function(gamepad) {
var mapping = this._resolveMapping(gamepad);
var count;
var i;
gamepad.state = {};
gamepad.lastState = {};
gamepad.updater = [];
count = mapping.buttons.byButton.length;
for (i = 0; i < count; i++) {
this._addButtonUpdater(gamepad, mapping, i);
}
count = mapping.axes.byAxis.length;
for (i = 0; i < count; i++) {
this._addAxisUpdater(gamepad, mapping, i);
}
this.gamepads[gamepad.index] = gamepad;
this._fire(Gamepad.Event.CONNECTED, gamepad);
};
Gamepad.prototype._addButtonUpdater = function(gamepad, mapping, index) {
var updater = nullFunction;
var controlName = getControlName(Gamepad.StandardButtons, index, 'EXTRA_BUTTON_');
var getter = this._createButtonGetter(gamepad, mapping.buttons, index);
var that = this;
var buttonEventData = {
gamepad: gamepad,
control: controlName
};
gamepad.state[controlName] = 0;
gamepad.lastState[controlName] = 0;
updater = function() {
var value = getter();
var lastValue = gamepad.lastState[controlName];
var isDown = value > 0.5;
var wasDown = lastValue > 0.5;
gamepad.state[controlName] = value;
if (isDown && !wasDown) {
that._fire(Gamepad.Event.BUTTON_DOWN, Object.create(buttonEventData));
} else if (!isDown && wasDown) {
that._fire(Gamepad.Event.BUTTON_UP, Object.create(buttonEventData));
}
if ((value !== 0) && (value !== 1) && (value !== lastValue)) {
that._fireAxisChangedEvent(gamepad, controlName, value);
}
gamepad.lastState[controlName] = value;
};
gamepad.updater.push(updater);
};
Gamepad.prototype._addAxisUpdater = function(gamepad, mapping, index) {
var updater = nullFunction;
var controlName = getControlName(Gamepad.StandardAxes, index, 'EXTRA_AXIS_');
var getter = this._createAxisGetter(gamepad, mapping.axes, index);
var that = this;
gamepad.state[controlName] = 0;
gamepad.lastState[controlName] = 0;
updater = function() {
var value = getter();
var lastValue = gamepad.lastState[controlName];
gamepad.state[controlName] = value;
if ((value !== lastValue)) {
that._fireAxisChangedEvent(gamepad, controlName, value);
}
gamepad.lastState[controlName] = value;
};
gamepad.updater.push(updater);
};
Gamepad.prototype._fireAxisChangedEvent = function(gamepad, controlName, value) {
var eventData = {
gamepad: gamepad,
axis: controlName,
value: value
};
this._fire(Gamepad.Event.AXIS_CHANGED, eventData);
};
Gamepad.prototype._createButtonGetter = (function() {
var nullGetter = function() {
return 0;
};
var createRangeGetter = function(valueGetter, from, to) {
var getter = nullGetter;
if (from < to) {
getter = function() {
var range = to - from;
var value = valueGetter();
value = (value - from) / range;
return (value < 0) ? 0 : value;
};
} else if (to < from) {
getter = function() {
var range = from - to;
var value = valueGetter();
value = (value - to) / range;
return (value > 1) ? 0 : (1 - value);
};
}
return getter;
};
var isArray = function(thing) {
return Object.prototype.toString.call(thing) === '[object Array]';
};
return function(gamepad, buttons, index) {
var getter = nullGetter;
var entry;
var that = this;
entry = buttons.byButton[index];
if (entry !== -1) {
if ((typeof(entry) === 'number') && (entry < gamepad.buttons.length)) {
getter = function() {
return gamepad.buttons[entry];
};
}
} else if (buttons.byAxis && (index < buttons.byAxis.length)) {
entry = buttons.byAxis[index];
if (isArray(entry) && (entry.length == 3) && (entry[0] < gamepad.axes.length)) {
getter = function() {
var value = gamepad.axes[entry[0]];
return that._applyDeadzoneMaximize(value);
};
getter = createRangeGetter(getter, entry[1], entry[2]);
}
}
return getter;
};
})();
Gamepad.prototype._createAxisGetter = (function() {
var nullGetter = function() {
return 0;
};
return function(gamepad, axes, index) {
var getter = nullGetter;
var entry;
var that = this;
entry = axes.byAxis[index];
if (entry !== -1) {
if ((typeof(entry) === 'number') && (entry < gamepad.axes.length)) {
getter = function() {
var value = gamepad.axes[entry];
return that._applyDeadzoneMaximize(value);
};
}
}
return getter;
};
})();
Gamepad.prototype._disconnect = function(gamepad) {
var newGamepads = [],
i;
if (typeof(this.gamepads[gamepad.index]) !== 'undefined') {
delete this.gamepads[gamepad.index];
}
for (i = 0; i < this.gamepads.length; i++) {
if (typeof(this.gamepads[i]) !== 'undefined') {
newGamepads[i] = this.gamepads[i];
}
}
this.gamepads = newGamepads;
this._fire(Gamepad.Event.DISCONNECTED, gamepad);
};
Gamepad.prototype._resolveControllerType = function(id) {
id = id.toLowerCase();
if (id.indexOf('playstation') !== -1) {
return Gamepad.Type.PLAYSTATION;
} else if (
id.indexOf('logitech') !== -1 || id.indexOf('wireless gamepad') !== -1) {
return Gamepad.Type.LOGITECH;
} else if (id.indexOf('xbox') !== -1 || id.indexOf('360') !== -1) {
return Gamepad.Type.XBOX;
} else {
return Gamepad.Type.UNKNOWN;
}
};
Gamepad.prototype._resolveMapping = function(gamepad) {
var mappings = Gamepad.Mappings;
var mapping = null;
var env = {
platform: this.platform.getType(),
type: this._resolveControllerType(gamepad.id)
};
var i;
var test;
for (i = 0; !mapping && (i < mappings.length); i++) {
test = mappings[i];
if (Gamepad.envMatchesFilter(test.env, env)) {
mapping = test;
}
}
return mapping || Gamepad.StandardMapping;
};
Gamepad.envMatchesFilter = function(filter, env) {
var result = true;
var field;
for (field in filter) {
if (filter[field] !== env[field]) {
result = false;
}
}
return result;
};
Gamepad.prototype._update = function() {
this.platform.update();
this.gamepads.forEach(function(gamepad) {
if (gamepad) {
gamepad.updater.forEach(function(updater) {
updater();
});
}
});
if (this.gamepads.length > 0) {
this._fire(Gamepad.Event.TICK, this.gamepads);
}
},
Gamepad.prototype._applyDeadzoneMaximize = function(
value,
deadzone,
maximizeThreshold) {
deadzone = typeof(deadzone) !== 'undefined' ? deadzone : this.deadzone;
maximizeThreshold = typeof(maximizeThreshold) !== 'undefined' ? maximizeThreshold : this.maximizeThreshold;
if (value >= 0) {
if (value < deadzone) {
value = 0;
} else if (value > maximizeThreshold) {
value = 1;
}
} else {
if (value > -deadzone) {
value = 0;
} else if (value < -maximizeThreshold) {
value = -1;
}
}
return value;
};
exports.Gamepad = Gamepad;
})(((typeof(module) !== 'undefined') && module.exports) || window);
parser
文件:parser.html
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>Image Parser</title>
<link href="parser.css" rel="stylesheet">
<script src="parser.js"></script>
</head>
<body onload="load()">
<h1>Sprite Image Converter</h1>
<div id="sources" style="float:left" >
<div id="left" class="column">
<h2>Upload files</h2>
<div id="dropzone">Drag & drop here</div>
<ol id="curlist"></ol>
</div>
<div id="middle" class="column" style="max-width:420px">
<h2>Select your color palette</h2>
<div id="palettes">
</div>
</div>
</div>
<div id="right" class="column">
<h2>Get your output</h2>
<ol id="outlist"></ol>
</div>
</body>
</html>
parser.css
* {
text-shadow: 1px 1px 3px white;
transition: all 350ms linear;
}
body {
margin: 0;
}
html {
background: rgb(245,245,245);
font-family: Georgia;
}
grey {
color: rgb(140,140,140);
}
weak {
font-style: italic;
margin-left: 14px;
}
.column {
margin: 14px;
background: white;
border-radius: 7px;
border: 1px solid rgb(210,210,210);
box-shadow: 3px 3px 7px rgb(210,210,210);
float: left;
min-width: 280px;
}
h1 {
background: black;
border-bottom: 1px solid white;
color: white;
margin: 0;
padding: 0 0 3px 3px;
}
h2 {
margin-top: 3px;
padding: 0 7px 0 7px;
}
h3 {
padding: 0 0 0 14px;
}
#dropzone {
margin: 7px 7px -7px 7px;
padding: 14px;
font-size: 1.4em;
border: 2px dashed rgb(140,140,140);
border-radius: 7px;
text-align: center;
}
#dropzone:hover {
background: rgb(252,252,252);
border-color: rgb(117,117,210);
}
#scaler {
margin-top: 14px;
}
#scaler h3 {
margin: 7px;
float: left;
}
#scaler div {
width: 35%;
float: right;
clear: right;
margin: -3px 3px 0 7px;
}
#scaler input {
width: 70px;
}
#curlist {
clear: both;
}
.squares {
margin: 3px 0 3px 0;
transition: 140ms all;
clear: both;
cursor: pointer;
}
.squares:hover, .squares.selected {
margin-left: 7px;
background: rgb(245,245,245);
}
.palettename {
margin: 7px 0 0 14px;
padding: 3px 7px 0 0;
float: right;
font-style: italic;
color: darkgrey;
}
.square {
margin: 3px;
width: 28px;
height: 28px;
border: 1px solid white;
outline: 1px solid darkgrey;
display: inline-block;
background: url('squarebackground.gif');
}
.squarein {
width: 100%;
height: 100%;
}
#outlist {
overflow: hidden;
}
.output {
padding-bottom: 7px;
height: 84px;
width: 490px;
border: 1px solid rgb(210,240,210);
border-top-left-radius: 3px;
border-bottom-left-radius: 7px;
}
.status {
height: 0;
padding-top: 7px;
padding-left: 7px;
font-weight: bold;
}
.progress {
background: lightgreen;
height: 35px;
margin-top: -7px;
width: 0;
z-index: 7;
}
.title {
position: absolute;
width: 70px;
text-align: right;
}
.displayer { margin-bottom: 3px; }
.display {
margin: 3px 0 0 77px;
font-family: "Courier New", "Courier", monospace;
width: 406px;
}
parser.js
var num_files, dropzone, curlist, outlist, numdisplay, files, scale_x = 1, scale_y = 1, digitsize = 1,
palette, palettes, palette_name, palette_names, palette_elem, palette_elems,
max = Math.max, min = Math.min, round = Math.round, abs = Math.abs;
function load() {
dropzone = document.getElementById("dropzone");
curlist = document.getElementById("curlist");
outlist = document.getElementById("outlist");
numdisplay = document.getElementById("num_files");
num_files = 0;
dropzone.onchange = handleInputChange;
dropzone.ondragover = handleDragOver;
dropzone.ondragleave = handleDragOff;
dropzone.ondrop = handleFileSelect;
initializePalettes();
}
function handleInputChange(event) {
dropzone.ondragleave();
event.target.ondragleave();
console.log(window.e = event);
}
function handleFileSelect(event) {
preventAll(event);
this.style.backgroundColor = "";
var files = window.files = event.dataTransfer.files,
output = [],
type;
for(var i = 0, f; f = files[i]; i++) {
type = f.type.split("/")[1];
if(type == "gif" || type == "png" || type == "jpeg" || type == "jpg") {
++num_files;
output.push("<li><strong>", f.name, "</strong> <grey>(", type, ")</grey>");
outlist.appendChild(getWorkerElement(f));
}
else output.push("<li>Only images are supported! <grey>(" + type + ")</grey></li>");
}
dropzone.innerHTML = files.length + " file" + (files.length == 1 ? "" : "s") + " selected"
curlist.innerHTML = output.join("");
}
function getWorkerElement(file) {
var element = getOutputListElement(file.name),
reader = new FileReader();
reader.onprogress = updateProgress;
reader.element = element;
reader.onloadend = startWorking;
reader.readAsDataURL(file);
return element;
}
function getOutputListElement(name) {
var element = document.createElement("li"),
status = document.createElement("div"),
progress = document.createElement("div"),
base64 = document.createElement("div"),
results = document.createElement("div"),
close = document.createElement("div");
element.name = name;
element.statusbase = status.innerText = "Uploading " + name + "...";
element.status = status;
element.progress = progress
element.base64 = base64,
element.results = results;
element.close = close;
element.appendChild(status);
element.appendChild(progress);
element.appendChild(base64);
element.appendChild(results);
element.appendChild(close);
status.className = "status";
element.className = "output";
progress.className = "progress";
base64.className = "base64";
results.className = "results";
close.className = "close";
setTextDisplayer(base64, "Base 64");
setTextDisplayer(results, "Sprite");
return element;
}
function updateProgress(event) {
if(event.lengthComputable) {
var percentLoaded = round((event.loaded / event.total) * 100);
if(percentLoaded <= 100) {
this.element.status.innerText = this.element.statusbase + " (" + percentLoaded + "%)";
this.element.progress.style.width = percentLoaded + "%";
}
}
}
function startWorking(event) {
var reader = event.currentTarget,
element = reader.element,
result = reader.result;
setTimeout(function() {
element.status.innerText = "Working on " + element.name + "...";
element.progress.style.backgroundColor = "rgb(117,175,245)";
}, 350);
setDisplayerText(element.base64, result);
var canvas = document.createElement("canvas"),
context = canvas.getContext("2d");
var img = document.createElement("image");
img.src = result;
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0);
var data = context.getImageData(0, 0, img.width, img.height),
output;
setTimeout(function() {
element.status.innerHTML = "<strong>" + element.name + "</strong><weak><grey style='text-shadow:none;'>(" + palette_name + ")</grey></weak>";
element.status.style.color = "white";
element.progress.style.backgroundColor = "rgb(35,35,70)";
output = parseData(data.data, element, palette);
setDisplayerText(element.results, output);
}, 350);
}
}
function parseData(data, element) {
var outs = [],
occurences = {},
me,
i, j, len = data.length;
for(i = 0, j = 0; i < len; i += 4, ++j) {
me = outs[j] = getClosestPalette([data[i], data[i+1], data[i+2], data[i+3]]);
if(occurences[me]) ++occurences[me];
else occurences[me] = 1;
}
return combineSimilarChars(outs, getNewPaletteFromOccurences(occurences));
}
function combineSimilarChars(textraw, paletteinfo) {
var newpalette = paletteinfo[0],
digitsize = paletteinfo[1],
threshold = max(3, round(4 / digitsize)),
text = "",
i, j, len, cur;
console.log(digitsize);
for(i = 0, len = textraw.length; i < len; ++i) {
j = i + 1;
cur = textraw[i];
while(cur == textraw[j]) ++j;
if(j - i > threshold) {
text += "x" + makedigit(cur, digitsize, newpalette) + String(j - i) + ",";
i = j - 1;
}
else text += makedigit(cur, digitsize, newpalette);
}
return "p[" + grabKeys(newpalette) + "]" + text;
}
function getNewPaletteFromOccurences(occurences) {
var counts = [],
key, len = 0;
for(key in occurences) {
counts[key] = len;
++len;
}
console.log(len);
return [counts,getDigitSizeFromLength(len)];
}
function makedigit(num, digitsize, newpalette) {
return fillChars(max(0, digitsize - String(num).length), "0") + newpalette[num];
}
function fillChars(num, a) {
var text = "";
while(num--) text += a;
return text;
}
function grabKeys(object) {
var output = [], i;
for(i in object) output.push(i);
return output.join(",");
}
function getClosestPalette(rgba) {
var i, bestloc, diff, bestdiff = Infinity;
for(i = palette.length - 1; i >= 0; --i) {
diff = arrayDiff(rgba, palette[i]);
if(diff < bestdiff) {
bestdiff = diff;
bestloc = i;
}
}
return bestloc;
}
function arrayDiff(a, b) {
var sum = 0, i;
for(i = a.length - 1; i >= 0; --i) sum += abs(a[i] - b[i]);
return sum;
}
function arrayEquals(a,b) { return !(a<b || b<a); }
function handleDragOver(event) {
preventAll(event);
event.dataTransfer.dropEffect = "copy";
this.style.backgroundColor = "lightgrey";
}
function handleDragOff(event) {
this.style.backgroundColor = "";
}
function preventAll(event) {
event.stopPropagation();
event.preventDefault();
}
function setTextDisplayer(element, intitle) {
element.className += " displayer";
var title = element.title = document.createElement("div"),
display = element.display = document.createElement("input"),
copyout = element.copyout = document.createElement("div");
title.innerText = intitle + ": ";
title.className = "title";
display.className = "display";
element.appendChild(title);
element.appendChild(display);
}
function setDisplayerText(element, text) {
element.display.value = text;
}
function initializePalettes() {
palettes = [
[
[0,0,0,0],
[255,255,255,255],
[0,0,0,255]
],
[
[0,0,0,0],
[255,255,255,255],
[0,0,0,255],
[199,199,192,255],
[128,128,128,255]
],
[
[0,0,0,0],
// Grayscales (1-4)
[255,255,255,255],
[0,0,0,255],
[188,188,188,255],
[116,116,116,255],
// Reds & Browns (5-11)
[252,216,168,255],
[252,152,56,255],
[252,116,180,255],
[216,40,0,255],
[200,76,12,255],
[136,112,0,255],
[124,7,0,255],
// Greens (12-14)
[168,250,188,255],
[128,208,16,255],
[0,168,0,255],
// Blues (15-20)
[24,60,92,255],
[0,128,136,255],
[32,56,236,255],
[156,252,240,255],
[60,188,252,255],
[92,148,252,255]
]
];
palette_names = [
"Black & White",
"GameBoy",
"Mario"
];
var container = document.getElementById("palettes"),
i, j, len, current, mine, square, squarein;
palette_elems = []
for(i = 0, len = palettes.length; i < len; ++i) {
current = palettes[i];
palette_elems[i] = mine = document.createElement("div");
mine.innerHTML = "<p class='palettename'>" + palette_names[i] + "</p>";
for(j = 0; j < current.length; ++j) {
square = document.createElement("div");
squarein = document.createElement("div");
square.className = "square";
squarein.className = "squarein";
squarein.style.background = getColorFromArray(current[j]);
square.appendChild(squarein);
mine.appendChild(square);
}
mine.palettenum = i;
mine.onclick = setCurrentPalette;
mine.className = "squares";
container.appendChild(mine);
}
palette_elems[localStorage.palette_num || 0].click();
}
function getColorFromArray(arr) {
return "rgba(" + arr.join(", ") + ")";
}
function setCurrentPalette(event) {
var num = this.palettenum;
palette = palettes[num];
palette_name = palette_names[num];
digitsize = getDigitSize(palette);
digitsize = palette.length >= 10 ? 2 : 1;
if(palette_elem) palette_elem.className = "squares";
palette_elem = this;
this.className = "squares selected";
localStorage.palette_num = num;
}
function getDigitSize(palette) { return Number(String(palette.length).length) }
function getDigitSizeFromLength(length) { return Number(String(length).length) }
function setScaleValue(event) {
window["scale_" + this.alpha] = Number(this.value) || 1;
}
function sum(a,b) { return Number(a) + Number(b); }
Maps
文件:World12.js
map.locs = [
new Location(0, walkToPipe),
new Location(1),
new Location(2),
new Location(1, exitPipeVert),
new Location(3, exitPipeVert),
new Location(1, false, 1000)
];
map.areas = [
new Area("Overworld", function() {
setLocationGeneration(0);
pushPreCastle();
pushPrePattern("backcloud", 0, 4, 1);
pushPreFloor(0, 0, 24);
pushPreThing(PipeSide, 80, 16, 1);
pushPrePipe(96, 0, 32);
}),
new Area("Underworld", function() {
setLocationGeneration(1);
fillPreThing(Brick, 0, 8, 1, 11, 8, 8);
pushPreFloor(0, 0, 80);
makeCeiling(48, 83);
pushPreThing(Block, 80, jumplev1, Mushroom);
fillPreThing(Block, 88, jumplev1, 4, 1, 8, 8);
pushPreThing(Goomba, 128, 8);
pushPreThing(Stone, 136, 8);
pushPreThing(Goomba, 136, 16);
pushPreThing(Stone, 152, 16, 1, 2);
pushPreThing(Stone, 168, 24, 1, 3);
pushPreThing(Stone, 184, 32, 1, 4);
pushPreThing(Stone, 200, 32, 1, 4);
pushPreThing(Stone, 216, 24, 1, 3);
pushPreThing(Goomba, 232, 8);
pushPreThing(Brick, 232, 40, Coin);
pushPreThing(Stone, 248, 24, 1, 3);
pushPreThing(Stone, 264, 16, 1, 2);
fillPreThing(Brick, 312, 32, 1, 3, 8, 8);
pushPreThing(Brick, 320, 32);
pushPreThing(Coin, 321, 39);
fillPreThing(Brick, 328, 32, 1, 3, 8, 8);
fillPreThing(Coin, 330, 63, 4, 1, 8, 8);
pushPreThing(Brick, 336, 48);
pushPreThing(Brick, 344, 48);
fillPreThing(Koopa, 352, 12, 2, 1, 12);
fillPreThing(Brick, 352, 32, 1, 3, 8, 8);
// pushPreThing(Coin, 360, 62);
pushPreThing(Brick, 360, 32);
fillPreThing(Brick, 368, 32, 1, 2, 8, 8);
pushPreThing(Coin, 361, 39);
pushPreThing(Brick, 368, 48, Star);
fillPreThing(Brick, 416, 32, 2, 5, 8, 8);
fillPreThing(Brick, 432, 16, 2, 3, 8, 8);
fillPreThing(Brick, 432, 72, 2, 2, 8, 8);
fillPreThing(Brick, 464, 32, 4, 1, 8, 8);
fillPreThing(Brick, 464, 72, 5, 2, 8, 8);
fillPreThing(Coin, 465, 39, 4, 1, 8, 8);
pushPreThing(Koopa, 472, 12);
fillPreThing(Brick, 496, 32, 2, 7, 8, 8);
pushPreThing(Goomba, 494, 8);
pushPreThing(Goomba, 510, 8);
fillPreThing(Brick, 528, 72, 4, 2, 8, 8);
fillPreThing(Brick, 536, 32, 1, 5, 8, 8);
fillPreThing(Brick, 544, 32, 2, 1, 8, 8);
pushPreThing(Coin, 545, 39);
pushPreThing(Brick, 552, 40, Mushroom);
fillPreThing(Brick, 576, 32, 2, 1, 8, 8);
pushPreThing(Brick, 576, 40);
fillPreThing(Brick, 576, 48, 2, 3, 8, 8);
pushPreThing(Brick, 584, 40, Coin);
pushPreThing(Goomba, 584, 72);
fillPreThing(Brick, 608, 32, 4, 1, 8);
fillPreThing(Brick, 608, 72, 4, 2, 8);
fillPreThing(Goomba, 608, 40, 2, 1, 12);
pushPreFloor(664, 0, 34);
fillPreThing(Brick, 672, 40, 6, 2, 8, 8);
fillPreThing(Coin, 674, 64, 6, 1, 8, 8);
pushPreThing(Brick, 712, 88, [Mushroom, 1]);
makeCeiling(720, 45);
fillPreThing(Goomba, 768, 8, 3, 1, 12, 8);
pushPrePipe(800, 0, 24, true, 2);
pushPrePipe(848, 0, 32, true);
pushPrePipe(896, 0, 16, true, false, 3);
pushPreFloor(952, 0, 2);
fillPreThing(Brick, 952, 8, 2, 3, 8, 8);
pushPreFloor(984, 0, 12);
pushPreThing(Stone, 1040, 8);
pushPreThing(Stone, 1048, 16, 1, 2);
pushPreThing(Stone, 1056, 24, 1, 3);
pushPreThing(Stone, 1064, 32, 1, 4);
pushPreThing(Stone, 1072, 32, 1, 4);
pushPrePlatformGenerator(1096, 6, 1);
// pushPreThing(PlatformGenerator, 1096, ceilmax, 6, 1);
pushPreFloor(1144, 0, 8);
fillPreThing(Brick, 1144, 40, 5, 1, 8, 8);
pushPreThing(Koopa, 1152, 12, true);
pushPreThing(Brick, 1184, 40, Mushroom);
pushPrePlatformGenerator(1224, 6, -1);
// pushPreThing(PlatformGenerator, 1224, ceilmax, 6, -1);
pushPreFloor(1266, 0, 32);
fillPreThing(Brick, 1266, 8, 17, 3, 8, 8);
pushPreThing(PipeSide, 1314, 40, 4);
pushPreThing(PipeVertical, 1330, 88, 64);
makeCeiling(1274, 7);
fillPreThing(Brick, 1346, 32, 7, 7, 8, 8);
pushPreThing(ScrollEnabler, 1340, ceilmax);
makeCeiling(1346, 17);
pushPreWarpWorld(1400, 0, [[4,1],[3,1],[2,1]], 0, true);
fillPreThing(Brick, 1506, 8, 2, 11, 8, 8);
}),
new Area("Underworld", function() {
setLocationGeneration(2);
pushPreFloor(0, 0, 17);
fillPreThing(Brick, 0, 8, 1, 11, 8, 8);
fillPreThing(Coin, 25, 7, 9, 1, 8, 8);
fillPreThing(Brick, 24, 32, 9, 1, 8, 8);
fillPreThing(Coin, 33, 39, 8, 1, 8, 8);
pushPreThing(Brick, 96, 32, Coin);
fillPreThing(Brick, 24, 64, 10, 4, 8, 8);
fillPreThing(Brick, 104, 24, 2, 9, 8, 8);
pushPreThing(PipeSide, 104, 16, 3);
pushPreThing(PipeVertical, 120, 100, 100);
}),
new Area("Overworld", function() {
setLocationGeneration(4);
pushPrePattern("backreg", 104, 0, 1);
pushPreFloor(0, 0, 58);
pushPrePipe(0, 0, 16, false, false, 4);
pushPreThing(Stone, 16, 8);
pushPreThing(Stone, 24, 16, 1, 2);
pushPreThing(Stone, 32, 24, 1, 3);
pushPreThing(Stone, 40, 32, 1, 4);
pushPreThing(Stone, 48, 40, 1, 5);
pushPreThing(Stone, 56, 48, 1, 6);
pushPreThing(Stone, 64, 56, 1, 7);
pushPreThing(Stone, 72, 64, 2, 8);
endCastleOutside(148);
})
];
World13.js
map.time = 300;
map.locs = [
new Location(0, true)
];
map.areas = [
new Area("Overworld", function() {
setLocationGeneration(0);
pushPreCastle();
pushPrePattern("backcloud", 0, 4, 5);
pushPreFloor(0, 0, 16);
pushPreTree(144, 8, 4);
pushPreTree(192, 32, 8);
pushPreTree(208, 64, 5);
fillPreThing(Coin, 217, 71, 3, 1, 8, 8, true);
pushPreThing(Koopa, 240, 76, true);
pushPreTree(256, 8, 3);
pushPreThing(Coin, 266, 15);
pushPreTree(280, 40, 5);
fillPreThing(Coin, 297, 87, 2, 1, 8);
pushPreTree(320, 72, 7);
fillPreThing(Goomba, 352, 80, 2, 1, 16);
pushPreTree(400, 0, 4);
fillPreThing(Coin, 402, 55, 2, 1, 8, 8);
pushPreThing(Platform, 440, 56, 6, [moveFloating, -4, 56]);
pushPreTree(472, 0, 5);
pushPreThing(Block, 472, 24, Mushroom);
pushPreTree(480, 64, 4);
fillPreThing(Coin, 482, 71, 4, 1, 8);
pushPreTree(520, 0, 5);
pushPreTree(560, 32, 3);
pushPreThing(Koopa, 592, 76, true, [16, 88]);
pushPreTree(608, 56, 6);
pushPreThing(Goomba, 640, 64);
fillPreThing(Coin, 681, 63, 2, 1, 8, 8);
pushPreThing(Platform, 688, 40, 6, [moveSliding, 660, 720]);
fillPreThing(Coin, 745, 71, 2, 1, 8, 8);
pushPreThing(Platform, 752, 32, 6, [moveSliding, 700, 776]);
fillPreThing(Coin, 777, 71, 2, 1, 8, 8);
pushPreTree(784, 16, 4);
pushPreTree(832, 48, 8);
pushPreThing(Koopa, 880, 60, true);
pushPreTree(904, 0, 3);
fillPreThing(Coin, 906, 7, 3, 1, 8, 8);
pushPreThing(Koopa, 912, 68, true, [4, 76]);
pushPreTree(928, 32, 4);
fillPreThing(Coin, 962, 63, 2, 1, 8, 8);
pushPreTree(976, 32, 4);
pushPreFloor(1032, 0, 46);
pushPreThing(Platform, 1048, 56, 6, [moveSliding, 1008, 1076]);
pushPreThing(Koopa, 1064, 12, true);
pushPreThing(Stone, 1104, 32, 1, 4);
pushPreThing(Stone, 1112, 32, 1, 4);
pushPreThing(Stone, 1120, 48, 1, 6);
pushPreThing(Stone, 1128, 48, 1, 6);
pushPreThing(Stone, 1136, 64, 1, 8);
pushPreThing(Stone, 1144, 64, 1, 8);
endCastleOutside(1220, 0, true, 11);
})
];
注意:
由于博客字数限制,本篇文章只展示了部分代码。本项目的完整代码及素材包我已上传至资源