Difficulté pour choisir méthode a appliquer dans une application.

Résolu
Messages postés
242
Date d'inscription
lundi 6 mars 2006
Statut
Membre
Dernière intervention
17 janvier 2018
-
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
-
Bonjour !

Je suis en train de développer un nouveau jeu qui consiste à écrire les mot d'une liste en cliquant sur des lettres qui défilent à l'écran (voir http://www.dothack.com/gu/datadrain/ pour se faire une idée, car c'est de ce jeu dont je compte m'inspirer) et un problème méthodologique se pose pour la chute des lettres servant à écrire les mots :

En effet, ces lettres sont censées tomber en continue une fois le jeu lancé, à des vitesses pouvant être différentes et le tout simultanément.
Pour respecter ces trois points, deux méthodes me sont venues à l'esprit :
     - boucle globale qui fait tomber les colonnes de lettre. problème : le critère simultané et le critère vitesse seront difficiles à respecter;

     - multi threading: un thread est affecté a chaque colonne et lance une boucle propre qui dure jusqu'à la fin de la partie. problème : risque d'accès a des données critiques, utilisation du CPU peut être abusive (plusieurs boucle générale lancées simultanément tout de meme).

Bien que la deuxième solution m'apparaissent la plus adaptée, je reste malgré tout réservé vis a vis de l'utilisation du CPU et je ne sais donc pas si cette méthode est vraiment bien ..

Pourriez vous me donner quelques conseils quand à une méthode à adopter ? (après avoir testé le jeu sur le lien joint au message si possible)

Cordialement, KiTe

6 réponses

Messages postés
254
Date d'inscription
jeudi 29 juillet 2004
Statut
Membre
Dernière intervention
2 avril 2010

Salut,

si tu connais le nombre de lettres qui tomberont, tu peux essayer le background worker.

Cordialement,

Swan94
===============Si la réponse vous convient, merci de l'accepter=================
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
11
Salut,
Pas besoins de BackgroundWorker... La seul chose qui pose des problème de lenteur dans le soft que tu veux faire, c'est l'affichage. Or il est impossible de contrôler ton affichage dans un thread autre que le principal, un BackgroundWorker est donc totalement inutile... mais rien à voir avec le taux d'utilisation du CPU (faire du multithreading ne veux pas dire avoir un taux d'utilisation CPU plus important)

Tu veux donc faire ça en GDI32? (Windows Forms, Graphics dans .NET)
Tu peux faire ça comme un "jeu normal", même si en GDI32 on ne fait normalement pas comme ça:
Créé un objet (je dirait une structure) pour chaque élément que tu veux afficher qui définira la position, l'apparence graphique et la vitesse de chaque lettre. Dans ta boucle:
1° gérer les cliques souris/entrée au clavier
2° gérer les position de chaque lettre
3° afficher chaque lettre

Pour le facteur vitesse, voici comment c'est gèré dans un jeu:
- Les vitesses des éléments sont définies en pixel par ticks (par exemple)
- A chaque itération de la boucle principale, tu regarde combiens de ticks se sont écoulé. La nouvelle position des éléments sera donc [Position actuelle] + [Ticks écoulés] * [Vitesse de l'élément]

Le problème avec cette méthode de coder, c'est que ton CPU sera toujours à 100% (comme dans un "vrai jeu")

Sinon, pour une animation GDI32, souvent on utilise tout simplement un Timer avec un interval entre 20 et 30 ms. La gestion de la vitesse des éléments peut se faire de la même façon que ce que j'ai dis plus haut.
Messages postés
242
Date d'inscription
lundi 6 mars 2006
Statut
Membre
Dernière intervention
17 janvier 2018

humm je ne saurais pas le nombre précis, juste le nombre de colonnes de lettres.. je ferais quelques recherche sur cette voie
Messages postés
242
Date d'inscription
lundi 6 mars 2006
Statut
Membre
Dernière intervention
17 janvier 2018

Hum merci pour tes conseils, c'est de toute façon comme cela que j'ai toujours procédé dans mes jeux ^^

Le problème qui me dérangeait le plus était le pompage de CPU, ce qui parrait inévitable apparamant :s
 
Et le problème d'une boucle globale qui n'est pas en tache de fond (dans un thread ou backgroundworker à part), c'est  l'imposibilité de récupérer les events utilisateurs sans passer par application.doevents, dont je ne raffole pas.

Je pense donc que le moteur du jeu sera comme je l'avais pensé : dans un backgroundWorker pour tout ce qui concerne directement la chute des lettres (boucle en tache de fond) et le reste en événementiel.

Pour ce qui est des structures,j'ai évidement crééles classes "lettre" "colonne" "gameEngine" pour la gestion de la vitesse, etc.

Merci de vos avis =]

