2017-06-29 8 views
1

Je travaille actuellement sur un Top-Down-Shooter et j'ai quelques problèmes de collision. Mon monde est fait de carreaux (64x64). Les tuiles et les entités sont des rectangles. Le joueur se déplace avec une vitesse de 2,74 (et pas en pixels pour un mouvement plus fluide). Mais quand il s'agit de la collision entre le joueur (une entité) et un mur, j'ai quelques problèmes. Pour vérifier s'il y a une collision, je prends la position actuelle de mon joueur et sa vitesse de déplacement pour calculer où sa prochaine position serait et s'il y a une collision. Mais je vérifie chaque pixel sur le chemin, donc je ne peux pas sauter un obstacle même si la vitesse de déplacement est très élevée. Disons simplement que la position actuelle du joueur est X: 200 Y: 200 et qu'il déplace 2.74 Pixels dans la direction x. Mon jeu vérifie maintenant s'il y a une collision à X: 201 Y: 200, X: 202 Y: 200 ou X: 202.74 Y: 200 et sinon déplace le joueur à cette position. Si j'essaie maintenant de déplacer le joueur plus loin dans la direction x et qu'il y a un mur à 0.26 Pixels, le joueur ne bougera pas et laissera un petit espace. J'ai essayé de calculer la distance entre le joueur et le mur et d'ajouter ce montant à la position des joueurs mais pour cela j'ai besoin de savoir de quel côté du mur le joueur touche. Je veux aussi que le joueur puisse se déplacer de haut en bas quand le mur qu'il frappe est en face de lui et vice-versa.Java - Pixel-Perfect Collision - écart entre le joueur et le mur

Voici ma méthode de collision (en Java):

public static boolean collision(float ex, float ey, int width, int height) { // ex, ey would be the next position of the player 
    if (ex < 0 || ex + width > worldWidth || ey < 0 || ey + height > worldHeight) return true; // checks if this position is in the world 
    int firstTileX = (int) (ex/Tile.TILE_SIZE); // calculates tiles he could possible collide width 
    int firstTileY = (int) (ey/Tile.TILE_SIZE); 
    int lastTileX = (int) ((ex + width - 1)/Tile.TILE_SIZE); 
    int lastTileY = (int) ((ey + height - 1)/Tile.TILE_SIZE); 
    for (int y = firstTileY; y <= lastTileY; y++) { 
     if (y < 0) continue; // checks for out of bounds 
     if (y >= worldTileHeight) break; 
     for (int x = firstTileX; x <= lastTileX; x++) { 
      if (x < 0) continue; 
      if (x >= worldTileWidth) break; 
      if (tiles[y][x].solid) return true; // if the tile is solid -> collision found 
     } 
    } 
    return false; // no collision found 
} 

Et ma méthode de mouvement:

public void move(float xa, float ya) { 
    float nx, ny; 
    while (xa != 0 || ya != 0) { 
     nx = x; 
     ny = y; 
     if (xa != 0) { 
      if (Math.abs(xa) > 1) { // if the x-speed is greater than 1 
       nx = x + MathUtil.abs(xa); // returns -1 for negative numbers and 1 for positiv 
       xa -= MathUtil.abs(xa); 
      } else { // less than 1 
       nx = x + xa; 
       xa = 0; 
      } 
     } 
     if (ya != 0) { // same here 
      if (Math.abs(ya) > 1) { 
       ny = y + MathUtil.abs(ya); 
       ya -= MathUtil.abs(ya); 
      } else { 
       ny = y + ya; 
       ya = 0; 
      } 
     } 
     if (!Level.collision(nx, ny, width, height)) setPosition(nx, ny); // checks if there is an collision and sets the new position if not 
     else if (!Level.collision(nx, y, width, height)) x = nx; // if there was a collision check if the player can walk in x direction 
     else if (!Level.collision(x, ny, width, height)) y = ny; // or in y direction 
    } 
} 

Mon problème est le peu près la même chose que le problème de CoderMusgrove dans son poste() :

Résumé & question

J'ai un problème où si la vitesse d'une entité est plus grande que la distance de la tuile dans laquelle elle va, elle laissera au moins un pixel entre elle et la tuile, et je n'aime vraiment pas ça. Quel type d'algorithme puis-je utiliser pour trouver la plus petite différence entre l'entité et la tuile?

Si vous avez besoin d'informations supplémentaires, je pourrai plaisir de l'ajouter.

Merci pour votre aide!

+0

Cochez cette réponse https://stackoverflow.com/a/43979300/5343269, c'est pour Javascript mais je pense que les concepts sont les mêmes. – 11thdimension

Répondre

0

Facilement résolvable en changeant votre interprétation.

Vous maintenez une position fractionnaire à des fins de vitesse à grain fin. Ignorer la fraction à des fins de détection de collision et d'affichage (si vous deviez effectuer un rendu de sous-pixels, effectuez la collision sur le niveau de précision de rendu du sous-pixel).

int screenX = (int) Math.round(objX); 
int screenY = (int) Math.round(objY); 
// rendering and collision detection based on rounded position