Effet Torche ?!

Programmation avancée de jeux en PureBasic
Mytic
Messages : 466
Inscription : mer. 25/juil./2007 0:13

Effet Torche ?!

Message par Mytic »

Je veux crée l’effet de torche.
Alors j’ai crée ce bout de Code, mais le problème c’est qu’il est très lent !!
Y’a-t-il un moyen de l’optimisé ?
:?

Code : Tout sélectionner

UseJPEGImageDecoder()
UsePNGImageDecoder()

InitSprite()
InitScreen()
InitMouse()
InitKeyboard()

Structure info
x.d
y.d
couleur.l
EndStructure

Global Dim pixel.info(99999)
;----------(changez l'image par une dans votre DD de préférence 500x500 ou plus)
LoadImage(0,"c:\image.jpg")

OpenWindow(0,0,0,500,500,"teste")
OpenWindowedScreen(WindowID(0),0,0,500,500,0,0,0)
FlipBuffers()


Repeat

;ClearScreen(0)
ExamineMouse()
posx = MouseX()
posy = MouseY()
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape)
End
EndIf

If posx <> bpx And posy <> bpy
ClearScreen(0)
StartDrawing(ImageOutput(0))
bpx = posx
bpy = posy
i = 0
For r = 0 To 80
For a = 0 To 450
an.d = a / 70
x.d = Sin(an)
y.d = Cos(an) 
x = x * r  + posx
y = y * r + posy
If (x > 1) And (y > 1) And (x < 490) And (y < 490)
coul = Point(x,y)
ro = Red(coul)-r*3
g = Green(coul)-r*3
b = Blue(coul)-r*3
If ro < 0:ro = 0:EndIf
If g < 0:g = 0:EndIf
If b < 0:b = 0:EndIf
coulf = RGB(ro,g,b)
pixel(i)\x = x
pixel(i)\y = y
pixel(i)\couleur = coulf
max = i
i = i + 1
EndIf
Next a
Next r
StopDrawing()


StartDrawing(ScreenOutput())
For n = 0 To max
Plot(pixel(n)\x,pixel(n)\y,pixel(n)\couleur)
Next n
StopDrawing()
FlipBuffers()
EndIf

event = WindowEvent()
Until event = #PB_Event_CloseWindow
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Je vais pas te faire un cours, mais moins tu auras d'instructions dans la boucle principale, plus ce sera rapide. Sers-toi de tableaux pour mémoriser les valeurs au lieu de l'écran. Essaie d'éviter les tests en étudiant comment se comporte ton programme. En dernier recours, tu pourras remplacer plot par une fonction plus rapide.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

tiens !!
juste pour te rapeller que c'est la fonction POINT() qui est lente
pas plot() !!

Code : Tout sélectionner

UseJPEGImageDecoder()
UsePNGImageDecoder()

InitSprite()

InitMouse()
InitKeyboard()

Structure info
  x.d
  Y.d
  Couleur.l
EndStructure

Global Dim pixel.info(99999)
Global Dim tableau(500,500)
;----------(changez l'image par une dans votre DD de préférence 500x500 ou plus)
LoadImage(0,"D:\Mes_Photos\SV101293.JPG")

OpenWindow(0,0,0,500,500,"teste")
OpenWindowedScreen(WindowID(0),0,0,500,500,0,0,0)
FlipBuffers()

; met l'image en tableau pour accelerer le traitement !!
; et evite le point() pendant la boucle !! 
StartDrawing(ImageOutput(0))
For y1=0 To 500
  For x1=0 To 500
    tableau(x1,y1)=Point(x1,y1)  
  Next x1
Next y1
StopDrawing()


Repeat
  
  ;ClearScreen(0)
  ExamineMouse()
  posx = MouseX()
  posy = MouseY()
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape)
    End
  EndIf
  
  If posx <> bpx And posy <> bpy
    ClearScreen(0)
    StartDrawing(ImageOutput(0))
    bpx = posx
    bpy = posy
    i = 0
    For r = 0 To 80
      For a = 0 To 450
        an.d = a / 70
        x.d = Sin(an)
        Y.d = Cos(an)
        x = x * r  + posx
        Y = Y * r + posy
        x1.l=x
        y1.l=Y
        If (x > 1) And (Y > 1) And (x < 490) And (Y < 490)
          coul =  tableau(x1,y1)  ; <------------------------------- ici on a remplacé le point() par une lecture tableau, beaucoup plus rapide !!
          ro = Red(coul)-r*3
          g = Green(coul)-r*3
          b = Blue(coul)-r*3
          If ro < 0:ro = 0:EndIf
          If g < 0:g = 0:EndIf
          If b < 0:b = 0:EndIf
          coulf = RGB(ro,g,b)
          pixel(i)\x = x
          pixel(i)\Y = Y
          pixel(i)\Couleur = coulf
          max = i
          i = i + 1
        EndIf
      Next a
    Next r
    StopDrawing()
    
    
    StartDrawing(ScreenOutput())
    For n = 0 To max
      Plot(pixel(n)\x,pixel(n)\Y,pixel(n)\Couleur)
    Next n
    StopDrawing()
    FlipBuffers()
  EndIf
  
  Event = WindowEvent()
  Delay(2)
