Grâces aux vacances suivant la dernière soutenance, le projet a pu être développé à plusieurs à raison de 24 heures par jour. Mais la rentrée a fait diminuer nos quotas de code se limitant à 10 heures par nuits. Des nouvelles fonctionnalités permettent de voir une évolution journalière comme les collisions, le tir, la création des bâtiments et unités, les ressources, et bien d'autres choses encore.
2. Guillaume
1) Editeur de cartes e42
L’éditeur de cartes est maintenant globalement terminé.
Il en est à un stade ou la structure de base est solidement encrée,
les améliorations possibles étant l’ajout de nouveaux décors,
nouvelles unités, et d’un autre tileset.
Je vais ici vous présenter ce qui a été
fait depuis la dernière soutenance.
Les montagnes (Higher Ground)
Pour pouvoir simuler le relief tridimensionnel dans 42 Minutes Pour
Vivre, il est indispensable d’avoir une autre sorte de sol. J’ai choisi
de reprendre le système de Patchs (présentes a la dernière
soutenance) pour faire des montagnes, ou plutôt des hauts plateaux,
sur lesquels nos unités pourront évoluer.
Comme pour les patchs d’herbes, j’ai choisi de reprendre des tiles
de StarCraft (ils sont si biens). Mais cette fois ci, le système
n’etait pas tout à fait aussi simple que pour les patchs d’herbe.
En effet, au lieu d’avoir 6 zones de 4 tiles, les patchs de ‘higher ground’
comportent seulement 2 zones de 4 tiles ( C et D ), ainsi que 4 zones de
6 tiles :

Ce changement apporta deux difficultés a la réalisation du système :

Les zones rouges sur cette image sont les zones de collisions entre
C-A et D-B.
Il faut dans ce cas avoir d’autres tiles sont en fait la combinaison
des deux tiles en collision. Et ceci pour chaque configuration, car il
y a beaucoup plus de collisions possibles, selon l’orientation des deux
patchs, et je n’ai malheureusement pas eu le temps a consacrer à
traiter tous les cas. Donc dans l’éditeur, certaines configurations
génèreront des tiles qui casseront l’image générale.
Cependant, j’ai fait en sorte de choisir les configurations qui viennent
le plus souvent quand on fait des cartes.
Quand l’algo détermine qu’aucune des zones de tiles doivent
être modifiées, les 4 tiles du milieu sont mis en Walkable
et Closed, pour que l’on puisse mettre des unités dessus, et qu’elles
ne puissent pas en sortir.
Dans StarCraft, on trouve un objet appelé Rampe que l’on peut
poser sur le bord d’un high ground pour que les unités puissent
en descendre et monter dessus sans avoir recours au transports aériens.
Je n’ai encore ajoute cet objet, mais si le temps le permet, il sera la
pour la soutenance finale.
Donc pour l’instant, si l’on pose des unités sur du high ground
dans l’éditeur, elles n’ont aucuns moyens de descendre (grâce
au superbe algo de recherche de cheminement d’Alexandre, qui gère
les surfaces de tiles dites Closed, ou fermées du reste), et les
unités en dehors ne pourront pas monter.
Par contre, les tiles en high ground on la propriété
High, et donc les unités seront avantages si elles tirent de cette
position vers des unités ennemis sur le sol.
Et il ne faut surtout pas oublier que le décor est un point
important dans les tile-based-games, contribuant à créer
une atmosphère réaliste, ce qui donne le joueur plus envie
d’y participer.
Closed Surfaces
En parlant des surfaces Closed, j’ai aussi ajoute une option pour choisir des rectangles de tiles qu’on veut mettre à Closed, par exemple, pour fermer une zone entourée d’arbres. Si ce n’est pas fait, l’algo de cheminement du jeu ne sera pas content, et des figages peuvent avoir lieu pendant que l’ordinateur essaye de calculer le chemin sur toute la carte…
Création de bâtiments
Nous avons maintenant plusieurs bâtiments, et chaque bâtiment
a été incorpore dans l’éditeur de carte.
J’ai développé un algo qui permet de voir si on a le
droit de poser un bâtiment sur la carte.
Quand l’utilisateur choisi de créer des bâtiments, et
qu’il bouge la souris au-dessus de la carte, le bâtiment est dessine,
avec un quadrille vert ou rouge par-dessus chaque tile qu’il occupe.
Ceci est exactement identique a la méthode StarCraft.
Les quadrilles sont en fait deux petites images de 32x32 pixels, un
quadrille vert sur du rose (couleur de transparence) et un quadrille rouge.
Le bâtiment est rendu en dehors de la boucle de rendement normale,
et on blit ensuite les quadrilles au-dessus des tiles. Pour déterminer
si le quadrille utilise est le rouge ou le vert, on regarde tout simplement
si le tile est Walkable ou non, ou s’il contient des unités.

