Page 2 sur 2

Publié : mar. 07/juil./2009 9:34
par djes
;)
Franchement, le quadtree pour faire du test de pixel, ça me parait SUPER lourd, et je ne vois pas du tout l'intérêt niveau rapidité, ni niveau algo. Un quadtree pour tester les interactions de plusieurs objets, d'accord; mais là, franchement je vois pas! Je me trompe peut-être... En plus le parcours d'une liste est assez lent... :?:

Publié : mar. 07/juil./2009 12:25
par cha0s
@djes : si tu parcours la liste dans l'ordre au contraire c'est rapide ! C'est a sa que serve les iterateurs en C++ et en JAVA. L'intérêt du QuadTree et de partir d'un problème complexe et de la simplifier. En gros j'ai mon carré qui représente mon sprite et le quadtree me permet d'ignorer les zones vides ce qui correspond a ne tester aucun pixel de la zone vide.

@beauregard:j'utilise un masque rectangulaire pour la collision avec le joueur et les tirs, mais pour les ennemies la collision doit être parfaite. De plus le moteur ne doit pas être exclusivement dédié au maniaque.

@CLP : comme je vient de le dire insuffisant dans certain cas.


Mais je doit encore réfléchir a tout sa je suis encore a porter mes algos pour la gestion des ressources.

Publié : mar. 07/juil./2009 12:50
par Backup
le plus simple et le plus rapide consiste
a prendre le centre du sprite en X et y

et a considerer la distance qui separe ce centre du centre de l'objet a considerer !! :)

en fait tu compare simplement la distance qu'il y a entre 2 sprites !

et ensuite tu en tire la conclusion suivante ,
si la distance est inferieur a la surface de ton sprite , il y a collision :)

je ne pense pas qu'il existe plus rapide que ça !

comme on considere les centres des sprites, il s'agit d'un test 'circulaire'
autour du sprite .. :)

mais rien n'empeche un test sur les Y séparement ces X

dans ce cas la zone de collision est 'carré' :)

tu peux reduire la distance de collision a volonté , et comme ça
tu as un system tres rapide, et fiable :)

j'avais fait quelques petits travaux de recherche sur les collisions
et voici ce que j'ai appelé la super_collision
super, parcequ'elle te retourne quel coté du sprite est touché !
j'ai trouvé a l'epoque, que les fonctions de collision du Purebasic
manquaient de précision, sur le "Coté" du sprite touché

ce code retourne en toute lettre , quel coté du sprite est touché
le but est de faire la collision avec le curseur (la souris)

le tout synthétisé sous forme de procedure :

super_collision(sprite_numero1, x_sprite1, y_sprite1, sprite_numero2, x_sprite2, y_sprite2)

voici mon code :

Code : Tout sélectionner


; prg realisé par Dobro
#dobro=1
#Police=1
#sprite=1

Declare.s super_collision(sprite_numero1, x_sprite1, y_sprite1, sprite_numero2, x_sprite2, y_sprite2)
; cette procedure renvoie du quelle coté le sprite a été touché !

; sprite_numero1= le numero du sprite 1 a tester
;  largeur_spr1 = largeur en pixel du sprite numero 1
; hauteur_spr1 = hauteur en pixel du sprite numero 1
; x_sprite1 = coordonée X du sprite numero 1
; y_sprite1=coordonée Y du sprite numero 1
; --------------------------------------------------------------------------
; sprite_numero2=  le numero du sprite 2 a tester
;  largeur_spr2 = largeur en pixel du sprite numero 2
; hauteur_spr12 = hauteur en pixel du sprite numero 2
; x_sprite2 = coordonée X du sprite numero 2
; y_sprite2 coordonée Y du sprite numero 2

Enumeration
  #Window
  #sprite_cible
  #sprite_souris
  #sprite_text 
EndEnumeration

Structure sprite
  x.w
  y.w 
EndStructure
Dim sprite.sprite(1)

Dim ecran(640,400)
For x = 0 To 640 ; un écran de couleurs aléatoires
  For y = 0 To 400
    r=Random(255)
    G=Random(255)
    b=Random(255)
    c=RGB(r,G,b)
    ecran(x,y)= c
  Next y
