Détection des collisions en 2D
-
- Messages : 8
- Inscription : mar. 24/juil./2007 11:45
- Localisation : Aix en Provence
- Contact :
Détection des collisions en 2D
Bonjour, j'ai une grosse question qui est expliquée en détails ici :
http://olivier.pons.free.fr/blog/question_fr.php
et je suis suis fait ch..suer à la traduire en Anglais au cas où :
http://olivier.pons.free.fr/blog/question_en.php
J'aimerais avoir une idée, ou des idées sur le comment faire.
Et cette question n'est valable que pour des sprites qui ne sont pas animés !
Il faudrait faire la même pour les sprites animés !
En attente de votre retour,
Olivier Pons
PS : je suis sincèrement désolé que Purebasic ne soit pas plus connu car il est impressionnant de rapidité par rapport à tous les autres xxxbasic de sa catégorie.
http://olivier.pons.free.fr/blog/question_fr.php
et je suis suis fait ch..suer à la traduire en Anglais au cas où :
http://olivier.pons.free.fr/blog/question_en.php
J'aimerais avoir une idée, ou des idées sur le comment faire.
Et cette question n'est valable que pour des sprites qui ne sont pas animés !
Il faudrait faire la même pour les sprites animés !
En attente de votre retour,
Olivier Pons
PS : je suis sincèrement désolé que Purebasic ne soit pas plus connu car il est impressionnant de rapidité par rapport à tous les autres xxxbasic de sa catégorie.
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
Re: Détection des collisions en 2D
bonjour compagnon de galère ! Je développe un jeu de p.f. depuis longtemps, et sache que c'est une entreprise véritablement gigantesque. Dans l'histoire des jeu vidéo, les jeux de p.f. sont apparus après les jeux de tir, et ceux pour une bonne raison.
Et c'est pourquoi je te conseille donc de commencer par un jeu de tir, car ce type de jeu requiert beaucoup moins de variables à gérer.
Un jeu de p.f. se doit d'avoir un défilement d'écran ( scrolling). Si ce n'est pas le cas, il s'agira d'un jeu nommé "à tableau" comme donkey kong, ou buble boble, ou encore snow bros.
Pour les collisions:
-> Tu souhaite que ton personnage se déplace à la mario (vitesse variable), aime-tu la difficulté ?
-> 16 pixels, c'est beaucoup, c'est quoi comme champignon ?
-> bon, pour les collisions, il suffit de tester les coordonnés X et Y, exemple de ton champignon (taille 16*16 ; variable globales : Xchap et Ychap) allant vers la droite:
stopmur=0
If Xchap+16>Xmur-1 and Xchap+16<Xmur+8:stopmur=1:endif
If stopmur=0:Xchap+2:endif
heu... attend, faut que je me replonge dans mon code pour me rafraichir la mémoire, j'crois que j'ai oublié un truc là... je reviens
Et c'est pourquoi je te conseille donc de commencer par un jeu de tir, car ce type de jeu requiert beaucoup moins de variables à gérer.
Un jeu de p.f. se doit d'avoir un défilement d'écran ( scrolling). Si ce n'est pas le cas, il s'agira d'un jeu nommé "à tableau" comme donkey kong, ou buble boble, ou encore snow bros.
Pour les collisions:
-> Tu souhaite que ton personnage se déplace à la mario (vitesse variable), aime-tu la difficulté ?
-> 16 pixels, c'est beaucoup, c'est quoi comme champignon ?

-> bon, pour les collisions, il suffit de tester les coordonnés X et Y, exemple de ton champignon (taille 16*16 ; variable globales : Xchap et Ychap) allant vers la droite:
stopmur=0
If Xchap+16>Xmur-1 and Xchap+16<Xmur+8:stopmur=1:endif
If stopmur=0:Xchap+2:endif
heu... attend, faut que je me replonge dans mon code pour me rafraichir la mémoire, j'crois que j'ai oublié un truc là... je reviens
Salut à tous , voici un bon lien , en flash , mais facilement adaptable :
http://www.tonypa.pri.ee/tbw/start.html
et en FR
:
http://www.jeflash.com/_tutos/index.php?Tilebased-games
http://www.tonypa.pri.ee/tbw/start.html
et en FR

