Problème de collision entre une balle et un rectangle, des solutions ?

General

loic

6 years ago

Hey !

Je suis débutant en programmation mais relativement assez acharné pour être arrivé jusqu'ici sans aide, malgré ça c'est le moment d'en demander alors je fait appel à un connaisseur en la matière ;)

Voila l'histoire, après le pong je m'essaye à un casse brique, et je m'en sort plutôt bien... enfin jusqu'à maintenant.

Le reste de mon code source est dans un autre fichier (que je peut montrer si il y a des intéressés) mais plus bas j'ai copié mon code source concernant l'affichage des briques et des collisions à celles-ci.

Donc le problème ici c'est que ma balle tape les briques et les fait disparaitre cependant elle tape aux centres des briques et non aux bords (sans parler des angles qui sont carrément snober par ma très chère balle).

J'ai bien essayer de rajouter la taille de la balle aux positions des briques (dans la fonction de collision) mais alors un coté touche et son opposé est traversé (donc c'est pas mieux ^^).

Pour l'instant j'émet plusieurs hypothèses (sans grand succès), peut être un problème de vitesse de la balle (pourtant de 1 ici), les fonctions collideRectRect mal placées ou un paramètre qui manque ???

Je sèche carrément ^o^ 

Merci d'avance pour les âmes charitables de passage par là !


//info : ballSize = 3, et ma fonction "void brick" est réutilisée au début de ma fonction "void setup"
//info : il y a 10 briques réparties sur 3 lignes => 4 puis 2 puis 4
///////////////////////////////////////////////
//////////////affichage briques et collision//////////////////////////

  //variable brique
  const int brickX = 20;
  const int brickY = 20;
  const int brickW = 10;
  const int brickH = 4;

 ///////variable marge de séparation//////
//ligne de brique (séparation entre les briques)
  const int sepaY2 = 6;
  const int sepaY3 = 12;

  //variables etat des briques
  int brick1 = 1;
  int brick2 = 1;
  int brick3 = 1;
  int brick4 = 1;
  int brick5 = 1;
  int brick6 = 1;
  int brick7 = 1;
  int brick8 = 1;
  int brick9 = 1;
  int brick10 = 1;

void brick ()
{
  ////////////////////////////////////////////////////////////////////////////
  /////////////ligne 1////////////////////////////////////////////////////////
  while (brick1) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX,brickY,brickW,brickH);
    
    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX,brickY,brickW,brickH)) {
      brick1 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  while (brick2) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + brickW + 1,brickY,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + brickW + 1,brickY,brickW,brickH)) {
      brick2 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  while (brick3) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*2) + 2,brickY,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*2) + 2,brickY,brickW,brickH)) {
      brick3 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  while (brick4) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*3) + 3,brickY,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*3) + 3,brickY,brickW,brickH)) {
      brick4 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  ////////////////////////////////////////////////////////////////////////////////////
  ///////////////ligne 2/////////////////////////////////////////////////////////////
  while (brick5) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + brickW + 1,brickY + sepaY2,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + brickW + 1,brickY + sepaY2,brickW,brickH)) {
      brick5 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  while (brick6) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*2) + 2,brickY + sepaY2,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*2) + 2,brickY + sepaY2,brickW,brickH)) {
      brick6 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  ////////////////////////////////////////////////////////////////////////////
  /////////////ligne 3////////////////////////////////////////////////////////
  while (brick7) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX,brickY + sepaY3,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX,brickY + sepaY3,brickW,brickH)) {
      brick7 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  while (brick8) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + brickW + 1,brickY + sepaY3,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + brickW + 1,brickY + sepaY3,brickW,brickH)) {
      ballSpeedY = -ballSpeedY;
      brick8 = 0;
    }
    break;
  }
  while (brick9) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*2) + 2,brickY + sepaY3,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*2) + 2,brickY + sepaY3,brickW,brickH)) {
      brick9 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
  while (brick10) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*3) + 3,brickY + sepaY3,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*3) + 3,brickY + sepaY3,brickW,brickH)) {
      brick10 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }
}

geed

NEW 6 years ago

