2016-11-29 15 views
2

javascriptでカスタムゲームオブジェクトを作成する方法を理解しようとしています。キャンバス上で作業しています。オブジェクトに関する情報を含む一般的なゲームオブジェクトを作成できると思った位置、形状など、「移動」、「火」、「表示」などの機能を持っています。キャンバスゲームアーキテクチャ:JavaScriptオブジェクトの親機能へのアクセス

"create(canvas)"という関数を作成しました。キャンバスを取得し、ローカル変数を初期化してから、 "onload"関数でdisplay関数を呼び出します。 しかし、オブジェクトの表示機能にアクセスすることはできません。 さらに、私はいつもローカル変数または関数にアクセスするために "this"構文を使用します。それは何かが間違っていると感じさせる。

あなたは

<script> 


    var gameObject = { 

     x: 0, 
     y: 0, 
     velocity: 5, 
     width: 40, 
     height: 40, 
     triggerObject:null, 
     imgUrl: "/assets/minionframe/1.png", 
     img:null, 
     canvas:null, 
     context:null, 
     display:function(){ 
      this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 

      this.context.drawImage(this.img,this.x,this.y,this.width,this.height); 
     }, 
     move: function (direction) { 
      if (direction == "right") 
       x += this.velocity; 
      else if (direction == "left") 
       x -= this.velocity; 
      else if (direction == "up") 
       y -= this.velocity; 
      else if (direction == "down") 
       y += this.velocity; 
      this.display(); 
     }, 
     fire: function() { 

     }, 
     create: function (canvas) { 
      this.canvas = canvas; 
      this.context = canvas.getContext('2d'); 
      img = new Image(); 
      img.src = this.imgUrl; 
      img.onload = function() { 
       this.display()//i cant doing this :(
      } 
      return this; 
     } 
    } 

</script> 
<canvas id="scene" width="800" height="600"></canvas> 
<script> 

    var scene = document.getElementById('scene'); 
    var obj = gameObject.create(scene); 


</script> 

おかげでたくさん以下のコードを見ることができます。

答えて

2

私はthisを使用するために、代わりにロジックおよび状態/データを分離しないようお勧めします。

  • 状態::次のように

    概念的には、あなたのゲームを構成することができ、世界の現在の状態を記述するオブジェクト、つまりは、自分の位置、速度、色でオブジェクトを...

  • 更新機能:この関数はすべてのゲームステップで呼び出されます。これは、世界の現在の状態とユーザーの入力を受け取り、新しい状態を返します。
  • レンダリング機能:世界の状態をとり、画面に描画します。

あなたのゲームロジックは次のようにまとめることができます。

// initialize state 
const state = { /*...*/ } 

// set up game loop 
window.requestAnimationFrame(function() { 
    userInput = getUserInput(); 
    state = update(state, userInput); 
    render(state); 
}); 

なぜ?コアロジックのようなゲームのさまざまな部分、レンダリングとユーザー入力の読み方は、できるだけ互いのことを知っている必要があります。つまり、互いに独立して開発することができます。

また、ゲームの状態を論理から分離することで、ゲームの明確な「精神的なモデル」を開発するだけでなく、多くの手助けをします。保存/読み込み機能を実装したいと思っているだけです。ゲームの状態をシリアル化/逆シリアル化するだけです。

私はあなたのコードにこの概念を適用しようとしました:

var state = { 
 
    x: 0, 
 
    y: 0, 
 
    velocity: 5, 
 
    width: 40, 
 
    height: 40, 
 
    triggerObject: null, 
 
    imgUrl: "/assets/minionframe/1.png" 
 
    img: null 
 
} 
 

 
function display(context, state) { 
 
    context.clearRect(0, 0, this.canvas.width, this.canvas.height); 
 
    context.drawImage(state.img, state.x, state.y, state.width, state.height); 
 
} 
 

 
function move(direction, state) { 
 
    if (direction == "right") 
 
    state.x += state.velocity; 
 
    else if (direction == "left") 
 
    state.x -= state.velocity; 
 
    else if (direction == "up") 
 
    state.y -= state.velocity; 
 
    else if (direction == "down") 
 
    state.y += state.velocity; 
 
    
 
    return state; 
 
} 
 

 
function loadImage(state) { 
 
    var img = new Image(); 
 
    img.src = state.imgUrl; 
 
    state.img = img 
 
} 
 

 
var context = document.getElementById('scene').getContext('2d'); 
 
