読者です 読者をやめる 読者になる 読者になる

フニゲの開発日記

Electronとか...

はじめてのゲーム (1)

原稿


2014/02/15修正。

まずindex.htmlから

 ここから実際に手を動かして、ゲームを作っていきたいと思います。サンプルなので、Sampleという名前にしましょう。そのまんまですね。まず前章で見たサンプルのHelloHTML5Worldをそっくりコピーして、Sampleという名前のフォルダを作ります。

$ mkdir ~/apps
$ cd ~/apps
$ cp -r ~/cocos2d-html5/HelloHTML5World Sample

 フォルダの中身はこれだけです。

f:id:funige:20131207135354p:plain

 いちばん大きいのは先頭のbuild.xmlですが、これは本書では使わないので削除していいです。res/の中はぜんぶ画像ファイルみたいですね。残りのHTMLファイルとJSファイルについては、これから順に解説していきます。

 あと一つ大事なファイルが欠けているのですが、その説明をする前に、ゲーム画面がブラウザに表示されるまでの流れを頭に入れておきましょう。ブラウザに表示されるのは、もちろんindex.htmlです。

<!DOCTYPE html>
<html>
<head>
   ...
</head>
<body style="padding:0; margin: 0; background: #000;">
<canvas id="gameCanvas" width="800" height="450"></canvas>
<script src="cocos2d.js"></script>
</body>
</html>

 canvasタグとscriptタグがひとつずつ。headの中身は省略しましたが、それにしてもシンプルなページです。このページにどんな魔法を使ってゲームを表示しているのでしょうか。

cocos2d.jsのはたらき

 Cocos2d-html5とは、簡単に言うと200個弱のjavaScriptファイルの集まりです。
 index.htmlにはまず最初にcocos2d.jsというスクリプトが読み込まれます。このスクリプトの仕事は、Cocos2d-html5の残りすべてのファイル(とユーザーの書いたゲーム)を読み込むことです。ブートローダーって奴ですね。古いバージョンではboot-html5.jsという名前でした。個人的には、前の名前の方が役割がはっきりしていて良かったんじゃないかと思いますが、まあ、言ってもしょうがないですか。
 名前の善し悪しはさておき、ここではcocos2d.jsの仕事がとても重い処理だという点に注目しましょう。ローカルでHTTPサーバーを立ち上げて試しているうちはたぶん気がつきませんが、数百個のjavaScriptファイルをインターネットからダウンロードするのは大変な処理です。十秒以上かかることも珍しくありません。ユーザーの多くは途中であきらめてしまいます。
 こういう時にWebの世界でよく使われるのが、複数のファイルを一個にまとめる最適化ですね。Cocos2d-html5ももちろんこの最適化に対応しています。ゴチャゴチャしているのでソースコードは示しませんが、中身を読めば3種類の読み込み方法をサポートしていることがわかるでしょう。

  1. ぜんぶバラバラに読み込む方法(デフォルト)
  2. Cocos2d-html5は一つにして、ゲームはバラバラに読み込む方法
  3. ぜんぶ一つのファイルにして読み込む方法

 3が最も高速ですが、面倒なので本書では扱いません。最初に「削除していいです」と言ったbuild.xmlがそうなのですが、……いや扱いませんよ。2の方法で十分です。

 2のCocos2d-html5を一個にまとめたファイルは~/cocos2d-html5/lib/に用意されていますので、これをSampleプロジェクトのフォルダにコピーしてください。

$ cp ~/cocos2d-html5/lib/Cocos2d-html5-v2.2.1.min.js Sample/

 このファイルをロードするように、cocos2d.jsを修正します。

// cocos2d.js 38行目あたり
  //engineDir:'../cocos2d/',
  SingleEngineFile:'Cocos2d-html5-v2.2.1.min.js',

 これでゲームを実行できるようになりました。やり方はサンプルで遊んだときと同じです。もし前章のHTTPサーバーがまだ実行中でしたら、新しいサーバーを起動する前にControl-Cで停止してください。

$ cd ~/apps
$ python -m SimpleHTTPServer

Serving HTTP on 0.0.0.0 port 8000 ...

 今回は~/appsでサーバーを起動したので、~/­apps/­Sample/­index.htmlのURLはlocalhost:­8000/­Sample になります。これをブラウザのアドレスバーに入力してください。

f:id:funige:20131207135423p:plain

 まだ何も変更していないので、当然サンプルのままです。これに自分のコードを追加していけばいいんですけど、さて、どこに追加すればいいんでしょう?

ゲームの起点はmain.js

 ここまで、index.htmlとcocos2d.jsの2つのファイルのはたらきを見てきました。3つめに説明するのがmain.jsです。ここがゲームの起点になります。概要を以下に示します。