Cordialement, KiTe
Messages postés
242
Date d'inscription
lundi 6 mars 2006
Statut
Membre
Dernière intervention
17 janvier 2018

Ah, et pour ce qui est du problème d'affichage a cause du threading, je peux tjr créer des fonctions déléguées ou encore mettre la propriété checkforillegal ... a false, ce qui permet de modifer le GUI en passant par des thread tiers.
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
11
"Le problème qui me dérangeait le plus était le pompage de CPU, ce qui parrait inévitable apparamant :s"
Forcément, si tu fais une boucle infinie, c'est à dire du code qui est exécuté continuellement sans interruption, ton processeur calcul continuellement sans interruption
En utilisant un Timer, tu peux gérer le FPS maximum que tu veux (= 1 / interval), et donc la charge du CPU sera réduite si le code peut-être exécuté pendant le laps de temps entre 2 appels à Timer_Tick. Mais dans un jeu, on ne se gène pas de prendre toutes les resources CPU pour avoir un max de performances, donc on utilise la boucle infinie.
"Et le problème d'une boucle globale qui n'est pas en tache de fond
(dans un thread ou backgroundworker à part), c'est  l'imposibilité de
récupérer les events utilisateurs sans passer par application.doevents,
dont je ne raffole pas."
Dans un "vrai jeu", il n'y a pas d'événements (que je sache), les états des entrées utilisateur (clavier et souris) sont testé à chaque itération de la boucle principale. C'est du plus bas niveaux que les événements du genre Mouse_Mouve. Mais rien ne t'empêche de créer ton propre événement MouseMove si la position du curseur à changé entre 2 itérations de la boucle.
"Je pense donc que le moteur du jeu sera comme je l'avais pensé : dans
un backgroundWorker pour tout ce qui concerne directement la chute des
lettres (boucle en tache de fond) et le reste en événementiel."
J'ai des doutes... Pourquoi la fluidité de tes lettres serait-elle meilleure si tu gère l'affichage dans un autre thread? Un autre thread ne sera pas plus performant que le thread principal pour afficher tes éléments, bien au contraire. Sur une machine monocoeur, le multithreading réduit les performances globales, car le CPU doit passer d'un contexte à l'autre (threads). Dans un "vrai jeu", il n'y a pas de multithreading non plus d'ailleurs. Aujourd'hui le multithreading est envisageable puisque nous avons des machines multicoeur (moi pas encore ^^), on peut par exemple gérer les mouvements (l'affichage) sur un thread et l'IA sur un autre, mais chaque thread reste tout de même très linéaire et sans événements, et les échanges de données entre les 2 threads sont réduits au maximum.
Le multithreading est bien pour avoir l'impression que 2 applications
s'exécutent en même temps, mais si on veut un maximum de performances,
on évite les changements de contextes et on travail avec un seul thread
(comme je l'ai dis au dessus, ceci devient discutable).

Et fais gaffe avec le BackgroundWorker, il s'agit d'un thread en tâche de
fond, et donc sa priorité est basse (il ne s'éxécute seulement lorsque
du temps CPU est libre).
"Ah, et pour ce qui est du problème d'affichage a cause du threading, je
peux tjr créer des fonctions déléguées ou encore mettre la propriété
checkforillegal ... a false, ce qui permet de modifer le GUI en passant
par des thread tiers."
Pour les déléguées c'est une très mauvaise idée. L'utilisation des déléguées permet d'attendre que le thread appelé soit libre pour y exécuter du code, il y a donc un impact très négatif sur les performances (on passe d'un thread à l'autre, c'est lent)
Pour le CheckForIllegal=False c'est une idée. Je ne sais pas ce que ça peut donner, mais à ta place j'essaierais voir ce que ça donne