Until Event = #PB_Event_CloseWindow   
Dernière modification par Backup le mar. 25/sept./2007 12:44, modifié 1 fois.
Mytic
Messages : 466
Inscription : mer. 25/juil./2007 0:13

Message par Mytic »

En effet ! Avec un tableau c’est déjà plus rapide.
Merci… Dobro & Djes
(Je devrai réorganiser mon Code, vu que l’IDE de PureBasic ne le fait pas automatiquement)

Une autre petite question ?!
Si faire ça ! demande toute la puissance du microprocesseur pour à la fin donner des résultats pas très concluants !!
Comment font les développeurs de jeux vidéo pour créer tout un monde avec plein d’effets de ce genre + une I.A et ça tourne à 50-70 Fps voir plus ?

Ça n’aurait pas par hasard un rapport avec la programmation directe sur Carte graphique ?
:idea:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Mytic a écrit : Une autre petite question ?!
Si faire ça ! demande toute la puissance du microprocesseur pour à la fin donner des résultats pas très concluants !!
heu ! tu part mal la !! :)

ou ça prends toute la puissance du processeur ?? 8O

c'est facile d'accuser le purebasic, au lieu de se remettre en question !! :D

tel quel (ma version de ton prg ) prends 48 en temps machine .. pourquoi ??

parcequ'apres un

Code : Tout sélectionner

Event = WindowEvent()
il faut toujour faire suivre d'un Delay(2) !!
cela permet au purebasic de rendre la main au system !!

Delay(2) est comparable a "Do EVENTs" en Visual Basic !!

donc apres la ligne 87 met :

Code : Tout sélectionner

Event = WindowEvent()
  Delay(2)
Until Event = #PB_Event_CloseWindow 
et voila plus de temps machine du tout !! :lol:
Patrick88
Messages : 1564
Inscription : mer. 21/janv./2004 18:24

Message par Patrick88 »

les routines "sensiblent" sont peut-être codées en assembleur...

pat
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Patrick88 a écrit :les routines "sensiblent" sont peut-être codées en assembleur...

pat
je te rapel que coder en purebasic c'est implicitement coder en assembleur !! :D
Mytic
Messages : 466
Inscription : mer. 25/juil./2007 0:13

Message par Mytic »

Je n’ai en aucun cas accusé PureBasic ! Au contraire je l’aime entre guillemets. :lol:
Ce que je voulais dire, c’est que les programmeurs de jeux vidéo ont une technique spéciale pour ce genre d’effets.
Ils partagent peut être la tache entre le microprocesseur et celui de la carte graphique ? (Supposition)

:?:
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Ne mélangez pas tout! Vous travaillez effectivement sur un système multitâches, où tous les programmes se partagent les ressources, et donc le processeur. Ce n'est pas en mettant un delay que le processeur travaillera moins, c'est juste qu'il y aura plus de temps pour les autres applications, donc moins pour la vôtre (puisque vous l'aurez mise en pause pour un certain temps).

Dans le cas d'un effet, le but n'est pas de partager les ressources, mais d'exploiter celles qui nous sont fournies au maximum. Avec purebasic, tu as les mêmes possibilités qu'avec n'importe quel autre langage, plus des instructions "faciles d'emploi" pour exploiter la carte graphique, la carte son et autres Après, c'est à toi d'apprendre à les agencer de la meilleure façon possible pour que ça soit fluide.

Par exemple, dans ton code, je vois plein de choses qui pourraient être améliorées et qui le rendraient beaucoup plus rapide. On pourrait *multiplier* sa vitesse très facilement! Même si ça ne sert à rien parce qu'à la base il est mal conçu puisqu'à mon sens il fonctionne à l'envers (mais ça, tu n'es pas encore assez expérimenté pour le voir). En outre, on peut faire aussi bien (et plus rapide) avec la carte graphique.

Des exemples bien sûr!

Je ne passe pas sur les boucles qui vont trop loin : de 0 à 80, ça fait 81, attention! Soit tu vas de 0 à 79, soit de 1 à 80.