loadImage(state); 
 

 
// some kind of game loop 
 
window.requestAnimationFrame(function() { 
 
    var direction = "right"; // TODO read from user input 
 
    state = move(direction, state); 
 
    display(context, state) 
 
})

しかし、これはまだ完全に分離されていない:

  • display場合、それは理想的である(私たちのレンダリング関数)は、引数contextを必要としません。それが最初に実行されるときに、キャンバス自体を初期化する必要がありますか?
  • imgおよびimgUrlは冗長です。おそらく、imgUrlを落として初期化中にimgに設定することは理にかなっていますか?

これは、とにかく始めるために役立ちますようにお願いします。

+0

ありがとうございました。それは私にゲーム開発アプローチのもう一つの視点を与えてくれます。私はJavaScriptのオブジェクトはC#やJavaのような他のオブジェクト指向プログラミング言語のように動作しますが。だから、私はJava Objectのような構造を構築しようとしていました。 –

+0

"img"はオブジェクトの外観です。私はそれが私のゲームオブジェクトの一部であるかもしれませんが。 –

+0

あなたは大歓迎です!私はJSの開発において、 "古典的な" OOスタイルよりも優れた機能スタイルを見つけました。上記のデザインは、より機能的なスタイルからインスピレーションを受けています。 'img'に関するあなたのコメントは、私の答えを更新しました(最後のコメントを参照) –

0

こんにちはthisの代わりに、ローカル変数_thisRefにこれを直接格納します。

更新されたコードを確認してください。

<script> 


    var gameObject = function(){ 

     x: 0, 
     y: 0, 
     velocity: 5, 
     width: 40, 
     height: 40, 
     triggerObject:null, 
     imgUrl: "/assets/minionframe/1.png", 
     img:null, 
     canvas:null, 
     context:null, 
     _thisRef:this, //storing this refrence. 
     display:function(){ 
      _thisRef.context.clearRect(0, 0, _thisRef.canvas.width, _thisRef.canvas.height); 

      _thisRef.context.drawImage(_thisRef.img,_thisRef.x,_thisRef.y,_thisRef.width,_thisRef.height); 
     }, 
     move: function (direction) { 
      if (direction == "right") 
       x += _thisRef.velocity; 
      else if (direction == "left") 
       x -= _thisRef.velocity; 
      else if (direction == "up") 
       y -= _thisRef.velocity; 
      else if (direction == "down") 
       y += _thisRef.velocity; 
      _thisRef.display(); 
     }, 
     fire: function() { 

     }, 
     create: function (canvas) { 
      _thisRef.canvas = canvas; 
      _thisRef.context = canvas.getContext('2d'); 
      img = new Image(); 
      img.src = _thisRef.imgUrl; 
      img.onload = function() { 

      } 
      //return _thisRef; //no need 
     } 
    } 

</script> 
<canvas id="scene" width="800" height="600"></canvas> 
<script> 

    var scene = document.getElementById('scene'); 

    var obj = gameObject.create(scene); 

    var obj = new gameObject(); //creating object of gameObject class. 
    obj.create(scene); //passing Canvas element. 
    obj.display(); // this will call display function. 

</script> 
+0

「_thisRef.imgUrl」の使用と「imgUrl」の直接使用の違いは何ですか? –

+0

同じ名前のローカル変数がない場合、そのような違いはありません。 その関数内にimgUrl変数があり、それを直接使用している場合は、クラスレベルの変数ではなくそのローカル変数を参照します。 – spankajd

関連する問題