Ciel qui change en fonction du temps qui passe (Jour/Nuit)

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Ciel qui change en fonction du temps qui passe (Jour/Nuit)

Message par Thyphoon »

Voici un code qui permet dans mon jeu d'avoir le ciel qui change avec le temps qui passe. Levé de soleil, ciel bleu, couché de soleil, nuit etc...
ça s'écoule doucement (10 minutes par étape je pense)
Le PB c'est que je voudrais réussir a faire le fondu des images un peu plus rapide (mais sans que ça se remarque) et je voudrais surtout que ça prennent moins de ressource car ça bouffe vachement de temps machine ... quelqu'un a une idée ?

Image 1
Image 2
Image 3
Image 4

Code : Tout sélectionner

#Window = 0
#Width = 640
#Height = 480
;- Init DirectX
If InitSprite() = 0 Or InitSprite3D() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
  MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0)
  CloseWindow(#Window) : End
EndIf

res = OpenWindow(#Window, 0, 0, #Width, #Height, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "")
OpenWindowedScreen(res, 0, 0, 800, 600, 0, 0, 0)
; OpenScreen( #Width , #Height , 32 , "M3D_Matrix3D" )
; Préparation de la structure des projectils

UsePNGImageDecoder()
LoadSprite(1, "data/env/p_daysky.png", 0)
LoadSprite(2, "data/env/p_sunset.png", 0)
LoadSprite(3, "data/env/p_nightsky.png", 0)
LoadSprite(4, "data/env/p_sunrise.png", 0)
CreateSprite(10, 640, 480)
CreateSprite(11, 640, 480)
CopySprite(1, 11)
Global Paysage_x
Global Paysage_y
Global Paysage_scroll
Global Paysage_id1
Global Paysage_id2
Global fad
Global waitpaysage
Paysage_id1 = 1
Paysage_id2 = 2
Dim Col1s(400)
Dim Col2s(400)

Procedure paysage()
  If ElapsedMilliseconds() > waitpaysage
    waitpaysage = ElapsedMilliseconds() + 100
    Paysage_scroll = Paysage_scroll + 1
  EndIf
  If Paysage_scroll = 640 : Paysage_scroll = 0 : EndIf
  
  Paysage_x = Paysage_x + 1
  If Paysage_x > 640
    Paysage_y = Paysage_y + 1
    Paysage_x = 0
    fad = fad + 2
    If fad > 255
      fad = 0
      Paysage_id1 = Paysage_id1 + 1
      Paysage_id2 = Paysage_id1 + 2
      If Paysage_id1 > 4 : Paysage_id1 = 1 : EndIf
      If Paysage_id2 > 4 : Paysage_id2 = 1 : EndIf
    EndIf
  EndIf
  
  
  StartDrawing(SpriteOutput(Paysage_id1))
    For z = 1 To 400
      Col1s(z) = Point(Paysage_x, z)
    Next
  StopDrawing()
  StartDrawing(SpriteOutput(Paysage_id2))
    For z = 1 To 400
      Col2s(z) = Point(Paysage_x, z)
    Next
  StopDrawing()
  StartDrawing(SpriteOutput(11))
    For z = 1 To 400
      r1 = Red(Col1s(z))
      v1 = Green(Col1s(z))
      b1 = Blue(Col1s(z))
      r2 = Red(Col2s(z))
      v2 = Green(Col2s(z))
      b2 = Blue(Col2s(z))
      r3 = r1 - fad * (r1 - r2) / 255
      v3 = v1 - fad * (v1 - v2) / 255
      b3 = b1 - fad * (b1 - b2) / 255
      Plot (Paysage_x, z, RGB(r3, v3, b3))
    Next
    
    
    
  StopDrawing()
  
  DisplaySprite(11, (0 - Paysage_scroll), 0)
  DisplaySprite(11, (640 - Paysage_scroll), 0)
EndProcedure


Repeat
  
  If f > 255 : f = 0 : EndIf
  FlipBuffers()
  ClearScreen(0, 0, 0)
  paysage()
  While WindowEvent() : Wend ; evite le plantage clic gauche
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

et simplement avec des DisplayTranslucideSprite() ?
on superpose 2 images, une sans transparence qui est l'étape actuelle de la journée et la suivante en transparence au dessus de l'autre avec un DisplayTranslucideSprite()
par contre, au niveau perf, je ne sais pas ce que ça donne
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Oui c'était une très bonne idée ! DisplayTranslucideSprite() je n'y avait absolument pas pensé !!(lolllllllllll trop nul le Thyphoon... :P ) dire que je me suis arraché les cheveux pour pondre mon code alors qu'en 2 minutes ça aurait pu être fait !
Parcontre il m'arrive un truc currieux avec un SpecialFX()
Lorsque j'affiche un sprite il se trouve décalé de 640 pixel en horizontal... Peut être un bug a moi... je vais regardé et je posterais mon nouveau code ce soir ! En tout cas c'est infiniment plus rapide que ce que j'avais pond la première fois ! Merci Soldat Inconnu (pas si inconnu que ça) Defenseur de la veuve et du debutant en purebasic :lol:
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

voilà le nouveau code beaucoup plus rapide mais j'ai un bug que je ne m'explique pas !
Ligne 60 et 61 ça bug
en théorie on devrait avoir
DisplaySprite(601,(0- Paysage_scroll),0)
DisplaySprite(601,(640- Paysage_scroll),0)
mais lorsqu'on fait ça plus rien n'apparait a l'ecran !
et si on fait
DisplaySprite(601,(0- Paysage_scroll),0)
;DisplaySprite(601,(640- Paysage_scroll),0)
Alors leça commence sur du noir mais l'image finit par arriver... seulement decalé de 640 pixel horizontalement ...bref je trouve ça tres tres curieux... Surtout que si on désactive les SpecialFX() ça marche très bien mais c'est super lent ! Enfin voilà le code

Code : Tout sélectionner

#Window = 0
#Width = 640
#Height = 480
;- Init DirectX
If InitSprite() = 0 Or InitSprite3D() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
  MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0)
  CloseWindow(#Window) : End
EndIf

res = OpenWindow(#Window, 0, 0, #Width, #Height, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "")
OpenWindowedScreen(res, 0, 0, 800, 600, 0, 0, 0)
; OpenScreen( #Width , #Height , 32 , "M3D_Matrix3D" )
; Préparation de la structure des projectils

UsePNGImageDecoder()
LoadSprite(1, "data/env/p_daysky.png", #PB_Sprite_Memory )
LoadSprite(2, "data/env/p_sunset.png", #PB_Sprite_Memory )
LoadSprite(3, "data/env/p_nightsky.png", #PB_Sprite_Memory )
LoadSprite(4, "data/env/p_sunrise.png", #PB_Sprite_Memory )
LoadSprite(10, "data/env/lune.png", 0)
CreateSprite(601, 640,480)
Global Paysage_x
Global Paysage_y
Global Paysage_scroll
Global Paysage_id1
Global Paysage_id2
Global fad
Global waitpaysage
Paysage_id1 = 1
Paysage_id2 = 2
Dim Col1s(400)
Dim Col2s(400)
TransparentSpriteColor(-1, 255, 0, 255)
Procedure paysage()
  If ElapsedMilliseconds() > waitpaysage
    waitpaysage = ElapsedMilliseconds() + 200
    Paysage_scroll = Paysage_scroll + 1
  EndIf
  If Paysage_scroll = 640 : Paysage_scroll = 0 : EndIf
  

    fad = fad + 10
    If fad > 255
      fad = 0
      Paysage_id1 = Paysage_id1 + 1
      Paysage_id2 = Paysage_id2 + 1
      If Paysage_id1 > 4 : Paysage_id1 = 1 : EndIf
      If Paysage_id2 > 4 : Paysage_id2 = 1 : EndIf
    EndIf

  
  
  UseBuffer(601)
  StartSpecialFX() 
  DisplaySprite(Paysage_id1,0 ,0)
  DisplayTranslucideSprite(Paysage_id2,0,0, fad)
  StopSpecialFX()
  UseBuffer(-1)
   
   DisplaySprite(601,(0- Paysage_scroll),0)
   ;DisplaySprite(601,(640- Paysage_scroll),0)
   
EndProcedure


Repeat
  
  If f > 255 : f = 0 : EndIf
  FlipBuffers()
  ClearScreen(0, 0, 0)
  z=ElapsedMilliseconds()
  paysage()
  ;Debug(Str(ElapsedMilliseconds()-z))

    ;- FPS:
    If Val(FormatDate("%ss", Date())) = sek
      FPS + 1
    Else
      FPS$ = Str(FPS)
      FPS = 0
    EndIf
    sek = Val(FormatDate("%ss", Date()))
    
    StartDrawing(ScreenOutput())
      DrawingMode(1)
      FrontColor(255, 255, 255)
      Locate(1, 1)
      DrawText("FPS: " + FPS$ + " Scroll :"+Str(Paysage_scroll))
    StopDrawing()
  While WindowEvent() : Wend ; evite le plantage clic gauche
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Bon je t'avoue tout de suite que j'y connais rien sur les commandes 2d,3d

Mais bon, il m'apparaît plus que normal que l'affichage soit noir lorsque tu utilises ces deux lignes en même temps:

Code : Tout sélectionner

  DisplaySprite(601,(0- Paysage_scroll-200),0)
  DisplaySprite(601,(600- Paysage_scroll),0)


puisque le premier affiche un sprite noir qui part de 640 (tout l'écran) et rétrécie vers la gauche au rythme de Paysage_scroll, alors que le deuxième démarre de la droite et s'étend vers la gauche, autrement dit exactement le contraire avec le même point de départ!


Pour s'en rendre compte, il suffit de décaler le changer le point de départ du premier sprite:

Code : Tout sélectionner

  DisplaySprite(601,(0- Paysage_scroll-200),0)
  DisplaySprite(601,(600- Paysage_scroll),0) 
DisplaySprite(601,(0- Paysage_scroll),0)
;DisplaySprite(601,(640- Paysage_scroll),0)
Alors leça commence sur du noir mais l'image finit par arriver... seulement decalé de 640 pixel
ça fait ça parce que tu l'as programmé comme ça :lol:

:)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

héhé !! non, non je l'ai pas programmé comme ça

Histoire de voir le problème
execute le programme avec puis sans le StartSpecialFx() tu comprendra ce que je veux dir e!
En tout cas un grand merdi de jeter un oeil c'est sympa !

Code : Tout sélectionner

#Window = 0
#Width = 640
#Height = 480
;- Init DirectX
If InitSprite() = 0 Or InitSprite3D() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
  MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0)
  CloseWindow(#Window) : End
EndIf

res = OpenWindow(#Window, 0, 0, #Width, #Height, #PB_Window_TitleBar | #PB_Window_ScreenCentered, "")
OpenWindowedScreen(res, 0, 0, 800, 600, 0, 0, 0)
; OpenScreen( #Width , #Height , 32 , "M3D_Matrix3D" )
; Préparation de la structure des projectils

UsePNGImageDecoder()
LoadSprite(1, "data/env/p_daysky.png", #PB_Sprite_Memory )
LoadSprite(2, "data/env/p_sunset.png", #PB_Sprite_Memory )
LoadSprite(3, "data/env/p_nightsky.png", #PB_Sprite_Memory )
LoadSprite(4, "data/env/p_sunrise.png", #PB_Sprite_Memory )
LoadSprite(10, "data/env/lune.png", 0)
CreateSprite(601, 640,480)
Global Paysage_x
Global Paysage_y
Global Paysage_scroll
Global Paysage_id1
Global Paysage_id2
Global fad
Global waitpaysage
Paysage_id1 = 1
Paysage_id2 = 2
Dim Col1s(400)
Dim Col2s(400)
TransparentSpriteColor(-1, 255, 0, 255)
Procedure paysage()
  If ElapsedMilliseconds() > waitpaysage
    waitpaysage = ElapsedMilliseconds() + 200
    Paysage_scroll = Paysage_scroll + 1
  EndIf
  If Paysage_scroll = 640 : Paysage_scroll = 0 : EndIf
  

    fad = fad + 10
    If fad > 255
      fad = 0
      Paysage_id1 = Paysage_id1 + 1
      Paysage_id2 = Paysage_id2 + 1
      If Paysage_id1 > 4 : Paysage_id1 = 1 : EndIf
      If Paysage_id2 > 4 : Paysage_id2 = 1 : EndIf
    EndIf

  
  
  UseBuffer(601)
  ;StartSpecialFX() 
  DisplaySprite(Paysage_id1,0 ,0)
  DisplayTranslucideSprite(Paysage_id2,0,0, fad)
  ;StopSpecialFX()
  UseBuffer(-1)
   
   DisplaySprite(601,(0- Paysage_scroll),0)
   DisplaySprite(601,(640- Paysage_scroll),0)
   
EndProcedure


Repeat
  
  If f > 255 : f = 0 : EndIf
  FlipBuffers()
  ClearScreen(0, 0, 0)
  z=ElapsedMilliseconds()
  paysage()
  ;Debug(Str(ElapsedMilliseconds()-z))

    ;- FPS:
    If Val(FormatDate("%ss", Date())) = sek
      FPS + 1
    Else
      FPS$ = Str(FPS)
      FPS = 0
    EndIf
    sek = Val(FormatDate("%ss", Date()))
    
    StartDrawing(ScreenOutput())
      DrawingMode(1)
      FrontColor(255, 255, 255)
      Locate(1, 1)
      DrawText("FPS: " + FPS$ + " Scroll :"+Str(Paysage_scroll))
    StopDrawing()
  While WindowEvent() : Wend ; evite le plantage clic gauche
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
donc là version lente mais qui fonctionne et ensuite version sois disante plus rapide mais qui ne fonctionne pas du tout
il te suffite de corriger par ces lignes là

Code : Tout sélectionner

  StartSpecialFX() 
  DisplaySprite(Paysage_id1,0 ,0)
  DisplayTranslucideSprite(Paysage_id2,0,0, fad)
  StopSpecialFX()
Si tu veux quand même voir quelques chose lorque StartSpecialFx est actionné corrige avec ça

Code : Tout sélectionner

 
   ;DisplaySprite(601,(0- Paysage_scroll),0)
   DisplaySprite(601,(640- Paysage_scroll),0)
El là l'image arrivé !
le principe est simple une image qui boucle sur elle même donne un impression que les nuages bouges !
Alors tu vois le problème ou je suis pas tres claire ? (foncé ? :lol: )
filperj
Messages : 395
Inscription : jeu. 22/janv./2004 1:13

Message par filperj »

Je crois qu' en fait le problème c'est que specialFX et UseBuffer se marient mal, j'ai essayé comme ça:

Code : Tout sélectionner

;UseBuffer(601)
  StartSpecialFX()
  DisplaySprite(Paysage_id1,0-paysage_scroll ,0)
  DisplayTranslucideSprite(Paysage_id2,0-paysage_scroll,0, fad)
  StopSpecialFX()
  ;UseBuffer(-1)
Le chaos l'emporte toujours sur l'ordre
parcequ'il est mieux organisé.
(Ly Tin Wheedle)
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Désolé, quand je vous disais que je ne connaissait pas! :lol:


Bon, j'ai fait ça, je ne sais pas ce que ça vaut:

Code : Tout sélectionner

Procedure paysage() 
  If ElapsedMilliseconds() > waitpaysage 
    waitpaysage = ElapsedMilliseconds() + 200 
    Paysage_scroll = Paysage_scroll + 1 
  EndIf 
  If Paysage_scroll = 640 : Paysage_scroll = 0 : EndIf 
  
  
  fad = fad + 5 
  If fad > 255 
    fad = 0 
    Paysage_id1 = Paysage_id1 + 1 
    Paysage_id2 = Paysage_id2 + 1 
    If Paysage_id1 > 4 : Paysage_id1 = 1 : EndIf 
    If Paysage_id2 > 4 : Paysage_id2 = 1 : EndIf 
  EndIf 
   
  UseBuffer(601)
  StartSpecialFX()
  DisplayTranslucideSprite(Paysage_id1,(0-Paysage_scroll),0, 255)
  DisplayTranslucideSprite(Paysage_id2,(0-Paysage_scroll),0, fad)
  DisplayTranslucideSprite(Paysage_id1,(600-Paysage_scroll),0, 255)
  DisplayTranslucideSprite(Paysage_id2,(600-Paysage_scroll),0, fad) 
  StopSpecialFX() 
EndProcedure 
Je serais pas étonné d'être complètement à coté de la plaque. :lol:
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

merci Nico et filperj

je constate qu'on arrive tous plus ou moins a la même conclusion ! Suppression de UseBuffer.
Donc c'est ce que je vais faire.
En vérité le pb c'est que cette procedure lorsqu'elle fonctionne fait passer le jeu que je prépare de 59 images/sec a 29 images/sec... Donc Elle reste assez lourde mais je crain qu'on ne puisse pas y faire grand chose !
Donc merci enormement pour le coup de main ! et si un jour vous trouvez une meilleur solution pour ce genre d'effet n'hesitez pas
Répondre