14KB JavaScriptããªãªãã³ã¼ããªã¼ãã£ã³ã°ãã¦ã¿ãã
JavaScriptã§æ¸ãããã¹ã¼ãã¼ããªãªãããã14KBã®ãµã¤ãºã§ãã®ããªãªãåç¾ããã¨ãããã¨ã§è©±é¡ã§ãã
http://blog.nihilogic.dk/2008/04/super-mario-in-14kb-javascript.html
ããã¯ã½ã¼ã¹ãèªã¾ãã°ãªãã¾ããã¨ãããã¨ã§ã³ã¼ããªã¼ãã£ã³ã°ãã¦ã¿ã¾ããã14KBã¨ãã£ã¦ãYUI compressorã§å§ç¸®ããã¦ããã®ã§ãè¦ãã¹ãã¯å§ç¸®åã®æ¹ã®ã½ã¼ã¹ã§ãã
http://www.nihilogic.dk/labs/mario/mario.js
å§ç¸®åã¨ãã£ã¦ããã®ãããã§ãããããã空è¡ãã³ã¡ã³ããé©åã«å
¥ãã¦ãåãããããå¤æ°åãã¤ãã¦ããããç»åãé³æ¥½ããã¹ã¦ããã¹ããã¼ã¿ã¨ãã¦ã½ã¼ã¹ä¸ã«å®ç¾©ãã¦ãããã§ãã£ãã®35KBã1200è¡ã
ãã¼ããä¿¡ããããªããæµãã£ã©ã®AIã¯ï¼ç»åãã¼ã¿ã¯ï¼JavaScriptã§ã©ããã£ã¦é³æ¥½é³´ããã®ï¼ã¨ãèå³ã¯ã¤ãã¾ããã
ããã§ã²ã¼ã ã®ä»æ§ã«ã¤ãã¦ã¡ãã£ã¨ã¾ã¨ãã¦ããã¾ãã
- ï¼é¢ã®ã¿ãå°ä¸ãªã
- ï¼åæ»ãã ãã²ã¼ã ãªã¼ãã¼ãï¼UPãªã
- BGMã¯ã²ã¼ã ä¸ã¨ã²ã¼ã ãªã¼ãã¼ã®ï¼ç¨®
- æµã¯ã¯ãªãã¼ã®ã¿
- ããã³ãã¹ã¿ã¼ãªã
- ã¹ãã¼ã¸ã¯ãªã¢ã®æãªããã¹ãã¼ã¸ã¯ãªã¢ã¼ãããåºã¾ã£ã¦çµäºã
ããªã大èã«å ã®è¦ç´ ãåãæ¨ã¦ã¦ãã¾ãããããã§ãã©ãè¦ã¦ãããªãªã§ããã¨ããã«ã»ã³ã¹ãæãã¾ãã
ã§ã¯èªãã§ããã¾ããä½æ¦ã¨ãã¦ã¯è¡¨ç¤ºãå
¥åã®ä»çµã¿ãåå¥ã«è¦ã¦è¡ã£ã¦ãçãµã¤ãºã®ç§å¯ãèªã¿è§£ãã¦ããã¾ãã
ããã¦ãã®ãã¨ã«ã²ã¼ã å
¨ä½ã®æµããæ´ãäºå®ã
ã©ã¤ã»ã³ã¹(1è¡ç®)
MITã©ã¤ã»ã³ã¹ã§ãã
/* * The Javascript Mario Experiment v0.1 * Copyright (c) 2008 Jacob Seidelin, [email protected] * MIT License [http://www.opensource.org/licenses/mit-license.php] */
ãã©ã³ã(465è¡ç®)
ã²ã¼ã ã£ã¦ãã©ã³ãåºåãèªåã§ãããªãã¡ããããªããã大å¤ã§ãããmario.jsã®ãã©ã³ãã¯base128å½¢å¼ã§ã¨ã³ã³ã¼ãããæååã¨ãã¦å®ç¾©ããã¦ãã¾ããã
var aFont = [ "<F・・・R<", // 0 ",<,,,,`", // 1 "_ï½¥'>]ï½²ï¾", // 2 "`&,>#ï½¥_", // 3
å®ç¾©ãã¦ããæåã¯ã0123456789MARIOx-WLDTEãã®ã¿ãã¨ããã®ãçµæ§ãããã確ãã«ã²ã¼ã ç»é¢ã«åºã¦ããåèªã¯WORLDã¨ãTIMEãããã ããæ°ä»ããªãã£ããã©ãSTARTãããGAME OVERãã表示ãã¦ãªãã®ãã
使ãæ¹ã§ãããwriteTexté¢æ°ã«æååã渡ãã¨ãï¼æåãã¤writeCharé¢æ°ãå¼ãã§ããã®ãã©ã³ããã¼ã¿ãbase128ToBitStringé¢æ°ã§ãã³ã¼ãããªãããããããã¦ããã¾ããã¡ããããããã£ã¦éåã«è¨ããªãJavaScriptã ãã
ãã¯ã»ã«æç»å¦ç(250è¡ç®)
plotPixelé¢æ°ãåé¡ã®ããããå¦çã§ããã¾ã大ããªä¸é æ¼ç®åã§ãcanvasã¿ã°ã«å¯¾å¿ãã¦ãããã©ã¦ã¶ãã©ãããå¤æãé¢æ°ã®ä¸èº«ãåãæ¿ãã¦ã¾ãããããcanvasã使ãã¨ã°ã©ãã£ãã¯å¦çã¨ãã§ãããããã§ããã®ããªãªãcanvasããªãã¯ãã®IEã§ãåããã§ããã©â¦â¦ã
ãããcanvas対å¿ã®æ¹ã®æç»å¦çãæ®éã§ããiPixSizeã¯è¡¨ç¤ºåçãæã£ã¦ãã¾ãã
plotPixel = bHasCanvas ? function(iColor, x, y, oCtx, iWidth) { if (aPalette[iColor] != "") { oCtx.fillStyle = "#" + aPalette[iColor]; oCtx.fillRect(x * iPixSize - iWidth * iPixSize, y * iPixSize, iWidth * iPixSize, iPixSize); } } :
ãã¼ã¨ãcanvasæªå¯¾å¿ã®æ¹ã¯â¦â¦ããããã1ãã¯ã»ã«ã«ã¤ãï¼åãã¤ãæå®è²ãèæ¯ã«ããSPANã¿ã°ãçæãã¦ãã¾ãï¼ç¡è¶ãããªãã
function(iColor, x, y, oSpan, iWidth) { appChild(oSpan, createSpan( (x - iWidth) * iPixSize, y * iPixSize, iWidth * iPixSize, iPixSize, aPalette[iColor] ) ); },
ããããããå®ç¾©(494è¡ç®)
ãããããã£ã©ã¯ã¿ã¼ã¯ã©ããã£ã¦å®ç¾©ãã¦ãã®ããªãä¾ã«ãã£ã¦base128ã¨ã³ã³ã¼ãã§ãããã¹ãã©ã¤ãã¨ãç°¡åã«è¨ã£ã¦ããã©ããã©ã¦ã¶ã«ãããªæ©è½ãªãã£ã¦ã°ãã©ãããã®ï¼
aSpriteData = [ "}\"ï½¹-コ\"ï¾+コ\"ï¾+コ\"ï¾+コ\"ï½¿ï½¤ï¾ ~C_ ^?+コ\"ï¾+コ\"ï¾+コ\"ï¾*P7ï½²OK%ï½¾+ï½½u_\"ï¾<。a。a。bM@ï½±@ェ", // 0 ground "a ' ![ï½± 7ï½°ï½³bï½£[mt<Nï½µ7z]~ィORï½»[f_7l},tl},^?+}%XNï½²Sb[blï½£[ï½±%Y_ï½¹ !@ $", // 1 qbox "!A % @,[] ï½±}ï½°@;ï½µnヲ&Xï½£ <$ ァ、 8}}@Prc'U#Z'H'@ï½· カ\"is 、&08@ï½£(", // 2 mario
aSpriteHTML = ["", loadSpriteData([5,4,0,3], aSpriteData[0]), // 01 Ground loadSpriteData([3,4,5,0], aSpriteData[1]), // 02 Question Box loadSpriteData(aPalette2, aSpriteData[5]), // 03 Pipe Left
loadSpriteDataé¢æ°ã¯ã使ãè²ããã¬ãããã¼ãã«ããï¼ã¤é¸ãã§ãã¹ãã©ã¤ããã¼ã¿ãæå®ããã¨ãæç»ããããã®ãDOMã¨ã¬ã¡ã³ãã¨ãã¦æ»ã£ã¦ãã¾ããã¡ã¢ãªä¸ã«æç»ããã ãã§ç»é¢ã«ã¯ã¾ã æããã¾ãããçãµã¤ãºã®ããã«ãè¯ã使ããã¬ããã®çµã¿åããã¯aPalette2ã®ããã«å¤æ°ã§å®ç¾©ãã¦ã¾ãããã¾ã第ï¼å¼æ°ãæå®ããã¨éåãã®ç»åãæç»ãã¦ãããã®ã§ãèªãã£ã©ã¯å³åãã¨å·¦åãã®ä¸¡æ¹ãç¨æãã¦ããã¾ãã
é³æ¥½(651è¡ç®)
BGMã®å®ç¾©ã¯ãããªæãã
aSounds = [ // very small, very simple mario theme. Sequenced by Mike Martel. "data:audio/mid;base64,TVRoZAAAAAYAAQAEAMBNVHJrAAAAGQD/UQMFeãâ¦â¦ï¼çç¥ï¼
ããããã¨ã«ã以ä¸ã®ãããªembedã¿ã°ãåçã«çæãã¦MIDIã¨ãã¦é³´ããã¦ã¾ãããªãã»ã©JavaScriptã®ä¸çã§ã¯ãªããHTMLã®ä¸çã§é³´ãããã§ããããã¼ã¿ã¯base64ã§ã¨ã³ã³ã¼ãããã¦ã¾ãããããã¯èªåã§ãã³ã¼ãããªãã¨ããã®ã¾ã¾ãã©ã¦ã¶ã解éãã¦ããã¾ãã
<embed id="sound_1" src="data:audio/mid;base64,TVRoZAAAAAYAAQAEãï¼çç¥ï¼ã8A" autostart="true" style="position: absolute; left: -1000px;" type="audio/mid"/>
æ»ãã ã¨ãã¯ãã®ã¿ã°ãåé¤ãã¦ã代ããã«ã²ã¼ã ãªã¼ãã¼ç¨ã®embedã¿ã°ãæ¿å ¥ãã¾ãã
ã½ã¼ã¹ã³ã¼ãã¸é³æ¥½ãç»åãåãè¾¼ãæ¹æ³ã«ã¤ãã¦ã¯Embedding and Encoding in JavaScriptã«ã詳ããæ¸ãã¦ããã®ã§åèã«ã
ãã¼å ¥åï¼392è¡ç®ã1153è¡ç®ï¼
使ã£ããã¨ãªãã£ããã©ãJavaScriptã§ã¯ãããã£ã¦ãã¼å
¥åã¤ãã³ãåããã®ãã
ããã§ã¯çç¥ãã¾ããããã¼ã¢ããå¦çããã£ã¦ãã¹ãã¼ã¿ã¹ãå
ã«æ»ããããã¦ã¾ãã
document.onkeydown = fncKeyDown;
fncKeyDown = function (e) { var keyCode = (e||event).keyCode; if (keyCode == 39 && iPlayerMovementX < 1) { bPlayerMoveX = 1; iPlayerDirection = 0; } if (keyCode == 37 && iPlayerMovementX > -1) { bPlayerMoveX = iPlayerDirection = 1; } if (keyCode == 17 || keyCode == 38) { if (bPlayerIsOnGround) jump(); else iPreJump = 8; } },
ã¡ãªã¿ã«ãã¼ã³ã¼ãã®æå³ã¯37(â)ã39(â)ã17(Ctrl)ã38(â)ã§ãã
å é度(419è¡ç®)
ããªãªã¯ç§»åé度ãä¸å®ã§ã¯ãªããå³ãã¿ã³ãæ¼ãã¦ããå¾ã ã«é度ãä¸ããã¾ãããã®å¦çãããã50msecæ¯ã«å¼ã°ãã¦ãé度ãï¼æªæºã ã£ããï¼ãã¤å éãã¦ããã¾ãã
fncMoveTimer = function() { if (bPlayerMoveX) { if (iPlayerDirection == 0 && iPlayerMovementX < 6) { iPlayerMovementX += 1; } else if (iPlayerMovementX > -6) { iPlayerMovementX -= 1; } } else { if (iPlayerMovementX < 0) iPlayerMovementX++; if (iPlayerMovementX > 0) iPlayerMovementX--; } setTimer(fncMoveTimer, 50); },
å¥ã®ç®æ(1010è¡ç®)ã§ãããè½ä¸é度ããããªæãã§å¢å ãã¦ããã¾ãã
// constantly increase fall speed to the max if (iPlayerMovementY < 8) iPlayerMovementY++;
æµãã¼ã¿ã®åãï¼632è¡ç®ï¼
ãã¼ããããã ãã§ãã¹ã¦ã®æµã®åä½ãå®ç¾©ãã¦ãã¾ãã
ãã¼ã¿ã¯é çªã«åæ座æ¨XãYã左端ãå³ç«¯ã§ããæµã¯åæ座æ¨ããå·¦åãã«ç§»åãã¦ãã£ã¦ç¸å¯¾ä½ç½®ã§å·¦ç«¯ã«éãããåããå¤ãã¾ããããã¦ã¾ãå³ç«¯ã«éãããåããå¤ããã¨ããåããå管ããããã¯ã¨è¡çªå¤å®ãã¦ããããããªããã§ããã
[ 23,12,-24,1, 41,12,-4,1, 52,12,-7,1, 50,12,-5,3, 94,12,-8,36, 92,12,-6,38, 111,12,-25,19, 109,12,-23,21, 121,12,-35,9, 119,12,-33,11, 125,12,-39,5, 123,12,-37,7, 79,5,-2,5, 77,5,0,7 ] // goombas
ã¡ãªã¿ã«æµï¼ã¯ãªãã¼ï¼ã¯ãã½ã¼ã¹ä¸ã§ã¯Goombaã¨å¼ã°ãã¦ãã¾ãã
éãåããæç»(876è¡ç®ç)
éãåããã§ãããDOMã«ãã£ã¦ã¹ãã©ã¤ãæ©è½ãå®ç¾ãã¦ãã¾ããã¾ãå ¨ã¦ã®è¦ªã¯oLevelElementã§ããåæåå¦çã§ã¯ãããã«å ¨ã¦ã®èæ¯ã¨ã¬ã¡ã³ããappendChildãã¾ãã次ã«æµã§ããoGoombaElementããèªãã£ã©ã§ããoPlayerElementãoLevelElementã«appendChildãã¾ãã
// setup player sprite
oPlayerElement = appChild(oLevelElement, createSpan(4*iTileSize,4*iTileSize,iTileSize,iTileSize)),
å¾ã¯ãã£ã©ã®style.topå±æ§ãstyle.leftå±æ§ãå¤æ´ãããã¨ã§ãããä¸ãåãåãã¾ãã
oPlayerStyle.left = iNewX;
ããããããç»åã«è¦ãããã©ãå®ã¯<canvas>ã ã£ãã<span>ã ã£ããããã®ã§ãDOMæä½ã§ç°¡åã«ç§»åãéãããããã§ãããã£ã¦ç¢ºãã«ããã ãã©ã¡ãã£ã¨ç®ããã¦ãã³ã
ã¹ã¯ãã¼ã«(1114è¡ç®)
ã¹ã¯ãã¼ã«å¦çãåãçºæ³ãå ¨ã¦ã®è¦ªã§ããoLevelElementã®style.leftå±æ§ãå¢ããã¦ããã ãã§ããããã®ãã¨ç»é¢ã®ä¸¡ç«¯ã®ã¯ã¿åºãé¨åãè¨ç®ãã¦ãshowHideé¢æ°ã§è¡¨ç¤ºï¼é表示è¨å®ãã¦ã¾ããã
var iNewX = toInt(oLevelElement.style.left) + x; if (iNewX < 0) { oLevelElement.style.left = iNewX; var iLeftX = floor(-iNewX / iTileSize)-1, iRightX = iLeftX + 17, bShowRight; if (x > 0) { iRightX++; iLeftX++; bShowRight = 1; } for (var iRow in aTileMap) { var aRow = aTileMap[iRow]; if (aRow[iRightX]) showHide(aRow[iRightX], !bShowRight); if (aRow[iLeftX]) showHide(aRow[iLeftX], bShowRight); } }
ã¢ãã¡ã¼ã·ã§ã³(857è¡ç®ç)
ãã£ã©ãã³ã¤ã³ã®ã¢ãã¡ã¼ã·ã§ã³ãã¿ã¼ã³ã¯ãåãä½ç½®ã«ã¢ãã¡ã¼ã·ã§ã³ãã¿ã¼ã³ã®DOMãè¨å®ãã¦ããã¦ãã¿ã¤ãã¼ã§showHideé¢æ°ãå¼ãã§è¡¨ç¤ºï¼é表示ãåãæ¿ãã¦ãã¾ãã
if (aCoinSprites[i]) { showHide(aCoinSprites[i].s[0]); showHide(aCoinSprites[i].s[1]); showHide(aCoinSprites[i].s[2]); showHide(aCoinSprites[i].s[3]); } showHide(aCoinSprites[i].s[iCoinState],1);
çãµã¤ãºã®å·¥å¤«(10è¡ç®)
æ°ãã¤ãåãããã«æ¶ãã¾ããå¥åå®ç¾©ãã¦ã¾ãããå§ç¸®ããããã¨å¤æ°åããã¹ã¦ï¼æåã«ãªããããã£ããå¹ãã¦ãã¾ãã
// our own variables can be compressed, builtin functions can't var toInt = parseInt, setTimer = setTimeout, getElement = function(id){return document.getElementById(id);},
ãã¨ã¯ãã¸ãã¯ãã³ãã¼ãå¤ãã§ãããaSpriteHTML[12]ã¯å³åãããªãªã ã¨ããã³ã¡ã³ãã§ãã©ãã¼ãã¦ããã®ã§ãã»ã©èªã¿ã¥ããã¯ãªãã¨æãã¾ãã
ã¨ã³ããªã¼ãã¤ã³ã(8è¡ç®)
ãã®JavaScriptããã°ã©ã ã¯å
¨ä½ã大ããªã²ã¨ã¤ã®Marioé¢æ°ã«ãªã£ã¦ã¾ããã¯ã©ã¹ã¯ä½¿ã£ã¦ã¾ããã
BODYã¿ã°ã®onloadã§ãã®é¢æ°ãå¼ã³ã¾ããå¼æ°ã¯BGMã®æç¡ã¨è¡¨ç¤ºåçã§ãã
var Mario = function(bMusic, iScale)
ã¿ã¤ãã¼
ã²ã¼ã ã¨ããã°ãã£ã±ãã¿ã¤ãã¼å¦çãè¤éã§éè¦ã§ãããã¿ã¤ãã¼ã§å¨æçã«å¼ã°ããå¦çã¯ä»¥ä¸ã®ãã®ãããã¾ããã
- ã²ã¼ã ã®æå°ãµã¤ã¯ã«ã®ã¿ã¤ãã¼ï¼gameCycle, 32msecå¨æï¼
- ã¹ã¯ãã¼ã«ä½ç½®ã®ãã§ãã¯ï¼checkScroll, 32msecå¨æï¼
- æ®ãæéã®ã«ã¦ã³ããã¦ã³ï¼updateTime, 1000msecå¨æï¼
- ãã¬ã¤ã¤ã¼ç§»åé度調æ´ï¼funcMoveTimer, 50msecå¨æï¼
- ã³ã¤ã³ã®ã¢ãã¡ã¼ã·ã§ã³(fncAnimCoin, 100msecå¨æ)
- ãï¼ããããã¯ã®ã¢ãã¡ã¼ã·ã§ã³(fncFlashCoinBoxes, 100msecå¨æ)
- æµã®ã¢ãã¡ã¼ã·ã§ã³(fncFlipGoomba, 300msecå¨æ)
- ç»é¢ã«ãã©ã¼ã«ã¹ãæ»ãå¦ç(100msecå¨æ)
ã²ã¼ã ãµã¤ã¯ã«(894è¡ç®)
ã¡ã¤ã³ã«ã¼ãã¨ãªãgameCycleã¯å¤§ããã®ã§å¼ç¨ãã¾ããããä¸èº«ã¯ä»¥ä¸ã®ãããªæµãã§ãã
- è¡çªå¤å®
- ã³ã¤ã³åºç¾å¦ç
- èªãã£ã©ã¢ãã¡ã¼ã·ã§ã³
- èªãã£ã©ç§»å
- æµã¨ã®è¡çªå¤å®
- æµã®ã¢ãã¡ã¼ã·ã§ã³
ãããã«
ã¨ãããã以ä¸ã§ãããµã¤ãºã®å²ãã«èªã¿ããããã¨ã«ãé©ãã¾ãããMITã©ã¤ã»ã³ã¹ãªã®ã§ããããå ã«èªåã§ã²ã¼ã ãä½ã£ããããã®ã«ã使ãããã§ãã
ãµã¼ããç²ãæ§ã§ããã