SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

「crocro.jscam」ライブラリの使い方
――JavaScriptでWebカメラの画像やマーカー情報を取得するライブラリ

ダウンロード jscam_1.1.0.zip (60.2 KB)

ゲームコントローラのサンプル

 次は、WebカメラとARマーカーを使って、ゲームのコントローラーを簡易的に作るサンプルを紹介します。

 「crocro.jscam」では、配列を引数にして、Webページ上にARマーカーを作成する機能もあります。ここでは、この機能を使い、Webページ上にARマーカーを表示します。このARマーカーをWebカメラで撮影して、動かすことで、Canvas上の仮想コントローラーの向きや長さを変えます。

 この方法を応用することで、楽しいWebカメラゲームを作ることができます。

ゲームコントローラのサンプル

 それでは実際にソースコードを見てもらいます。

ゲームコントローラのサンプル
<!DOCTYPE html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>「crocro.jscam」 - サンプル ゲームコントローラ - クロノス・クラウン</title>
    <script
        type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"
    ></script>
    <script type="text/javascript" src="jscam.js"></script>
    <script language="javascript">
        // 変数
        var cap;

        // 起動時処理
        $(document).ready(function() {
            // JSカメラ初期化
            crocro.jscam.initSwfCam();
            crocro.jscam.setFilter(["bin", "label", "detectMarker", "drawMarker"]);
                                                  // ………【1】フィルタ設定
            cap = crocro.jscam.makeCaptureObject("cnvsCap");

            // コールバックの設定
            cap.setBackDataType(["markerData"]);  // ………【2】コールバック設定

            // マーカーの設定
            viewMarker();

            crocro.jscam.ready(function() {  // 準備ができたら開始
                cntrl();  // コントロール
            });
        });

        // 画像取得
        function cntrl() {
            cap.capture(function(resObj){    // 各戻り値ごとの処理
                var resArr = [];
                if ("markerData" in resObj) {  // ………【3】マーカーデータ
                    // 出力
                    var s = "";
                    var md = resObj.markerData;
                    $.each(md, function(k, v) {s += k + ":" + v + ", "});
                    s += "<br>"
                    s += "lt(" + md.ltX + ", " + md.ltY + ") / "
                        + "rt(" + md.rtX + ", " + md.rtY + ")<br>";
                    s += "lb(" + md.lbX + ", " + md.lbY + ") / "
                        + "rb(" + md.rbX + ", " + md.rbY + ")";
                    resArr.push("<hr>markerData : " + s);

                    // 中心からのコーン
                    var ctx = cap.cntxtObj;        // 2Dコンテクストを取得
                    ctx.clearRect(0, 0, cap.w, cap.h);
                    drawLine(ctx, "#ff0000", 3, [
                         [md.ltX, md.ltY]
                        ,[md.rtX, md.rtY]
                        ,[md.rbX, md.rbY]
                        ,[md.lbX, md.lbY]
                    ]);
                    drawLine(ctx, "#ff0000", 3, [
                         [md.ltX - 2, md.ltY - 2]
                        ,[md.ltX + 2, md.ltY - 2]
                        ,[md.ltX + 2, md.ltY + 2]
                        ,[md.ltX - 2, md.ltY + 2]
                    ]);

                    drawLine(ctx, "#8f0000", 1, [
                         [cap.w / 2, cap.h / 2]
                        ,[md.ltX, md.ltY]
                    ]);
                    drawLine(ctx, "#8f0000", 1, [
                         [cap.w / 2, cap.h / 2]
                        ,[md.rtX, md.rtY]
                    ]);
                    drawLine(ctx, "#8f0000", 1, [
                         [cap.w / 2, cap.h / 2]
                        ,[md.rbX, md.rbY]
                    ]);
                    drawLine(ctx, "#8f0000", 1, [
                         [cap.w / 2, cap.h / 2]
                        ,[md.lbX, md.lbY]
                    ]);

                    // 傾きと大きさ
                    var cntrX = (md.ltX + md.rtX + md.rbX + md.lbX) / 4;
                    var cntrY = (md.ltY + md.rtY + md.rbY + md.lbY) / 4;
                    var dirX = ((md.ltX + md.rtX) / 2 - cntrX);
                    var dirY = ((md.ltY + md.rtY) / 2 - cntrY);

                    drawLine(ctx, "#0000ff", 5, [
                         [cap.w / 2, cap.h / 2]
                        ,[cap.w / 2 + dirX, cap.h / 2 + dirY]
                    ]);
                }
                $("#resData").html(resArr.join("<br>"));
            });
            setTimeout(cntrl, 50);
        }

        // 線描画
        function drawLine(ctx, col, width, arr) {
            ctx.strokeStyle = col;
            ctx.lineWidth = width;
            ctx.beginPath();
            ctx.moveTo(arr[0][0], arr[0][1]);
            for (var i = 1; i < arr.length; i ++) {
                ctx.lineTo(arr[i][0], arr[i][1]);
            }
            ctx.lineTo(arr[0][0], arr[0][1]);
            ctx.closePath();
            ctx.stroke();
        }

        // キャプチャ
        function captureImg() {
            cap.capture();  // キャプチャ
        }

        // マーカー設定
        var mrkrArr = crocro.jscam.util.swapXY(16, 16, [  // ………【4】マーカー配列
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
        ]);

        // マーカー表示
        function viewMarker() {
            // マーカーの作成
            crocro.jscam.util.makeMarker("marker", mrkrArr, 13, true,
                                                          // ………【5】マーカー作成
                function(x, y, prm){
                    mrkrArr[x][y] = prm;
                    crocro.jscam.setMarker(mrkrArr);
                }
            );
        }
    </script>
</head>
<body bgcolor="#ffffff">

    <div id="jscamAS" class="boxOut">
        <table border=0><tr><td valign="top">
            <script language="javascript">
                crocro.jscam.write();
            </script>
        </td><td valign="top" style="padding-left: 32px;">
            ●マーカー形式<br>
            <br>
            <div id="marker"></div>
        </td></tr></table>
    </div>
    <div id="jscamJS" style="">
        <table border=0><tr><td valign="top">
            <canvas id="cnvsCap" width="320" height="240"></canvas>
        </td><td valign="top">
            <div id="resData"></div>
        </td></tr></table>
    </div>

</body>
</html>
	

 それでは簡単な解説を行います。まずは【1】の setFilter です。ここでは、 ["bin", "label", "detectMarker", "drawMarker"] と指定することで、「2値化」「ラベリング」「マーカー検出」「マーカー表示」を設定しています。

 次に【2】の setBackDataType です。ここでは ["markerData"] だけを指定しています。画像のデータを取得しないことで、高速に、そして少ないメモリーの消費で、マーカーのデータを取得しています。このように、必要なデータに絞ってコールバックさせることで、処理を最適化することができます。

 【3】の部分では、受け取ったデータを元に、仮想コントローラーの値を計算しています。描画は、一般的なHTML5のCanvasを利用した方法です。

 【4】【5】では、配列データを元に、ARマーカーをWebページ上に生成しています。

 ここでは、 makeMarker メソッドの第4引数(編集が可能かのフラグ)を true にしています。そのため、マーカーをクリックすれば、マーカーの形をドット絵のように編集することができます。

次のページ
全部盛りのサンプル

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/6393 2012/02/15 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー