『enchant.js入門【公式ガイド】 』を読んで, ゲームを作りました

phiary に引っ越しました. 毎日プログラミングやWebに関する情報を発信しています! RSS 登録してたまに覗いたり, tweet やハテブして拡散してもらえると幸いです.

Pocket

前回のエントリー『HTML5とJavaScriptでスマートフォンゲーム作成! ゼロからはじめるenchant.js入門【公式ガイド】』を読んだのでレビューってみるで, この本を読みながら作ったゲームを公開します. と宣言していたので公開します.

下に全コードを載せています. また, ダウンロードできるようにしてあるのでローカルで色々イジって遊んでみてください.

Play Game Download

About

最近話題の『HTML5とJavaScriptでスマートフォンゲーム作成! ゼロからはじめるenchant.js入門【公式ガイド】』 をひと通り読んで作ったゲームです.

主に”第5章 ゲームデザイン” を参考にアレンジして作りました.

もともとのゲームは9leapにある『もぐらたたき』です.

制限時間内にひょこひょこ出てくるドロイド君(モグラ)をタッチしてハイスコアを目指すシンプルなゲームです.

サウンドが再生されたり, たまにスーパードロイド君(ハイスコアモグラ)が出てきたりします.

本当は人っぽいのも穴から出してタッチすると減点!!なんてこともやろうと思ったのですが, 絵を用意するのが面倒くさくてw だれか絵書くよって人いたらご連絡下さい.

Code

今回制作したゲームのコード全体です.

参考書を見ながら作ったといっても, ほぼ自分っぽくコーディングしなおしているのでコード自体は別物です.

クセというか, 普段仕事では C++ を使う機会が多いので, 趣味でやっている Web プログラミングでは, C++ っぽくない書き方をよくします.

穴(Pit)クラスの実装を見てもらえればわかるかと思うのですが, 状態を変数として持つのではなく変数として更新関数を持ち状況に応じて入れ替えているのがわかるかと思います.

/**
 * phi
 */

// --------------------------------
// 定数
// --------------------------------
var SCREEN_SIZE = 320;
var PIT_SIZE    = 48;
var MOGURA_INTERVAL         = 4;
var SUPER_MOGURA_INTERVAL   = 1;

var MOGURA_IMAGE_NAME       = "img/mogura.png";
var SUPER_MOGURA_IMAGE_NAME = "img/super_mogura.png";

// --------------------------------
// グローバル
// --------------------------------
var game        = null;
var scoreLabel  = null;

// --------------------------------
// おまじない
// --------------------------------
enchant();

// --------------------------------
// main
// --------------------------------
window.onload = function()
{
    game = new Game(SCREEN_SIZE, SCREEN_SIZE);
    game.fps = 30;
    
    // 画像をロード
    game.preload(MOGURA_IMAGE_NAME, SUPER_MOGURA_IMAGE_NAME);
    // サウンドロード
    tm.Sound.load("sound/hit", "hit");
    tm.Sound.load("sound/hit2", "hit2");
    tm.Sound.load("sound/clap00", "clap00");
    tm.Sound.load("sound/clap01", "clap01");
    
    game.onload = function() {
        var scene = game.rootScene;
        scene.backgroundColor = "rgb(240, 240, 240)";
        
        // 穴生成
        for (var i=0; i<4; ++i) {
            for (var j=0; j<4; ++j) {
                var pit = new Pit();
                pit.x = i*55+50;
                pit.y = j*55+50;
                scene.addChild(pit);
            }
        }
        
        // スコア
        scoreLabel = new ScoreLabel();
        scoreLabel.x = 5;
        scoreLabel.y = 5;
        scene.addChild(scoreLabel);
        
        scene.onenter = function() {
            game.frame = 0;
        };
        
        scene.onenterframe = function() {
            if ((game.frame/game.fps) > 15) {
                gameOver();
            }
        };
    };
    game.start();
};


