質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.05%

変数の使用方法について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,295

score 41

現状

自作ゲームを制作しようとしている、プログラミング初心者です。
現在JavaScriptを用いてゲームを作成しているのですが、意図しない動作をしたので
質問したいと思います。

内容

まずは、このコードです。
少し長いかもしれませんが、見ていただきたいです。

enchant();

var canvas;

var Pscene;     //待期シーン
var play;

var RsceneW;    //勝利シーン
var RsceneL;    //敗北シーン
var RsceneD;    //引き分けシーン


window.onload = function(){
    var game = new Core(320, 320);
    game.preload('img/chara1.png', 'img/enchant.png', 'img/sirokuma.png','sound/bakumatsubukyoku_hananoran.mp3');
    game.fps = 15;

    game.onload = function(){

        Pscene = new Scene();
        var bear = new Sprite(32, 32);
        bear.image = game.assets['img/chara1.png'];
        bear.x = 30;
        bear.y = 80;
        bear.frame = 0;
        Pscene.addChild(bear);

        var enemy = new Sprite(32, 32);
        enemy.image = game.assets['img/sirokuma.png'];
        enemy.x = 200;
        enemy.y = 80;
        enemy.scaleX = -1;
        enemy.frame = 2;
        Pscene.addChild(enemy);

        play = function(){
            game.pushScene(Pscene);
        }

    }
    game.start();
};

play();

現在Psceneなどを関数で表示しようとしているのですが、
window.onloadの外側で変数playを定義して、window.onladの内側で変数playに、
Psceneを表示させる関数を代入し、
その変数playを、window.onloadの外側で呼び出すことをしようとしているのですが

main.js:41 
Uncaught 
TypeError: play is not a function
    at main.js:41


と、エラーメッセージが表示されました。
自分の変数が誤っているのは、理解できるのですが
現在自分が考えているような事
〔変数playにPsceneを表示する関数を代入し、window.onloadの外側で関数を呼び出す〕
をするためには、どのような解決策がありますか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

考え方はあってますが、イベントの知識が足りないのかなと思いました。

::追記
kei344さんがおっしゃるように、非同期処理も学んでみてください。
javascriptではイベントと非同期処理が非常に重要になります。
ただ、非同期処理はテストがとても面倒になることにもなるので
そのあたりは設計を頑張ってくださいね。
::追記ここまで

以下の

window.onload


に対して代入するのは、関数です。ちゃんと関数が代入されていますが、
この代入した関数が実行されるタイミングより前に、[play();]としている
ため、代入処理がなされる前に実行されます。

現状のコードは以下のような順番で実行されます。

// 実行開始 1
enchant();

var canvas;

var Pscene;     //待期シーン
var play;

var RsceneW;    //勝利シーン
var RsceneL;    //敗北シーン
var RsceneD;    //引き分けシーン

 // ここでは window の onload イベントが実行された時に実行される関数を
  // 登録する処理
window.onload = 
     /*
    =====================================================================
    ここからは、 window の onload イベントが実行された後に行われる
      */
     function(){
        var game = new Core(320, 320);
        game.preload('img/chara1.png', 'img/enchant.png', 'img/sirokuma.png','sound/bakumatsubukyoku_hananoran.mp3');
        game.fps = 15;


      // ここでは game 変数に格納された Coreの onloadイベントが実行されたときに
        // 実行される関数を登録する処理
        game.onload = 

        /*

         ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      ここからは、 gameに格納された Core の onload イベントが実行された後に行われる

        */
      function(){

            Pscene = new Scene();
            var bear = new Sprite(32, 32);
            bear.image = game.assets['img/chara1.png'];
            bear.x = 30;
            bear.y = 80;
            bear.frame = 0;
            Pscene.addChild(bear);

            var enemy = new Sprite(32, 32);
            enemy.image = game.assets['img/sirokuma.png'];
            enemy.x = 200;
            enemy.y = 80;
            enemy.scaleX = -1;
            enemy.frame = 2;
            Pscene.addChild(enemy);

            play = function(){
                game.pushScene(Pscene);
            }

        }
        /*

      ここまで、 gameに格納された Core の onload イベントが実行された関数の終了
         ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        */
        game.start();
    };

     /*
    ここまで、 window の onload イベントが実行された関数の終了
    =====================================================================
      */

// 上記より +++ で囲まれた領域が実行されていないのにplayを関数呼び出しするため
// playの内容はデフォルト値の undefined にたいして関数実行をするためエラーとなる
play();

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/12 22:25

    なるほど、ということは、
    1. enchant(); ~ var RsceneD;
    2.play();
    3.window.onload
    という順番で実行されるため、エラーが発生すると言うことですか?

    それならば、自分が意図している動きを再現する方法は非同期の関係で不可能ですか?

    キャンセル

  • 2017/06/13 00:42

    window.onloadのイベント発火時に処理する関数の登録直後にplayを実行するのは無理かと思います。

    game.onloadeイベント発火後に処理されることが確定するのであれば可能かとおもいます。

    そうでなければ、playを利用する前に毎回playが関数かをtypeofで判断して関数なら利用するというような判定処理が必要ですがあまり現実的ではないかと。

    キャンセル

  • 2017/06/14 19:25

    なるほど、有り難うございます。

    キャンセル

+2

非同期 JavaScript」で検索してみてください。

//play();

play = function(){
    game.pushScene(Pscene);
}
play(); // ここで始めて実行できる

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る