2010-02-11 24 views
1

我遇到了碰撞檢測問題。基本上,當我打到一塊堅實的瓷磚時,我的角色的身體已經在瓷磚的一半。這是我的代碼。基於磁貼的環境中的碰撞檢測

屬性wY和wX是我的遊戲世界定位。不是舞臺定位。 dx和dy是角色旅行的速度。這第一段代碼是在一個遊戲循環中。我的性格的焦點在x軸上

package com.objects 
{ 
    import flash.display.MovieClip; 
    import com.eapi.EngineApi; 
    import flash.events.Event; 

    /** 
    * ... 
    * @author Anthony Gordon 
    */ 
    public class Engine extends EngineApi 
    { 
     public var friction:Number = 0.93; 
     protected var Heros:Array; 

     public function Engine(w:Number = 540,h:Number = 360, tw:Number = 50, th:Number = 50) 
     { 
      super(w, h, tw, th); 
      Heros = new Array(); 
     } 

     override protected function loop(e:Event):void 
     { 
      UpdateObjects(); 
      Rules(); 
      CheckHero(); 
      UpDateMap(); 
     } 

     public function AddHero(g:GameObject):void 
     { 
      Heros.push(g); 
     } 

     protected function Rules():void 
     { 
      //Everything Has friction 
      for (var i:Number = 0; i < gameObjects.length; i++) 
      { 
       var char:GameObject = GameObject(gameObjects[i]); 
       char.dx *= friction; 
       //char.dy *= friction; 

       //Below is the tile positioning of my character 
       var cgridx:Number = Math.floor(char.wX/tileW); 
       var cgridy:Number = Math.floor(char.wY/ tileH); 

       //This is the tile in front of the character 
       var nextx:Number = Math.floor((char.wX + char.dx)/tileW); 
       var nexty:Number = Math.floor((char.wY + char.dy)/tileH); 

       //We assume the character is in the air before we figure it to be false 
       char.onGround = false; 

       //I am about to remove the vars from cgrid below. Keep a look out for issues in the future 
       if (mapHolder[currentMap][nexty][cgridx] == 0 || mapHolder[currentMap][nexty][cgridx] == 2) 
       { 
        //If character is falling down 
        if (char.dy > 0) 
        { 
         char.wY = (nexty * tileH) - 1; 
         cgridy = Math.floor(char.wY/tileH); 
         char.dy = 0; 
         char.onGround = true; 
        } 
        else if (char.dy < 0)//If character is going up 
        { 
         char.wY = (nexty * tileH) + (tileH + 1); 
         cgridy = Math.floor(char.wY/tileH); 
         char.dy = 0; 
        } 
       } 

       //mapHolder is a array that holds an array of maps and their tile numbers 
       if (mapHolder[currentMap][cgridy][nextx] == 2) 
       { 
        if (char.dx > 0)//if character is going right 
        { 
         char.wX = ((nextx * tileW) - 1); 
        } 
        else if (char.dx < 0)// if character is going left 
        { 
         char.wX = (nextx * tileW) + (tileW + 1); 
        } 

        char.dx = 0; 
       } 
       //if character is not on ground then keep faling 
       if (char.onGround == false) 
       { 
        char.dy += .9; 
        if (char.dy > 30) char.dy = 5; 
       } 
      } 
     } 

     protected function CheckHero():void 
     { 
      var char:Hero = Heros[0]; 
      char.x = char.wX - offsX; 
      char.y = char.wY - offsY; 

      if (char.wX < 0) 
      { 
       char.wX = 0; 
       char.dx = 0; 
      } 

      if (char.wY < 0) 
      { 
       char.wY = 0; 
       char.dy = 0; 
      } 

      offsX = char.wX - (vWidth/2); 
      offsY = char.wY - (vHeight/2); 

      if (offsX < 0) 
      { 
       offsX = 0; 
      } 

      if (offsY < 0) 
      { 
       offsY = 0; 
      } 

      //If screen hits the world END STOP!!! 
      if ((offsX + vWidth) > wWidth) 
      { 
       offsX = (wWidth - vWidth); 
      } 

      if ((offsY + vHeight) > wHeight) 
      { 
       offsY = (wHeight - vHeight); 
      } 
      ///// 

      //If char hits the end, Stop!! 
      if (char.wX > wWidth) 
      { 
       char.wX = char.wX - wWidth; 
       char.wX = wWidth; 
      } 

     } 


    } 

} 