http://www.jeflash.com/_tutos/index.php?Tilebased-games
pour repondre a la question directement
en fait c'est simple !:D
il faut utiliser la Ruse de guerre !
genre on fait croire que tout est hasard, alors qu'en fait pas du tout !!
tout l'astuce viens de l'enoncé de ton probleme !!

c'est bete, mais cela reprend le principe des Dames ou des echec
il ne viendrai pas a l'idée aux joueurs de placer une piece entre 2 cases !

bref dans ton exemple c'est ton mur qui est mal placé !
c'est au partie Fixe du décord d'etre au bon endroits, pour que les partie mobile puisse coincider parfaitement !
c'est pourquoi l'utilisation de feuilles cadrié est une bonne idée pour dessiner le decors du jeux !!
considerant que les case represente le pas de deplacement du sprite et sa largeur ... (la pas pouvant etre plus petit mais pas plus grand !!
)
en fait c'est simple !:D
il faut utiliser la Ruse de guerre !

genre on fait croire que tout est hasard, alors qu'en fait pas du tout !!
tout l'astuce viens de l'enoncé de ton probleme !!
ben voila ! il te suffit qu'il n'y est pas de mur a cette position, mais a une position qui soit multiple de 16 si ton sprite de 16 se deplace de 16 en 16 !!nt supposons qu'il y ait un mur à la position 103.

c'est bete, mais cela reprend le principe des Dames ou des echec
il ne viendrai pas a l'idée aux joueurs de placer une piece entre 2 cases !

