Bonjour à tous et à toutes,
Après une assez longue absence du monde de la programmation, me revoilà.
Je m'étais donc relancé dans mon projet de jeu vidéo, l'éditeur suffisamment avancé, je me suis dit : "Allez, il est temps d'optimiser tout ça et de comprendre pourquoi cela bouffe autant de proc".
Après plusieurs essais, j'en suis arrivé à la conclusion (peut-être fausse, corrigez moi si je me trompe) que cela venait de la méthode .Draw() de ma RenderWindow.
C'est pour cela que je me tourne vers vous aujourd'hui. Actuellement j'utilise une méthode un peu barbare (qui ne consommait rien sur la 1.6, étrange, je vous l'accorde). Cette méthode consiste à dessiner case par case, couche par couche (sur lesquelles il y a quelque chose à afficher, les cases vides sont pas dessinées, faut pas déconner) des cases de 32*32pix.. Ce qui correspond donc à 19*14*7=1862 petites cases à dessiner (si toutes les couches sont remplies par des tiles non nuls, bien entendu).
Voici mon code, j'aimerais que vous m'aidiez à l'optimiser pour parvenir à réduire la consommation processeur anormalement élevée pour de la 2D. Je souhaiterais également comprendre et pas me faire balancer une solution comme ça. Merci.
Voici ma boucle de refresh (Gameloop) :
' - Boucle de rafraichissement du jeu Public Sub Gameloop
() While _Socket
.Connected ' Affichage graphique If EnJeu
Then FenetreRendu
.Clear(New Color
(160,
160,
160)) ' Affichage des couches inférieures For x
= 0 To MAX_MAPX
For y
= 0 To MAX_MAPY
If Not x
< 0 And Not x
> 30 And Not y
< 0 And Not y
> 30 Then With Map
(MapActuelle
).Cases(x, y
) If .Sol <> 0 Then Call AfficherCase
(MapActuelle, x, y,
0) End If If .Inf1 <> 0 Then Call AfficherCase
(MapActuelle, x, y,
1) End If If .Inf2 <> 0 Then Call AfficherCase
(MapActuelle, x, y,
2) End If If .Inf3 <> 0 Then Call AfficherCase
(MapActuelle, x, y,
3) End If End With End If Next Next'Petit commentaire pour vous, j'afficherais les joueurs ici, c'est pourquoi j'ai fais deux boucles. ' Affichage des couches supérieures For x
= 0 To MAX_MAPX
For y
= 0 To MAX_MAPY
If Not x
< 0 And Not x
> 30 And Not y
< 0 And Not y
> 30 Then With Map
(MapActuelle
).Cases(x, y
) If .Sup1 <> 0 Then Call AfficherCase
(MapActuelle, x, y,
4) End If If .Sup2 <> 0 Then Call AfficherCase
(MapActuelle, x, y,
5) End If If .Sup3 <> 0 Then Call AfficherCase
(MapActuelle, x, y,
6) End If End With End If Next Next ' Affichage de la grille If Grille
Then Call AfficherGrille
() End If ' Affichage du tiles selectionné Call AfficherPreviTiles
() FenetreRendu
.Display() FPS
+= 1 End If Application
.DoEvents() End While MsgBox("Connexion avec le serveur perdue ! Merci de le signaler à l'équipe du jeu.", MsgBoxStyle
.Critical,
"Erreur fatale") End End Sub
Ainsi que ma méthode de dessin (Ce n'est pas tant les calculs qui sont lourds, j'ai fais des tests, mais si vous avez une meilleure optimisation, je suis preneur car je n'ai pas encore optimisé la partie calculs) :
' - Affichage d'une case sur la map
Public Sub AfficherCase(ByVal mapnum As Integer, ByVal X As Byte, ByVal Y As Byte, ByVal Couche As Byte)
Dim tX As Byte
Dim tY As Byte
Select Case Couche
Case 0 ' Sol
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).SolSet))
tX = DecodeX(Map(mapnum).Cases(X, Y).Sol)
tY = DecodeY(Map(mapnum).Cases(X, Y).Sol)
Case 1 ' Inf1
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).Inf1Set))
tX = DecodeX(Map(mapnum).Cases(X, Y).Inf1)
tY = DecodeY(Map(mapnum).Cases(X, Y).Inf1)
Case 2 ' Inf2
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).Inf2Set))
tX = DecodeX(Map(mapnum).Cases(X, Y).Inf2)
tY = DecodeY(Map(mapnum).Cases(X, Y).Inf2)
Case 3 ' Inf3
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).Inf3Set))
tX = DecodeX(Map(mapnum).Cases(X, Y).Inf3)
tY = DecodeY(Map(mapnum).Cases(X, Y).Inf3)
Case 4 ' Sup1
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).Sup1Set))
tX = DecodeX(Map(mapnum).Cases(X, Y).Sup1)
tY = DecodeY(Map(mapnum).Cases(X, Y).Sup1)
Case 5 ' Sup2
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).Sup2Set))
tX = DecodeX(Map(mapnum).Cases(X, Y).Sup2)
tY = DecodeY(Map(mapnum).Cases(X, Y).Sup2)
Case 6 ' Sup3
sprtTiles = New Sprite(imgTiles(Map(mapnum).Cases(X, Y).Sup3Set))
tX = DecodeX(Map(mapnum).Cases(X, Y).Sup3)
tY = DecodeY(Map(mapnum).Cases(X, Y).Sup3)
End Select
sprtTiles.TextureRect = New IntRect(tX * 32, tY * 32, 32, 32)
sprtTiles.Position = New Vector2f(X * 32, Y * 32)
FenetreRendu.Draw(sprtTiles)
sprtTiles.Dispose()
End Sub
Voilà, je remercie ceux qui ont pris le temps de me lire, de réfléchir et de m'aider. :)
Bonne journée !
J'avais oublié que les RenderTexture n'avaient pas de fond transparent
Pourquoi pas ?
rtexture.clear(sf::Color::Transparent);
Et n'oublie pas de dessiner les tiles sans blending, pour que l'alpha soit copié et non interprété.
rtexture.draw(tile, sf::BlendNone);
Je suppose que le vertex array n'aura pas de fond transparent non plus ?
Le vertex array n'est pas un pré-dessin, c'est juste un regroupement de sprites. Donc si ces sprites ont de la transparence, ils en auront toujours dans le vertex array. Et, au risque de me répéter, je te conseille vivement cette solution, qui réglera tous tes problème de manière simple et presque élégante. Au lieu de te faire ch*** avec d'autres choses pour rien ;D
Je crois que je tiens LE bug de l'année ! Accrochez-vous bien, ça décoiffe !
En fait c'est connu. Chrome change le timing global de l'ordonnanceur Windows, donc ça affecte toutes les applications qui tournent en même temps. Ca impacte notamment sf::sleep, qui passe d'une granularité de 15 ms à une granularité de 1 ms.