Sprite collision

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Sprite collision

Message 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
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Sprite collision

Message 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
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Sprite collision

Message 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.
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Sprite collision

Message par Fig »

Sinon avec des quadtrees :wink:
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: Sprite collision

Message 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:
Only PureBasic makes it possible
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Sprite collision

Message 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 :)
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Re: Sprite collision

Message 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).
config de mon ordi: seven, directx11, Pentium(R) DualCore E5700, RadeonHD 4550 512MB, PureBasic 4.61 x86
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Sprite collision

Message 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 ;)
Répondre