わずか1.7キロバイトのJavaScript マリオ風のゲーム (脱力系)
1.7キロバイトのJavaScriptで,一応,右画像のようなスーパーマリオ風のゲームができた。
(1.3キロバイトに改良されました。)
こちらからプレーできます
http://www.name-of-this-site.org/coding/game/aamario.html
遊び方:
わずか565バイトテトリス
http://zapanet.info/blog/item/1130
自分のはその3倍で,22行(×79文字)もあるので,ショートコーディングとは言い難いけども…
下記はソースコードで,テキストにこれだけ貼り付ければ動作する。
1.7キロ版
<body id=d onKeydown=k(event.keyCode-38)><table style=position:absolute height= 100><tr><td width=280 id=td1 valign=bottom><div id=r>○<div id=t>大</div></div> <td valign=top><p id=g style="position:absolute"></p></table><script>bm=r.vx=r. vy=r.ax=0;r.ay=-4;b=10;xx=3*(yy=90);py(bm,r);px(20,r);function py(y,e){e.my=yy- parseInt(e.style.paddingTop=yy-y+"px");}function px(x,e){e.mx=parseInt(e.style. paddingLeft=x+"px");}function l(s){g.innerHTML=s;}function dpx(dx,e){fx=dx+e.mx ;if(0<fx&&fx<xx){px(fx,e);}else{e.vx=e.ax=0;}}function dpy(dy,e){fy=dy+e.my;if( bm<fy&&fy<yy){py(fy,e);}else{r.vy=0;py(bm,e);if(!go){t.innerHTML="大";}}}l(n=0) ;j2=false;r.style.position="relative";function te(){cE();mE();}function tm(){r. kvy=r.vy;r.ky=r.my;r.vy+=r.ay;dpx(r.vx,r);dpy(r.vy,r);}function k(kc){dpx(b*kc, r);if(kc==0&&(r.my==bm||j2)){r.vy+=b*1.8;t.innerHTML="方";j2=false;}}function v (){r.vy+=b*3;clearInterval(me);t.innerHTML="出";k=function(){};go=true;}q=15;ae =[0,0,0,0,0,0,0,0];go=false;setInterval(tm,150);me=setInterval(te,150);function mE(){for(i=0;i<ae.length;i++){if(ae[i]>0){ee=D.getElementById("e"+i);dpx ((-b)*((i==5)?2:1),ee);if(ee.mx<20){ae[i]=0;d.removeChild(ee);}ey=ee.my-w;if(r. mx>ee.mx-q*0.1&&r.mx<ee.mx+q*1.3&&r.my>ey-q*1.5&&r.my<ey+q*1.5){if(i%3!=1&&r.ky >0){ee.innerHTML="☆";ae[i]=0;k(0);j2=true;d.removeChild(ee);ee.innerHTML="";l( n+=100);}else{v();}}}}}w=-20;D=document;function cE(){if(Math.random()<0.11+(n/ 50000)){for(j=0;j<ae.length;j++){if(!ae[j]){ae[j]=1;break;}}if(j<ae.length){kr= D.createElement("div");kr.id="e"+j;kr.innerHTML=(j==4)?"砲":(j%3==1)?"棘":j%2== 0?"亀":"栗";d.appendChild(kr);px(xx-b,kr);kr.style.position="absolute";py(w+((j ==4)?40:0),kr);}}}</script></body>
キャラクターがかわいいと思う。
遊び方のコツ:
- 飛行中に左右への移動を駆使する。
- 右足のあたりで踏むとちょうど倒せる。
- 無理に倒そうとせず,画面の先を見て,生き残ること優先で進めるとよい。
- 敵を踏んだ直後に上キーを押して連続ジャンプができる。
コードを少しでも短くするために
- f(a=b) や a=b=c を多用
- a?b:c を多用
- document, bodyなどにも1文字の名前をふる (※これには高速化の効果もある。http://d.hatena.ne.jp/uupaa/20081005/1223196093 test12を参照)
- 速度や位置などはDOMエレメントそのものに持たせる
- 動的に追加すると管理が大変になる。かわりに,あらかじめ決めておいた配列の範囲内でローテーションを行なう
- 関数はエレメント間で汎用に
- 押されたキーのコードから38引いておき,左右の判別を容易に
- parseIntで文字列から数値のみ取り出す
など,一般的なコツを心がけた。
evalによる文の使い回しは,後から手がつけられなくなりそうなので控えた。
関数の役割はそれぞれ,
- px,py : 位置指定
- dpx,dpy : 差分動作指定
- tm,te : マリオと敵キャラの動作タイマー
- cE, mE : 敵キャラを作り,動かす(衝突判定含む)
- k : キーボード押下イベント
- gv : ゲームオーバー
となっている。
1.3キロ版
こちらは17行。
<body id=d onKeydown=k(event.keyCode-38)><div id=I height=100 width=280 valign= bottom><div id=r>○<div id=t>大</div></div></div><p id=g><script>a=-4;b=10;X=3* (Y=90);D=document;s=setInterval;S=parseInt;H="innerHTML";A="style";p="position" ;O="absolute";g[A][p]=I[A][p]=O;r[A][p]="relative";l(o=B=r.v=J=n=0);Q(B,r);P(20 ,r);q=15;E=[0,0,0,0,0,0,0,0];L=E.length;s(G,150);M=s(h,150);w=-20;function Q(z, e){e.y=Y-S(e[A].paddingTop=Y-z+"px");}function l(z){g[H]=z;}function G(){r.v;r. K=r.y;r.v+=a;if(B<(F=r.v+r.y)&&F<Y){Q(F,r);}else{r.v=0;Q(B,r);if(!o){t[H]="大"; }}}function h(){if(Math.random()<0.11+n/50000){for(j=0;j<L;j++){if(!E[j]){E[j]= 1;break;}}if(j<L){T=D.createElement("div");T.id="e"+j;T[H]=(j==4)?"砲":(j%3==1) ?"棘":j%2==0?"亀":"栗";d.appendChild(T);P(X-b,T);T[A][p]=O;Q(w+((j==4)?40:0),T) ;}}for(i=0;i<L;i++){if(E[i]>0){c=D.getElementById("e"+i);R((-b)*((i==5)?2:1),c) ;if(c.x<20){E[i]=0;d.removeChild(c);}if(r.x>c.x-q*0.1&&r.x<c.x+q*1.3&&r.y>(C=c. y-w)-q*1.5&&r.y<C+q*1.5){if(i%3!=1&&r.K>0){E[i]=0;k(0);J=1;d.removeChild(c);c[H ]="";l(n+=100);}else{r.v+=b*3;t[H]="出";clearInterval(M);k=function(){};o=1;}}} }}function P(z,e){e.x=S(e[A].paddingLeft=z+"px");}function R(z,e){if(0<(f=z+e.x )&&f<X){P(f,e);}else{e.V=0;}}function k(z){R(b*z,r);if(!z&&(r.y==B||J)){r.v+=b* 1.7;t[H]="方";J=0;}}</script>
変数の説明
/* A : "style" a : y方向加速度 B : 画面の底 b : 移動ベース距離 C : 移動させたい敵キャラの正味のy位置 c : 移動させたい敵キャラ D : document d : body E : 敵の利用フラグ配列 e : 関数内での一時変数 F : 移動予定先y位置 f : 移動予定先x位置 G : マリオの毎秒の移動操作 g : ログ出力スペース H : "innerHTML" h : 敵の毎秒の移動操作 I : ステージ領域 i : カウンタ J : 連続ジャンプ可能フラグ j : カウンタ K : 一瞬前のy位置 k : キー押下イベント L : Eの長さ l : ログ出力 M : 敵キャラを動かすタイマーのID n : スコア O : "absolute" o : ゲームオーバーフラグ P : x位置セット p : "position" Q : y位置セット q : 衝突判定のあそび R : x差分移動 r : マリオ全体 S : parseInt s : setInterval T : 生成する敵キャラ t : マリオの胴体 V : x方向速度 v : y方向速度 w : 敵の表示y位置のオフセット X : x境界 x : x位置 Y : y境界 y : y位置 z : 関数内での一時変数 */
番外
なお,本格的なJavaScriptマリオをたった14キロバイトで作成した方もいる。
Jacob Seidelinさんである。
NIHILOGIC:Super Mario in 14kB Javascript
http://blog.nihilogic.dk/2008/04/super-mario-in-14kb-javascript.html非圧縮版ソース
ttp://www.nihilogic.dk/labs/mario/mario.js圧縮版ソース
ttp://www.nihilogic.dk/labs/mario/mario_compressed.jsaike氏によるコードリーディング
http://d.hatena.ne.jp/aike/20080412
後にその14キロバイトのソースはPNGファイルに埋め込まれ,ファイルサイズは8キロバイトになった。
8KB JavaScriptマリオ
http://d.hatena.ne.jp/aike/20080505
追記
この中途半端なプログラムの作成によって会得したショートコーディングのコツは,下記の記事にまとめました。
JavaScript ショートコーディングの10のコツ
http://d.hatena.ne.jp/language_and_engineering/20081009/1223469525
関連する記事:
あなたが,勝つことも引き分けることもできない三目並べ (jQueryプラグイン「jQuery.fakeTicTacToe.js」によるマルバツ・ゲーム) - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20121204/jQueryFakeTicTacToeJs
日経平均株価の下落ぶりをMIDIサウンドで味わう (コマンドラインでMIDI生成) - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20081027/1225038111
touchではないiPod (mini + nano + classic) で,自作はどこまで可能か - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20081106/1225988771