bref dans ton exemple c'est ton mur qui est mal placé !
c'est au partie Fixe du décord d'etre au bon endroits, pour que les partie mobile puisse coincider parfaitement !
c'est pourquoi l'utilisation de feuilles cadrié est une bonne idée pour dessiner le decors du jeux !!
considerant que les case represente le pas de deplacement du sprite et sa largeur ... (la pas pouvant etre plus petit mais pas plus grand !!

-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
simple, mais fastieux, mais économe en ressource, mais...
voilà de quoi est capable purebasic, alors que je l'ai exploré uniquement en surface
(touche fleche droite ou gauche et touche R pour reset):

Code : Tout sélectionner
; ------------------------------------------------------------
; droit dans le mur - 2007 - source purebasic 4. et des poussières
;
; Collision sans fonction.
;
; France - Toulouse - H. Philippe - pseudo: beauregard
; ------------------------------------------------------------
;UsePNGImageDecoder () ; oui, toi t'es obligatoire.
If InitMouse ()=0 Or InitSprite ()=0 Or InitKeyboard ()=0 Or InitSprite3D ()=0
MessageRequester ( "Error" , "Can't open DirectX 7 or later" , 0)
End
EndIf
Enumeration ; ici, on donne un petit nom à nos sprites( non, chuis pas un numéro !):
; tout en sprites3D, même le décor (pourquoi s'embéter ?):
#fondA
#fondA3D
; dirigé par le joueur durand la phase de jeu:
#champi ;
#champi3D
; bloc solide:
#blocs
#blocs3D
; permet au progammeur de repèrer les positions des divers objets qu'il teste à l'écran:
#repere
#repere3D
EndEnumeration
;Global page.w=0,niveau.w=1
;Global placemX=512,placemY=384
; chamcoll-> =1 collision à droite, =2 collision à gauche.
Global champX.w, champY.w,champsol.w,chamcoll.w
Global nbrebs
Structure balle
id.l
x.w
Y.w
sensx.l
sensy.l
sr.w
attract.w
EndStructure
Global NewList bs.balle(); bloc solide, c'est à dire infranchissable des 4 côtés.
Declare Fchampignon()
Declare Fcloneblocs()
; Si votre PC ne peut pas afficher une haute résoution résolution en 32bit, Alors arrêt du programme.
;If OpenScreen (1440, 900, 32, "droit dans le mur" )=0
If OpenScreen (1024, 768, 32, "droit dans le mur" )=0
MessageRequester ( "Error" , "Can't open a 1024*768 - 32 bit screen !" , 0)
End
EndIf
; fond:
CreateSprite ( #fondA ,64,64, #PB_Sprite_Texture )
StartDrawing ( SpriteOutput ( #fondA ))
BackColor ( RGB (0,0,0))
Box (0,0, 64, 64, RGB (108,119,206))
Box (8,8, 56, 56, RGB (26,45,190))
StopDrawing ()
CreateSprite3D ( #fondA3D , #fondA ) ; osons les amis, osons !
; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; champignon:
CreateSprite ( #champi ,64,64, #PB_Sprite_Texture ) ; objet dirigé par le joueur.
StartDrawing ( SpriteOutput ( #champi ))
BackColor ( RGB (0,0,0))
Box (0,0, 128, 128, RGB (255,255,255))
StopDrawing ()
CreateSprite3D ( #champi3D , #champi )
; decor blocsolide
CreateSprite ( #blocs ,64,64, #PB_Sprite_Texture ) ; objet intéractif (mur, sol, plafond).
StartDrawing ( SpriteOutput ( #blocs ))
BackColor ( RGB (0,0,0))
Box (0,0, 128, 128, RGB (200,115,115))
StopDrawing ()
CreateSprite3D ( #blocs3D , #blocs )
; repere ( utilisé uniquement par le programmeur):
CreateSprite ( #repere ,4,4, #PB_Sprite_Texture )
StartDrawing ( SpriteOutput ( #repere ))
BackColor ( RGB (0,0,0))
Box (0,0, 4, 4, RGB (255,255,255))
StopDrawing ()
CreateSprite3D ( #repere3D , #repere )
Global zutA,zutB,zutC ; pour repère la variable qui n'aurait la bonne valeur.
;MouseLocate(449,62)
; ******************************************************************************************************
Repeat ; Boucle principale
; ******************************************************************************************************
ExamineMouse():ExamineKeyboard ()
Start3D ()
For a=0 To 15 ; 1024/64=16
For b=0 To 11 ; 768/64=12
DisplaySprite3D(#fondA3D, a*64, b*64) ; 16*12
Next
Next
; **********************************************************************************************
; fabrication bloc solide:
If nbrebs<1:nbrebs+1:Fcloneblocs():EndIf
; Affichage clone bloc solide si existe:
ForEach bs()
; chamcoll -> =1 collision à droite, =2 collision à gauche.
If champX+64>bs()\x-1 And champX+64<bs()\x+16
If (champY+32>bs()\y+15 And champY+32<bs()\y+49)
chamcoll=1
EndIf
EndIf
If champX>bs()\x+48 And champX<bs()\x+65
If (champY+32>bs()\y+15 And champY+32<bs()\y+49)
chamcoll=2
EndIf
EndIf
; champsol -> =1 collision avec la partie haute du bloc solide:
If (champX>bs()\x-1 And champX<bs()\x+65) Or (champX+64>bs()\x-1 And champX+64<bs()\x+65)
If (champY+64>bs()\y-1 And champY+64<bs()\y+16)
champsol=1
EndIf
EndIf
DisplaySprite3D ( bs()\id , bs()\x, bs()\y, 255)
Next
; Contrôlé par le joueur:
If depart=0:depart=1:champX+512:champY+64:EndIf
Fchampignon()
Stop3D ()
; ligne de test afin de connaître la valeur des variables:
StartDrawing ( ScreenOutput ())
DrawingMode (1)
FrontColor ( RGB (255,255,255))
chamcoll$= Str (chamcoll)
champsol$= Str (champsol)
zutB$= Str (zutB)
zutC$= Str (zutC)
DrawText (50,1+20, "chamcoll: " +chamcoll$)
DrawText (50,1+40, "champsol: " +champsol$)
DrawText (50,1+60, "testX: " +testX$)
DrawText (50,1+80, "testY: " +testY$)
DrawText (50,1+260, "zutB: " +zutB$);:zutB=0
DrawText (50,1+280, "zutC: " +zutC$);:zutC=0
DrawText (350,20, "appuyez sur la touche R pour remise à 0 du code")
StopDrawing ()
Gosub fps ; nombre d'image par seconde.
If KeyboardPushed ( #PB_Key_R ):champY=0:EndIf ; reset
; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; remise à 0 des variables avertissant d'une collision:
chamcoll=0:champsol=0;
; °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
FlipBuffers (): ClearScreen ( RGB (0,0,0));FlipBuffers (60)
; ******************************************************************************************************
Until KeyboardPushed ( #PB_Key_Escape ): End ; fin de la boucle principale (appuyez sur la touche Esc)
; ******************************************************************************************************
fps:
If Val ( FormatDate ( "%ss" , Date ()))=sek ; regardez pas là, c'est trop compliqué. Arrêtez j'vous dis! Bon ben, je
; vous aurez prévenu...
fps+1
Else
FPS$= Str (fps)
fps=0
EndIf
sek= Val ( FormatDate ( "%ss" , Date ()))
StartDrawing ( ScreenOutput ())
DrawingMode (1)
FrontColor ( RGB (255,255,255))
DrawText (1,1, "FPS: " +FPS$)
StopDrawing ()
Return
; ***********************************************************************************************
; ********************************* ici commence les procedures *********************************
; ***********************************************************************************************
Procedure Fcloneblocs() ; 64*64 fabrication clone bloc solide:
; placement clone bloc solide:
; faisons le sol:
For a=0 To 15
LastElement(bs())
AddElement(bs())
bs()\id=#blocs3D
bs()\x=a*64:bs()\y=704
Next
; faisons 2 autres blocs ( mur):
LastElement(bs()):AddElement(bs())
bs()\id=#blocs3D:bs()\x=0:bs()\y=640
LastElement(bs()):AddElement(bs())
bs()\id=#blocs3D:bs()\x=1024-64:bs()\y=640
; et faisont mumuse avec d'autres constructions...
LastElement(bs()):AddElement(bs())
bs()\id=#blocs3D:bs()\x=448:bs()\y=640
LastElement(bs()):AddElement(bs())
bs()\id=#blocs3D:bs()\x=512:bs()\y=640
LastElement(bs()):AddElement(bs())
bs()\id=#blocs3D:bs()\x=448:bs()\y=576
EndProcedure
Procedure Fchampignon() ; 64*64
; chamcoll-> =1 collision à droite, =2 collision à gauche.
If KeyboardPushed ( #PB_Key_Right ) And chamcoll<>1
champX+8;+8
EndIf
If KeyboardPushed ( #PB_Key_Left ) And chamcoll<>2
champX-8;-8
EndIf
If champsol=0
champY+4
EndIf
DisplaySprite3D ( #champi3D , champX, champY, 255)
EndProcedure
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
elle brille au soleil
oui, j'ai mis les 2, grâce à toi, au cas où sa machine aurait connu l'angoissante période du bug de l'an2000Dobro a écrit :pour rire remplace FlipBuffers () par FlipBuffers (60)
et regarde le FPS

Tes conseils sur un déplacement par paquet de 16 sont judicieux, mais surfer_ix veut bruler les étapes, et s'attaquer directement au plus dur ! Mais après tout, s'il est doué, pourquoi pas ?
Je ne sais pas si ça peut t'interessé comme astuce. Mais pour un jeu que j'ai développé (un peu mis de côté part manque de temps)...l'information de collision est caché dans le poids faible de la couleur..en gros je lis la couleur et je regarde si le premier bit est a 1 alors c'est un mur sinon on passe a travers. Surtout ne pas utiliser point(x,y) pour prendre la couleur. utilise un pointeur voir un peekl(adr). On peut réussir a faire des choses extraordinaires avec cette technique. J'ai donc fabriqué un petit editeur de sprite (32x32) qui permet de definir chaque pixel comme étant un obstacle ou pas... tres precis et tres rapide.


Tu as vu ça où dans la doc ? dis moi le vite que je la corrigeDobro a écrit :FlipBuffers (60)

Les valeurs possibles pour FlipBuffer() sont 0,1 et 2.
Si tu mets autre chose ça doit être interprété comme 0.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Dans ce cas tu n'as pas d'autre choix que de tester chaque pixel comme tu l'expliques si bien sur ton blog.On veut pouvoir y dessiner ce qu'on veut n'importe où sur l'image
la seule façon d'anticiper une collision c'est de connaitre à l'avance la géométrie du terrain , peu importe la technique utilisée :
- terrain 3D basé sur des triangles
- terrain 2D basé sur des tiles
- terrain construit avec des formes géométriques connues (des polygones convexes par exemple)
- Fractales (il y a un exemple sur le forum anglais ici)
pour chacun de ces cas il existe des méthodes pour calculer les collisions, et même les anticiper en tenant compte de la vitesse de déplacement du personnage (à condition qu'il soit représenté par une forme géométrique lui aussi ). Avec la méthode des tiles tu peux précalculer si tu vas rencontrer un obstacle ou non , mais ensuite il faudra appliquer ta méthode, pixel par pixel.
Tu peux aussi tester plusieurs sprites invisibles autour de ton personnage pour connaitre dans quelle direction à lieu la collision. J'avais fait un jeu de plateforme basé sur ce principe (inspiré de Game Factory). Il y avait environ 5 ou 7 sprites autour du personnage :
1 au dessus de la tête (collision pendant les sauts)
1 à gauche (collision quand on avance à gauche)
1 à droite
1 à chaque pied (collision avec le sol quand on tombe)
Il devait y en avoir d'autres qui servaient à détecter un terrain en pente pour suivre la pente .
Plus un au bout de chaque main pour détecter les rebords (pour s'accrocher à un rebord)
Enfin pour l'instant c'est tout ce que je vois comme solution.
[EDIT]
Voila j'ai retrouvé le bout de code que j'avais mis sur le forum à l'époque, je viens de le mettre en version V4.10, c'est pas codé terrible mais bon , ça permet de voir le principe.
http://herved25.free.fr/sources/plateforme6.zip
Dernière modification par comtois le mar. 24/juil./2007 19:58, modifié 4 fois.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Pour ma part , j'utilise le code de comtois pour les collisions , cela fonctionne parfaitement.
http://www.purebasic.fr/french/viewtopi ... E9parateur
je l'ai bien entendu adpaté à mes besoins
http://www.purebasic.fr/french/viewtopi ... E9parateur
je l'ai bien entendu adpaté à mes besoins

Je suis curieux de voir ce que ça donneCpl.Bator a écrit :je l'ai bien entendu adpaté à mes besoins

http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
-
- Messages : 1307
- Inscription : dim. 08/juil./2007 18:32
- Localisation : Toulouse
idée: un metal slug sans contraite arcade
Merci pour ta générosité, c'est génialVoila j'ai retrouvé le bout de code que j'avais mis sur le forum à l'époque, je viens de le mettre en version V4.10, c'est pas codé terrible mais bon , ça permet de voir le principe.

Mais comme j'avais pris mes petites habitudes, le plis était déjà pris comme on dit.
Dernière modification par beauregard le ven. 17/juil./2009 16:27, modifié 2 fois.