Page 1 sur 3
problème d'affichage
Publié : sam. 10/févr./2007 14:45
par fly
je suis en train de programmer un jeu de stratégie du style "Age of empire" et je suis confronté à un problème de ralentissement de l'affichage malgré un ordinateur puissant. Lorsque j'arrive à environ 1000 personnages à l'écran, mon FPS passe de 60 à 30 voire moins. Etant donné que je fais de la programmation que depuis 1 an je ne maitrise pas encore purebasic.
Pour la création de mes personnages j'utilise les listes chainées, le problème ne viendrait pas de là par hasard ?
Voici la partie du code qui permet d'afficher mes personnages :
FOREACH perso()
displaytransparentsprite(perso()\id_perso,perso()\pos_x,perso()\pos_y)
NEXT
Est ce que le fait d'afficher tous mes personnages d'un coup serait le problème de mon ralentissement.
Merci d'avance pour vos réponses
Publié : sam. 10/févr./2007 15:53
par Anonyme
Oui, le fait d'afficher tout les perso hors écran pose problème, la solution est de trier les unitées visibles (élément du décors, perso,ect...)
Code : Tout sélectionner
FOREACH perso()
if perso()\pos_x > 0 and perso()\pos_x< ecran_x and perso()\pos_y > 0 and perso()\pos_yx< ecran_y
displaytransparentsprite(perso()\id_perso,perso()\pos_x,perso()\pos_y)
endif
NEXT
Publié : sam. 10/févr./2007 16:37
par bernard13
dis moi Fly
as tu des captures d'ecran de ton travail?
merci d'avance
Publié : sam. 10/févr./2007 18:47
par fly
Merci Cpl.bator d'avoir repondu mais j'utilise deja la solution que tu m'as donné. Par souci de simplicité je ne l'ai pas mis dans mon message précedent parce que mon probleme de ralentissement se manifeste lorsque j'ai mes 1000 personnages à l'écran, quand ils sont en dehors,mon FPS revient à la normal.
Je ne comprend pas pourquoi il y a un ralentissement alors ce ne sont que des sprites et que j'ai un ordinateur relativement puissant.
Je n'ai pas encore de capture d'ecran mais je vais essayer d'en faire.
Publié : sam. 10/févr./2007 19:34
par Backup
ça n'a rien a voir , avec le pure tu peux afficher nettement plus que 1000
sprites ,il ne ralentira pas
j'ai un casse brique que j'ai fait accessible sur mon site (purenoide 1 et 2)
ou rien que les étoiles d'arriere plans c'est deja 1000 sprites !!
l'erreur la plus flagrante de ralentissement ,fait par les debutant en purebasic
c'est d'inclure les "StartDrawing()" et "StopDrawing()" a l'interieur des boucles for-next
bref ça c'est pas bon :
Code : Tout sélectionner
for x=0 to 1000
StartDrawing()
; bla bla
StopDrawing()
next x
il faut faire
Code : Tout sélectionner
StartDrawing()
for x=0 to 1000
; bla bla
next x
StopDrawing()
et la c'est le turbo qui est en route :D
(pareil pour les Flipbuffer()) ect ..
Publié : sam. 10/févr./2007 19:49
par comtois
pour afficher un sprite tu n'as pas besoin de startDrawing() d'ailleurs le code de fly est correct, du moins le morceau de code qu'il nous montre, faudrait voir le reste.
Est-ce que tu as le débogueur désactivé ?
Code : Tout sélectionner
FOREACH perso()
displaytransparentsprite(perso()\id_perso,perso()\pos_x,perso()\pos_y)
NEXT
Mais Dobro a raison 1000 sprites ça devrait s'afficher correctement. Enfin ça dépend ils font quelle taille ?
Publié : sam. 10/févr./2007 19:52
par fly
moi je n'utilise pas "StartDrawing()","StopDrawing()" et pas non plus de boucle for-next . Comme j'utilise les listes chainées j'utilise foreach-next.
Je ne vois pas du tout ou est le problème
Publié : sam. 10/févr./2007 20:05
par fly
Je ne sais pas si mon debogueur est désactiver. Ca change quoi?
Pour mes personnage j'utilise des image qui pèse 1 mo environ mais comme je l'ai découpe pour créer des animations avec clipsprite cela donne des sprites qui pèse que quelque ko.
Publié : sam. 10/févr./2007 20:52
par Anonyme
je ne sais pas ce que vaut le clipsprite en terme de rapidité, mais essaye d'avoir des sprites séparé avec grabsprite(), tu auras certainement un gain de rapidité.
Découpe un sprite en 64*64
Code : Tout sélectionner
GrabNumber = 1
For y = 0 To SpriteHeight(0) - 1 Step 64
For x = 0 To SpriteWidth(0) - 1 Step 64
GrabSprite(GrabNumber, x, y, 64, 64)
GrabNumber=GrabNumber + 1
Next x
Next y
Publié : sam. 10/févr./2007 21:33
par Anonyme
Autre chose, si tu es un maniaque de l'optimisation, tu peut toujours laisser tombé les listes chainées au profit d'allocatememory()
Voici un p'tit exemple qui te donne un ordre d'idée en terme de rapidité :
Code : Tout sélectionner
#Item = 5000000
Timer_A0 = ElapsedMilliseconds()
Dim Tableau_A(#Item)
For i = 0 To #Item
Tableau_A(i) = Random(2147483647)
Next
Timer_A1 = ElapsedMilliseconds()
Timer_B0 = ElapsedMilliseconds()
NewList Tableau_B()
For i = 0 To #Item
AddElement(Tableau_B())
Tableau_B() = Random(2147483647)
Next
Timer_B1 = ElapsedMilliseconds()
Timer_C0 = ElapsedMilliseconds()
*Tableau_C = AllocateMemory(#Item*4)
For i = 0 To #Item
PokeL(*Tableau_C+(i*4),Random(2147483647))
Next
Timer_C1 = ElapsedMilliseconds()
Timer_A0_ = ElapsedMilliseconds()
For i = 0 To #Item
R = Tableau_A(i)
Next
Timer_A1_ = ElapsedMilliseconds()
Timer_B0_ = ElapsedMilliseconds()
ForEach Tableau_B()
R = Tableau_B()
Next
Timer_B1_ = ElapsedMilliseconds()
Timer_C0_ = ElapsedMilliseconds()
For i = 0 To #Item
R = PeekL(*Tableau_C+(i*4))
Next
Timer_C1_ = ElapsedMilliseconds()
OpenConsole()
PrintN("RESULTAT DECLARATION & ALLOCATION SUR "+Str(#Item)+" ELEMENT(S)"+Chr(10))
PrintN("Tableau = " +Str(Timer_A1-Timer_A0)+" ms")
PrintN("Liste C = " +Str(Timer_B1-Timer_B0)+" ms")
PrintN("Pointeur&Alloc = " +Str(Timer_C1-Timer_C0)+" ms"+Chr(10))
PrintN("RESULTAT LECTURE SUR "+Str(#Item)+" ELEMENT(S)"+Chr(10))
PrintN("Tableau = " +Str(Timer_A1_-Timer_A0_)+" ms")
PrintN("Liste C = " +Str(Timer_B1_-Timer_B0_)+" ms")
PrintN("Pointeur&Alloc = " +Str(Timer_C1_-Timer_C0_)+" ms")
Repeat
ForEver
Bien entendu , rare sont les listes chainées avec 5000000 d'éléments , mais tu te rendra compte , surtout dans un jeu notament pour les tests de collisions une boucle du style :
En admetant que chaque liste contient 1000 element cela revient à faire une boucle a 1000*1000 soit 1000000 , a savoir aussi, qu'il reste le pathfinding, l'ia, l'affichage, etc...
Donc l'optimisation n'est pas à prendre à la légère

Publié : sam. 10/févr./2007 21:43
par fly
Merci Cpl.bator je vais essayer ta technique
Mais pour comprendre ou je me plante j'ai fait un petit code qui utilise le même principe de création et d'affichage des personnages mais qui est super simple et il se passe le même problème de ralentissement.Peut etre que vous mon erreur.
voici le code:
Code : Tout sélectionner
InitSprite()
InitKeyboard()
InitMouse()
InitSound()
InitSprite3D()
OpenScreen(1440,900,32,"essai")
UsePNGImageDecoder()
UseJPEGImageDecoder()
LoadSprite(0,"data\porte etendart.png")
Structure terrain_1
x.f
y.f
EndStructure
Global NewList terrain.terrain_1()
Declare principal()
Repeat
FlipBuffers()
ClearScreen(0)
ExamineKeyboard()
If Second < ElapsedMilliseconds()
Second = ElapsedMilliseconds()+1000
fps = Frame_Counter
Frame_Counter = 0
EndIf
If Second > ElapsedMilliseconds()
Frame_Counter + 1
EndIf
StartDrawing(ScreenOutput())
DrawText(0,0,"FPS : "+Str(fps))
StopDrawing()
; création des procedures
principal()
Until KeyboardPushed(#PB_Key_Escape)
Procedure principal()
If CountList(terrain())<1000
AddElement(terrain())
terrain()\x=Random(1440)
terrain()\y=Random(900)
EndIf
ForEach terrain()
DisplayTransparentSprite(0,terrain()\x,terrain()\y)
Next
EndProcedure
Publié : sam. 10/févr./2007 22:02
par Anonyme
Code : Tout sélectionner
InitSprite()
InitKeyboard()
InitMouse()
InitSound()
InitSprite3D()
OpenScreen(1024,768,32,"essai")
UsePNGImageDecoder()
LoadSprite(0,"C:\Documents and Settings\Ortali\Bureau\01.png",#PB_Sprite_Texture)
CreateSprite3D(0,0)
Structure terrain_1
x.f
y.f
EndStructure
Global *Memoire = AllocateMemory(1000*SizeOf(terrain_1))
Global Count.l
Macro principal()
While Count<1000
PokeL(*Memoire+(Count*4),Random(1024))
PokeL(*Memoire+(Count*4)+4,Random(768))
Count + 1
Wend
Start3D()
For i = 0 To 1000
x = PeekL(*Memoire+(i*4))
y = PeekL(*Memoire+(i*4)+4)
DisplaySprite3D(0,x,y)
Next
Stop3D()
EndMacro
Repeat
FlipBuffers(0)
ClearScreen(0)
ExamineKeyboard()
If Second < ElapsedMilliseconds()
Second = ElapsedMilliseconds()+1000
fps = Frame_Counter
Frame_Counter = 0
EndIf
If Second > ElapsedMilliseconds()
Frame_Counter + 1
EndIf
; création des procedures
principal()
StartDrawing(ScreenOutput())
DrawText(0,0,"FPS : "+Str(fps))
DrawText(0,20,"NBR : "+Str(Count))
StopDrawing()
Until KeyboardPushed(#PB_Key_Escape)
Voila, pas tout a fait pareil, mais c'est optmiser ^^
utilise la balise
Publié : sam. 10/févr./2007 22:07
par fly
Pourrais tu me dire ce qui faisais que mon code ralentissait
Publié : sam. 10/févr./2007 22:10
par comtois
fly a écrit :Je ne sais pas si mon debogueur est désactiver. Ca change quoi?
ça ralentit le programme.
Pour savoir si le débogueur est activé regarde l'icone utiliser le débogueur.
ou dans le menu débogueur.
@Cpl.Bator, je ne suis pas convaincu que le ClipSprite soit plus lent ? tu as fait des tests ? Moi je n'en ai pas fait , c'est pour ça que je te demande

Publié : sam. 10/févr./2007 22:31
par fly
merci Cpl.bator pour ton aide
Comtois , je pense pas non plus que clipsprite ralentissement mon progamme. Dans le code que j'ai mis sur le forum je n'utile pas clisprite et pourtant j'ai le même problème de ralentissement
Peut t'étre que mon ralentissement est normal et que purebasic n'est pas capable d'afficher 1000 sprite(environ 100*100 pixel) à un fps de 60.Mais cela m'étonne tout de même.