Et, non cette image n’est pas une capture de StarCraft, mais de l’éditeur
42 Minutes Pour Vivre :) Cependant il est toujours plus facile de copier
que de créer, mais comme l’expression artistique n’est pas vraiment
prise en compte dans ce projet… De toute façon ce projet est sensé
être un StarCraft-Like donc…
2) Direct3d
A la dernière soutenance, je prévoyais l’incorporation
de Direct3d dans le projet pour pouvoir exploiter du matériel vidéo
accéléré, notamment ma Voodoo3.
Direct3d est, comme DirectDraw, très puissant et facile a utiliser,
une fois les frustrations et confusions engendrées par l’initialisation
passées.
Mon but etait tout d’abord de pouvoir afficher une texture par dessus
ma surface DirectDraw principale.
D’abord, il faut initialiser Direct3d :
DirectDraw.QueryInterface(IID_IDirect3D7,Direct3d);
Direct3D.CreateDevice(IID_IDirect3DHALDevice,BackSurface,Direct3dDev);
Ceci va m’attacher le device Direct3d a ma surface BackSurface, pour qu’au moment ou je fasse du rendu avec Direct3d, le résultat soit imprimé dans BackBuffer, que je flip ensuite sur l’écran. Le Direct3dHALDevice, c’est le Hardware Abstraction Layer device, c’est à dire l’abstraction de matériel. C’est le driver qu’il faut utiliser pour pouvoir accéder au capabilitées 3d accélérées de la carte vidéo.
Une texture Direct3d est tout simplement une surface DirectDraw, mais si on veut qu’une surface puisse servir de texture a Direct3d, il faut attribuer certains paramètres a son SurfaceDescripteur :
SurfaceDesc.dwFlags := DDSD_CAPS or
DDSD_HEIGHT or DDSD_WIDTH or DDSD_TEXTURESTAGE or DDSD_CKSRCBLT;
SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_TEXTURE;
SurfaceDesc.ddsCaps.dwCaps2 := DDSCAPS2_TEXTUREMANAGE;
Problème a noter, certaines cartes vidéo ne supportent
pas tous ces paramètres. Si le temps le permet, je ferai une vérification
du matériel 3d pour que l’utilisateur puisse choisir le meilleur
rendu possible.
Ensuite, pour dire à Direct3d que c’est avec cette surface que
l’on veut texturiser au prochain appel de la fonction de rendu, il faut
appeler la fonction :
Direct3dDev.SetTexture(0,ShadowSurface);
Ensuite, avant de pouvoir dessiner, il faut définir :
Donc comme viewport j’utilise :
ViewPort.dwX := X;
ViewPort.dwY := Y;
ViewPort.dwWidth:= 128;
ViewPort.dwHeight:= 128;
ViewPort.dvMinZ := 0.0;
ViewPort.dvMaxZ := 1.0;
Direct3dDev.SetViewport(viewport);
Avec X et Y le point sur ma surface ou je veux dessiner le sprite, une
image de 128x128 pixels.
J’avais besoin d’utiliser du matériel accéléré
pour pouvoir faire du alpha-blending rapidement, mon algorithme en assembleur
n’etait pas assez rapide avec DirectDraw.
Donc pour faire marche l’alpha-blending :
Direct3dDev.SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1 );
Voilà, maintenant je peux rendre mon image en ‘ouvrant une scène’, ensuite en appelant la fonction DrawPrimitive, et finalement ‘fermant la scène’. La fermeture de la scène envoyée la texture directement sur ma BackSurface.
Direct3dDev.BeginScene();
Direct3dDev.DrawPrimitive( D3DPT_TRIANGLESTRIP,
D3DFVF_VERTEX,ImgVertex, 4,0);
Direct3dDev.EndScene();
Les ombres avec DrawPrimitive
Contrairement a ce que j’avais réussi à faire manuellement
en assembleur, il s’avérait impossible d’utiliser les fichiers images
des hélicoptères directement pour faire des ombres sur le
sol. Cédric m’a donc fait 2 fichiers d’ombres qui contenaient en
fait les Une chose m’ayant pris un bon moment a trouver, c’etait les bons
paramètres pour pouvoir transformer l’alpha-blending en système
d’ombrage. Après une multitude d’essais, j’ai trouve qu’il faut
mettre les paramètres du D3dRenderState: SrcBlend a 1 et DestBlend
a 4.
Cela produit en fait, l’image négative de la source (l’ombre),
mixé avec la destination (le décor), ce qui donne un assombrissement
de l’image destination, mais juste dans les confinement de l’image source,
ce qui nous donne l’ombre de l’hélicoptère sur le sol.
Direct3dDev.SetRenderState(41, 1);
Direct3dDev.SetRenderState( D3DRENDERSTATE_SRCBLEND,
1 );
Direct3dDev.SetRenderState( D3DRENDERSTATE_DESTBLEND,
4 );
Le premier SetRenderState allume la fonction Color-Keying, ce qui permet
d’utiliser un sprite avec des contours transparents (rose).
Pour plus de details voir mon d3d.htm
Autres Utilisations
En jouant un peu avec les matrices de transformations et les viewports,
j’ai réussi à faire un système qui dessine un sprite
en boucle, tout en agrandissant ce sprite.
En fait, l’impression d’agrandissement est due au zoom dans l’axe z
que je fais subir à l’image.
Avec cette méthode j’ai pu créer une espèce d’explosion
bulle, qui sera en fait le tir orbital de du satellite SOL utilise par
les américains dans le jeu (vous avez vu AKIRA ? Non ? Vous devriez
:).
J’ai aussi crée une petite procédure qui fait un alpha
blend additive sur tout l’écran, créant ainsi un flash, d’une
intensité réglable en paramètre. Je l’utilise à
la fin de l’explosion, pour tout faire fondre au blanc, et ce sera aussi
utilise pour simuler des éclairs.
3) Effets Environnementaux
En parlant d’éclairs (pas ceux au chocolat, ni au café), je vais maintenant vous parler du petit système d’effets environnementaux que j’ai crée.
La Pluie
Pour simuler la pluie, j’ai tout simplement crée un tableau d’éléments
‘raindrops’.
Chaque raindrop contient des coordonnées écran x, y,
et une longueur.
Dans une procédure Rain, qui est appelé dans la boucle
de rendu principale, on ajoute à tous les raindrops.y leur longueur,
et on les dessine à l’écran. Ce sont en faite tout simplement
des petites lignes. Certaines plus longues que d’autres, les plus longues
tombant plus vite que les plus petites, créant ainsi une impression
de profondeur tridimensionnelle.
Pour chaque raindrop, si random(200) > 180, alors on réinitialise
sa position sur l’écran, pour simuler la chute sur le sol. Ainsi,
chaque raindrop a une probabilité de 20/200 = 10/100 = 1/10 = 0.1
de disparaître pour apparaître quelque part d’autre a la prochaine
itération de la boucle de rendu. Ceci crée un effet assez
réaliste de pluie, bien qu’il puisse être beaucoup amélioré..
La Neige
Pour simuler la neige, j’ai utilise presque exactement la même
méthode que pour la pluie.
Sauf que, au lieu d’augmenter raindrops.y, j’augmente ou diminue aussi
leur x, de façon aléatoire, créant des flocons qui
tombent globalement vers la droite, mais pas de façon linéaire.
En ce qui concerne la façon de les dessiner, ce sont pas des lignes
ici mais deux ou trois pixels (aléatoire aussi) par flocon.
Les Eclairs
Ne sont pas encore actifs, mais le code Direct3d pour faire un flash est en place, il me reste plus qu’a faire des flashs de temps en temps.
4) Système d'écriture
Pour que le jeu puisse communiquer avec le joueur, il fallait mettre
en place un système d’écriture, gérant une police
de caractères qui pourrait être rendu sur la backsurface facilement
a partir d’une chaîne.
Pour respecter notre tradition StarCraft-Like, j’ai lance StarCraft,
et j’ai tapé tous les caractères ascii pour les voir à
l’écran, puis j’ai fais une capture d’écran. J ‘ai ensuite
mis tous ces caractères dans un fichier bitmap. J’ai donc un tableau
de Trect qui contient tous les rectangles sur ce bitmap de tous les caractères.
Donc pour afficher du texte, je prends la valeur ascii de chaque caractère
avec la fonction ord, et j’utilise cette valeur comme index dans mon tableau
de Trect, qui me renvois donc le rectangle source sur l’image du caractère
en question. Ensuite il me suffit de le blit vers BackSurface
5) Le Panel
Le panel aussi a été extracté de StarCraft. Il
est redessine à la fin de la boucle principale de rendement. Ensuite
est dessine la minimap dans sa case réservée sur le panel,
et ensuite les 9 icônes a droite du panel. Les icônes sont
des petites images de 32x32 pixels.
Ils sont en fait gérés par un tableau de 9 bytes. Quand
une unité est sélectionnée, ce tableau est mis à
jour par rapport aux actions possibles de cette unité (ou du bâtiment
sélectionné)
Quand le joueur click dans le panel, une procédure vérifie
si la souris est au-dessus d’un des icônes, si c’est le case, on
lance la procédure qui est demande par l’index de l’icône
a cet endroit.
Par exemple si le Main Bunker est sélectionné et qu’on
click sur l’icône du soldat, la procédure de création
de soldats sera lancée.
6) Collisions d’unités
Alexandre ayant été un peu trop ambitieux dans sa gestion
des collisions des unités, j’ai essaye de l’implémenter moi-même.
J’ai applique une méthode qu’il avait suggère mais que
je croyais inefficace vu sa nature fortement calculatoire. C’etait ce principe
:
Si une unité collisionée avec une autre (intersection
des GroundRects), alors on recalcule le chemin avec l’algo de cheminement,
en traitant le tile contenant l’unité de collision comme un tile
non-walkable.
J’ai trouve un compromis pour ce système.
Il s’agit en fait de créer un nouvel état ‘attente’ pour
les unités.
Le principe est le suivant :
Si l’unité de collision est immobile, alors on recalcule le
chemin.
Si elle est en mouvement, alors, on met l’unité en attente.
Dans l’etat attente, l’unité va augmenter un compteur attente,
et essayer de se déplacer.
Si elle arrive à se déplacer sans entrer en collision
avec une autre unité, alors on la remet à l’état de
marche, sinon, elle reste en attente, jusqu'à ce que le compteur
arrive à une limite pre-definie au début du programme. A
ce moment la, on met l’état de l’unité a 1, l’arrêt.
Ce système fonctionne correctement mais il y a encore présence
de quelques bugs d’implémentation.
7) Les ressources
Les ressources sont gérées par trois indicateurs :
8) Conclusion personnelle
Voilà, je sais que c’est un peu court et compresse cette fois, donc si vous avez des questions sur n’importe lequel de ces sujets, ou autre chose du projet, n’hésitez pas a m’envoyer un petit mail.