Page 1 sur 2

collision glissante 2d

Publié : ven. 13/févr./2004 13:35
par cederavic
comment faire des collision glissante 2D??
j'ai essayer pas mal de truc mais rien de bien conveincant...
c'est pour un rpg 2d avec deplacement a la sourie
merci d'avance :)

Publié : ven. 13/févr./2004 18:53
par Invité
Qu'es tu apelles collision glissante 2D??

Publié : ven. 13/févr./2004 19:10
par comtois
regarde dans la demo plateforme 3D , la procedure EntityCollision gère ça , bon c'est loin d'être parfait , mais ça fonctionne un peu .

Je le gère comme de la 2D , il y a juste la dimension Y à supprimer. et peut-être à adapter un peu , par rapport à l'axe z qui est dans le sens inverse de l'axe y de l'écran

en clair
dans mon truc 3D
l'axe x reste le même pour la 2D
l'axe y n'est plus utile en 2D
l'axe z devient l'axe y pour la 2D

Sinon , tu gères tes collisions comment ? c'est des sprites 3D ou 2D ?
tes sprites peuvent prendre n'importe quel angle ?

Publié : ven. 13/févr./2004 23:37
par cederavic
je vais voir ça :)
ce sont de sprite 2d animé, pas de rotation

Publié : sam. 14/févr./2004 2:14
par comtois
Et tu as prévu combien de directions possibles ? 4 ou 8 ?
sûrement 8 , sinon avec 4 je ne vois pas comment tu veux faire une collision glissante ?
Le principe :

Tu ne peux glisser que si tu te déplaces en diagonal.
si tu te déplaces à la verticale ou à l'horizontale et que tu rencontres un obstacle , tu es bloqué .Confirme si c'est bien ce que tu veux faire .

par contre si tu rencontres un obstacle sur ta droite et que tu te déplaces en diagonal (en haut à droite ), il suffira de ne plus modifier la position x et seulement la position en y donc haut pour longer l'obstacle.

Déjà il faut tester les collisions entre le perso et le décor .
Ensuite , une fois que l'on connait le sprite en collision , il faut savoir de quel côté on touche en testant la position du perso et la position du sprite en collision , ainsi que les dimensions ,avec ça tu devrais pouvoir déterminer de quel côté tu touches.

l'instruction SpriteCollision indique s'il y a un chevauchement , il reste à replacer le perso à la limite de l'autre sprite .
en gros , il faut corriger la position sur un axe pour ne pas rentrer dans le décor , et modififier l'autre axe pour avancer le long de l'obstacle.

c'est purement théorique tout ça , je n'ai pas testé et je considère que les obstacles sont orthogonaux ce qui devrait simplifier le problème , sinon , faudrait tenir compte de l'angle de l'obstacle , peut-être calculer la normale etc .

Publié : sam. 14/févr./2004 10:03
par T€r$@k€n
C'est un Code Pour DB pro, mais si ça peut t'aider :wink:

Code : Tout sélectionner

`-----------------------------
`--- Collisions Glissantes ---
`--- By T£rsAk£n Studio    ---
`-----------------------------
`---- Je Remecie Dri ---------
`-----------------------------

`------------
`--- Init ---
`------------

 Set Display Mode 640,480,16
 Sync On : Sync Rate 30
 Hide Mouse

`-----------------
`--- Variables ---
`-----------------


 Dim Map(10,10)   : LoadMap() 

 GloBal Angle#,Move
 GloBal Y_Perso# = 240.0
 Global X_Perso# = 320.0
 Global X_Old#,Y_Old#

`-------------------------
`--- Boucle Principale ---
`-------------------------

 Do
  Cls
  Controle()
  Collision() 
  Affiche()
  Sync
 Loop

`-----------------
`--- Fonctions ---
`-----------------

Function Collision()	
  Detection()
  if X_Perso#=X_Old# and Y_Perso#=Y_Perso#
   inc X_Perso#, move*cos(Angle#-45)
  endif
  Detection()
  if X_Perso#=X_Old# and Y_Perso#=Y_Perso#
   inc Y_Perso#, move*sin(Angle#-45)
  endif 
  Detection() : Move = 0
 endfunction 0	
`-------------------------------------------	
 Function Affiche()
  `Carte.
  for yloop = 0 to 9 : for xloop = 0 to 9
   Ink rgb(0,0,255),0	
   If Map(xloop,yloop) <> 0 : Box xloop*64,yloop*48,xloop*64+64,yloop*48+48 : endif
  next xloop : next yloop 	 	
  `Personnage.	
  ink rgb(255,0,0),0
  Line X_perso#,Y_Perso#,X_Perso#+20*cos(wrapvalue(Angle#)),Y_Perso#+20*sin(Angle#)
  ink rgb(0,255,0),0
  Line X_Perso#,Y_Perso#,X_Perso#+20*cos(WrapValue(Angle#-90)),Y_Perso#+20*sin(WrapValue(Angle#-90))
 endfunction 0
`------------------------------------------
 Function Controle()
   X_Old# = X_Perso# : Y_Old# = Y_Perso#	
   Inc Angle#,( Rightkey() - LeftKey() ) * 3
   Angle# = WrapValue(Angle#)
   move = ( downkey()-upkey() ) * 3
   inc X_Perso#, Move*cos(Angle#-45)
   inc Y_Perso#, Move*sin(Angle#-45)
 EndFunction 0