var gameOver = function(msg)
{
    msg = scoreLabel.score + "point です.";
    console.log(scoreLabel.score, msg);
    game.end(scoreLabel.score, msg);
    
    // 拍手
    if (scoreLabel.score < 500) {
        tm.Sound.play("clap00");
    }
    else {
        tm.Sound.play("clap00");
    }
};

// --------------------------------
// 穴クラス
// --------------------------------
var Pit = Class.create(Sprite, {
    initialize: function() {
        enchant.Sprite.call(this, PIT_SIZE, PIT_SIZE);
        
        // タイプをセット
        this.changeType();
        // ランダムな時間待って出現処理に切り替える
        this.setWait(Math.random()*200, this.appear);
        
        // タイム進行関数を登録
        this.addEventListener("enterframe", function() {
            ++this.time;
        });
    },
    
    ontouchstart: function() {
        // 2~4フレームのときのみタッチ可能
        if (1 < this.frame && this.frame < 5) {
            // 気絶処理に切り替える
            this.frame = 5;
            this.onenterframe = this.damage;
            this.time = 0;
            
            // スコア加算
            if (this.interval == SUPER_MOGURA_INTERVAL) {
                tm.Sound.play("hit2");
                scoreLabel.add(100);
            }
            else {
                tm.Sound.play("hit");
                scoreLabel.add(10);
            }
        }
    },
    
    appear: function() {
        if (this.time % this.interval == 0) {
            this.frame += 1;
        }
        
        if (this.frame >= 4) {
            this.setWait(this.interval*10, this.hide);
        }
    },
    
    hide: function() {
        if (this.time % this.interval == 0) {
            this.frame -= 1;
        }
        
        if (this.frame <= 0) {
            this.setWait(Math.random()*200, this.appear);
            this.changeType();
        }
    },
    
    damage: function() {
        if (this.time > 20) {
            this.frame = 0;
            this.setWait(Math.random()*200, this.appear);
            this.changeType();
        }
    },
    
    wait: function() {
        if (this.time > this.waitTime) {
            this.onenterframe = this.nextFunc;
        }
    },
    
    setWait: function(waitTime, nextFunc) {
        this.onenterframe   = this.wait;
        this.time           = 0;
        this.nextFunc       = nextFunc;
        this.waitTime       = waitTime;
    },
    
    changeType: function() {
        if (Math.floor(Math.random()*16) == 1) {
            this.interval = SUPER_MOGURA_INTERVAL;
            this.image = game.assets[SUPER_MOGURA_IMAGE_NAME];
        }
        else {
            this.interval = MOGURA_INTERVAL;
            this.image = game.assets[MOGURA_IMAGE_NAME];
        }
    },
});


// --------------------------------
// Score Label
// --------------------------------
var ScoreLabel = Class.create(Label, {
    initialize: function()
    {
        Label.call(this, "SCORE: ");
        this.font = "16px 'Consolas', 'Monaco', 'MS ゴシック'";
        this.set(0);
    },
    
    set: function(p)
    {
        this.score = p;
        this.refresh();
    },
    
    add: function(p)
    {
        this.score += p;
        this.refresh();
    },
    
    refresh: function()
    {
        var score_text = this.score+'';
        while (score_text.length < 4) { score_text = '0'+score_text; }
        this.text = "SCORE:" + score_text;
    }
});
[/code]

プログラミング系の参考書を読む際のコツ, というか私が心がけていることを少しだけ書きます.

プログラミング系の参考書を読みながらプログラミングをする際は, 本に書いてあるコードを丸写ししたり, サンプルコードをコピペしたりするのではなく, アルゴリズムだけを参考にし, 自分なりの作り方でコーディングすることをオススメします.

そうすれば, やりたいことをプログラミングの落としこむ能力が鍛えられます.

参考になれば幸いです.

TRACK BACK URL

POST COMMENT

メールアドレスが公開されることはありません。

COMMENT