OJAG workshop@Naha Vol.12に参加してゲーム作ってきた!

昨日は日本Androidの会 沖縄支部の勉強会に参加しました。

成果物は9leap : OJAG Naha Hackathon by hanachin_ - どこでも遊べる、投稿型ゲームサイト

今回の勉強会は

  • 9leapの伏見様([twitter:@sidestepism])のお話
    • 今回のために来沖(日帰り)してくださったみたいです。超ありがたいです。
    • enchantと9leapの紹介
    • ライブコーディング
  • enchant.jsを使ったハッカソン!
    • ハックとマラソンを掛け合わせた言葉で皆で集まって開発する感じのイベント
    • 今回は2時間半ちょい黙々とゲーム作成。
  • 懇親会
    • 10時間で21本ゲーム作成の話などなど
  • 懇親会2

という感じでした。
僕も2時間半ぐらい黙々といじってTouchTheNumbers風のゲームを作成しました。懇親会も楽しかったです。
以下、当日聞いた内容の自分なりのまとめと、ハッカソンで作ったもの、作ってた時の過程を書きます。

9leapについて

9leapという若いプログラマ向けのゲームコンテストサイトがあります。(enchant.jsで作られたゲームが数多く投稿されています)
その9leapのプロジェクトリーダーの伏見様が1時間ほどenchant.jsの紹介とライブコーディングをしてくださいました!(テキストエディタはCotEditorでした)
スライドはまだあがってないようですが内容的には「enchant.js & PRO」第21回 html5とか勉強会 ショートセッションのような感じでした。

enchant.jsについて

enchant.jsはJSでBASICみたいにゲームを短く楽しく書けてしかも軽い、モダンなブラウザがあればどこでもゲームが動く!というすごいものです。
確かに書いてみるとめっちゃ楽でした。1枚の画像にまとめられてる複数の絵を切り出すのがプロパティ指定するだけで出来たり。
ゲームがっつり書いたことない自分でも2時間半で1つゲームが作れました!
こんなに簡単に作れるなんて中身がどうなってるのか気になるので是非enchant.jsソース読みしたい。
あと、ゲームつくり楽しかったのでリトライしてみたくなりました。っていうかリトライしますw

enchant PRO

スマートフォンのカメラ等をenchant.jsから簡単に扱えるらしい。ARも簡単に書けるようでめっちゃ気になる…

ハッカソンで作ったもの

TouchTheNumbers(5x5のますにランダムに配置された1から25までの数字を順番よく押して時間を競うゲーム)を作りました。
先輩のiPod touchでプレイしてハマってしまったのが理由。
動きのあるサンプル見せてもらったのに動きが地味なのもの作ってしまったので後でもっと楽しい感じに書き直そうかと orz
9leapで公開したので以下のリンクからプレイ出来ます!
9leap : OJAG Naha Hackathon by hanachin_ - どこでも遊べる、投稿型ゲームサイト

作ってた時の過程

画像の出し方、移動程度は予習してました。
目標は「必ず完成させて公開する」でした。
私が今受講している週末ものづくり講座の影響です。

ステップ

ステップとしては

  1. 数値を画像に変換
    1. まずは0から9までの変換
    2. それを利用してn桁対応
  2. 数値の入ったますを作る
    1. まずは普通のますを作る
    2. 数値を画像に変換してそのますにのっける
  3. 1から25までの数値の入ったますをランダムに配置
  4. 1から順に押されているかのチェック
  5. 時間の計測
  6. 9leap公開・スコア送信

という感じで進めていきました。
数値の入ったますを作る処理が出来るまででハッカソンの時間の2/3、順に押されてるかのチェックと時間の計測を実装したとこで2時間経過、その後9leap公開、送信ちょっとした修正で30分ぐらいかかりました。

ソース

ソースコードは以下のような感じ。
9leap : OJAG Naha Hackathon by hanachin_ - どこでも遊べる、投稿型ゲームサイトからzipで一式落とせます。