以下爲本是我的性格類

package com.objects 
{ 
    import flash.display.MovieClip; 
    import flash.events.*; 
    /** 
    * ... 
    * @author Anthony Gordon 
    */ 
    [Embed(source='../../../bin/Assets.swf', symbol='Hero')] 
    public class Hero extends GameObject 
    { 
     private var aKeyPress:Array; 
     private var jumpDisabled:Boolean = false; 

     public function Hero() 
     { 
      wY = 150; 
      wX = 90; 
      speed = .5; 
      aKeyPress = new Array(); 
      TheGame.sr.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener); 
      TheGame.sr..addEventListener(KeyboardEvent.KEY_UP,keyUpListener); 
     } 

     private function keyDownListener(e:KeyboardEvent):void { 
      //trace("down e.keyCode=" + e.keyCode);   
      aKeyPress[e.keyCode]=true; 
     } 

     private function keyUpListener(e:KeyboardEvent):void { 
      //trace("up e.keyCode=" + e.keyCode); 
      aKeyPress[e.keyCode]=false; 
     } 

     override public function UpdateObject():void 
     { 
      Controls(); 
      updatePosition(); 
     } 

     private function Controls():void 
     { 
      wX += dx; 
      wY += dy; 

      if (aKeyPress[38])//Key press up 
       ;//vy -= speed;   
      else if (aKeyPress[40])//Key press down 
       ;//dy += speed; 

      if (aKeyPress[37])//left 
       dx -= speed; 
      else if (aKeyPress[39])//Right 
       dx += speed; 

      if (aKeyPress[32]){//space 
       jump(); 
      }     
     }//End Controls 

     private function jump():void 
     { 
      if (!jumpDisabled) 
      { 
       if (onGround) 
       { 
        dy = -15; 
        jumpDisabled = true; 
       } 
      } 
      else 
      { 
       jumpDisabled = false;    
      } 
     } 
    } 

} 

回答

0

那麼我解決了這個問題。它不是最偉大的,但它之前好十倍。這裏是我做過什麼..

我改......

if (mapHolder[currentMap][cgridy][nextx] == 2) 
       { 
        if (char.dx > 0)//if character is going right 
        { 
         char.wX = ((nextx * tileW) - 1); 
        } 
        else if (char.dx < 0)// if character is going left 
        { 
         char.wX = (nextx * tileW) + (tileW + 1); 
        } 

        char.dx = 0; 
       } 

要這個......

if (mapHolder[currentMap][cgridy][right] == 2) 
       { 
        char.wX = right * (tileW) - (tileW/2); 
        char.dx = 0; 
       } 
       else if (mapHolder[currentMap][cgridy][left] == 2) 
       { 
        char.wX = right * (tileW) + (tileW/2); 
        char.dx = 0; 
       } 

我的性格中心點是在中間在y軸和x都軸。所以要做到這一點,我做了以下

if (mapHolder[currentMap][cgridy][left] == 2) 
       { 
        char.wX = (left + 1) * (tileW) + (tileW/2); 
        char.dx = 0; 
       } 

       if (mapHolder[currentMap][cgridy][right] == 2) 
       { 
        char.wX = right * (tileW) - (tileW/2); 
        char.dx = 0; 
       } 

左和右是英雄的左側和右側的瓷磚。對於左邊我做的是我通過做這個(左+ 1)得到了右邊的下一個圖塊。然後我通過它乘以它的像素位置(左+ 1)*(tileW)。我所有的瓷磚焦點都是左上角。所以爲了讓角色定位在正確的位置。我不得不添加另一半的瓷磚。否則,我的英雄的中心點將位於左側方塊和右側方塊之間(即左側+ 1)。右邊幾乎是一樣的。但你得到的照片......我希望。

