Le mieux dans ces cas là c'est d'utiliser une ou plusieurs DLL définissant le moteur et tout ce qui est commun à l'éditeur / jeu, et après faire un exécutable éditeur et un autre jeu.
Le mieux dans ces cas là c'est d'utiliser une ou plusieurs DLL définissant le moteur et tout ce qui est commun à l'éditeur / jeu, et après faire un exécutable éditeur et un autre jeu.
Oui c'est en général comme ça qu'on fait. Il faut attendre l'intervention de LittleWhite pour savoir pourquoi il a utilisé des #ifdef EDITOR dans les cpp.
Ma remarque portait surtout sur le fait que certain cpp étaient protégés comme ça et pas d'autres (homogénéité)
Oki j'ai pas regardé le code source de toute façon ^^
Les warnings / errors (?) ont été corrigé ... juste que la release est pas mis à jour (le SVN si :p) ... enfin ... je ne sais pas de quelle version vous parlez
Pour les dll / so ... je ne sais pas du tout comment faire ...
Et je ne vois pas trop l'utilité ...
Mais c'est faisable (tout est faisable)
Pour les #ifdef EDITOR ... ce ne sont que des blocs qui évitent que des fichiers de l'editeur soit compilé dans le jeu . Après, il est certain que la décision fut un peu étrange, et que à la fin, on verra une jointure des deux projets pour tout proposé aux joueurs, sans avoir à changer de programme.
BAh, je suis un peu incertain de la solution. Je veux dire -> carte plus grande == déplacement plus lent pour le curseur (== ennui). Après c'est plus ... même jeu partout, pour tous ... c'est à voir donc.- Ça pourrait être bien d'afficher des cartes plus grande sur desktop
Cela a déjà été dit ... je vais remplir une feuille de demande de feature (il sert à ça le bug tracker, vous pouvez l'utiliser )une petite page d'aide au démarrage de l'éditeur pour expliquer les touches
Ah ?dommage que tout se fasse au clavier sur l'éditeur.
Bah moi je joue à Advance Wars sur GameBoy ... donc ... cela ne me gêne pas ... mais j'y penserai
Merci pour le retour
Petit problème dans le svn : toutes les données ne sont pas présentes (cf par exemple http://openawars.googlecode.com/svn/...ata/gfx/units/)
De plus, le programme plante quand les fichiers sont absents (au lieu de quitter gentillement en disant "désolé mais il faudra repasser ")
Oui j'avoue, mon truc est encore très foireux
Le jeu plante moins ... mais ce prends une exception ... l'éditeur plante.
Je corrigerai cela bientot
Bonjour LittleWhite
J'ai plusieurs questions/remarques sur ton code (je connais pas le monde des jeux vidéo) :
- problème d'indentation : tu utilises des tabulations qui ne sont pas rendu de la même façon en fonction de l'éditeur. A remplacer par des espaces (la plupart des EDI le font automatiquement)
- code bien documenté (commentaires), rien que ça, ça montre le sérieux du projet
- forte dépendance entre tes classes (je ne sais pas si c'est évitable, je n'ai pas regardé l'architecture en détail) et surtout avec SDL. Je ne sais pas si ça se fait habituellement dans les jeux, mais je me dis que si tu avais rassemblé dès le départ toutes tes accès à la SDL dans une classe wrapper unique, tu pourrais plus facilement porter ton programme sur différentes plateforme (par exemple Qt pour mettre sur Symbian je sais, je ne change pas) ou faciliter l'évolution vers OpenGL pour l'accélération matériel.
Par exemple, tu as une classe Renderer, qui utilise directement des types SDL et 2 sous-classes RSDL et ROpenGL. Tu aurais pu, par exemple, redéfinir les types en fonction de la classe utilisée, en remplaçant :
par
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class Renderer { virtual bool drawTile(SDL_Rect& tile, const SDL_Color& colour)const=0; };
et dans le reste de ton code, tu utilises simplement Renderer::Rect et Renderer::Color, sans te préoccuper du type réel.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 class Renderer { virtual bool drawTile(Rect& tile, const Color& colour) const; }; class RSDL { typedef SDL_Rect Rect; typedef SDL_Color Color; virtual bool drawTile(Rect& tile, const Color& colour) const; }; class ROpenGL { struct Color { float x, y, w, h }; typedef glColor Color; virtual bool drawTile(Rect& tile, const Color& colour) const; };
- autre chose statique, la liste des tiles ou des unités. Pareil, je ne sais pas comment cela se passe en général dans les jeux, mais je me dis que si tu avais utilisé un xml ou des DP collection/factory, ton jeu pourrait plus facilement évoluer, en ajoutant simplement des fichiers (xml+png) ou des plugins (et donc sans recompilation)
Ça ne se faisait pas pour les jeux anciens (donc openwars) mais maintenant, j'ai l'impression que pour augmenter la durée de vie, c'est un moyen facile et à faible coût (hop, on ajoute une nouvelle unité par semaine pour que l'intérêt pour le jeux dure plus longtemps)
Bon boulot dans tous les cas.
Oui j'avais remarqué (sur Google code) ... il faut que je le change ...
Merci- code bien documenté (commentaires), rien que ça, ça montre le sérieux du projet
J'avais appris cela en cours (principe de la boite noire). Je vois parfaitement ce que vous voulez dire- forte dépendance entre tes classes (je ne sais pas si c'est évitable, je n'ai pas regardé l'architecture en détail) et surtout avec SDL. Je ne sais pas si ça se fait habituellement dans les jeux, mais je me dis que si tu avais rassemblé dès le départ toutes tes accès à la SDL dans une classe wrapper unique, tu pourrais plus facilement porter ton programme sur différentes plateforme (par exemple Qt pour mettre sur Symbian je sais, je ne change pas) ou faciliter l'évolution vers OpenGL pour l'accélération matériel.
Par contre, le support d'OpenGL est déjà bon (je pense) ... sauf que dans tout les cas, la fenêtre est ouverte par SDL ...
Ouep ... je suis entièrement d'accord avec vous ... il y a bien des choses qu'il faut changer (perso, je ne suis pas très fan du XML).- autre chose statique, la liste des tiles ou des unités. Pareil, je ne sais pas comment cela se passe en général dans les jeux, mais je me dis que si tu avais utilisé un xml ou des DP collection/factory, ton jeu pourrait plus facilement évoluer, en ajoutant simplement des fichiers (xml+png) ou des plugins (et donc sans recompilation)
Ça ne se faisait pas pour les jeux anciens (donc openwars) mais maintenant, j'ai l'impression que pour augmenter la durée de vie, c'est un moyen facile et à faible coût (hop, on ajoute une nouvelle unité par semaine pour que l'intérêt pour le jeux dure plus longtemps)
En fait, j'ai parlé un peu avec fearyourself sur le chat, et je lui disais que j'allais faire un super gros refactoring ... car ce va un peu dans tout les sens.
Maintenant, ce refactoring est prévu pour les vacances de Noel (si je joue pas trop ) ... parce que c'est dernier temps, j'ai était plutot très occupé (entre autre à cause de l'école )
Le problème est que du coup, tu t'obliges à utiliser la SDL pour avoir OpenGL. Et sur de l'embarqué peu performant, il pourrait être intéressant de se débarrasser de la SDL (je ne sais pas si la SDL est lourde ou pas, mais je suppose que c'est forcement plus lourd que de rien utiliser )Par contre, le support d'OpenGL est déjà bon (je pense) ... sauf que dans tout les cas, la fenêtre est ouverte par SDL ...
Moi non plus L'idée est surtout de mettre les caractéristiques dans un fichier texte.perso, je ne suis pas très fan du XML
Dans la même idée, il pourrait être intéressant d'ajouter un langage de script pour que le comportement des unités puisse évoluer facilement (comprendre "sans devoir recompiler")
Pour le refactoring, peut être le faire en 2 temps : la conception (diagramme "made-house", pas besoin de faire de l'UML stricte) puis l'implémentation. A mon avis, il y a des intervenants C++ qui sont très au point niveau conception.
Ouep ... enfin ... la SDL ... je pense que c'est assez rapide... et puis elle est compatible avec un tres bon nombre de plateforme. Mais bon ... on va faire une jolie boite noire
J'imagine que je vais devoir me pencher tres serieusement sur LUA cette foisMoi non plus L'idée est surtout de mettre les caractéristiques dans un fichier texte.
Dans la même idée, il pourrait être intéressant d'ajouter un langage de script pour que le comportement des unités puisse évoluer facilement (comprendre "sans devoir recompiler")
Oui, y a de tres tres bons intervenantsPour le refactoring, peut être le faire en 2 temps : la conception (diagramme "made-house", pas besoin de faire de l'UML stricte) puis l'implémentation. A mon avis, il y a des intervenants C++ qui sont très au point niveau conception.
tu as totalement raison et je l'ai écris plusieurs fois.
Il faut dans la mesure du possible écrire du code générique c/c++ et tout ce qui est appelle à SDL l'isoler dans des classes à part.
Parce que le jour ou on veut passer à une autre couche logicielle eh bien il faut tout réecrire le code.
SDL n'est pas toujours performante sur mon vieux portable ça rame ( contrairement évidemment à Direct X ) ; au bout de quelques heures j'ai arrêté de programmer avec.
Pour du code portable je prendrais Irrlicht3d qui permet de faire de la 2d et qui est performant
Je suis d'accord que la SDL c'est lent ... mais c'est portable. Son GROS probleme, c'est qu'elle n'est pas optimise sur la couche materielle (a part sur la GP2X). Alors du coup, il faut faire un renderer OpenGL.
Desole si vous avez cru que je ne vous ecoutais pas. Je sais bien que mon code est assez ... tres ... moyen / nul. Je dois dire que je suis parti d'une facon a coder le jeu (la couche visible) le plus rapidement possible ... surement une mauvaise idee ...
Désolé de répéter des remarques déjà dites. Il est vrai que vu le nombre de post, c'est dur de se rappeler de tout.tu as totalement raison et je l'ai écris plusieurs fois.
En bref, que ce soit pour des raisons de performances ou de portabilité, il est toujours bien de concevoir en couches séparéesJe suis d'accord que la SDL c'est lent ... mais c'est portable. Son GROS probleme, c'est qu'elle n'est pas optimise sur la couche materielle (a part sur la GP2X). Alors du coup, il faut faire un renderer OpenGL.
Malgré les critiques, il ne faut pas que tu oublies :Desole si vous avez cru que je ne vous ecoutais pas. Je sais bien que mon code est assez ... tres ... moyen / nul. Je dois dire que je suis parti d'une facon a coder le jeu (la couche visible) le plus rapidement possible ... surement une mauvaise idee ...
- que si tu as de nombreuses critiques, c'est que ton projet intéresse beaucoup de monde
- que le nombre de projet aussi abouti développé par une seule personne sont relativement rare
- que le code est globalement bon, avec de bonnes habitudes d'écriture (commentaires, assert)
- que les remarques concernent plus l'évolution du projet que le résultat en lui même
Bref, du bon boulot (encore )
AHAH, victoire
Sinon beau boulot, ça avance !
EDIT (Pour mon voisin du dessous) : Effectivement, Python c'est déjà beaucoup plus un "vrai" langage, pas génial pour l'embarqué.
Lua est très léger. Sinon, y'a les scripts vraiment spécialisés dans l'"embedding", comme AngelScript qui a l'air très sympa, mais j'ai pas testé.
Autant je ne sais pas pour LUA, autant je peux d'ores et déjà te déconseiller python.. C'est vraiment pas fait pour je trouve..
Enfin, je reviens avec une mise à jour (et même une capture d'écran).
Ceci est le dernier ajout de fonctionnalité avant le refactoring.
Il en est ainsi car j'avais commencé cet ajout, bien avant de me décider de faire du refactoring. Comme j'ai aussi décidé de ne pas couper une tache pour une autre, il fallait bien que je finisse celle-ci.
Cette mise à jour, met en place une nouvelle couche de carte (appelé carte des effets) afin de dessiner les effets d'indication de déplacement (et d'attaque) que le joueur peut effectué. J'utilise un nouveau sprite, blanc transparent pour montrer au joueur là ou il peut se déplacer.
La fonction qui met à jour la carte des effets, pour les déplacements est récursive:
En commançant par la position actuelle de l'unité, elle regarde autour d'elle. Si la case suivante n'est pas valide (soit en dehors de la carte), on ne l'essaie pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 void MapGame :: setMoveHighlight(const UVec2& origPosition, const UnitType ut, const int movement) { // ToDo: Cost of the tile for movement if ( movement <= 0 || effectMap[origPosition.y][origPosition.x].isHighlight || !testTile(origPosition, ut) ) { return; } if ( (this->getUnitType(origPosition) == UT_NO_UNIT) ) { effectMap[origPosition.y][origPosition.x].isHighlight = true; } { UVec2 newPosition(origPosition); newPosition.x+=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } { UVec2 newPosition(origPosition); newPosition.x-=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } { UVec2 newPosition(origPosition); newPosition.y+=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } { UVec2 newPosition(origPosition); newPosition.y-=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } }
Si la case est occupé, on ne la colorie pas (mais on ne stoppe pas l'algorithme)
Si la case ne peut pas être utilisé par l'unité en cours, on stoppe.
Si la case est déjà colorié, il n'y a pas besoin de refaire l'algorithme, donc on stoppe aussi.
Actuellement, il manque l'implémentation pour le cout de la case. Ainsi que du repérage des unités ennemies (factions ennemies) qui elle, feront stoppé l'algorithme.
Voilà.
Maintenant, on va commencer à réflechir à propos du réfactoring.
La première étape va être de déplacé tout les commentaires pour la doc doxygen afin qu'elle ne soit pas emmélé avec le code. Effectivement, j'ai trouvé en lisant la doc, la méthode pour séparé les deux \o/ (et faire plus propre)
Deuxième point, va être de faire une boite noire afinc d'implémenté une interface entre le programme et la SDL (pour pouvoir changer la bibliothèque rapidement, sans touché au programme).
Le troisième et peut être dernier point, sera une amélioration du design du jeu, car je pense que je suis parti un peu dans tout les sens
C'est pas un peu optimisable tout ça ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 { UVec2 newPosition(origPosition); newPosition.x+=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } { UVec2 newPosition(origPosition); newPosition.x-=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } { UVec2 newPosition(origPosition); newPosition.y+=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } } { UVec2 newPosition(origPosition); newPosition.y-=1; TileType nextTileType = this->getTileType(newPosition); if ( nextTileType != TT_Invalid ) { setMoveHighlight(newPosition,ut,movement-1); } }
Parce que tu réppete +/- les meme choses, les meme tests, sans parler des constructeur/destructeur des TileType et UVec2 qui sont appellé a nouveau dans chaque bloc.
Enfin j'dis ça j'dis rien
J'ai regardé la fonction setMoveHighlight() afin de l'amélioré comme le suggère Ange_Blond. Les copies des positions, sont retirables en jouant sur les valeurs, comme suit:
Ce qui pour moi, ne me semble pas possible pour les raisons suivantes:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 // Gauche position.x--; fctRecursive(position); // Droite position.x+=2; // Je saute de 2 car nous étions en -1 ... fctRecursive(position);
- Le code devient un peu plus dur à lire.
- si je garde le paramètre constant ... je ne peux pas (le compilateur me l'interdit). Je peux le déconstifier, mais après, les appels récursifs vont me déplacer de bien plus d'une case. Et si j'enlève le pointeur ... bah je reviens à la copie de l'élément, mais cette fois, implicite.
Voilà pourquoi, je ne vois pas vraiment ou je peux enlever des copies.
Par contre, j'avoue pleinement que mon histoire de bloc de code est plus une source de ralentissement (création / destruction de variables forcée).
Voici ma nouvelle proposition:
On notera que j'ai déplacé les conditions avant l'appel de la fonction (récursion) afin d'éviter des appels à la fonction qui sont inutile. La condition de mouvement aurait du aussi être déplacé, mais tant que je n'ai pas mon test propre (en comptant le cout de déplacement selon le terrain, je ne fais rien :p)).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 void MapGame :: setMoveHighlight(const UVec2& origPosition, const UnitType ut, const int movement) { // ToDo: Cost of the tile for movement // Stopping condition if ( movement <= 0 ) { return; } // TODO: Add faction detection // If not same faction -> stop // else this if ( (this->getUnitType(origPosition) == UT_NO_UNIT) ) { effectMap[origPosition.y][origPosition.x].isHighlight = true; } // Continue the recursivity TileType nextTileType; // Right UVec2 rightPosition(origPosition.x+1,origPosition.y); nextTileType = this->getTileType(rightPosition); if ( nextTileType != TT_Invalid && !effectMap[rightPosition.y][rightPosition.x].isHighlight && testTile(rightPosition, ut) ) { setMoveHighlight(rightPosition,ut,movement-1); } // Up UVec2 upPosition(origPosition.x,origPosition.y-1); nextTileType = this->getTileType(upPosition); if ( nextTileType != TT_Invalid && !effectMap[upPosition.y][upPosition.x].isHighlight && testTile(upPosition, ut) ) { setMoveHighlight(upPosition,ut,movement-1); } // Down UVec2 downPosition(origPosition.x,origPosition.y+1); nextTileType = this->getTileType(downPosition); if ( nextTileType != TT_Invalid && !effectMap[downPosition.y][downPosition.x].isHighlight && testTile(downPosition, ut) ) { setMoveHighlight(downPosition,ut,movement-1); } // Left UVec2 leftPosition(origPosition.x-1,origPosition.y); nextTileType = this->getTileType(leftPosition); if ( nextTileType != TT_Invalid && !effectMap[leftPosition.y][leftPosition.x].isHighlight && testTile(leftPosition, ut) ) { setMoveHighlight(leftPosition,ut,movement-1); } }
Si vous voyez des problèmes, n'hésitez pas à me le dire. (et à m'expliquer le pourquoi, ou m'envoyer le cours sur un point que j'aurais loupé).
---
Comme prévu, j'ai modifié tous mes fichiers d'entêtes afin d'avoir la documentation mis à l'écart du code. Je trouve que cela rend le code plus lisible
Maintenant, je vais pouvoir me pencher pleinement sur la mise en place d'une interface générique pour les bibliothèques de fenêtrage / dessin.
Je ne vois pas trop de soucis avec cette solution. Je pense que ca peut fonctionner, regarde avec un profiler si vraiment ce bout de code est sur le chemin critique.
Jc
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager