Page 1 sur 2

Petit problême qui me prends la tête...

Publié : sam. 10/juil./2004 9:45
par Polux
Est-ce que quelqu'un saurait comment determiner quel côté d'un sprite est touché lors d'une collision avec un autre? ( droite ou gauche, haut ou bas )... je galère là... :?

Publié : sam. 10/juil./2004 10:01
par Chris
A part faire une comparaison de la position de l'objet qui touche le sprite par rapport à celle du sprite, je ne vois pas trop :?

Chris :)

Publié : sam. 10/juil./2004 11:46
par Backup
ben oui c'est ça la solution !!!

tu compare le x du bateau avec le x du continent

si le x du bateau est plus grand que le x du continent au moment de l'impact
ça veux obligatoirement dire que le bateau se situe a droite de la rive !!
donc que le bateau est touché du coté gauche !!

pareil avec les autres coordonées !! :)

Publié : sam. 10/juil./2004 13:01
par Chris
Voilà à peu près tout ce que je sais faire dans ce domaine.

C'est pas très au point, mais ça doit pouvoir s'améliorer :?

Code : Tout sélectionner

#Window = 0 
#Width = 300 
#Height = 300 

Enumeration 
  #balle1
  #balle2
EndEnumeration 

Global SprFix_X,SprFix_Y,SprMob_X,SprMob_Y
Procedure Affichage()
  PosMobX$ = LSet(Str(SprMob_X),3,"_")+" x "
  PosMobY$ = LSet(Str(SprMob_Y),3,"_")
  PosFixX$ = LSet(Str(SprFix_X),3," ")+" x "
  PosFixY$ = LSet(Str(SprFix_Y),3," ")
  
  
  StartDrawing(ScreenOutput())
  DrawingMode(1) : FrontColor($C0,$C0,$C0)
  Locate(10,10)
  DrawText("Mobile = "+PosMobX$+PosMobY$+" ["+LSet(Str(SprMob_X+24),3,"_")+" - "+Str(SprMob_Y+24)+"]")
  Locate(10,30)
  DrawText("Fixe     = "+PosFixX$+PosFixY$+" ["+Str(SprFix_X+24)+" - "+Str(SprFix_Y+24)+"]")
  StopDrawing()
EndProcedure