Regarde dans mon programme Oubliettes, j'ai été confronté à des soucis similaires.
Du coup :

  • j'ai assimilé ma balle à un carré
  • j'applique le déplacement avec la vitesse, puis, si et seulement si, il y a une collision "j'annule" le déplacement.
  • Je détecte la collision sur la ligne "au dessus" de la plateforme, et pas "sur" la plateforme

loic

NEW 6 years ago

Ok merci bien. Je vais voir si je peux trouver une solution dans ton programme alors ;)

loic

NEW 5 years ago

Pour les personnes faisant face au même problème, la solution était de changer la taille de la balle (3*3 à la base et maintenant devenu 4*4) je ne comprend pas très bien pourquoi mais cela doit avoir un rapport avec la taille des briques (ici 4 de hauteur). La taille d'un objet doit pouvoir etre un multiple de la taille de l'objet avec lequel elle rentre en collision. Cette hypothèse reste à vérifier mais ça a régler mon problème. Merci Geed je l'ai déduis avec ton programme ;)

clement

NEW 5 years ago

si je peux me permettre , tu peux remplacer tous tes while(brick)

  while (brick10) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*3) + 3,brickY + sepaY3,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*3) + 3,brickY + sepaY3,brickW,brickH)) {
      brick10 = 0;
      ballSpeedY = -ballSpeedY;
    }
    break;
  }


par des if


  if (brick10 == true) 
  {
    gb.display.setColor(ORANGE);
    gb.display.fillRect (brickX + (brickW*3) + 3,brickY + sepaY3,brickW,brickH);

    if (gb.collideRectRect(ballX,ballY,ballSize,ballSize,brickX + (brickW*3) + 3,brickY + sepaY3,brickW,brickH)) {
      brick10 = false; //Note le boolean <--------------------------- a initialiser boolean brick10 = true;
      ballSpeedY = -ballSpeedY;
    }
  }


ca ne resoud en rien ton probleme de collision mais tu utilisera la bonne syntax au bon endroit


De plus tu devrais regarder du coter des tableau pour tes briques mais ca peu venir dans un deuxieme temps.


its just my two cent  ;) 


loic

5 years ago

Salut clement ! Merci pour les conseils je vais changer mes fonctions while en if de ce pas ;) 

Et pour les tableaux, à vrai dire cela fait un mois que je suis en train de l'étudier tout comme les chaines et les pointeurs, mais pas moyen d'y trouver une utilité pour raccourcir mon code :/ Pour l'instant j'ai encore un problème de collision du coté gauche et droit des briques.

loic

NEW 5 years ago

clement clement

Salut clement ! Merci pour les conseils je vais changer mes fonctions while en if de ce pas ;) 

Et pour les tableaux, à vrai dire cela fait un mois que je suis en train de l'étudier tout comme les chaines et les pointeurs, mais pas moyen d'y trouver une utilité pour raccourcir mon code :/ Pour l'instant j'ai encore un problème de collision du coté gauche et droit des briques.

Drakker

NEW 5 years ago

Le plus simple c'est de faire la collision avec les bordures des cellules dans ta grilles et de vérifier quand to passes d'une cellule à l'autre s'il y a une brique dans la cellule. En gros, à chaque frame, tu prends ton angle, tu calcules la distance que tu dois traverser pour arriver à la prochaine bordure verticale ou horizontale et tu vérifie si ta balle touche une brique. Si oui, tu la déplaces à cet endroit et tu inverses la direction verticale ou horizontale. Ensuite tu continue ce calcul jusqu'à temps que tu aies fini de déplacer ta balle. Cette méthode a l'avantage d'être résistance aux très grandes vitesses (par exemple 5 cellules par frame... même si tu ne comptes pas avoir une balle à cette vitesse). Ça supporte aussi les double collisions dans un seul frame, par exemple quand la balle cogne dans le coin entre deux briques. Aussi, avec cette méthode, tu n'as pas vraiment besoin de calculer la grosseur de la balle, tu peux calculer uniquement le centre de la balle. Elle va probablement se dessiner un peu par dessus les briques lors des collisions à très basse vitesse, mais personne ne va remarquer.

loic

5 years ago

Hum ! Oui sa semble plutot efficace j'en aurais bien besoin, cependant je ne pense pas avoir encore le niveau nécéssaire. Je vais me pencher sur cette méthodes et voir ce que je peux bidouiller, mais franchement je suis pas sure d'avoir tout compris, enfin bon faut tenter après tout !! Merci Drakker

