How to detect collisions ?

Help & questions

geed

6 years ago



Hi, 

I 'm working on my first game (falldown), and i have many problem with collisions now ! 

I tried to use gb.collideRectRect() but it's not fast enough to detect colisions. My player (the green square) goes trough plateforms.

I tried to "create" a fonction to detect when the player is ON a plateform but it doesn't work :(

Have-you some "tricks" to do this sort of things ?

I created my first github for the occasion ;) :
https://github.com/legeed/meta-falldown


Thanks !


-------


Bonjour, 

Je n'ai toujours pas lâché l'affaire et j'arriverai bien un jour à sortir ce fichu Falldown ! :)
J'ai toutefois bien avancé, et en décortiquant l'exemple "physics" de la bibliothèque j'ai maintenant un joli scrolling réglable de plateformes qui montent et une balle carrée qui va de gauche à droite ! Bref, ça commence à ressembler à quelque chose.

Mais, je n'arrive toujours pas à faire en sorte de détecter quand le joueur est posé SUR une plateforme. Je souhaiterai dans ce cas inverser sa vitesse verticale pour le faire remonter en même temps que la plateforme sur lequel il est. Mais irrémédiablement, il finit par la "traverser" de part en part.

Je bloque, j'ai essayé de bidouiller mais sans résultats.

J'ai ouvert (et découvert) pour l'occasion un github, si une bonne âme se sent de'y jeter un œil et de me lancer une "piste" pour corriger mon soucis ça serait super gentil !

Merci d'avance ! 







ripper121

NEW 6 years ago

Try to update the Platforms bevor the Player

updatePlateforms();
updatePlayer();

geed

6 years ago

thanks, but no :(

same problem ... i don't understand why they didnt detect overlap, it's strange !


geed

NEW 6 years ago

ripper121 ripper121

thanks, but no :(

same problem ... i don't understand why they didnt detect overlap, it's strange !


jicehel

NEW 6 years ago

Tu as une partie dédié dans le tutoriel "Pong"

COLLISIONS ET BOUCLES IF

Maintenant que vous avez ajouté une variable pour contrôler la vitesse de la balle, on va pouvoir s’attaquer aux vrais problèmes : la balle sort de l’écran.

Comment est-ce qu’on pourrait s’y prendre ? Pas besoin d’avoir fait d’études en physique :

  • Si la balle arrive en bas de l’écran alors la balle repart vers le haut
  • Si la balle arrive en haut de l’écran alors la balle repart vers le bas

Pour ça, on va utiliser la boucle conditionnelle if (de l’anglais « si »). Elle s’utilise de la façon suivante :

// si la condition est vraie
if(condition){   //alors exécuter les instructions qui sont entre les accolades
}

Dans notre cas, quelle serait la condition ? Comment est-ce qu’on pourrait l’exprimer ?

Indice : on peut utiliser des opérateurs de comparaison comme :

  • if (a < b) si a est inférieur à b
  • if (a <= b) si a est inférieur ou égal à b
  • if (a > b) si a est supérieur à b
  • if (a >= b) si a est supérieur ou égal à b
  • if (a == b) si a est strictement égal à b

On peut également effectuer des opérations directement dans notre condition :

  • if (a < (b + 3)) si a est inférieur à (b + 3)
  • if (a >= (b + c)) si a est supérieur ou égal à (b + c)

Sinon normalement tu as les fonctions:

  • gb.collideRectRect

  • gb.collidePointRect

  • gb.collideBitmapBitmap


gb.collideRectRect

Description

Checks if there is a collision (overlapping) between two rectangles.

Syntax

gb.collideRectRect(x1, y1, w1, h1, x2, y2, w2, h2);

Parameters

  • x1: horizontal coordinate of the top left corner of first rectangle.
  • y1: vertical coordinate of the top left corner of first rectangle.
  • w1: width of the first rectangle.
  • h1: height of the first rectangle.
  • x2: horizontal coordinate of the top left corner of the second rectangle.
  • y2: vertical coordinate of the top left corner of the second rectangle.
  • w2: width of the second rectangle.
  • h2: height of the second rectangle.

Returns

  • true: if the two rectangles overlap.
  • false: if the two rectangles don't overlap.



gb.collidePointRect

Description

Checks if a specified point is within a rectangle.

Syntax

gb.collidePointRect(x1, y1, x2, y2, w, h);

Parameters

  • x1: horizontal coordinate of the point.
  • y1: vertical coordinate of the point.
  • x2: horizontal coordinate of the top left corner of the rectangle.
  • y2: vertical coordinate of the top left corner of the rectangle.
  • w: width of the rectangle.
  • h: height of the rectangle

Returns

  • true: if the point is inside the rectangle.
  • false: if the point is not inside the rectangle.



gb.collideBitmapBitmap

Description

Checks pixel by pixel if two bitmaps are overlapping.

Syntax

gb.collideBitmapBitmap(x1, y1, b1, x2, y2, b2);

Parameters

  • x1: horizontal coordinate of the first bitmap
  • y1: vertical coordinate of the first bitmap
  • b1: first bitmap
  • x2: horizontal coordinate of the second bitmap
  • y2: vertical coordinate of the the second bitmap
  • b2: second bitmap

Returns

  • true: if the two bitmaps have at least one overlapping pixel
  • false: if the bitmaps are not overlapping


jicehel

NEW 6 years ago

j'ai un doute sur ta formule gb.collideRectRect((int)player.x, (int)player.y, player.w, player.h, borders[i].x, borders[i].y, borders[i].w, borders[i].h)

Je ne sais pas pourquoi tu arrondi à l'entier. Pourquoi ne pas travailler sur la valeur exacte de player.x et player.y ?

Comme je suis au boulot, je ne peux pas trop regarder le code mais j'ai des doute. Par exemple pour la collision en y, tu calcules yv avant le déplacement mais tu le force à la fin s'il y a eu collision mais il sera recalculé avant d'être testé me semble-t-il en ayant jeté un coup d'oeil très rapide dessus.

geed

NEW 6 years ago

So ... after 4 hours, it works !!! i rewrite some code, problem was very simple in fact ... thanks both :)

  • i just inverted the order of detection collision, now :
  • 1) i applied the scrolling, player go up
  • 2)if he don't stand on a plateform, i applied gravity (go down)
  • 3)i detect collision, if it, it rebound.

