2016-11-29 40 views
2

我想了解如何在javascript中創建自定義遊戲對象。我在畫布上工作,我認爲可以創建一個包含對象信息的常規遊戲對象位置,形狀等和功能,如「移動」,「火」,「顯示」等的Canvas遊戲體系結構:在JavaScript中訪問父級函數對象

我創建一個名爲「創建(畫布)」函數。獲取畫布並初始化局部變量,然後在「onload」函數中調用顯示函數。 但我無法訪問對象的顯示功能。 此外,我總是使用「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。也許它應該初始化畫布本身,當它第一次運行?
  • imgimgUrl是冗餘的。也許這將是有意義的初始化期間下降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