2011-05-13 12 views
7

Estoy trabajando en un juego en C# con XNA y he estado aprendiendo el programa en C# gracias a los tutoriales de Nick Gravelyn, pero me he encontrado con un problema. Mientras estoy usando el sistema de colisión de Nick, no estoy usando su código de jugador. Estoy usando uno basado en un tutorial de Fatso784 que he modificado. Entonces, como resultado, estoy teniendo problemas para hacer que mi versión modificada del sistema de colisión funcione correctamente. Lo tengo al punto de que empuja al jugador fuera de ciertas fichas, pero necesito que sea más sólido porque el jugador todavía puede caminar a través de las paredes de vez en cuando. Estoy bastante seguro de que estoy manejando mal la colisión, pero podría ser que la colisión es un poco blanda. Así que aquí está el código relevante de mi clase de jugador, el código de movimiento:¿Cómo puedo hacer que mi colisión sea más sólida?

public void Move() 
    { 
     pos.X = bounds.X; 
     pos.Y = bounds.Y; 

     offsetPos.X = bounds.Width; 
     offsetPos.Y = bounds.Height; 

     if (frameCount % delay == 0) 
     { 
      switch (direction) 
      { 
       case "stand": 
        if (sideCollide == "none") 
        { 
         Equalize(2); 
        } 
        else if (sideCollide == "left") 
        { 
         speed += 1f; 
        } 
        else if (sideCollide == "right") 
        { 
         speed -= 1f; 
        } 
        bounds.X += (int)speed; 
        if (frameCount/delay >= 8) 
         frameCount = 0; 
        srcBounds = new Rectangle(frameCount/delay * 64, 0, 64, 64); 
        break; 
       case "left": 
        if (sideCollide != "left") 
        { 
         if (speed > -maxspeed) 
         { 
          speed -= acceleration; 
         } 
         else if (speed < -maxspeed) 
         { 
          speed -= acceleration; 
          speed += drag; 
          Equalize(2); 
         } 
         speed += friction; 
        } 
        bounds.X += (int)speed; 
        if (frameCount/delay >= 4) 
         frameCount = 0; 
        srcBounds = new Rectangle(frameCount/delay * 64, 64, 64, 64); 
        break; 
       case "right": 
        if (sideCollide != "right") 
        { 
         if (speed < maxspeed) 
         { 
          speed += acceleration; 
         } 
         else if (speed > maxspeed) 
         { 
          speed += acceleration; 
          speed -= drag; 
          Equalize(2); 
         } 
         speed -= friction; 
        } 
        bounds.X += (int)speed; 
        if (frameCount/delay >= 4) 
         frameCount = 0; 
        srcBounds = new Rectangle(frameCount/delay * 64, 64, 64, 64); 
        break; 
       case "up": 
        if (speed > -4 && speed < 4) 
         srcBounds.Y = 128; 
        else 
         srcBounds.Y = 64; 
        if (srcBounds.Y == 0 || srcBounds.Y == 128) 
        { 
         if (jumpCount < 2) 
         { 
          if (frameCount/delay >= 9) 
           frameCount = 0; 
         } 
         else if (jumpCount > 2 && jumpCount <= 10) 
         { 
          if (frameCount/delay > 3) 
           frameCount = 2 * delay; 
         } 
         else if (jumpCount > 10 && jumpCount <= 18) 
         { 
          if (frameCount/delay > 5) 
           frameCount = 4 * delay; 
         } 
         else if (jumpCount > 18) 
         { 
          if (frameCount/delay >= 9) 
           frameCount = 0; 
         } 

         srcBounds = new Rectangle(frameCount/delay * 64, 128, 64, 64); 
        } 
        else if (srcBounds.Y == 64) 
        { 
         if (frameCount/delay >= 4) 
          frameCount = 0; 
         if (jumpCount <= 10) 
          srcBounds = new Rectangle((frameCount/delay)/2 * 64, 64, 64, 64); 
         else 
          srcBounds = new Rectangle(frameCount/delay * 64, 64, 64, 64); 
        } 
        if (jumpCount == 0) 
         startY = bounds.Y; 
        bounds = new Rectangle(bounds.X + (int)speed, 
         (jumpCount - 10) * (jumpCount - 10) - 100 + startY, 64, 64); 
        jumpCount++; 
        if (bounds.Y > startY) 
        { 
         bounds.Y = startY; 
         direction = "stand"; 
         jumpCount = 0; 
        } 
        break; 
      } 
     } 

     frameCount++; 
    } 