you can download the .bin to test the engine on the emulator :)

  • LEFT/RIGHT to go left/right (thanks cap'tain obvious :D )
  • UP to jump !
  • A to scroll
  • B to scroll at high speed
  • A+B to invert scrolling


Coming :

  • Menu
  • Scoring
  • and some pixel-art :)



------


Merci à vous deux pour les pistes de réflexion !

Du coup, le soucis venait de plusieurs choses. La fonction collide fonctionne donc très bien avec des float. J'ai "décomposé" les étapes jusqu'à trouver d'où venait le soucis, en gros j'avais la gravité et le scrolling qui s'opposaient ET un soucis de } dans ma fonction qui détect si le joueur est posé sur une plateforme. 

Le principe de calculer la nouvelle position, tester puis revenir à l'ancienne en cas de collision fonctionne bien au final. ça va vite et ça économise des IF , je réutiliserai ce principe à l'occasion.

Bref, ça marche et le comportement de la "balle" est vraiment comme je l'attendais (un peu imprévisible à cause de l'inertie et des rebonds)

et merci Rodot pour l'exemple de code au passage dans la bibliothèque, sans ça je n'y serai pas arrivé ! j'étais parti dans un truc avec des formules de math, des moment d'inertie et cie, l'horreur !)


Prochaines étapes : 

  • un menu
  • un système de scoring et de gameover
  • et surtout plaquer des sprites sur mes "boites" (de la lave en haut, de l'eau en bas et de la terre) !








jicehel

NEW 6 years ago

Cool, bon courage pour terminer le moteur du jeu mais c'est sûr, tu as fait le plus dur.

Après pour la partie graphique, on va voir tes talents d'artiste du pixel   ;)   

JFT

NEW 5 years ago

Bonjour,

J’ai pu créer ma fonction de collision mais elle n’est pas prise en compte.

Elle est utilisée dans un sous fichier .ino et je l’ai crée dans mon fichier parent (le fichier ino du jeu).

Si je déplace ma fonction dans le sous fichier cela ne fonctionne pas non plus.

Par contre si je place ma fonction dans le fichier parent et que je l’utilise dans ce même fichier cela fonctionne bien.

1. Comment faire pour l’utiliser dans n’importe quel fichier si je la crée dans le fichier parent?

2. Comment faire si je veux regrouper uniquement mes différentes fonctions dans un seul fichier? Comment les appeler ensuite depuis n’importe quel fichier?

Merci

jicehel

NEW 5 years ago

Tu peux regarder mon tuto sur le sokoban ici:  https://gamebuino.com/fr/creations/sokoban-partie-2-ajoutons-les-graphismes, jessaye d'y expliquer comment faire (si ce n'est pas clair, dis le moi stp pou que j'essaye de faire mieux) sinon tu as ce lien: https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c/15212-la-programmation-modulaire

JFT

NEW 5 years ago

Bonjour,

Oui j'ai regardé ton tuto mais il est vrai que pour moi ce n'est pas trop clair... Je m'y repenche et vais également regarder ton autre lien.
De plus pourquoi ma fonction ne fonctionne-t-elle que quand elle est déclarée ET utilisée dans le fichier parent de mon jeu ?

jicehel

NEW 5 years ago

Si tu l'as déclarée dans le .h et que tu appelles le .h dans ton programme, ça devrait marcher. Du coup pour pouvoir mieux t'aider, il faudrait voir les sources. Il doit y avoir une petite erreur quelque part... Dur d'imaginer ce que ça peut être sans les sources.

JFT

NEW 5 years ago

Bon, je crois que mon problème est en fait dû à ma fonction lol... Je tenterai de la vérifier, sans doute un souci de variables en fait...
En effet, en affichant mes variables à l'écran, je me rend compte qu'elles ne changent pas quelles que soient les positions de mes objets à tester pour les collisions...

jicehel

NEW 5 years ago

Si tu veux ou si tu galères, postes ton code et on t'aidera

JFT

NEW 5 years ago

En fait je me suis juste emmêlé les pinceaux.
J'avais bien créé un fichier .h, renseigné ma fonction dedans. Mais s'il ne se passait rien c'est que j'avais oublié d'incrémenter ma variable pour vérifier les collisions...

Pour ceux qui sont étourdis comme moi (et les autres) :
il est très pratique de faire afficher à l'écran les variables sur lesquelles vous travaillez pour vérifier s'il n'y a pas de souci dans votre programme.
Ici cela m'a aidé à voir que j'avais tout simplement oublié l'incrémentation d'une variable.

JFT

NEW 5 years ago

Pour résumer, j'ai mon fichier principal LAST-DEFENDER.INO (nom peut-être provisoire du jeu) depuis lequel j'appelle graphic.h (inclus sprites et décors) et function.h .
Je n'ai pas créé de .CPP car je ne comprends pas à quoi il sert.
Et cela fonctionne bien comme ça.

Pour le fichier function.h, par contre, si je souhaite utiliser une variable déclarée dans un de mes fichiers .INO, cela ne fonctionne pas.
J'ai le message "MA_VARIABLE was not declared in this scope".
Donc, les variables déclarées dans n'importe quel fichier .INO sont reconnues dans tous les fichiers .INO appelés, mais pas dans les fichiers .H : correct ?
Comment donc utiliser une variable d'un fichier .INO dans un fichier .H ?
J'ai tenté de mettre "extern int MA_VARIABLE = 1;" dans mon fichier .INO mais idem.

chris-scientist

5 years ago

Dans le .h tu dois avoir la déclaration de tes fonctions, alors que dans le .cpp tu dois avoir les définitions.

Et pour utiliser une variable de ton programme principal (.ino) dans tes autres fichiers il suffit de la passer en paramètre.

En clair, dans ton programme principal (que je ne réécris pas pour l'exemple) :

/* ... */
#include "Display.h"
uint8_t i;

void setup() {
  i = 0;

}

void loop() {
  /* ... */
  paint(i); // tu passe ici ta variable "i" au reste de ton programme
  i++; // on fait un simple incrément

}


Dans .h, que nous nommerons Display.h tu as :

#ifndef DISPLAY
#define DISPLAY


#include <Gamebuino-Meta.h>


void paint(uint8_t param);


#endif


Dans Display.cpp :

#include "Display.h"


void paint(uint8_t param) {
  gb.display.printf("%d", param);

}


N'hésiste pas si tu as encore des questions.

Steph

5 years ago

You will probably see more clearly when you read this article:

Tu y verras sans doute + clair en lisant cet article :

http://www.cplusplus.com/forum/articles/10627

chris-scientist

NEW 5 years ago

JFT JFT

Dans le .h tu dois avoir la déclaration de tes fonctions, alors que dans le .cpp tu dois avoir les définitions.

Et pour utiliser une variable de ton programme principal (.ino) dans tes autres fichiers il suffit de la passer en paramètre.

En clair, dans ton programme principal (que je ne réécris pas pour l'exemple) :

/* ... */
#include "Display.h"
uint8_t i;

void setup() {
  i = 0;

}

void loop() {
  /* ... */
  paint(i); // tu passe ici ta variable "i" au reste de ton programme
  i++; // on fait un simple incrément

}


Dans .h, que nous nommerons Display.h tu as :

#ifndef DISPLAY
#define DISPLAY


#include <Gamebuino-Meta.h>


void paint(uint8_t param);


#endif


Dans Display.cpp :

#include "Display.h"


void paint(uint8_t param) {
  gb.display.printf("%d", param);

}


N'hésiste pas si tu as encore des questions.