Array.prototype.shuffle = function() {
    var i = this.length;
    while(i){
        var j = Math.floor(Math.random()*i);
        var t = this[--i];
        this[i] = this[j];
        this[j] = t;
    }
    return this;
}

enchant();

count = 0;

window.onload = function() {
    var game = new Game(320, 320);
    game.fps = 15;
    game.preload('font.png');
    game.onload = function() {
    	function makeBlock(w, h) {
    		var block = new Sprite(w, h);
    		block.x = 0;
    		block.y = 0;
    		return block;
    	}
    	function squareBlock(size) {
    		var bg = makeBlock(size, size);
    		return bg;
    	}
    	function addBorder(block, size, color) {
    		var wrap = new Group();
    		var bg = makeBlock(block.width + size * 2, block.height + size * 2);
    		bg.x = 0;
    		bg.y = 0;
    		bg.backgroundColor = color;
    		block.x += size;
    		block.y += size;
    		wrap.addChild(bg);
    		wrap.addChild(block);
    		return wrap
    	}
    	function numBlock(n) {
    		var block = new Group();
    		block.x = 0;
    		block.y = 0;
    		block.width = 44;
    		block.height = 44;
    		// 64
    		var bg = squareBlock(44);
    		bg.backgroundColor = "#fff";
    		var bg = addBorder(bg, 2, "#2f4f4f");
    		block.addChild(bg);
    		
    		var nums = (""+n).split('').map(function (x) { return parseInt(x); });
    		for (var i = 0; i < nums.length; i++) {
    			var sp = numSprite(nums[i]);
    			sp.x = i * 16 + 8;
    			sp.y = 16;
    			block.addChild(sp);
    		}
    		return block;
    	}
    	function numSprite(n) {
    		var sp = new Sprite(16, 16);
    		sp.image = game.assets['font.png'];
    		sp.x = 0;
    		sp.y = 0;
    		sp.frame = n + 16;
    		return sp;
    	}
    	
    	function init() {
    		// var scene = new Scene();
    		var scene = game.currentScene;
    		
    		var nums = [];
    		for (var i = 1; i <= 25; i++) { nums.push(i); }
    		nums.shuffle();
    		
    		for (var i = 0; i < 5; i++) {
    			for (var j = 0; j < 5; j++) {
        			var index = (i * 5) + j;
        			var block = numBlock(nums[index]);
        			block.x = j * 48;
        			block.y = i * 48;
        			
        			var click = (function () {
        				var n = nums[index];
        				var b = block;
            			return function (e) {
            				var x = e.x;
            				var y = e.y;
            				if (b.x < x && x < b.x + 48
            						&& b.y < y && y < b.y + 48
            						&& count == n) {
            					count++;
            					b.backgroundColor = "black";
            					var paint = squareBlock(48);
            					paint.x = b.x;
            					paint.y = b.y;
            					paint.backgroundColor = "#fff";
            					scene.addChild(paint);
            					
            					if (count == 26) {
            						var score = Math.floor((start / game.fps) * 10)/10;
            						game.end(10000 - score, "Your score is " + score);
            					}
            				}
            			}
        			});
        			block.addEventListener("touchstart", click());
        			
                	scene.addChild(block);
    			}
    		}
    		
    		count = 1;
    		
    		//game.replaceScene(scene);
    	}
    	
    	init();
    	
    	start = 0;
    	
    	game.rootScene.addEventListener('enterframe', function () {
    		start++;
    	});
    };
    game.start();
};

感想

ハッカソン楽しい。動いたもの公開して人が遊んでくれるとやっぱり嬉しい。
ゲームプログラミングやるとプログラミングが出来るよになるというのも話されていたのでゲームを作りたい。
そして作ったゲームを9leapにドシドシ投稿していきたいです。

刺激を受けた部分としては懇親会でお話されていた10時間で21本というのを聞いて自分も手をもっと早く動かせるようになりたいなぁ、と。
# enchant PROのARやTwitterでやりとりされていたnode.jsでエアホッケーとかすごく楽しそう