1

那麼,這是沒有在那裏調試一個很難的事情,但這裏的東西卡住了對我來說。

這兩條線之間的差異令我奇怪:

char.wX = ((nextx * tileW) - 1); 

去爲上走左邊

char.wX = (nextx * tileW) + (tileW + 1); 

爲什麼你(tileW + 1)第二個結尾?我會認爲這些線將是相同的。我不確定爲什麼第一行有-1,但我認爲這些行至少應該是相同的。

此外,爲什麼當第一個地方是dx和dy的時候,這是一個基於瓦片的東西,而且這個人只能從我所看到的一個瓦片增量中移動。你做這件事的方式對我來說似乎很奇怪。

+0

char.wX =(nextx * tileW)+(tileW + 1);我從一本書中引用它。我不知道他爲什麼使用它。也許我的重點應該放在英雄的左邊,而不是放在中間。不,英雄可以以常規像素增量移動。我更新了我的代碼。 Wx和Wy是遊戲世界的定位。它們仍然等同於一個像素。 – numerical25 2010-02-12 14:43:53

2

你應該在移動之前進行測試。

從我可以從上面的代碼中解析出來,你正在移動播放器,然後測試碰撞。如果是這樣的話,那麼你需要做好準備,如果它觸及任何東西(這不是有趣的事情或調試),就會退出。

更簡單地說,您可以調用一個IsBlocked()方法,該方法只是查看坐在玩家即將移動的方向上的圖塊。

if (!player.IsBlocked()) 
{ 
    player.Move(); 
} 
else 
{ 
    player.HandleCollision(); 
} 
+0

我很可能是錯的,但我認爲他在移動前檢查。這就是mapHolder的檢查。然後再次,他的代碼不是特別清楚,所以也許我錯了。 – 2010-02-12 05:59:34

+0

我很感激幫助。我添加了更多的代碼,詳細闡述了我正在嘗試做的事情。在引擎類中有一個循環顯示我檢查對象的順序。 – numerical25 2010-02-12 14:47:28

+0

如果我將焦點設置在英雄的右側或左側。那麼焦點所在的那一邊,就有一個精確的碰撞。它工作完美。如果我將它設置在中間位置,那麼就是中間位置。看起來好像它在任何時候都非常有效。但我不知道如何去修復它在角色兩側的作用。 – numerical25 2010-02-12 14:56:59

2

我不能真正理解你的代碼,但是從製作我的曼人引擎我學到了一些我可以分享的東西。我的碰撞處理方法涉及嘗試移動,然後退出一定數量。您還需要知道您接近該塊的方向,這不是微不足道的。

1)嘗試移動。 player.position += player.velocity

2)檢查用於使用包圍盒相交

2a)中找到播放機的的交點和該塊的邊界矩形的碰撞。我不打算爲此提供一個公式,這幾乎是微不足道的。 2b)要點:您必須將0高度或0寬度(但不是兩個)交點看作碰撞!否則,您的播放器將在碰撞表面「震動」。

3)使用相交矩形,找出接近方向。該算法涉及比較接近速度的斜率和相交矩形的對角線的斜率。4)根據逼近方向(水平或垂直)決定是否退出運動的x或y分量。使用交點的高度或寬度作爲還原量。

5)存儲你的玩家現在被阻止在這個方向的事實。請注意,您現在正在觸摸該塊,但未嵌入該塊。這就是爲什麼一個0尺寸的交叉點仍然是碰撞 - 如果不是,那麼下一幀他會認爲他不會碰撞並再次墜落,導致「振動」效應。

至於「已經在瓦片中途」 - 你是否意外地比較了玩家的中心點和瓦片的邊緣?

+0

我明白你的意思了。我會試試這個,而不是本書的內容。我會繼續嘗試 – numerical25 2010-02-12 15:54:17