Utilisation des doubles : précis, mais lent, surtout si tu veux que ton programme tourne partout.

x=sin(an)*r+posx-> tout ça tu peux le mettre dans un tableau, puisque c'est toujours la même chose.

If bla bla . Ce test est répété 81*451 fois (comme tout le reste d'ailleurs!), avec quatre conditions! Ca représente beaucoup d'instructions, c'est énorme! si tu pouvais éviter, ce serait mieux. Mais quelquefois ce n'est pas possible.

ro=Red(bla)... tout ça tu peux le mettre dans un tableau aussi. Les multiplications sont très lentes. L'appel aux fonctions Red(), green(), blue(), rgb() à chaque fois est à éviter.

Utilisation des structures. Joli code, mais lent. Il faut choisir, parfois il vaut mieux être un peu plus lent mais avoir un code "propre".

Bonne optim' :)
Avatar de l’utilisateur
case
Messages : 1545
Inscription : lun. 10/sept./2007 11:13

Message par case »

ben heuu avec des sprites3D par exemple :p


Image
Image
Image

Code : Tout sélectionner

InitSprite() 
InitSprite3D()
InitMouse() 
OpenWindow(0,0,0,800,600,"torche")
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)
UsePNGImageDecoder()
fond=LoadImage(0,"nénuphars.png") 				; charge l'image de fond
;buffer=CreateImage(1,800,600)					; cree une image pour le rendu
mask=LoadSprite(1,"test2.png")					;charge le masque
TransparentSpriteColor(1,RGB(255,0,255))
LoadSprite(0,"test.png",#PB_Sprite_Texture)		; charge le sprite 3D
CreateSprite3D(0,0)		
Start3D()
Repeat
	Repeat
    	Event = WindowEvent()
        Select Event 
        Case #PB_Event_Gadget
      		If EventGadget() = 0
            	Stop3D()
            	End
            	
          	EndIf
        Case #PB_Event_CloseWindow
        Stop3D()
          	End
      	EndSelect
    Until Event = 0
    ExamineMouse()    
    ClearScreen(RGB(0,0,0))
	temp=GrabImage(0,1,MouseX(),MouseY(),64,64)
	StartDrawing(ScreenOutput())
	DrawImage(temp,MouseX(),MouseY())
	StopDrawing()
	DisplayTransparentSprite(1,MouseX(),MouseY())	
	Sprite3DBlendingMode(3,9)
	DisplaySprite3D(0,MouseX(),MouseY())	
	FreeImage(1)
	
FlipBuffers()
ForEver
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Et... Sans les Sprites 3D ! ! ! !
Putain case, on ne peut pas faire une grasse mat avec toi :D
Excellent...

Code : Tout sélectionner

Mise à jour du code plus bas...
Dernière modification par Ollivier le mar. 25/sept./2007 14:13, modifié 1 fois.
Mytic
Messages : 466
Inscription : mer. 25/juil./2007 0:13

Message par Mytic »

@Djes
Merci Djes pour tes conseils précieux, parfois l’utilisation des tableaux résout l’affaire.

@case
Ton code marche à merveille, (je n’ai pas exploité le potentiel des sprites 3D)
Merci…

@Ollivier
Tu utilises la lumière d’un projecteur là ! Pas une torche :D
Mais t’as façon de procéder est vraiment intéressante (A étudier de plus près).

@ !????
C’est sympa de voir que chaque cerveau à une façon unique de procéder.
Je devrai les clonés et faire une mise à jour de mon Firmewar
:lol:
Avatar de l’utilisateur
case
Messages : 1545
Inscription : lun. 10/sept./2007 11:13

Message par case »

Ollivier a écrit :Et... Sans les Sprites 3D ! ! ! !
Putain case, on ne peut pas faire une grasse mat avec toi :D
Excellent...
ton pc te reveille quand on post sur le forum ? :p


bon sinon ton effet est plus joli bravo :)

/em vas etudier ce code
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Vienw on va buter des geons dons la forét!

Code : Tout sélectionner



Structure APIC
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
; (BBL V0.08)
; Structure permettant de gérer un BitMap créé par l'API pointé par ABmp
; et d'y accéder grâce l'imageID 
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
    ID.L      ; ID de l'image
    pBmp.L    ; (Pointeur 32 bits) Pointeur d'accès direct à l'image
    W.L       ; Largeur de l'image
    H.L       ; Hauteur de l'image

EndStructure



Macro Argb(A, R, G, B) 

    ((((A << 24) + (R << 16) ) + (G << 8) ) + B) 
    
