2013-10-25 32 views
0

http://jsfiddle.net/xknbn/ http://jsfiddle.net/xknbn/embedded/result/(JS/Canvas)的碰撞/運動的的sidescroller

嘿,夥計們。我遇到的問題讓我的碰撞系統無故障運行。目前,如果我的速度太快,我會嵌入到對象中,並且我的衝突解決失敗。我相當確定問題的發生是因爲我如何設置速度,但我不知道如何才能解決問題。任何幫助將不勝感激。

friction = 0.9, 
gravity = 0.3; 

function keycheck() { 

if (keys[32]) { 
    if (!player.jumping) { 
     player.jumping = true; 
     player.vely = -player.speed; 
    } 
} 

if (keys[68]) { 
    if (player.velx < player.speed) { 
     player.velx++; 
    } 
} 
if (keys[65]) { 
    if (player.velx > -player.speed) { 
     player.velx--; 
    } 
} 
} 

ctx.startx = player.x; 
ctx.starty = player.y; 
function playerupdate() { 

player.Intersects = function(object) {          
    return player.x < object.x + object.width + 1 && 
    player.x + player.width + 1 > object.x && 
    player.y < object.y + object.height + 1 && 
    player.y + player.height + 1 > object.y; 
} 

solidcount = 0; 
for (i = 0; i < tgen.length; i++) { 

    for (ii = 0; ii < tgen[i].length; ii++) { 

     if (player.Intersects(tgen[i][ii]) && tgen[i][ii].solid) { 
      var pright = player.x + player.width, 
       pleft = player.x, 
       ptop = player.y, 
       pbottom = player.y + player.height, 
       oright = tgen[i][ii].x + tgen[i][ii].width, 
       oleft = tgen[i][ii].x, 
       otop = tgen[i][ii].y, 
       obottom = tgen[i][ii].y + tgen[i][ii].height; 

      //if player is to the right of his previous position, and his right side has collided with objects left 
      if (player.x >= ctx.startx && pright > oleft - 1) { 
       player.x--; 
      } 
      //if player is to the left of his previous position, and his left side has collided with objects right 
      if (player.x <= ctx.startx && pleft < oright + 1) { 
       player.x++; 
      } 
      //if player is above his previous position, and his top side has collided with objects bottom 
      if (player.y <= ctx.starty && ptop < obottom + 1) { 
       player.y++; 
      } 
      //if player is below his previous position, and his bottom side has collided with objects top 
      if (player.y >= ctx.starty && pbottom > otop - 1) { 
       player.y--; 
       player.vely = 0; 
       player.jumping = false; 
      } 
      solidcount++; 
     } 
    } 

    if (i == tgen.length - 1 && solidcount == 0) { 
     player.jumping = true; 
    } 
} 

ctx.diffx = player.x - ctx.startx; 
ctx.diffy = player.y - ctx.starty; 

if (player.x <= bgimg.width - width/2 && player.x >= width/2) { 
    ctx.translate(-ctx.diffx,0); 
} 

if (player.y <= bgimg.height - 360 - player.height) { 
    ctx.translate(0,-ctx.diffy); 
} 

ctx.startx = player.x; 
ctx.starty = player.y; 

ctx.clearRect(player.x-width/2,player.y-height/2,width,height); 

ctx.fillStyle = 'red'; 
ctx.fillRect(player.x,player.y,player.width,player.height); 

keycheck(); 

player.velx *= friction; 
if (player.jumping) {player.vely += gravity;} 

player.x += player.velx; 
player.x = Math.round(player.x); 

player.y += player.vely; 
player.y = Math.round(player.y); 

if (player.y >= bgimg.height - player.height - 1) { 
    player.y = bgimg.height - player.height - 1; 
    player.vely = 0; 
    player.jumping = false; 
} 

if (player.x > bgimg.width - player.width) { 
    player.x = bgimg.width - player.width; 
    player.velx = 0; 
}; 

if (player.x < 0) { 
    player.x = 0; 
    player.velx = 0; 
} 

if (!keys[65] && !keys[68] && (player.velx < 0.2 && player.velx > -0.2)) {player.velx = 0}; 

console.log(player.x,player.y) 
requestAnimationFrame(playerupdate); 
} 

回答

0

所以這是一個常見的平臺引擎問題。如果你的球員移動得太快,它將直接通過障礙物,因爲在當前位置和下一個位置之間不會發生碰撞測試。您的目標是儘可能少地測試碰撞,但是要測試起始位置和目標之間所有可能的碰撞。此外,當您在路徑中檢測到碰撞時,您必須正確處理它。

移動物體安全

要安全地移動任何對象,你需要將它們移動的步驟,並測試每一步的碰撞。最簡單的選擇是一次將播放器移動1個像素,然後測試碰撞。這確實意味着要進行大量的碰撞測試。

爲了改善這一點,如果您只進行箱子碰撞測試,您可以每次移動播放器最大寬度的玩家。

與碰撞

交易所以在你的榜樣,您取決於玩家的方向移動玩家回到1個像素。如果玩家將5個像素陷入障礙物,那麼您的碰撞處理機制只會將玩家移回障礙物的4個像素。看起來玩家似乎慢慢地穿過障礙物。

如果您一次移動播放器1個像素,則您採取的方法有效。如果您一次將播放器移動超過1個像素,則必須將播放器向後移動,直至不再與障礙重疊。類似while(重疊) - >向後移動一個像素