jicehel

NEW 5 years ago

Pour que la balle n’apparaisse jamais sur la brique, il suffit que la vitesse de la balle soit supérieure au rayon. Ainsi on ne dessine jamais la balle sur la brique puisque l'on calcule sa prochaine position avant de la dessiner. Certain ajoute alors une image de la balle qui touche la brique avant de rebondir, ce qui peut avoir du sens en cas de vélocité importante pour bien voir que la balle rebondit. Sinon, on peut avoir l'impression visuelle qu'elle fait demi tour toute seule mais dans ce cas, il faut bien vérifier que l'emplacement de la balle est bien vide et sinon, recalculer le rebond.

C'est le cas par exemple s'il y a plusieurs rangées de briques et que la balle rebondit sur le côté d'une brique. La prochaine position de la balle pourrait être "dans" la brique de la ligne supérieure. Du coup, il faut afficher la balle contre cette brique et non dedans...etc ...

C'est aussi là que l'affichage de la balle contre la brique est sympa car selon l'angle s'il y a 3 ou 4 rebonds, ça permet de suivre la balle. Sinon, on pourrait avoir une balle qui se téléporte (par exemple si la balle rebondit entre 2 lignes de briques)


loic

5 years ago

Ok je vois l'idée, si je peu régler mon problème aussi facilement c'est top mais je crains d'avoir toujours quelques soucis avec les angles des briques. Je vais essayer ça aussi et faire des test

loic

NEW 5 years ago

Drakker Drakker

Hum ! Oui sa semble plutot efficace j'en aurais bien besoin, cependant je ne pense pas avoir encore le niveau nécéssaire. Je vais me pencher sur cette méthodes et voir ce que je peux bidouiller, mais franchement je suis pas sure d'avoir tout compris, enfin bon faut tenter après tout !! Merci Drakker

loic

NEW 5 years ago

jicehel jicehel

Ok je vois l'idée, si je peu régler mon problème aussi facilement c'est top mais je crains d'avoir toujours quelques soucis avec les angles des briques. Je vais essayer ça aussi et faire des test

Drakker

NEW 5 years ago

Pour les angles, tu peux faire une lookup table. Mon serveur web est mort, mais voici le code de Bricks que j'ai jamais fini pour le gamebuino original. Le code est très mal organisé et c'est plutôt un prototype, mais tu peux voir comment j'avais fais mes collisions. Aucune garantie que le code compile, c'est la version la plus récente de ma version de développement.


https://drive.google.com/open?id=1vJuu1ooLlAPxTw-N_FqN1bB3l8qO8WR6


loic

5 years ago

Wow ah oui en effet, c'est un sacré programme, j'ai repéré la partie collision donc je vais voir si je peux comprendre quelque chose mais là on est très loin de mon niveau ! En tout cas bien joué il y a l'aire d'avoir un tat de fonctionnalité que je comptais ajouter tel que les items, les animations, une gestion des collision plus précise comprenant même les angles ! Enfin je ne sais pas si il fonctionne mais déjà pour les collisions j'ai beaucoup chose à en apprendre ! Merci beaucoup ;)

loic

NEW 5 years ago

Drakker Drakker

Wow ah oui en effet, c'est un sacré programme, j'ai repéré la partie collision donc je vais voir si je peux comprendre quelque chose mais là on est très loin de mon niveau ! En tout cas bien joué il y a l'aire d'avoir un tat de fonctionnalité que je comptais ajouter tel que les items, les animations, une gestion des collision plus précise comprenant même les angles ! Enfin je ne sais pas si il fonctionne mais déjà pour les collisions j'ai beaucoup chose à en apprendre ! Merci beaucoup ;)

Drakker

5 years ago

Tant mieux si ça t'es utile! Prends notes que les librairies du Meta offrent un tas de fonctions pour faire des choses que j'ai faites à la main sur le Gamebuino classique. On peut faire beaucoup mieux aujourd'hui.

Drakker

NEW 5 years ago

loic loic

Tant mieux si ça t'es utile! Prends notes que les librairies du Meta offrent un tas de fonctions pour faire des choses que j'ai faites à la main sur le Gamebuino classique. On peut faire beaucoup mieux aujourd'hui.