Next x
; ***********************************
Resultat = InitSprite()
FontID = LoadFont(#Police, "arial", 18, #PB_Font_Bold )
EcranX = GetSystemMetrics_(#SM_CXSCREEN):;=largeur de l'ecran
EcranY = GetSystemMetrics_(#SM_CYSCREEN):;=hauteur de l'ecran
  WindowID = OpenWindow(#Window, 0, 0, 800, 600,  "hello",#PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered )
  
  Result = OpenWindowedScreen(WindowID(#Window),0,0, 800, 600, 1, 0,0)
  
  
  CreateSprite( #sprite_cible, 64, 64)  ; sprite exemple
  StartDrawing(SpriteOutput( #sprite_cible) ) ; on dessine dedans
  Box(0, 0, 64, 64, RGB($FF,$0,$80))
  StopDrawing()
  
  CreateSprite( #sprite_souris, 32, 32)  ; sprite souris
  StartDrawing(SpriteOutput( #sprite_souris) ) ; on dessine dedans
  Box(0, 0, 64, 64,RGB($13,$F8,$7))
  StopDrawing()
  
  bord$="aucun bord"
  CreateSprite(#sprite_text, 150,14)  ; le text
  StartDrawing(SpriteOutput(#sprite_text) ) ; on dessine dedans
  DrawText(1,1,bord$,RGB(0,0,0), RGB(255,255,255))
  StopDrawing()
  
  Resultat = InitMouse()  
  Repeat
    ExamineMouse()
    Event=WindowEvent()
    
    DisplaySprite(#sprite_cible, WindowWidth(#Window) /2+50,  WindowHeight(#Window)/2+100)
    sprite(1)\x=WindowWidth(#Window)/2+50
    sprite(1)\y=WindowHeight(#Window)/2+100
    
    DisplaySprite(#sprite_souris,  MouseX(),   MouseY())
    DisplaySprite( #sprite_text,  10,  10) 
    
    bord$=super_collision(#sprite_cible, sprite(1)\x,sprite(1)\y, #sprite_souris,MouseX(), MouseY())  
    
    StartDrawing(SpriteOutput(#sprite_text) ) ; on dessine dedans
    DrawText(1,1,"                              ", RGB(0,0,0), RGB(255,255,255))
    DrawText(1,1,bord$,RGB(0,0,0), RGB(255,255,255)) 
    StopDrawing() 
    If MouseButton(2)
      End
    EndIf 
    
    FlipBuffers():; affiche l'ecran
    ClearScreen(RGB(0, 0, 0)) :;efface l'ecran 
  Until Event=#PB_Event_CloseWindow
  
  
  
  
  
  
  Procedure.s super_collision(sprite_numero1, x_sprite1, y_sprite1, sprite_numero2, x_sprite2, y_sprite2)
    ; code Dobro
    spr1_milieu_x=x_sprite1+SpriteWidth(sprite_numero1) /2
    spr1_milieu_y=y_sprite1+SpriteHeight(sprite_numero1)/2
    spr2_milieu_x=x_sprite2+SpriteWidth(sprite_numero2)/2
    spr2_milieu_y=y_sprite2+SpriteHeight(sprite_numero2)/2
    
    spr1_hauteur=SpriteHeight(sprite_numero1)
    spr1_largeur=SpriteWidth(sprite_numero1)
    spr2_hauteur=SpriteHeight(sprite_numero2)
    spr2_largeur=SpriteWidth(sprite_numero2)
    
    
    If SpriteCollision(sprite_numero1,x_sprite1, y_sprite1,sprite_numero2,x_sprite2, y_sprite2)
      If  spr2_milieu_x<x_sprite1 And spr2_milieu_y<y_sprite1
        bord$="haut-gauche"
        Goto suite
      EndIf
      
      If  spr2_milieu_x>(x_sprite1+spr1_largeur) And spr2_milieu_y<y_sprite1
        bord$="haut-droit"
        Goto suite
      EndIf
      
      If spr2_milieu_x>x_sprite1+spr1_largeur And spr2_milieu_y>y_sprite1+spr1_hauteur
        bord$="bas-droit"
        Goto suite
      EndIf
      
      If spr2_milieu_x<x_sprite1 And spr2_milieu_y>y_sprite1+spr1_hauteur
        bord$="bas-gauche"
        Goto suite
      EndIf
      
      
      
      
      If x_sprite2+spr2_largeur>x_sprite1 And  x_sprite2<x_sprite1+spr1_largeur And spr2_milieu_y<y_sprite1
        bord$="haut"
        Goto suite
      EndIf
      
      If  y_sprite2+spr2_hauteur>y_sprite1 And y_sprite2<y_sprite1+spr1_hauteur And spr2_milieu_x>x_sprite1+spr1_largeur
        bord$="droit"
        Goto suite
      EndIf
      
      If  x_sprite2+spr2_largeur>x_sprite1 And x_sprite2<x_sprite1+spr1_largeur And spr2_milieu_y>y_sprite1+spr1_hauteur
        bord$="bas"
        Goto suite
      EndIf
      
      If  y_sprite2+spr2_hauteur>y_sprite1 And y_sprite2<y_sprite1+spr1_hauteur And  spr2_milieu_x<x_sprite1
        bord$="gauche"
        Goto suite
      EndIf
      
      
      
      
    EndIf
    
    suite:
    ProcedureReturn  bord$
  EndProcedure
  
  

Publié : mar. 07/juil./2009 13:00
par djes
Non mais là, on parle de test au pixel (ce qui est à mon avis un peu surabondant pour du shoot, à part dans certains cas comme xenon); arrêtez de l'embêter à lui dire qu'il faut le faire avec une bounding box ou un autre type de test!
Je me demande vraiment s'il y a un intérêt au quadtree ou s'il vaut mieux rester sur un masque classique. Faut que je réfléchisse là dessus :/

PS: désolé Dobro, pas vu ton post!