`------------------------------------------ 
 Function LoadMap()
  for yloop = 0 to 9 : for xloop = 0 to 9
   read map(xloop,yloop)
  next xloop : next yloop
 endfunction 0
`------------------------------------------- 
 Function Detection()
  if Map( Int ( X_Perso#/64.0 ), Int( Y_Perso#/48.0 ) ) <> 0
   X_Perso# = X_Old# : Y_Perso# = Y_Old#
  endif 	 
 EndFunction 0
`-------------------------------------------  
 
 
`------------------
`--- Etiquettes ---
`------------------

 Carte:
  Data 1,1,1,1,1,1,1,1,1,1
  Data 1,0,0,0,0,0,0,0,0,1
  Data 1,1,1,1,0,1,1,1,0,1
  Data 1,1,0,0,0,0,0,1,0,1
  Data 1,1,0,0,0,0,0,1,0,1
  Data 1,1,0,0,0,0,0,1,0,1
  Data 1,1,1,1,0,1,1,1,0,1
  Data 1,0,0,0,0,0,0,0,0,1
  Data 1,1,1,1,1,1,1,1,1,1
  Data 0,0,0,0,0,0,0,0,0,0

Publié : sam. 14/févr./2004 11:02
par cederavic
oui comtois, c'est bien ce que je faisait mais avec SpritePIXELCollision c'est pas le top, il faudrait une sorte de marge... mais je voi pa comment faire

Publié : sam. 14/févr./2004 16:05
par Dr. Dri
...

Publié : sam. 14/févr./2004 19:06
par cederavic
oui c'est le meme principe, mais imagine un decor arrondi, le perso va se bloquer a cause d'un seul pixel!!!
donc il faut une sorte de marge d'erreur... sinon le pathfinding (j'ai pas vraiment la tete a ça mais si c'est le seul moyen :s)

Publié : sam. 14/févr./2004 22:53
par Dr. Dri
...

Publié : dim. 15/févr./2004 10:39
par cederavic
c'est la methode que j'utilisai ;) mais pas de declic lol
je vai essayer en metant un peut de savon sur les bords des sprite, ça marchera peut etre :D

Publié : dim. 15/févr./2004 11:07
par comtois
si ça marche ,tu me donneras la marque de ton savon ? :lol:

Publié : dim. 15/févr./2004 19:47
par comtois
Voila un code qui ne marche pas, le but du jeu c'est de le faire fonctionner correctement :)

en fait j'ai triché , j'ai mis un random pour éviter de rester bloquer , mais du coup ça saccade . Et comme je ne veux pas y passer trop de temps pour corriger ça , je te le colle ici quand même , j'y réfléchirai à l'occasion , mais si d'ici là quelqu'un a une solution , elle sera la bienvenue :)

Code : Tout sélectionner

;-Initialisation 
#ScreenWidth = 800
#ScreenHeight = 600 
#ScreenDepth = 16
If InitSprite() = 0 Or InitKeyboard() = 0 
   MessageRequester( "Erreur" , "Impossible d'initialiser DirectX 7 Ou plus" , 0 )
   End