Y el código de colisión:

public void CollideOutside(TileMap tilemap) 
    { 
     Point cell = Engine.PointCell(PlayerCenter); 

     Point? upLeft = null, Up = null, upRight = null, Right = null, downRight = null, Down = null, downLeft = null, Left = null; 

     if (cell.Y > 0) 
     { 
      Up = new Point(cell.X, cell.Y - 1); 
     } 
     if (cell.Y < tilemap.collisionMap.HeightinPixels) 
     { 
      Down = new Point(cell.X, cell.Y + 1); 
     } 
     if (cell.X > 0) 
     { 
      Left = new Point(cell.X - 1, cell.Y); 
     } 
     if (cell.X < tilemap.collisionMap.WidthinPixels) 
     { 
      Right = new Point(cell.X + 1, cell.Y); 
     } 

     if (cell.X > 0 && cell.Y > 0) 
     { 
      upLeft = new Point(cell.X - 1, cell.Y - 1); 
     } 
     if (cell.X < tilemap.collisionMap.WidthinPixels - 1 && cell.Y > 0) 
     { 
      upRight = new Point(cell.X + 1, cell.Y - 1); 
     } 
     if (cell.X > 0 && cell.Y < tilemap.collisionMap.HeightinPixels - 1) 
     { 
      downLeft = new Point(cell.X - 1, cell.Y + 1); 
     } 
     if (cell.X < tilemap.collisionMap.WidthinPixels - 1 && cell.Y < tilemap.collisionMap.Height - 1) 
     { 
      downRight = new Point(cell.X + 1, cell.Y + 1); 
     } 

     if (Up != null && tilemap.collisionMap.GetCellIndex(Up.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Up.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (Down != null && tilemap.collisionMap.GetCellIndex(Down.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Down.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (Right != null && tilemap.collisionMap.GetCellIndex(Right.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Right.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = -1f; 
       sideCollide = "right"; 
      } 
      else 
      { 
       sideCollide = "none"; 
      } 
     } 
     if (Left != null && tilemap.collisionMap.GetCellIndex(Left.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Left.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = 1f; 
       sideCollide = "left"; 
      } 
      else 
      { 
       sideCollide = "none"; 
      } 
     } 
     if (upLeft != null && tilemap.collisionMap.GetCellIndex(upLeft.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(upLeft.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (upRight != null && tilemap.collisionMap.GetCellIndex(upRight.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(upRight.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (downLeft != null && Left != null && tilemap.collisionMap.GetCellIndex(downLeft.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(downLeft.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = 1f; 
       sideCollide = "left"; 
      } 
     } 
     if (downRight != null && Right != null && tilemap.collisionMap.GetCellIndex(downRight.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(downRight.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = -1f; 
       sideCollide = "right"; 
      } 
     } 

     if (Right == null && Left == null) 
     { 
      sideCollide = "none"; 
     } 
    } 

    public Rectangle Boundary 
    { 
     get 
     { 
      Rectangle rect = bounds; 
      rect.X = (int)pos.X; 
      rect.Y = (int)pos.Y; 
      return rect; 
     } 
    } 

Entonces, ¿cómo puedo mejorar la colisión?

Respuesta

1

Esta respuesta es principalmente en respuesta a la respuesta de Tim, porque ha dado un enfoque muy equivocado. (Su pregunta es un volcado de código muy grande, realmente no puedo jugar a detectar el error con ese código.)

El truco de la detección de colisiones - la forma en que lo hacen los motores de física "reales" - es siempre tratar sus objetos como sólidos. Usted siempre - cada cuadro - verifica los objetos para la interpenetración, y luego los separa si se interpenetran.

Si sólo prueba para moverse a través de el límite de un objeto que está pasando perderse colisiones. Esto incluye cualquier enfoque en el que intente predecir y evitar una colisión al hacer clic en la superficie. Si haces esto, solo estás pidiendo errores de precisión de punto flotante para permitirte deslizarte dentro de los objetos.

EDIT: por supuesto, su código todo parece estar basada en el número entero (Point y Rectangle). Por lo tanto, al menos la precisión de punto flotante no debería ser un problema. Pero tal vez tiene un < donde debería tener un <= o algo por el estilo?

(También está utilizando cadenas en muchos lugares donde debería estar usando enumeraciones)

Cuestiones relacionadas