Procedure Sprites()
  If CreateSprite(#balle1,24,24,0)           ; Sprite Fixe 
    StartDrawing(SpriteOutput(#balle1)) 
    Box(0,0,24,24,RGB($FF,$0,$0))
    StopDrawing() 
  EndIf 
  
  If CreateSprite(#balle2,24,24,0)           ; Sprite Mobile
    StartDrawing(SpriteOutput(#balle2)) 
    Box(0,0,24,24,RGB($0,$0,$FF))
    StopDrawing() 
  EndIf 
EndProcedure

Procedure Between(Value.l,Mini.l,Maxi.l)
  If Value >= Mini And Value <= Maxi
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

;- Initialisation de DirectX 
If InitSprite() = 0 Or InitKeyboard() = 0  Or InitMouse() = 0
  End 
EndIf 

hwnd = OpenWindow(#Window, 0, 0, #Width, #Height, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "") 
OpenWindowedScreen(hwnd, 0, 0, #Width, #Height, 0, 0, 0) 

Sprites()

Repeat 
  ClearScreen(0, 0, 0) : ExamineKeyboard() :ExamineMouse()
  SprFix_X = 138 : SprFix_Y = 138
  SprMob_X = MouseX() : SprMob_Y = MouseY()
  
  DisplayTransparentSprite(#balle1,SprFix_X,SprFix_Y) 
  DisplayTransparentSprite(#balle2,SprMob_X, SprMob_Y) 
  
  Affichage() 
  FlipBuffers() 
  
  If SpriteCollision(#balle1,SprFix_X,SprFix_Y,#balle2,SprMob_X,SprMob_Y)
    If SprMob_X < SprFix_X-2 And Between(SprMob_Y,SprFix_Y-20,SprFix_Y+20)
      SetWindowTitle(#Window,"Collision à gauche")
    EndIf
    If SprMob_X > SprFix_X And Between(SprMob_Y,SprFix_Y-20,SprFix_Y+20)
      SetWindowTitle(#Window,"Collision à droite")
    EndIf
    If SprMob_Y < SprFix_Y And Between(SprMob_X,SprFix_X-20,SprFix_X+20)
      SetWindowTitle(#Window,"Collision en haut")
    EndIf
    If SprMob_Y > SprFix_Y And Between(SprMob_X,SprFix_X-20,SprFix_X+20)
      SetWindowTitle(#Window,"Collision en bas")
    EndIf
  Else
    SetWindowTitle(#Window,"")
  EndIf
  
  Delay(2)
  If KeyboardPushed(#PB_Key_Escape) : quit = 1 : EndIf 
  While WindowEvent() : Wend 
Until quit = 1
Chris :)

Publié : sam. 10/juil./2004 13:33
par Polux
Merci les gars, j'essaye ça de suite! En fait c'est pour un casse brique... tout fonctionne bien mais j'ai du mal à gérer le rebond. Lorsque la balle touche une brique indestructible, elle devrait rebondir à l'inverse mais parfois elle passe au travers... je m'en sors pas...
Merci en tout cas! :wink:

Publié : sam. 10/juil./2004 14:02
par comtois
Imagine un perso qui court , et devant il y a un mur .
Ton mur n'est pas épais ( inférieur à la vitesse de déplacement du perso )

Premier tour de programme , tu testes la collision entre le perso et le mur , pas de contact ,le perso est devant .
le perso se déplace et se retrouve derrière le mur car son déplacement est supérieur à l'épaisseur du mur
au tour de programme suivant ,tu testes à nouveau la collision, et toujours pas de collision , le perso est derrière .
ça signifie , qu'il faut tenir compte du temps , pour contrôler la trajectoire du perso , ou alors mémoriser la position précédente ,et si le perso traverse un obstacle , il faut le replacer au contact et inverser son sens de déplacement .

En clair ,tu ne peux pas te contenter de la fonction Collision() de Pure , c'est à toi de faire le test .

Publié : sam. 10/juil./2004 14:23
par Chris
C'est vrai qu'elle est pas géniale, la fonction SpriteCollision().

Chris :)

Publié : sam. 10/juil./2004 14:33
par Polux
J'y comprends toujours rien...

Code : Tout sélectionner

DisplaySprite(brique()\style+1, brique()\x, brique()\y)
    If SpriteCollision(0,x,y,brique()\type+1,brique()\x, brique()\y) 
    If between(x,brique()\x,brique()\x+32) And Between(y,brique()\y,brique()\y+32)
    a=-a
    EndIf   
    b=-b
    If brique()\type=1
    DeleteElement(brique())
    EndIf 
    If brique()\type=2
    EndIf
    EndIf
Wend

j'ai essayé d'utiliser ta routine between chris.. marche toujours pas comme je veux... cette fois, la balle ne semble plus traverser mais son mouvement est obligatoirement toujours inversé à chaque collision... Grrrr

Publié : sam. 10/juil./2004 14:49
par Chris
Ben tu sais, je suis pas un spécialiste :?

La petite routine se contente de regarder si la position du sprite 1 se situe entre le début et la fin du sprite 2.
(En fait, c'est une procédure que je fais pour vérifier qu'une valeur est comprise entre deux autres valeurs).

Ensuite, c'est à toi de gérer le rebond et la direction de ta balle.

Chris :)

Publié : sam. 10/juil./2004 14:56
par Polux
ta routine est parfaite! mais je n'arrive toujours pas à gérer ce p.....*ù¨%* de rebond correctement...

Publié : sam. 10/juil./2004 16:51
par Backup
:)

n'oublie surtout pas que le calcul de collision est fait a partir
du coin superieur gauche des sprites !!!

donc pour le rebond droite c'est

si xball est en collision avec xbrique+largeur de brique alors rebond !!
pareil pour la collision de la balle avec le dessous de la brique(+hauteur de brique)

bref une petite fonction offset_sprite serai bienvenue pour decaler le point chaud !!
:)

Publié : sam. 10/juil./2004 17:21
par Chris
Et ne pas oublier, non plus, que si la balle est au dessus ou au dessous de la brique, il faut inverser Y et pas X, et que si la balle est à gauche ou à droite de la brique, il faut inverser X et pas Y. (Au moment de la collision, évidemment). :lol:

Mais bon... Je parle un peu dans le vide, là, parce que j'imagine que ça, tu le sais déjà!

(Et puis, faut bien que je poste un peu, de temps en temps :lol:)

Chris :)

Publié : sam. 10/juil./2004 18:55
par Chris
Petite modif du bout de code précédent.

J'ai viré le SpriteCollision(), le gros sprite rouge se déplace avec les touches fléchées, la balle se déplace toute seule, comme une grande.

Code : Tout sélectionner

#Window = 0 
#Width = 300 
#Height = 300 

Enumeration 
  #Spr_Fix
  #Spr_Mob
EndEnumeration 

Global SprFix_X,SprFix_Y,SprMob_X,SprMob_Y
dep = 1

Procedure Affichage()
  ; Cette procedure affiche les coordonnées des sprites
  PosMobX$ = LSet(Str(SprMob_X),3,"_")+" x "
  PosMobY$ = LSet(Str(SprMob_Y),3,"_")
  PosFixX$ = LSet(Str(SprFix_X),3," ")+" x "
  PosFixY$ = LSet(Str(SprFix_Y),3," ")
  
  
  StartDrawing(ScreenOutput())
  DrawingMode(1) : FrontColor($C0,$C0,$C0)
  Locate(10,10)
  DrawText("Mobile = "+PosMobX$+PosMobY$+" ["+LSet(Str(SprMob_X+24),3,"_")+" - "+Str(SprMob_Y+24)+"]")
  Locate(10,30)
  DrawText("Fixe     = "+PosFixX$+PosFixY$+" ["+Str(SprFix_X+12)+" - "+Str(SprFix_Y+12)+"]")
  StopDrawing()
EndProcedure

Procedure Sprites()
  ; Procedure de création des sprites
  If CreateSprite(#Spr_Fix,128,24,0)           ; Sprite Fixe 
    StartDrawing(SpriteOutput(#Spr_Fix)) 
    Box(0,0,128,24,RGB($FF,$0,$0))
    StopDrawing() 
  EndIf 
  
  If CreateSprite(#Spr_Mob,24,24,0)           ; Sprite Mobile
    StartDrawing(SpriteOutput(#Spr_Mob)) 
    Box(0,0,24,24,RGB($0,$0,$FF))
    StopDrawing() 
  EndIf 
EndProcedure

Procedure Between(Value.l,Mini.l,Maxi.l)
  ; Cette procédure vérifie que la valeur "Value" se situe entre
  ; "Mini" et "Maxi"
  If Value >= Mini And Value <= Maxi
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

;- Initialisation de DirectX 
If InitSprite() = 0 Or InitKeyboard() = 0
  End 
EndIf 

;- Ouverture de la fenêtre et de l'écran
hwnd = OpenWindow(#Window, 0, 0, #Width, #Height, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "") 
OpenWindowedScreen(hwnd, 0, 0, #Width, #Height, 0, 0, 0) 

Sprites()

;- Initialisation des sprites
SprFix_X = 86 : SprFix_Y = 138
SprMob_X = 0 : SprMob_Y = 0
SensX = 1 : SensY = 1

;- Boucle des évènements
Repeat 
  ClearScreen(0, 0, 0) : ExamineKeyboard()
  
  ; Affichage des sprites
  DisplayTransparentSprite(#Spr_Fix, SprFix_X, SprFix_Y) 
  DisplayTransparentSprite(#Spr_Mob, SprMob_X, SprMob_Y)
  
  ; Dessin des lignes du sprite mobile
  StartDrawing(ScreenOutput())
  Line(SprMob_X,0,0,300,RGB($C0,$C0,$C0))
  Line(SprMob_X+24,0,0,300,RGB($C0,$C0,$C0))
  Line(0,SprMob_Y,300,0,RGB($C0,$C0,$C0))
  Line(0,SprMob_Y+24,300,0,RGB($C0,$C0,$C0))
  StopDrawing()
  
  Affichage() 
  FlipBuffers() 
  
  SprMob_X + SensX : SprMob_Y + SensY
  
  ; Collision à gauche
  If SprMob_X + SpriteWidth(#Spr_Mob) = SprFix_X  
    If Between(SprMob_Y,SprFix_Y - SpriteWidth(#Spr_Mob), SprFix_Y + SpriteWidth(#Spr_Mob))
      SetWindowTitle(#Window,"Collision à gauche")
      SensX = -SensX
    EndIf
  
  ; Collision à droite
  ElseIf  SprMob_X = SprFix_X + 128  
    If Between(SprMob_Y,SprFix_Y - SpriteWidth(#Spr_Mob),SprFix_Y + SpriteWidth(#Spr_Mob))
      SetWindowTitle(#Window,"Collision à droite")
      SensX = -SensX
    EndIf
  
  ; Collision en haut
  ElseIf  SprMob_Y + SpriteHeight(#Spr_Mob) = SprFix_Y
    If Between(SprMob_X,SprFix_X - SpriteWidth(#Spr_Mob) ,SprFix_X + SpriteWidth(#Spr_Fix))
      SetWindowTitle(#Window,"Collision en haut")
      SensY = -SensY
    EndIf
 
  ; Collision en bas
  ElseIf  SprMob_Y = SprFix_Y + SpriteHeight(#Spr_Mob)   
    If Between(SprMob_X,SprFix_X - SpriteWidth(#Spr_Mob),SprFix_X +SpriteWidth(#Spr_Fix))
      SetWindowTitle(#Window,"Collision en bas")
      SensY = -SensY
    EndIf
  EndIf
  
  Delay(2)
  If KeyboardPushed(#PB_Key_Escape) : quit = 1    : EndIf
  
  If KeyboardPushed(#PB_Key_Left)   : SprFix_X - dep : EndIf
  If KeyboardPushed(#PB_Key_Right)  : SprFix_X + dep : EndIf
  If KeyboardPushed(#PB_Key_Up)     : SprFix_Y - dep : EndIf
  If KeyboardPushed(#PB_Key_Down)   : SprFix_Y + dep : EndIf
  
  If SprMob_X <=0   : SensX= -SensX    : EndIf
  If SprMob_Y <=0   : SensY= -SensY    : EndIf
  If SprMob_X >=276 : SensX= -SensX  : EndIf
  If SprMob_Y >=276 : SensY= -SensY  : EndIf
  
  While WindowEvent() : Wend 
Until quit = 1 
Chris :)

Publié : sam. 10/juil./2004 20:05
par Backup
bah moi aussi j'ai fait un truc pour toi mais j'ai garde sprite collision tiens :
:D

Code : Tout sélectionner

#dobro=1
#Police=1
#brique=1
#ball=2
; ***********************************
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(1, 0, 0, EcranX, EcranY,  #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered , "hello") 

WindowID = WindowID(1) 
Result = OpenWindowedScreen(WindowID,0,0, EcranX, EcranY, 1, 0,0)


;  creation d'un Sprite
CreateSprite(#brique, 350, 150)  ; cree un sprite brique
StartDrawing(SpriteOutput(#brique) ) ; on dessine dedans
Box(0, 0, 350, 150,RGB(255,0,255) ) ; un carre violet
StopDrawing() 

CreateSprite(#ball, 32, 32)  ; cree un sprite ball
StartDrawing(SpriteOutput(#ball) ) ; on dessine dedans
Circle(16,16, 16 ,RGB(255,255,255) )
StopDrawing() 

Resultat = InitMouse() 

xpas=20
ypas=10
xb=100
yb=450
xbrique=EcranX/2-150
ybrique=EcranY/2-50
Repeat
    ExamineMouse() 
    event=WindowEvent()
    Delay(1)
    If MouseButton(2)
        End
    EndIf
    
    xb=xb+xpas
    yb=yb+ypas
    
    
    DisplaySprite(#ball, xb,yb); affiche la balle
    DisplaySprite(#brique, xbrique,ybrique); affiche la brique
    
    If xb>EcranX-20 :xpas=-xpas:EndIf
    If xb<20 :xpas=-xpas:EndIf
    If yb>EcranY-20 :ypas=-ypas:EndIf
    If yb<20 :ypas=-ypas:EndIf
    
    If SpriteCollision(#ball, xb, yb, #brique, xbrique, ybrique)<>0 And xb<xbrique
        StartDrawing(SpriteOutput(#brique) ) ; on dessine dedans
        DrawText("touche a gauche ") 
        StopDrawing() 
        xpas=Random(5)+2
        xpas=-xpas
        Goto su ; sort du test !!!
    EndIf
    If SpriteCollision(#ball, xb, yb, #brique, xbrique, ybrique)<>0 And xb>xbrique+330
        StartDrawing(SpriteOutput(#brique) ) ; on dessine dedans
        DrawText("touche a droite ") 
        StopDrawing() 
        xpas=Random(5)+2
        
        Goto su ; sort du test !!!
    EndIf
    
    If SpriteCollision(#ball, xb, yb, #brique, xbrique, ybrique)<>0 And yb<ybrique
        StartDrawing(SpriteOutput(#brique) ) ; on dessine dedans
        DrawText("touche au dessus ") 
        StopDrawing()
        
        ypas=-ypas
        Goto su ; sort du test !!!
        
    EndIf
    If SpriteCollision(#ball, xb, yb, #brique, xbrique, ybrique)<>0 And yb>ybrique+130
        StartDrawing(SpriteOutput(#brique) ) ; on dessine dedans
        DrawText("touche au dessous ") 
        StopDrawing()
        
        ypas=-ypas
        Goto su ; sort du test !!!
        
    EndIf
    su:
    
    
    
    
    
    
    
    
    FlipBuffers():; affiche l'ecran
    ClearScreen(0, 0, 0) :;efface l'ecran
    
Until event=#PB_Event_CloseWindow 

Publié : sam. 10/juil./2004 20:28
par Polux
Merci les gars, ça éclaire ma lanterne! :wink:
ça y est, je crois que la routine fonctionne! Encore merci! Je devrais pouvoir vous fournir PureBreaker rapidement :D