Voilà mon objectif est de réaliser un jeu de plate-forme simple (oui je sais c'est pas ce qu'il y a de plus facile pour un débutant!). Pour cela je dois apprendre à gérer les collisions, mais c'est pas facile...
J'ai essayé de faire un code, mais ça ne marche pas toujours très bien.
Mon problème est que de temps à autres certaines boîtes se pénètrent sans collision et je ne sais pas pourquoi ? Il m'arrive carrément de voir parfois des boîtes se téléporter en dehors de la cage après une collision avec la paroi ?!?
Est-ce vous pourriez aussi m'aider à mieux commenter et mieux organiser mon code ? Etant novice je ne sais pas vraiment comment m'y prendre avec ce problème...
Pour faire fonctionner mon code, vous avez besoin de créer dans le même dossier trois petits fichiers bitmap :
- Box4.bmp : une ligne horizontale épaisse grise 600*5
- Box6.bmp : une ligne verticale épaisse grise 5*600
- Box7.bmp : un carré plein orange de 30*30
J'ai essayé de représenter les molécules d'un gaz enfermé dans une boîte. Pour ajouter la pesanteur il suffit de donner une valeur positive à la variable ay pour chacune des boîtes.
Code : Tout sélectionner
Enumeration
#win ;prévu pour un mode fenêtré
#box1 ;liste des objets
#box2
#box3
#box4
#box5
#box6
#box7
#box8
#box9
#box10
#box11
#box12
#box13
#box14
#box15
#box16
#box17
#box18
#box19
#box20
EndEnumeration
;Initialisations principales
If InitSprite()=0 Or InitKeyboard()=0 Or InitMouse()=0 Or OpenScreen(1280,800,32,"Collision!")=0
MessageRequester("Erreur","Impossible de démarrer le programme.")
End
EndIf
;Liste des paramètres
Structure Param
name$ ;nom de l'objet
type$ ;type d'objet
sprite.l ;sprite de l'objet
width.l ;largeur
height.l ;hauteur
x.f ;position x
y.f ;position y
newx.f ;nouvelle position x (utilité transitoire)
newy.f ;nouvelle position y (utilité transitoire)
vx.f ;vitesse x
vy.f ;vitesse y
newvx.f ;nouvelle vitesse x (utilité transitoire)
newvy.f ;nouvelle vitesse y (utilité transitoire)
ax.f ;accélération x
ay.f ;accélération y (pesanteur)
mass.f ;masse de l'objet
mob.b ;objet mobile ou non
flex.b ;flexibilité (contrainte sur les chocs inélastiques)
EndStructure
;Initialisation de la liste chaînée des objets
Global NewList Thing.Param()
Global time.l,dt.f,max.f
With Thing()
Procedure Loading()
LoadSprite(#box1,"Box4.bmp")
AddElement(Thing())
\name$="sol"
\type$="objet"
\sprite=#box1
\width=SpriteWidth(#box1)
\height=SpriteHeight(#box1)
\x=345
\y=705
\newx=0
\newy=0
\vx=0
\vy=0
\newvx=0
\newvy=0
\ax=0
\ay=0
\mass=1000
\mob=0
\flex=0
LoadSprite(#box2,"Box4.bmp")
AddElement(Thing())
\name$="sol"
\type$="objet"
\sprite=#box2
\width=SpriteWidth(#box2)
\height=SpriteHeight(#box2)
\x=345
\y=100
\newx=0
\newy=0
\vx=0
\vy=0
\newvx=0
\newvy=0
\ax=0
\ay=0
\mass=1000
\mob=0
\flex=0
LoadSprite(#box3,"Box6.bmp")
AddElement(Thing())
\name$="sol"
\type$="objet"
\sprite=#box3
\width=SpriteWidth(#box3)
\height=SpriteHeight(#box3)
\x=340
\y=105
\newx=0
\newy=0
\vx=0
\vy=0
\newvx=0
\newvy=0
\ax=0
\ay=0
\mass=1000
\mob=0
\flex=0
LoadSprite(#box4,"Box6.bmp")
AddElement(Thing())
\name$="sol"
\type$="objet"
\sprite=#box4
\width=SpriteWidth(#box4)
\height=SpriteHeight(#box4)
\x=945
\y=105
\newx=0
\newy=0
\vx=0
\vy=0
\newvx=0
\newvy=0
\ax=0
\ay=0
\mass=1000
\mob=0
\flex=0
For i=#box5 To #box12
LoadSprite(i,"Box7.bmp")
AddElement(Thing())
\name$="boîte n°"+Str(i-#box4)
\type$="objet"
\sprite=i
\width=SpriteWidth(i)
\height=SpriteHeight(i)
\x=360+(i-#box4)*60
\y=140+(i-#box4)*60
\newx=0
\newy=0
\vx=Random(500)-250
\vy=Random(500)-250
\newvx=0
\newvy=0
\ax=0
\ay=0
\mass=4/9
\mob=1
\flex=0
Next
For i=#box13 To #box20
LoadSprite(i,"Box7.bmp")
AddElement(Thing())
\name$="boîte n°"+Str(i-#box4)
\type$="objet"
\sprite=i
\width=SpriteWidth(i)
\height=SpriteHeight(i)
\x=910-(i-#box12)*60
\y=140+(i-#box12)*60
\newx=0
\newy=0
\vx=Random(500)-250
\vy=Random(500)-250
\newvx=0
\newvy=0
\ax=0
\ay=0
\mass=4/9
\mob=1
\flex=0
Next
EndProcedure
Procedure MoveOb()
Protected index1.l,index2.l,name1$,name2$,type1$,type2$,sprite1.l,sprite2.l
Protected width1.l,width2.l,height1.l,height2.l
Protected x1.f,x2.f,y1.f,y2.f,newx1.f,newx2.f,newy1.f,newy2.f,posx1.f,posx2.f,posy1.f,posy2.f
Protected vx1.f,vx2.f,newvx1.f,newvx2.f,vy1.f,vy2.f,newvy1.f,newvy2.f,Ux.f,Uy.f,ax1.f,ax2.f,ay1.f,ay2.f
Protected mass1.f,mass2.f,M.f,mob1.b,mob2.b,flex1.b,flex2.b,xcol.b,ycol.b,dis.f
ResetList(Thing())
Repeat
NextElement(Thing())
\newx=\x+\vx*dt+\ax*dt*dt/2
\newy=\y+\vy*dt+\ay*dt*dt/2
\newvx=\vx+\ax*dt
\newvy=\vy+\ay*dt
Until CountList(Thing())-1=ListIndex(Thing())
index1=0
Repeat
SelectElement(Thing(),index1)
name1$=\name$
type1$=\type$
sprite1=\sprite
width1=\width
height1=\height
x1=\x
y1=\y
newx1=\newx
newy1=\newy
vx1=\vx
vy1=\vy
newvx1=\newvx
newvy1=\newvy
ax1=\ax
ay1=\ay
mass1=\mass
mob1=\mob
flex1=\flex
index2=index1+1
Repeat
SelectElement(Thing(),index2)
name2$=\name$
type2$=\type$
sprite2=\sprite
width2=\width
height2=\height
x2=\x
y2=\y
newx2=\newx
newy2=\newy
vx2=\vx
vy2=\vy
newvx2=\newvx
newvy2=\newvy
ax2=\ax
ay2=\ay
mass2=\mass
mob2=\mob
flex2=\flex
M=mass1+mass2
Ux=Abs(vx1)+Abs(vx2)
Uy=Abs(vy1)+Abs(vy2)
xcol=0
ycol=0
If SpriteCollision(sprite1,newx1,y1,sprite2,newx2,y2)<>0
If x1<x2
dis=x2-x1-width1
Else
dis=x1-x2-width2
EndIf
posx1=Int(x1+dis*vx1/Ux)
posx2=Int(x2+dis*vx2/Ux)
If x1<x2
dis=posx2-posx1-width1
Else
dis=posx1-posx2-width2
EndIf
If dis<>0
xcol=0
Else
xcol=1
newx1=posx1
newx2=posx2
EndIf
ElseIf SpriteCollision(sprite1,x1,newy1,sprite2,x2,newy2)<>0
If y1<y2
dis=y2-y1-height1
Else
dis=y1-y2-height2
EndIf
posy1=Int(y1+dis*vy1/Uy)
posy2=Int(y2+dis*vy2/Uy)
If y1<y2
dis=posy2-posy1-height1
Else
dis=posy1-posy2-height2
EndIf
If dis<>0
ycol=0
Else
ycol=1
newy1=posy1
newy2=posy2
EndIf
EndIf
If xcol=1
If flex1=0 And flex2=0
newvx1=((mass1-mass2)*vx1+2*mass2*vx2)/M
newvx2=((mass2-mass1)*vx2+2*mass1*vx1)/M
Else
newvx1=(mass1*vx1+mass2*vx2)/M
newvx2=newvx1
EndIf
EndIf
If ycol=1
If flex1=0 And flex2=0
newvy1=((mass1-mass2)*vy1+2*mass2*vy2)/M
newvy2=((mass2-mass1)*vy2+2*mass1*vy1)/M
Else
newvy1=(mass1*vy1+mass2*vy2)/M
newvy2=newvy1
EndIf
EndIf
SelectElement(Thing(),index2)
If mob2=1
\newx=newx2
\newy=newy2
\newvx=newvx2
\newvy=newvy2
EndIf
index2+1
Until index2=CountList(Thing())
SelectElement(Thing(),index1)
If mob1=1
\newx=newx1
\newy=newy1
\newvx=newvx1
\newvy=newvy1
EndIf
index1+1
Until index1=CountList(Thing())-1
ResetList(Thing())
Repeat
NextElement(Thing())
\x=\newx
\y=\newy
\vx=\newvx
\vy=\newvy
\newx=0
\newy=0
\newvx=0
\newvy=0
Until CountList(Thing())-1=ListIndex(Thing())
EndProcedure
Procedure DisplayBack()
EndProcedure
Procedure DisplayOb()
ResetList(Thing())
Repeat
NextElement(Thing())
;If \type$="objet" Or \type$="vivant"
DisplayTransparentSprite(\sprite,\x,\y)
;EndIf
Until CountList(Thing())-1=ListIndex(Thing())
EndProcedure
Procedure DisplayFore()
EndProcedure
;Chargement des caractéristiques de toutes les boîtes
Loading()
;Temps de départ
time=ElapsedMilliseconds()
;-Boucle principale
;Calcul du temps et gestion des procédures
Repeat
FlipBuffers()
ClearScreen(RGB(255,255,255))
;Temps écoulé depuis la dernière mesure
dt=(ElapsedMilliseconds()-time)/1000
;Nouvelle mesure du temps
time=ElapsedMilliseconds()
;Record de temps écoulé entre deux mesures
If max<dt
max=dt
EndIf
;Calcul du déplacement des boîtes
MoveOb()
;Affichage de l'arrière-plan (vide)
DisplayBack()
;Affichage des objets
DisplayOb()
;Affichage du premier plan (vide)
DisplayFore()
;Affichage du temps
If StartDrawing(ScreenOutput())<>#Null
DrawText(20,20,"time="+StrF(time/1000,3)+" sec ; dt="+StrF(dt,3)+" sec ; dt(max)="+StrF(max,3)+" sec")
StopDrawing()
EndIf
;Touche "échap" pour arrêter le programme
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
EndWith