Page 1 sur 1

Sprite collision

Publié : mar. 08/mars/2011 14:17
par blendman
En ce moment, je regarde un peu les collisions avec les sprites, et je ne comprends pas comment fonctionne le spritePixelCollision().

Alors, déjà que ne soit pas pris en compte le canal alpha d'un png, bon, c'est dommage :(.
Mais en plus, dans mon code ça ne marche pas comme ça devrait, on dirait.

Un code très simple :
http://blendman.free.fr/dev/pb/menu/collision.zip

Vous pourriez me dire où mon erreur et pourquoi on n'a pas de vrai détection au pixel (ou presque) ?

Merci beaucoup.

ps : le code uniquement (le zip contient le code et les 2 images)

Code : Tout sélectionner

;{ ************************enumeration ***********************
Enumeration
#window
#sprite 
#sprite1
EndEnumeration
;}


;{ ************************ variables ************************
Global vitesse= 3
;}

;{ ************************ Structures ************************
Structure s_block
  position.Point
  previous.Point
  vitesse.i  
EndStructure

Global block.s_block
block\position\x = 15
block\position\y = 15
block\previous\x = block\position\x 
block\previous\y = block\position\y 
block\vitesse = 3
;}

;{ ************************ declare ***************************
Declare evenementClavier()
;}

;{ ************************ inititialisation *****************
InitKeyboard () 
InitSprite()
InitSprite3D()
UsePNGImageDecoder()
;}

;{ ************************ open window *********************
OpenWindow(#window, 0, 0,800, 600, "hello" , #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered )
OpenWindowedScreen( WindowID (#window),0,0, 800,600, 1, 0,0)
;}

;{ ************************ sprite et loading ***************
block_x = 350
block_y = 250

LoadSprite(#sprite,"col.png");
LoadSprite(#sprite1,"blockCollision.png");
TransparentSpriteColor(#sprite,RGB(255,0,0))
TransparentSpriteColor(#sprite1,RGB(255,0,0))
;}

;{ ************************ boucle principale ***************
Repeat
FlipBuffers ()
ClearScreen ( RGB (125,125,125)) 
Event= WindowEvent ()

ExamineKeyboard ()
evenementClavier()

If SpritePixelCollision(#sprite1,block\position\x, block\position\y,#sprite,block_x,block_y)
    block\vitesse =0
    block\position\x = block\previous\x 
    block\position\y = block\previous\y 
  Else
    block\vitesse = 3
 EndIf

DisplayTransparentSprite(#sprite1, block_x,block_y) 
DisplayTransparentSprite(#sprite, block\position\x, block\position\y) 

Until Event= #PB_Event_CloseWindow Or KeyboardPushed ( #PB_Key_Escape ) 
;}


Procedure evenementClavier()
  
If KeyboardPushed ( #PB_Key_Up )
    block\previous\y = block\position\y
    block\position\y - block\vitesse
EndIf

If KeyboardPushed ( #PB_Key_Down )
  block\previous\y = block\position\y
  block\position\y + block\vitesse
 EndIf

If KeyboardPushed ( #PB_Key_Left )
  block\previous\x = block\position\x
  block\position\x - block\vitesse
EndIf

If KeyboardPushed ( #PB_Key_Right ) 
  block\previous\x = block\position\x
  block\position\x +block\vitesse
EndIf  
  EndProcedure

Re: Sprite collision

Publié : mar. 08/mars/2011 17:22
par djes
Effectivement, ça bug avec DirectX9. En DirectX7 (tape directx7 dans subsystem dans les options du compilateur), ça va mieux. Mais franchement, il faut éviter d'utiliser cette fonction, très lente. Il est beaucoup plus rapide de tester soit par cercle, soit par points, soit par polygones (ou secteurs). En plus ça évite tout accès à la mémoire graphique (très très lent). Il y a un topic là dessus sur le forum allemand : http://www.purebasic.fr/german/viewtopic.php?t=9093

Re: Sprite collision

Publié : mar. 08/mars/2011 18:38
par blendman
salut

Merci pour le lien, j'ai regardé et effectivement, ça a l'air intéressant :). Maintenant, il faut que je vois comment je vais intégrer ça.

Sinon, avec directX7, ça fonctionne mieux.

Re: Sprite collision

Publié : mar. 08/mars/2011 19:11
par Fig
Sinon avec des quadtrees :wink:

Re: Sprite collision

Publié : mar. 08/mars/2011 20:25
par Cool Dji
Salut,

Effectivement, pour la plupart des cas, passer par un test de coordonnées (comme tu as fait avec tes boutons du menu) est la méthode la plus efficace et la plus rapide. Surtout, tu peux varier sur la forme de ta zone à tester (carré, cercle)
J'utilise très peu souvent spritepixelcollision (juste dans MadFire pour tester le contact entre le vaisseau et les décors).
Pour les tirs contre les ennemis j'utilisais des zones rectangulaires alors que j'aurais du tester des zones circulaires. Des fois les missiles explosent dans le vide... :lol:

Re: Sprite collision

Publié : mar. 08/mars/2011 23:12
par blendman
Fig : je ne sais pas ce qu'est un quadtree (pas encore), je vais essayer de regarder ça.
Cool Dji a écrit :Effectivement, pour la plupart des cas, passer par un test de coordonnées (comme tu as fait avec tes boutons du menu) est la méthode la plus efficace et la plus rapide. Surtout, tu peux varier sur la forme de ta zone à tester (carré, cercle)
ah ? comment puis-je faire une zone circulaire :) ?
J'utilise très peu souvent spritepixelcollision (juste dans MadFire pour tester le contact entre le vaisseau et les décors).
Pour les tirs contre les ennemis j'utilisais des zones rectangulaires alors que j'aurais du tester des zones circulaires. Des fois les missiles explosent dans le vide... :lol:
oui, ça peut être problématique. Moi, je pensais utiliser ça pour les collisions entre un ennemi et un sort de magie :)

Re: Sprite collision

Publié : jeu. 17/mars/2011 0:51
par beauregard
J'ai apporté les corrections nécessaire à ton programme, j'espère que tu en aura un bon usage :)

Pour l'image ci-dessous, il s'agit d'un losange sur lequel tu pourra faire "glisser" le pixel blanc sous ton contrôle.
Image

Code : Tout sélectionner

; 17/03/2011
; Les Listes Chainées (Linked Lists), tout une aventure !

;{ ************************enumeration ***********************
Enumeration
#window
#sprite 
#sprite1

#contact
EndEnumeration

;}


;{ ************************ variables ************************

Global vitesse= 3
;}

;{ ************************ Structures ************************

; liste chainée :
Structure objet
  id.w ; identité
  
  x.f ; abscisse
  y.f ; ordonnée
  
  dirX.w ; direction X (droite = 1 ; gauche = 2)
  dirY.w ; direction Y (haut = 1 ; bas = 2)
EndStructure

Global NewList boulette.objet()


Structure s_block
  position.Point
  previous.Point
  vitesse.i  
EndStructure

Global block.s_block
block\position\x = 15
block\position\y = 15
block\previous\x = block\position\x 
block\previous\y = block\position\y 
block\vitesse = 3

;}



;{ ************************ declare ***************************
Declare evenementClavier()
;}


;{ ************************ inititialisation *****************

InitKeyboard () 
InitSprite()
InitSprite3D()

UsePNGImageDecoder()

;}


;{ ************************ open window *********************

OpenWindow(#window, 0, 0,800, 600, "test de collision à l'aide d'un tout petit pixel ^^ - 17/03/2011 - pb 4.41 x86" , #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered )
OpenWindowedScreen( WindowID (#window),0,0, 800,600, 1, 0,0)

;}

;{ ************************ sprite et loading ***************

CreateSprite ( #contact , 1, 1, 0 ) ;- Fabrication d'un sprite servant au test de collision 
  StartDrawing ( SpriteOutput ( #contact ))
    BackColor ( RGB (0,0,0))
    Plot(0, 0, RGB (255, 255, 255)) ; un petit pixel ^^
  StopDrawing ()
  
  
;CreateSprite ( #contact , 10, 10, 0 ) ;- Fabrication d'un sprite servant au test de collision 
;  StartDrawing ( SpriteOutput ( #contact ))
;    BackColor ( RGB (0,0,0))
;    Box(0, 0, 10,10, RGB (255, 255, 255)) ; ça marche aussi avec un petit cube ^^
;  StopDrawing ()
  
  
Procedure.i Fboulette(id,x,y) ; Fabrication de clone des boulettes

  LastElement(boulette())
  AddElement(boulette())
  
  boulette()\id = id ; id = 1 correspond ici au test manuel
  boulette()\x = x
  boulette()\y = y
	
EndProcedure

Fboulette(1, 200, 200) ; on fabrique ici une boulette déplacé en manuel pour test (id=1)
;Fboulette(2, 256+16, 256) ; test de position (id=2)
  

block_x = 256
block_y = 256

LoadSprite(#sprite,"col.png");,#PB_Sprite_AlphaBlending|#PB_Sprite_Texture)
;CreateSprite(#sprite,SpriteWidth(#sprite),SpriteHeight(#sprite))

; blockCollision2.png --> image d'une taille de 128*128
LoadSprite(#sprite1,"blockCollision2.png");,#PB_Sprite_AlphaBlending|#PB_Sprite_Texture)
;CreateSprite(#sprite1,SpriteWidth(#sprite1),SpriteHeight(#sprite1))

;TransparentSpriteColor(#sprite,RGB(255,0,0)) ; boulette
;TransparentSpriteColor(#sprite1,RGB(255,0,0)) ; cible
;}

;{ ************************ boucle principale ***************

Repeat
FlipBuffers ()
ClearScreen ( RGB (0,0,0)) ;(125,125,125)) 
Event= WindowEvent ()

ExamineKeyboard ()
evenementClavier()

 

ForEach boulette(); pour chaque clone boulette
  If boulette()\id=1
    If boulette()\x>block_x And boulette()\x<block_x+128 And boulette()\y>block_y And boulette()\y<block_y+128 ; condition afin de limiter la zone de test
 
      If boulette()\dirX = 1
        If SpritePixelCollision(#contact,boulette()\x, boulette()\y, #sprite1, block_x, block_y)
          boulette()\x - block\vitesse
        EndIf
      EndIf
      If boulette()\dirX = 2
        If SpritePixelCollision(#contact,boulette()\x, boulette()\y, #sprite1, block_x, block_y)
          boulette()\x + block\vitesse
        EndIf
      EndIf

      If boulette()\dirY = 1
        If SpritePixelCollision(#contact,boulette()\x, boulette()\y, #sprite1, block_x, block_y)
          boulette()\y + block\vitesse
        EndIf
      EndIf

      If boulette()\dirY = 2
        If SpritePixelCollision(#contact,boulette()\x, boulette()\y, #sprite1, block_x, block_y)
          boulette()\y - block\vitesse
        EndIf
      EndIf
    EndIf
    boulette()\dirX = 0:boulette()\dirY = 0 ; remise à 0 des 2 variables de directions pour chaque boulette
  EndIf
  
  DisplayTransparentSprite(#contact, boulette()\x, boulette()\y) ; Affichage de chaque boulette
Next


  DisplayTransparentSprite(#sprite1, block_x,block_y) ; Affichage cible

Until Event= #PB_Event_CloseWindow Or KeyboardPushed ( #PB_Key_Escape ) 
;}


Procedure evenementClavier()
ForEach boulette(); pour chaque clone boulette
 If boulette()\id=1

  If KeyboardPushed ( #PB_Key_Right ) 
    boulette()\x + block\vitesse:boulette()\dirX = 1   
  EndIf

  If KeyboardPushed ( #PB_Key_Left )
    boulette()\x - block\vitesse:boulette()\dirX = 2
  EndIf
  
  If KeyboardPushed ( #PB_Key_Up )
    boulette()\y - block\vitesse:boulette()\dirY = 1
  EndIf

  If KeyboardPushed ( #PB_Key_Down )
    boulette()\y + block\vitesse:boulette()\dirY = 2
  EndIf

 EndIf  
Next

  
  EndProcedure
ps: la commande ClearScreen ne doit pas être utilisé car jugé trop gourmande. Et utiliser uniquement des sprite3D (images utilisant les capacités des cartes graphiques).

Re: Sprite collision

Publié : jeu. 21/avr./2011 7:44
par blendman
salut

désolé de répondre si tard, mais je viens juste de voir ton code beauregard, et merci beaucoup c'est très intéressant et je pense que cela va m'être bien utile ;)