J'ai fait un essai avec ton code
Chez moi le FPS est à 17.
Si j'enlève le test de l'obstacle, le FPS monte à 25.
;Obstacle=PeekL(Surface(#Mask)\Address+x*4+Surface(#Map)\Pitch*y)
Alors j'ai essayé avec un cercle et le lancer de rayon sur un cercle, et le FPS reste à 25 et l'obstacle est bien pris en compte.
Si ça t'intéresse je peux te filer le code pour le calcul de l'intersection d'un rayon et d'une boite, apparemment c'est ce que tu utilises dans ton code.
Faudrait que je complète ma procédure, elle ne calcule pas le point d'intersection parce que je n'en avais pas besoin, mais je peux l'ajouter.
bien sûr , ici il n'y a qu'un obstacle, quand il y en aura plusieurs, il faudra faire une boucle, le FPS risque d'en prendre un coup aussi ?
Enfin il y a de la marge par rapport à ton test à chaque pixel , j'ai gagné 8 points, presque 1/3 .
Code : Tout sélectionner
If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0
MessageRequester("Error","DirectX 7+ is needed.",0)
EndIf
Global ScreenWidth.l,ScreenHeight.l
ScreenWidth=640
ScreenHeight=480
Enumeration
#Screen
#Map
#Mask
#Buffer
EndEnumeration
;Constante
#Rad=2*3.1415/360
Structure Surface
*Address.l
Pitch.l
PixelFormat.l
Width.l
Height.l
EndStructure
Structure s_Vecteur
x.f
y.f
EndStructure
Structure s_Sphere
Origine.s_Vecteur
Rayon.f
DistanceCarre.f
EndStructure
Structure s_Rayon
;Informations dans R3
Origine.s_Vecteur
Direction.s_Vecteur
;Informations collisions
CollisionDetectee.l
DistanceLaPlusCourte.f
PointIntersection.s_Vecteur
EndStructure
Macro SOUSTRACTION_VECTEUR(V, V1, V2)
V\x = V1\x - V2\x
V\y = V1\y - V2\y
EndMacro
Macro NORME_AU_CARRE(V)
(V\x * V\x + V\y * V\y)
EndMacro
Macro PRODUIT_SCALAIRE(V1, V2)
(V1\x * V2\x + V1\y * V2\y)
EndMacro
Global Dim Surface.Surface(10)
;IncludeFile("2d.pb")
OpenScreen(ScreenWidth, ScreenHeight, 32, "Aliens")
UsePNGImageDecoder()
LoadSprite(1,"image.png")
LoadSprite(2,"mask.png")
CreateSprite(3,640,480)
;Initialisation des différentes surfaces
StartDrawing(ScreenOutput())
Surface(#Screen)\Address=DrawingBuffer()
Surface(#Screen)\Pitch=DrawingBufferPitch()
Surface(#Screen)\PixelFormat=DrawingBufferPixelFormat()
Surface(#Screen)\Width=ScreenWidth
Surface(#Screen)\Height=ScreenHeight
StopDrawing()
StartDrawing(SpriteOutput(1))
Surface(#Map)\Address=DrawingBuffer()
Surface(#Map)\Pitch=DrawingBufferPitch()
Surface(#Map)\PixelFormat=DrawingBufferPixelFormat()
Surface(#Map)\Width=SpriteWidth(1)
Surface(#Map)\Height=SpriteHeight(1)
StopDrawing()
StartDrawing(SpriteOutput(2))
Surface(#Mask)\Address=DrawingBuffer()
Surface(#Mask)\Pitch=DrawingBufferPitch()
Surface(#Mask)\PixelFormat=DrawingBufferPixelFormat()
Surface(#Mask)\Width=SpriteWidth(2)
Surface(#Mask)\Height=SpriteHeight(2)
StopDrawing()
StartDrawing(SpriteOutput(3))
Surface(#Buffer)\Address=DrawingBuffer()
Surface(#Buffer)\Pitch=DrawingBufferPitch()
Surface(#Buffer)\PixelFormat=DrawingBufferPixelFormat()
Surface(#Buffer)\Width=SpriteWidth(3)
Surface(#Buffer)\Height=SpriteHeight(3)
StopDrawing()
Global Sphere.s_Sphere
Global Rayon.s_Rayon
Sphere\Origine\x = 350
Sphere\Origine\y = 300
Sphere\Rayon = 60
Procedure IntersectionRayonSphere()
Define.f RayonCarre, ProjectionOrthogonale
Define.f DistanceCentreRayon
Define.s_Vecteur RayonSphere
SOUSTRACTION_VECTEUR(RayonSphere, Sphere\Origine, Rayon\Origine)
Sphere\DistanceCarre = NORME_AU_CARRE(RayonSphere)
RayonCarre = Sphere\Rayon * Sphere\Rayon
;L'origine du rayon est à l'intérieur de la sphère
If Sphere\DistanceCarre <= RayonCarre
t.f = ProjectionOrthogonale + Sqr(RayonCarre - (Sphere\DistanceCarre - (ProjectionOrthogonale * ProjectionOrthogonale)))
Rayon\PointIntersection\x = Rayon\Origine\x + t * Rayon\Direction\x
Rayon\PointIntersection\y = Rayon\Origine\y + t * Rayon\Direction\y
ProcedureReturn #True
EndIf
;Projection orthogonale du centre de la sphère sur le rayon
ProjectionOrthogonale = PRODUIT_SCALAIRE(RayonSphere, Rayon\Direction)
If ProjectionOrthogonale < 0
ProcedureReturn #False
EndIf
;Calcul intermédiaire à faire dans une variable !
CalculIntermediaire.f = RayonCarre - (Sphere\DistanceCarre - (ProjectionOrthogonale * ProjectionOrthogonale))
If CalculIntermediaire < 0
ProcedureReturn #False
EndIf
t.f = ProjectionOrthogonale - Sqr(CalculIntermediaire)
Rayon\PointIntersection\x = Rayon\Origine\x + t * Rayon\Direction\x
Rayon\PointIntersection\y = Rayon\Origine\y + t * Rayon\Direction\y
ProcedureReturn #True
EndProcedure
Procedure Norme(*V.s_Vecteur)
Norme.f = Sqr(*V\x * *V\x + *V\y * *V\y)
If Norme= 0
*V\x = 0
*V\y = 0
Else
*V\x / Norme
*V\y / Norme
EndIf
EndProcedure
Procedure Light(LightX.l,LightY.l,Angle.l,Anglef.l,Puissance.l,Color.l)
Define Vecteur.s_Vecteur
Dim MemPlot.b(640,480) ; Un petit tableau pour verifier si la pixel au coordonée x et y du faisceau lumineux a déjà été traité
p = puissance
Rayon\Origine\x = LightX
Rayon\Origine\y = LightY
For i = -Anglef/2 To Anglef/2 Step 1
a.f=(i/2+Angle)
f.l=0
;Calcul des coordonées X et Y a traité
X = LightX + P * Cos(a*#Rad)
Y = LightY + P * Sin(a*#Rad)
Rayon\Direction\x = X-LightX
Rayon\Direction\y = Y-LightY
Norme(@Rayon\Direction)
If IntersectionRayonSphere()
Vecteur\x = Rayon\PointIntersection\x - LightX
Vecteur\y = Rayon\PointIntersection\y - LightY
Distance.f = Sqr(NORME_AU_CARRE(Vecteur))
If Distance > puissance
Distance = puissance
EndIf
Else
Distance = puissance
EndIf
For p = 0 To Int(Distance)
;Calcul des coordonées X et Y a traité
X = LightX + P * Cos(a*#Rad)
Y = LightY + P * Sin(a*#Rad)
;On verifie si on tombe sur un obstacle: col=0,0,0 pas d'obstacte / col=255,255,255 il y a un obstacle
;Obstacle=PeekL(Surface(#Mask)\Address+x*4+Surface(#Map)\Pitch*y)
If Obstacle=0 Or f<10 ;Si il n'ya pas d'obstacle alors on trace (col=0) / si f>0 c'est qu'on a trouvé un obstacle mais il faut l'illuminé
If Obstacle>0 Or f>0:f=f+1:EndIf ;Si on a trouvé un obstacle on l'illumine
If MemPlot(X,Y)=0 ; si cette pixel n'a pas été traité on la traite
;On verifie qu'on est bien dans les limites
If X>0 And X<Surface(#Buffer)\Width And Y>0 And Y<Surface(#Buffer)\Height
;Je prélève la couleur dans le buffer au cas ou une autre source lumineuse serait déjà dans le coin
colb=PeekL(Surface(#Buffer)\Address+x*4+Surface(#Map)\Pitch*y)
;Je prend la couleur dans le decor
col=PeekL(Surface(#Map)\Address+x*4+Surface(#Map)\Pitch*y)
If f=0 Or Obstacle=0
;si on a pas encore trouvé d'obstacle alors on calcul l'éclairage
;lightlevel=(Puissance-p)*255/Puissance
lightlevel=(((Puissance-p)*255/Puissance+(255*(Anglef/2-Abs(i))/Anglef/2))/2);ça donne la forme de la luminosité
Else
;si on a trouvé un obstacle on calcul l'illumination de cet objet
lightlevel=255-(f*255/10)
EndIf
;il faut qu'il y est un minimum d'éclairage pour aller plus loin
If lightlevel>1 And lightlevel<256
;Calcul de la couleur de la pixem
red=(Red(col)*Red(Color)*lightlevel)/65025
green=(Green(col)*Green(Color)*lightlevel)/65025
blue=(Blue(col)*Blue(Color)*lightlevel)/65025
;col=RGB(red,green,blue)
;Melange de faisceau lumineux
If Red(colb)>red:red=Red(colb):Else:red=red:EndIf
If Green(colb)>green:green=Green(colb):Else:green=green:EndIf
If Blue(colb)>blue:blue=Blue(colb):Else:blue=blue:EndIf
col=RGB(red,green,blue)
;Je mémorise que cette pixel a été traité pour ce faisceau là
MemPlot(X,Y)=1
;Hop on affiche dans le buffer le pixel
PokeL(Surface(#Buffer)\Address+x*4+Surface(#Buffer)\Pitch*y,col)
EndIf
EndIf
EndIf
Else
Break;
EndIf
Next p
Next i
EndProcedure
Repeat
UseBuffer(3)
ClearScreen(0)
UseBuffer(-1)
Light(250,250,A+120,90,150,RGB(255,255,255))
Light(400,200,-A,90,90,RGB(255,255,255))
Light(200,240,180+A,25,150,RGB(100,100,255))
Light(200,240,A,25,150,RGB(100,100,255))
;Trace()
A=A+1
If A>360:A=A-360:EndIf
ExamineKeyboard()
Delay(1)
If Val(FormatDate("%ss", Date()))=sek
FPS+1
Else
FPS$=Str(FPS)
Time$=Str(ElapsedMilliseconds()-Elapsetime)
FPS=0
EndIf
sek=Val(FormatDate("%ss", Date()))
;Affichage
DisplaySprite(3,0,0)
StartDrawing(ScreenOutput())
DrawingMode(1)
FrontColor(RGB(255,255,255))
DrawText(320,1,"FPS: "+FPS$+" Time:"+Time$)
Elapsetime=ElapsedMilliseconds()
;Circle(Sphere\Origine\x,Sphere\Origine\y,Sphere\Rayon,$FF0000)
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End