ElseIf OpenScreen( #ScreenWidth , #ScreenHeight , #ScreenDepth , "Demo PlateForme" ) = 0
   MessageRequester( "Erreur" , "Impossible d'ouvrir l'écran " , 0 )
   End
EndIf

;/ Structures
Structure sprite
   x.l
   y.l
   Width.l
   Height.l
EndStructure

Structure joueur
   x.f
   y.f
   Width.l
   Height.l
   Sens.w
EndStructure
NewList mur.sprite()
Global Joueur.joueur
Global player1_move.f,player1_speed.f

;/Les sprites 
;Joueur
CreateSprite(0,16,16) 
StartDrawing(SpriteOutput(0)) 
  Circle(SpriteWidth(0)/2,SpriteHeight(0)/2,SpriteWidth(0)/2,RGB(255,255,55)) 
StopDrawing() 
Joueur\x = 100
Joueur\y = 50
Joueur\Width = SpriteWidth(0)
Joueur\Height = SpriteHeight(0)

;mur
CreateSprite(1,32,32) 
StartDrawing(SpriteOutput(1)) 
  Box(0,0,SpriteWidth(1),SpriteHeight(1),RGB(55,155,155)) 
StopDrawing() 

;- procedures 
Procedure InitGameTimer() 
   Shared _GT_DevCaps.TIMECAPS 
   timeGetDevCaps_(_GT_DevCaps,SizeOf(TIMECAPS)) 
   timeBeginPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure 

Procedure StopGameTimer() 
   Shared _GT_DevCaps.TIMECAPS 
   timeEndPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure 

Procedure Readmap()
   Restore map 
   For b = 0 To 15
      For a = 0 To 19
         Read c
         If c 
            AddElement(mur())
            mur()\Width = SpriteWidth(1)
            mur()\Height = SpriteHeight(1)
            mur()\x = a * mur()\Width
            mur()\y = b * mur()\Height            
         EndIf
      Next a
  Next b    
EndProcedure  

Procedure Affmap()
   ForEach mur()
      DisplaySprite(1,mur()\x,mur()\y)
   Next   
EndProcedure 

Procedure collision()
   ForEach mur()
      If SpriteCollision(0,Joueur\x,Joueur\y,1,mur()\x,mur()\y)
         ;corrige la position du perso 
         Ecartx = Joueur\x - mur()\x
         Ecarty = Joueur\y - mur()\y
         If Ecartx < 0
            decalX = Abs(Ecartx) - Joueur\Width
         Else
            decalX = mur()\Width - Ecartx
         EndIf   
         
         If Ecarty < 0
            decalY = Abs(Ecarty) - Joueur\Height
         Else
            decalY = mur()\Height - Ecarty
         EndIf  
         
         If Random(1)  ; pas terrible ça saccade , mais je ne sais pas comment faire autrement pour l'instant 
            If Abs(decalX)>= Abs(decalY) 
               decalX = 0
            Else             
               decalY = 0
            EndIf   
         Else
            If Abs(decalX)> Abs(decalY) 
               decalX = 0
            Else             
               decalY = 0
            EndIf 
         EndIf   
      
         Joueur\x + decalX
         Joueur\y + decalY 
         
         collision()

        Break
      EndIf
   Next
   
EndProcedure
Vitesse = 3
Readmap()
player1_speed.f = 0.250 

; timer initialisieren 
InitGameTimer() 
StartTime = TimeGetTime_() 
;StartTime = GetTickCount_() 
time= StartTime 
  
Repeat
   ; calculate multiplicator 
   multiplicator.f = StartTime 
   StartTime = TimeGetTime_() 
   ;StartTime = GetTickCount_()    
   multiplicator   = StartTime - multiplicator 
   
   ; calc framerate 
   If TimeGetTime_()-time >= 1000 
      ;If GetTickCount_()-time >= 1000    
      time   = TimeGetTime_() 
      ;time   = GetTickCount_() 
      FPS    = Frames-1 
      Frames = 1 
   Else 
      Frames+1 
   EndIf 
   ClearScreen(0,0,0)
   ; show framerate 
   StartDrawing(ScreenOutput()) 
   DrawingMode(1):FrontColor($80,$FF,$00) 
   Locate(50,50):DrawText("FrameRate: "+Str(FPS)) 
   StopDrawing() 
   
   ; calc move-step for player1 
   player1_move = player1_speed * multiplicator  
   
   Affmap()
   ExamineKeyboard()  
   If KeyboardPushed(#PB_Key_Up)  
      Joueur\y - player1_move
   ElseIf KeyboardPushed(#PB_Key_Down)
      Joueur\y + player1_move
   EndIf     
   If KeyboardPushed(#PB_Key_Left)  
      Joueur\x - player1_move
   ElseIf KeyboardPushed(#PB_Key_Right)
      Joueur\x + player1_move
   EndIf 

   collision()
   DisplaySprite(0,Joueur\x,Joueur\y)

   FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)

DataSection
map:
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1
Data.l 1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1
Data.l 1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1
Data.l 1,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1
Data.l 1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,1,0,1
Data.l 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1
Data.l 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1
Data.l 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data.l 1,0,0,0,1,1,1,0,0,1,0,1,0,1,1,1,0,0,0,1
Data.l 1,0,1,0,0,0,1,0,0,1,0,1,0,1,0,0,0,0,0,1
Data.l 1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1
Data.l 1,0,1,1,0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,1
Data.l 1,0,0,1,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,1
Data.l 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
EndDataSection

Publié : dim. 15/févr./2004 19:59
par cederavic
j'ai pas tout compris mais ça ç l'air d'etre ça :D
c'est quoi ton savon? :p
tu peut m'expliquer un peut plus stp? merci :)

Publié : lun. 16/févr./2004 0:39
par comtois
pour ne pas surcharger ,j'ai remplacé le code dans le post précédent , il n'y a pas grand chose de nouveau
j'ai changé les touches, je préfère avec les flèches
J'ai changé la forme et la taille du sprite du joueur
Et j'ai ajouté la gestion de la vitesse en recopiant le code de Danilo.
J'avais commencé des tests en faisant autrement , mais bon si danilo propose ça , c'est que c'est la meilleure solution , autant l'adopter :)

Je remettrai le code en forme plus tard si je trouve comment supprimer cet affreux Random() qui saccade encore un peu le jeu .

et ensuite seulement je pourrai expliquer , parce que là , ça marche, mais je ne sais pas pourquoi :) j'ai tatonné un peu en partant sur l'idée que je décris plus haut.