// main.js
var cocos2dApp = cc.Application.extend({
  ctor:function (scene) {
    this._super();
    this.startScene = scene;
    ...
  },
  applicationDidFinishLaunching:function () {
    ...
    cc.LoaderScene.preload(g_resources, function () {
      director.replaceScene(new this.startScene());
    }, this);

    return true;
  }
});
var myApp = new cocos2dApp(HelloWorldScene);

 アプリがスタートするのは、最後の行です。cocos2dAppのインスタンスが作られると、まず最初にcocos2dAppのctorメソッドが呼ばれます。ctorはコンストラクタ (Constructor) の略ですね。
 ctorでいろいろ初期化があって、その最後、ゲームがはじまる直前にapplication­Did­Finish­Launchingが呼ばれます。起動時に一度だけ実行したい処理があれば、ここに書くのがいいでしょう。
 application­Did­Finish­Launchingの最後でthis.­start­Scene(ここではHelloWorld­Scene)のインスタンスが作られて、このシーンからゲームがはじまります。

はじめてのシーン

 ゲームの本体、HelloWorldシーンはsrc/myApp.jsにあります。ここが自分のコードを追加する場所ですね。
 Cocos2dでゲームを書くということは結局、シーンを書くことです。一つのシーンだけでできたゲームもあるし、たくさんのシーンでできたゲームもあります。
 myApp.jsをちょっとずつ書き換えてもいいのですが、ここは思い切って新しく自分のシーンを追加してみましょう。
 myApp.jsと同じフォルダに、sample.jsというファイルを新規作成して、エディタで以下のコードを入力してください。
 全部打ち込むのが面倒な人は、まずmyApp.jsをぜんぶコピーしてから、不要な行を削っていった方が速いです。

// sample.js
var Sample = cc.Layer.extend({
  init:function () {
    this._super();
    var size = cc.Director.getInstance().getWinSize();

    this.helloLabel = cc.LabelTTF.create("Hello World", "Arial", 38);
    this.helloLabel.setPosition(cc.p(size.width / 2, 0));
    this.addChild(this.helloLabel, 5);

    this.setTouchEnabled(true);
    return true;
  },

  onTouchesBegan:function (touches, event) {},
  onTouchesMoves:function (touches, event) {},
  onTouchesEnded:function (touches, event) {},
  onTouchesCancelled:function (touches, event) {},
});

var SampleScene = cc.Scene.extend({
  onEnter:function () {
    this._super();
    var layer = new Sample();
    layer.init();
    this.addChild(layer);
  }
});

 これは要するに、myApp.jsから余計なコードを削って骨組みだけ残したものです。これぐらい削れば、ぐっと理解しやすくなります。前半のinitの中にあるthis.helloLabelというのが、画面に表示される”Hello World”のラベルですね。フォントは38ピクセルのArialですか。setPosition()で位置を決めて、addChild()で表示しているのは何となくわかるでしょう。
 HelloWorldSceneの代わりにこの新しく書いたシーンを表示したいので、main.jsの最後の行を修正します。

// main.js 最後の行
var myApp = new cocos2dApp(SampleScene);

 あともうひとつ修正するところがありました。新しいソースコードを追加したら、cocos2d.jsに追加しないといけません。必要なソースコードをすべてロードするのがcocos2d.jsの役割ですからね。

// cocos2d.js 42行目あたり
  appFiles:[
    'src/resource.js',
    //'src/myApp.js'//add your own files in order here
    'src/sample.js', // ここに追加します
  ]

 ここまでできたら、ブラウザに戻ってリロードボタンを押してみましょう。
 もしうまく動かないようなら、ブラウザのメニューから「表示」→「開発/管理」→「JavaScriptコンソール」でコンソールを開いて、エラーが出ている行番号を確認してください。たぶんどこかに書き間違いがあります。

f:id:funige:20131207135454p:plain

 うん、……HelloWordが画面からはみだしていますけど、これで正解なんです。骨組みだけ残すつもりが、ちょっと削りすぎたみたいです。ラベルの位置を変えてみますか。
 Cocos2dの座標系は、左下が原点なので、X座標を大きくすれば右に、Y座標を大きくすれば上にずれて表示されます。ついでに文字列も変更しておきましょう。いや、特に意味はないんですけど、「Hello World」という文字列を見ると、なんか他の文字列に変えて試したくなりません?僕だけですか?

// sample.js
// 6行目あたり
  this.helloLabel = cc.LabelTTF.create("(・ω・)", "Arial", 38);
  this.helloLabel.setPosition(cc.p(size.width/2, size.height/2));
  this.addChild(this.helloLabel, 5);

 変更したら、またブラウザでリロードボタンを押して結果を確認してください。ブラウザをリロードするだけで結果を確認できるのが便利ですね。今度は画面の中央に表示されるはずです。

広告を非表示にする