作業(最後)の整理整頓

ああ、私が苦手な作業ですね。え、あ、いや、やりますよやりますって。夏休みの最後の夜とかに。

追加・変更部分をまとめる

今回作ったゲームは、その場その場で調べながら作った形でした。これは「とりあえず動かす」「まずは何かきっかけを持つ」には適したやり方ですが、後から見るとまとまりが悪く、作成者自身でも読みづらい(変更しづらい)、可読性の低いプログラムになりがちです。プログラミングに限った事ではありませんが、整理することで、対処療法的な手法ではなく、課題解決の手段に昇華させる事ができます(大変耳が痛いです)。

今回整理する場所は

  1. 使わなくなった部分
    • →削除。後々別の不具合を誘発する可能性がある。
  2. 一時的なコメントアウトの部分
    • →削除。可読性が下がる。
  3. 新しく追加した部分
    • →変更を検討。読みやすさ・改修しやすさを考えてみる。

あたりでしょうか。新しく追加した部分は多いですが、特に1から作った部分といえばラベルの部分や終了画面の部分になるので、ここらへんは整理がいろいろ出てくるところになりそうです。

つぎに、まとめる方針です。これはあくまで私の場合ですが

  • 同じような処理は近くに書くかひとつにするように
  • 規模が大きくなりそうであれば、変数の命名規則(特に接頭辞)を決めておき、合わせる
  • 適切なコメントを追記する
  • インデントのずれを修正する
  • 後から変更したくなりそうなところは変数化しておく

という事には気を配っているつもりです。もっとも、これが変更しづらい原因になる事もありますが。

とにかくこういうのは色々書いてみるに限ります。そして、それをメンテナンスしてみてください。1週間経って無理なく自分のプログラムを読む事ができれば十分読みやすいコードと言っていいと思います。

下記に私が整理したソースを載せておきます。参考程度でどうぞ。本当にどういうコードがいいかは自分で探していってください。

enchant(); // initialize

window.onload = function(){

var game = new Core(320, 320);
game.preload('chara7.png', 'chara6.png', 'icon0.png'); // preload image
game.fps = 20;

game.onload = function(){

    // ----- ゲーム内共通利用変数 ---------
    var player; // プレイキャラクター
    var score; // スコアの値
    var lifecount; // 残ライフ数
    var info; // スコアなどのラベル表示

    // ----- 画面パーツ関係 ---------
    // プレイキャラクタークラス
    var Player = enchant.Class.create(enchant.Sprite, {
        initialize: function(){
            enchant.Sprite.call(this, 32, 32);
            this.image = game.assets['chara7.png'];
            this.x = 288;// add:右側に表示。320-32の位置
            this.frame = 10; // キャラクター
            this.attackframe = -1; // 攻撃状態確認用。0未満がデフォルト
            game.rootScene.addChild(this); // 画面にプレイキャラクター追加
        },
        attackstart: function(){
            this.frame = 16; // 斬っている瞬間の画像
            this.attackframe = 0; // 攻撃状態確認0回目
        },
        attackend: function(){
            if( this.attackframe < 0 ) return; // 攻撃状態では無い場合は後続処理をしない
            if( this.attackframe == 3 ) {
                this.frame = 10; // 普段の画像
                this.attackframe = -1;
            } else {
                this.attackframe ++;
            }
        },
        onenterframe:function(){ // フレーム単位でのプレイキャラクター監視
            this.attackend(); // attackstartしてから終わるまでをみはる
        },
        endgraphic: function(){ // ゲームオーバー時の表示
            this.frame = 29;
            this.rotation = -90;
            this.x = 140;
            this.y = 140;
            this.scale(3,3);
        }
    });

    // 敵キャラクラス
    var Enemy = enchant.Class.create(enchant.Sprite, {
        initialize: function(){
            enchant.Sprite.call(this, 32, 32);
            this.image = game.assets['chara6.png']; // set image
            this.moveTo(0, Math.floor(Math.random() * 320)); // 変更
            this.scaleX = -1;
            this.tl.moveBy(360, 0, 160);      // 変更
            this.frame = 9;                   // 敵キャラ画像
            game.rootScene.addChild(this);     // 画面に敵キャラ追加
        },
        onenterframe: function(){
            if(this.within(player) && player.attackframe >= 0){ // 敵を斬った場合
                game.rootScene.removeChild(this); //画面から削除
                info.plusscore(); // スコアカウントアップ
            }
            if(this.x >= 315){ // 敵が右端に到達した時
                game.rootScene.removeChild(this); // 画面から削除
                info.minuslife(); // ライフカウントダウン
            }
        }
    });

    // ラベル表示
    var Info = enchant.Class.create(enchant.Label, {
        initialize: function(){
            enchant.Label.call(this);
            this.x = 5;
            this.y = 5;
            this.color = "black";
            this.settext();
            game.rootScene.addChild(this);
        },
        settext: function(){
            this.text = 'Life : ' + lifecount + '  ' + 'Score : ' + score ;
        },
        minuslife: function(){ // ライフ減らす処理
            lifecount--; // 減らす
            this.settext(); // ラベルを更新
        },
        plusscore: function(){ // スコア増やす処理
            score++;
            this.settext();
        }
    });

    // ---- 追加シーン ------
    // ゲームオーバーシーン
    var endScene = enchant.Class.create(enchant.Scene, {
        initialize: function(){
            enchant.Scene.call(this);
            this.backgroundColor = '#666666';
            // プレイキャラクターをゲームオーバー状態表示にする
            player.endgraphic();
            this.addChild(player);
            // ゲームオーバーシーンにスコア表示追加
            var endlabel = new Label('ヤラレタ...<br>Score : ' + score);
            endlabel.color='#cccccc';
            endlabel.y = 200;
            endlabel.textAlign = 'center';
            this.addChild(endlabel); // ゲームオーバーシーンに追加
            game.pushScene(this); // シーン切り替え
        }
    });

    // 各利用変数に初期値を代入
    player = new Player();
    score = 0;
    lifecount = 3;
    info = new Info();

    // ----- 画面動作関係 ------
    // 敵キャラ生成(60フレーム単位)
    game.rootScene.tl.then(function() {
        new Enemy();
    }).delay(30).loop();

    // タッチスタート時処理
    game.rootScene.on('touchstart', function(evt){
        player.y = evt.localY;    // set position to touch-y position
        player.attackstart();
    });

    // タッチムーブ時処理
    game.rootScene.on('touchmove', function(evt){
        player.y = evt.localY;    // set position to touch-y position
    });

    // 画面フレームで監視
    game.rootScene.on('enterframe', function(){
        if(lifecount === 0){ //ゲームオーバー時処理
            new endScene();
            game.stop();
        }
    });
};
    game.start(); // start your game!
};

シーンの取り扱い方が平等でない気がしますが、まあ、(自分は)読めるし。

ということで、これくらいで止めています。