EndMacro 



Procedure DrawLocate(*Buffer.APIC, x.L, y.L) 

      With *Buffer
      
            *Adr = \pBmp + (((y * \W) + x) * 4)
            
      EndWith

      ProcedureReturn *Adr 
EndProcedure 



Procedure CreateAlphaImage(*Buffer.APIC, W.L, H.L) 
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
; (BBL V0.08)
; Crée une zone mémoire pour l'édition d'une image Alpha 
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
; Entrées *H (Structure ADESS)
; ¯¯¯¯¯¯¯ W (LONG) Largeur de l'image 
;         H (LONG) Hauteur de l'image
;
; Sortie Le buffer est modifié notamment le pointeur d'accès direct à 
; ¯¯¯¯¯¯ l'image pBmp
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 

      With *Buffer
      
            \W = W
            \H = H
            \pBmp = AllocateMemory((\W * \H) << 2) 
            
      EndWith
    
EndProcedure 



Procedure CatchAlphaImage(*Buffer.APIC) 
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
; (BBL V0.08)
; Crée une image Alpha de 32 bits de profondeur à partir d'une zone mémoire 
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
; Entrée Adresse pointant sur l'image 
; ¯¯¯¯¯¯ 
; Sortie Retourne le handle de l'image (= ImageID) 
; ¯¯¯¯¯¯ 
; Remarque >> Cette fonction s'exécute APRES CreateAlphaImage()
; ¯¯¯¯¯¯¯¯ 
;____________________________________________________________________________ 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯    
    
      With *Buffer
      
            \ID = CreateBitmap_(\W, \H, 1, 32, \pBmp)
            
      EndWith

EndProcedure 



Procedure InitPlugIn()
      UseJPEGImageDecoder() 
      UsePNGImageDecoder() 
      InitSprite() 
      InitMouse() 
      InitKeyboard() 
EndProcedure



Procedure InitDatas()
      LoadImage(0,Left(GetHomeDirectory(), 1) + ":\Windows\Web\Wallpaper\Automne.JPG")
EndProcedure



Procedure InitDisplay(W.L, H.L)
      OpenWindow(0, 0, 0, W, H, "teste") 
      OpenWindowedScreen(WindowID(0), 0, 0, W, H, 0, 0, 0) 
      FlipBuffers()      
EndProcedure



Procedure Init(X.L, Y.L)
      InitPlugIn()
      InitDisplay(X, Y)
      InitDatas()
EndProcedure



Procedure Main(W.L, H.L, Size.L)

      Init(W, H)
      
      Sombre.APIC
      
      CreateAlphaImage(Sombre, Size, Size)
      
      For y = 0 To Size - 1
      
            For x = 0 To Size - 1
            
                  dx = x - Size >> 1
                  dy = y - Size >> 1
                  dx * dx
                  dy * dy
                  Dist.F = Sqr(dx + dy)
                  Dist = (Dist * 255.0) / (Size / 2.0)
                  If (Dist <= 0.0): Dist = 1: EndIf
                  If (Dist > 255.0): Dist = 255: EndIf
                  C.L = Dist
                  C & $FF
                  C << 24
                  PokeL(DrawLocate(Sombre, x, y), C)
            
            Next
            PokeL(DrawLocate(Sombre, Size / 2, y), $FF000000)
      Next
      For x = 0 To Size - 1
            PokeL(DrawLocate(Sombre, x, Size / 2), $FF000000)
      Next
                 
      CatchAlphaImage(Sombre)
      
      Repeat
            AMx = Mx
            AMy = My 
            ExamineMouse()
            Mx = MouseX() 
            My = MouseY() 
            ExamineKeyboard() 
            If KeyboardPushed(#PB_Key_Escape) 
                  End 
            EndIf 
            If (AMx <> Mx) Or (AMy <> My)
                  GrabImage(0, 1, Mx, My, Size, Size)
                  StartDrawing(ScreenOutput())
                        Box(AMx, AMy, Size, Size, #Black)
                        DrawImage(ImageID(1), Mx, My)
                        DrawAlphaImage(Sombre\ID, Mx, My)
                  StopDrawing() 
                  FlipBuffers() 
            EndIf
            Event = WindowEvent() 
            Delay(5)
      Until Event = #PB_Event_CloseWindow  

EndProcedure


      Main(800, 500, 200)



     
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Par contre, ce qu'il est intéressant de voir, vu que je n'ai pas encore téléchargé les images de case, c'est de savoir lequel des codes bouffe en ressources CPU (le mien est assez gourmand).

Ollivier
Répondre