Little Blog Story

Game-Design & Modding le blog de belzaran.

Little God Story - DevBlog #2

Jeudi 29 juillet 2010 à 11:31

Les premiers pas

Dans un projet, il y a toujours le moment où il faut ramener son concept sur un plan plus pragmatique. Après le “j’aimerais faire ça“, il faut passer au niveau “suis-je capable de le faire ?” Plus expérimenté depuis mon projet précédent, je me suis penché immédiatement sur la partie programmation. En effet, Unreal Safari m’avait montré qu’il était essentiel d’avoir un prototype minimal pour commencer à faire un level-design un tant soit peu intéressant.

L’embryon de Little God Story est, sur le papier assez simple. Voilà les features qui m’intéressaient au départ :

1 - Le joueur peut changer d’élément et cela affecte certaines caractéristiques (vitesse et hauteur de saut)
2 - Certaines parties d’un niveau sont liées à un élément et interagissent avec le joueur selon l’élément dans lequel il est (par exemple, le joueur meurt dans le Feu sauf s’il est dans l’élément Eau)
3 - La vue est à la troisième personne

Coder cela m’a pris deux jours. En effet, il n’y a rien compliqué à cela. J’ai d’abord utilisé mes connaissances d’Unreal Safari pour faire changer les caractéristiques de saut et de déplacement (en gros, c’était le même principe). Pour la partie Eléments du monde, cela n’a pas été très difficile. En effet, il existe déjà un système de Volumes dans l’Unreal Engine dont les biens nommés UTWaterVolume et UTKillZVolume. En les combinant, il a été facile de créer des volumes qui ne blessent que selon l’élément utilisé.

Le prototype créé est ultra-simple et encore pas mal buggué (le temps de réaction aux touches est de l’ordre de la seconde, les volumes blessent le joueur systématiquement quand on entre dedans…). Cependant, il est suffisamment avancé pour commencer à faire des maps de tests et à déterminer les distances de saut pour chaque élément, les différences de vitesse entre feu et terre (ce qui est très important pour les puzzles incorporant un besoin de rapidité). En quelques clics, je teste le saut à travers le Feu (base originelle de mon concept). Je trouve ça sympa de devoir changer d’élément en plein saut. Voilà un aspect plateforme qui est déjà implanté et déjà agréable.

A peine le prototype terminé, j’ai ressenti le besoin de le perfectionner bien qu’il atteigne les objectifs que je m’étais fixés. En effet, il est très désagréable de ne pas pouvoir savoir avec quel élément on joue. Même si il y a des ressentis en jeu (ne serait-ce que la vitesse de déplacement), l’intégration d’un HUD, même sommaire, paraissait essentiel, ne serait-ce que pour contrôler que les éléments changeaient bien quand j’appuyais sur la touche voulue (c’est ainsi d’ailleurs que je me suis aperçu du temps de réponse de mon code…). Le premier HUD est alors ultra-simple et moche, mais fonctionnel.

Les contrôles

Premier HUD

Premier HUD

Deuxième souci qui va vite se manifester : l’ergonomie des contrôles. Même s’il est prévu que le joueur puisse les changer, le rôle de la souris va ici être prépondérant. En effet, à l’origine, il n’y a pas d’armes dans Little God Story. Résultat, les clics gauche et droit sont utilisés pour changer d’éléments. Or, dans le cadre d’une permutation d’élément, ce n’est pas forcément ce qu’il y a de plus pratique. Les contrôles sont encore un sujet de discussion avec les testeurs. En effet, une arme a été ajouté (clic gauche) et il y a de forte chance qu’un tir secondaire soit implanté (clic droit). Résultat : le changement d’élément risque de devenir plus compliqué à gérer et la partie plateforme moins ergonomique. Dès le départ (même quand le jeu était plus simple et proposait moins de features), le souci d’ergonomie s’est posé. Je précise quand même que l’idée d’adapter les contrôles à un pad ne m’a jamais effleuré l’esprit…

Rapidement, je me suis aperçu également qu’il faudrait restreindre l’utilisation des éléments. En effet, en jouant aux premiers niveaux de test, j’ai pris l’habitude de me balader en mode Feu systématiquement pour aller plus vite et à sauter en mode Air pour assurer la hauteur de saut. J’ai donc du intégrer une jauge de mana pour contrôler tout ça. Je reviendrais là-dessus dans un prochain article, ce genre de feature méritant beaucoup plus qu’un simple paragraphe…

Première modélisation du personnage

Première modélisation du personnage

La vue à la troisième personne

Dernière chose qui fut changée dès les premiers tests : la vue à la troisième personne. Les premiers testeurs ont en effet critiqué cet aspect là, en arguant qu’elle n’apportait rien. J’ai donc du réfléchir à l’éventualité de supprimer ou non cette vue. J’avais prévu de donner une identité visuelle originale à mon personnage afin de renforcer l’idée de “petit dieu”. Abandonner la troisième personne me faisait perdre un aspect prépondérant. En revanche, passer à une vue à la première personne faisait que la modélisation et l’animation du personnage n’étaient plus essentielles, du moins dans l’immédiat. De plus, cela m’évitait de nombreux problèmes de caméra inhérents au style plateforme vue de derrière. J’ai donc fait sauter sans trop de remord la vue à la troisième personne.

Cela a eu beaucoup d’influence dans le développement du jeu en lui-même. Ce changement de perspective a changé radicalement les sensations de jeu et m’a poussé ensuite à ajouter des armes car Little God Story avait perdu fortement en dynamisme. J’avoue être également un très gros joueur de FPS. C’est clairement ce que je préfère. Je pense être plus à même de comprendre ce que veulent des testeurs sur ce genre de jeu que pour un jeu à la troisième personne où mes seules références sont Prince of Persia : The Two Thrones et Prince of Persia : Warrior Within… (quoiqu’on me reproche pas mal de faire un FPS puzzle-game sans avoir joué à Portal…)

L’intégration des boutons

Rapidement, je comprend que l’aspect plateforme sera insuffisant pour faire un jeu réellement intéressant. Tous les jeux plateforme intègre un aspect différent, souvent des combats (Prince of Persia, Tomb Raider…). Le problème, c’est que faire des combats demande beaucoup de boulot :

  • Faire des personnages non-joueurs
  • Animer ces personnages
  • Animer leurs armes
  • Donner une IA à ces personnages
  • Ajouter des armes au personnage principal
  • Ajouter les animations de ces armes
  • Coder les effets de ces armes (impacts, muzzleflash, dégâts…)
  • Équilibrer les combats
  • … etc

Le bouton Terre, le plus fréquemment rencontré dans le jeu

Le bouton Terre, le plus fréquemment rencontré dans le jeu

J’ai donc vite rejeté cette idée. Non seulement parce-que cela me paraissait infaisable seul, mais aussi parce-que je ne voulais pas faire des combats peu intéressants avec des ennemis imbéciles. Je me suis donc orienté vers une partie réflexion. Je ne l’ai pas fait que par fainéantise, dès le concept j’avais quelques idées ce genre (un peu comme Prince of Persia comporte quelques énigmes). Je me suis donc lancé dans la programmation d’un système d’interrupteurs basé sur les éléments. Par exemple, voilà le genre d’énigme prévu :

  1. Pour ouvrir la porte, je dois activer un interrupteur Feu
  2. Je dois donc me changer en Feu
  3. L’interrupteur Feu est immergé dans l’Eau
  4. Je ne peux donc pas l’activer (sinon je meurs car en Feu, je ne peux aller dans l’Eau)
  5. Comment changer ça ? (retirer l’eau, faire sortir l’interrupteur, etc.)

Il est évident qu’avec les quatre éléments, ce genre d’interrupteurs permet de créer de nombreuses énigmes. Malheureusement, le jeu s’est vite orienté vers le principe : actionner les interrupteurs dans le bon ordre. Dès les premiers tests, il a été important de corriger cela et d’éviter un aspect un peu rébarbatif, sans supprimer ce concept pour autant, qui donne une identité visuelle et de gameplay au jeu. Il fallait dynamiser le jeu. J’ai donc été rapidement rattrapé par mes démons : si je voulais faire un jeu varié et intéressant, je n’avais pas le choix : il fallait ajouter des “armes”… (pour rappel : les armes sont une des étapes primordiales que je ne suis jamais arrivé à passer pour Unreal Safari, tant en terme d’imagination que de réalisation).

A ce stade, je suis un peu taraudé entre deux tendances : je tiens un concept intéressant mais j’ai conscience qu’il faut que je le développe un peu pour qu’il atteigne un niveau autre qu’un simple concept intéressant (comme on voit beaucoup pour les projets étudiants par exemple). Il est toujours difficile de passer le cap d’une idée à un jeu complet. Malgré le fait que je voulais être très prudent sur ce point-là, je me sentais obligé d’être plus ambitieux… Pour le meilleur et pour le pire !

Little God Story : DevBlog #1

Mercredi 28 juillet 2010 à 10:08

La génèse du projet

Avant de démarrer cette série d’article sur mon projet actuel, Little God Story, je tiens à préciser deux/trois choses afin qu’il n’y ait pas d’ambiguïté sur mes intentions. Ce devblog n’a pas pour but premier de faire la promotion de mon jeu, mais d’expliquer ce qui a guidé certains choix de game-design. Un jeu est une entité qui part d’un point de départ, avec certains objectifs, mais cela reste très changeant. Je vais ici parler de choix de game-design déjà effectués et validés par des tests extérieurs. Dernière chose : le début de ces articles démarre exactement là où mon post-mortem d’Unreal Safari se terminait. Je vous conseille la lecture de ce dernier pour bien comprendre les choix suivants.

Exil

Après une expérience en solitaire de près d’un an et demi sur Unreal Safari, j’arrivais au bout de ma motivation. Cherchant à intégrer une équipe pour un mod/jeu solo, je profitais du fait qu’Exil migre sur l’UDK pour postuler. Embauché en tant que mappeur, je me faisais plaisir en modélisant un monde médiéval sombre aux ombres tranchées. Cependant, Exil ne mit pas très longtemps à capoter. Je pense qu’il est important que je précise un petit peu ce qu’est réellement ce jeu.

Exil est un jeu en vue à la troisième personne. Au moment où j’intègre l’équipe, Exil est une sorte de clone de Prince of Persia (tendance les Sables du Temps). Si le monde diffère légèrement (plus médiéval qu’oriental) même le roi, Enklave, ressemble à s’y méprendre au prince de perse. Dans le cahier des charges, seul la notion de cristaux diffère du jeu original.

Lorsque j’ai commencé à mapper, le but était de rechercher une ambiance dans le but d’attirer le codeur (comme pour beaucoup d’équipe). Malheureusement, j’ai vite souffert du manque de programmation dans l’équipe. Sans un embryon de gameplay, difficile de faire quoi que ce soit. Mes premières demandes furent pour des choses bêtes : à quelle hauteur peut sauter Enklave ? Sur quelle longueur ? A quelle vitesse va-t-il ? Rapidement, je me suis lassé de mapper “pour mapper” et non pas pour du gameplay. Je n’ai jamais été intéressé par le mapping pur, j’ai toujours aimé le côté level-design qui est pensé avant tout par rapport à un joueur.

Nous avons alors eu une discussion avec Froyok, chef de projet, afin de définir précisément le gameplay d’Exil et d’essayer de le différencier un peu de Prince of Persia. L’idée était d’opposer cristaux et eau. J’avais alors comme idée que le personnage pourrait se transformer en cristaux et accroître ses performances (hauteur de saut, vitesse…). Le problème c’est que dans ce mode, il serait vulnérable à l’eau. Je voyais alors un gameplay où Enklave se transformerait en cristaux pour sauter plus loin mais devrait, en vol, redevenir normal pour traverser le filet d’eau qui le sépare de la plateforme suivante…

Cette idée n’a pas été retenue pour le gameplay d’Exil, mais j’ai senti qu’il y avait quelque chose à creuser. En attendant d’avoir un prototype de gameplay pour mapper pour Exil, j’ai travaillé ce concept en l’étendant aux quatre éléments. Plutôt que de n’avoir qu’une combinaison cristaux/eau, je multipliais les possibilités de gameplay avec terre/air/eau/feu. Pour traverser du Feu, il faut être en Eau. Mais pour sauter haut, il faut être en Air, etc. Rapidement, j’ai pu développer pas mal de combinaisons possibles. C’est pour cela qu’au départ, Little God Story est un jeu avant tout de plateforme en vue à la troisième personne. Au final, le concept évoluera beaucoup. Mais contrairement à Unreal Safari, j’ai pris le temps d’asseoir mon gameplay avant de démarrer quoi que ce soit.

Deux semaines plus tard, Exil s’interrompait (le projet a plus ou moins repris depuis). Le travail en équipe n’avait pas été productif et ne m’avait montré quasiment que des désavantages. Mon concept de jeu semblait assez solide et prometteur. C’était un jeu solo, linéaire et dans une ambiance qui me plaisait. Je commençais alors à travailler plus sérieusement sur Little God Story. En solitaire.

http://www.moddb.com/games/exil

http://www.moddb.com/games/little-god-story

Unreal Safari : Post-mortem (6)

Vendredi 23 juillet 2010 à 8:36

unrealsafari

Il est temps de clore cette série d’articles avec l’arrêt du développement d’Unreal Safari (qui, globalement, a traumatisé pas grand monde !). Les raisons principales sont évidemment toujours les mêmes et elles sont évidemment liées :

1 - La perte de la motivation
2 - La quantité (astronomique) de travail restant à faire

Le but de ce dernier article n’est pas de développer ce genre de propos, très banals,  mais d’expliquer les petits trucs qui petit à petit, amènent à ce ressenti.

1ère raison : je ne suis pas assez compétent

Il n’est jamais très agréable de l’avouer, mais il y a un moment où j’ai pris conscience de ma propre incompétence, notamment en terme de modélisation (pour les personnages et les armes, c’était assez flagrant), d’animation, d’effets visuels, voir de programmation. Quand on voit tout ce que j’ai appris à faire depuis le début, on pourrait penser que j’aurais pu me lancer dans l’aventure et apprendre comme pour les autres domaines. Mais trop c’est trop. Apprendre de nouvelles techniques à la pelle est intéressant et gratifiant mais ne fait qu’ajouter du boulot. Quand je modélisais une caisse à la truelle, ça me prenait 5 minutes. Quand je fais un model sympa avec des textures plus variées et le support de lightmaps par exemple (le minimum syndical en sorte), j’en ai pour la matinée. A force d’apprendre, on augmente aussi son temps de travail. Ce n’est pas nouveau, développer un jeu next-gen prend de plus en plus de temps et j’étais encore loin des techniques next-gen…

2ème raison : j’aime pas les jeux multijoueurs

Patator : Nevermind the Beach

Patator : Nevermind the Beach

Contrairement à ce que l’on pourrait croire, je ne joue quasiment jamais en multi. J’ai joué à une époque un petit peu à Counter-Strike : Source, Unreal Tournament III, Warcraft III ou Company of Heroes, mais jamais très longtemps. Cela vient aussi bien de mon faible niveau que de mon manque d’intérêt. Mais alors pourquoi mapper et modder pour le multi ?!

J’ai toujours eu en projet de faire un mod/jeu solo. J’avais à l’époque un scénario et une personnage, Patator. J’ai essayé de développer Patator sur FPS Creator, Far Cry, Half-Life ² et Crysis, avec des avancées plus ou moins grandes. Et un jour j’ai compris que l’avantage de faire des maps multijoueurs, c’est que ça demande moins de travail pur, car elles sont souvent plus petites et rejouables. Ce sera mon leitmotiv pour plus de 2 ans de rejet de mes pulsions primaires qui adorent les jeux solos.

Patator : Source

Puis ce fut le choc : j’ai joué à The Ball. Une révélation. En effet, contrairement aux screens que j’avais pu voir du mod, quand on joue au premier niveau, The Ball n’est pas renversant. Il est beau mais sans plus, très carré, très couloir et avec des mécanismes simples voire simplistes. Au fur et à mesure des niveaux, il se complexifie. Des NPCs apparaissent, les énigmes deviennent plus ardues, le monde devient plus beau et diversifié… A ce moment-là je me suis dit : “je peux faire ça ! (en moins beau)”. C’était certainement un peu utopiste de ma part, car si ce n’est pas dit clairement, il était sous-entendu que je considérais que j’espérais être capable de le faire tout seul… Bref, l’idée de faire un FPS solo sans combat trotte dans ma tête. A l’époque, je n’ai aucun concept en tête, mais la frustration de modder pour du multi s’installe.

http://www.moddb.com/games/the-ball

3ème raison : je suis frustré artistiquement

Cela peut paraître un peu pompeux, mais je rappelle que je suis allé modder sur UT3 pour pouvoir utiliser des lumières dynamiques. J’adore les jeux d’ombres. En cela, mes références graphiques sont Doom III, F.E.A.R. ou Bioshock. Alors forcément, un mod africain avec une lumière crue et forte, ce n’est pas ce que je préfère. L’univers que je développe est certes original mais n’exploite pas mes qualités de mappeur. En effet, je modélise de façon brute. Or, un éclairage fort et uniforme souligne ce côté simpliste. Comme mes éclairages étaient le point fort de mes maps précédentes, je commence à prendre conscience que si je suis passé sur UT3, ce n’est pas pour faire des maps comme ça.

4ème raison : j’ai perdu ma map !

Modèle de mur pour la mosquée

En commençant réellement la totale conversion, j’ai du créer un nouveau dossier “Unreal Safari” pour intégrer pleinement les armes/personnages/maps et sortir du côté “je bidouille un peu UT3″. Ceci ne s’est pas fait sans douleur et malgré toutes les manipulations, je continuais de devoir stocker mes maps dans le dossier UT3… Un jour de mauvaise manip, j’ai supprimé mes packages Unpublished au lieu de mes packages Published. Je vais tenter d’expliquer un peu la nuance entre les deux :

Unpublished : contient toutes les textures / models / sons / whatever bruts. Ils ne sont pas compressés et restent modifiables
Published : contient uniquement les textures / models / sons / whatever utiles au mod/jeu/map. Ils sont compressés et ne sont pas modifiables.

Modèle de colonne pour la mosquée

On pourrait croire que le fait de ne pas pouvoir modifier mes anciens assets n’était pas si grave, mais UT3 a décidé de me plomber bien plus encore ! Sur ma map SAF-Gizeh, il ne retrouve plus du tout les models et textures. Après quelques tentatives infructueuses, je m’aperçois que la map est fichue. Il faut tout recommencer…

Cela m’a freiné un peu, mais pas arrêté ! Après quelques semaines je m’y remet, décidant d’en profiter pour changer le level-design et de monter d’un cran en terme de graphismes. Quelle erreur ! Le level-design de SAF-Gizeh tenait la route et ne nécessitait pas de changer du tout au tout. Quand à l’amélioration graphique, si elle a été appréciée par les “fans” du mod, elle rejetait la sortie du mod à beaucoup plus tard…

5ème raison : comment vais-je faire jouer à mon mod ?

Si vous suivez un peu les releases de mod, il n’est pas rare de voir comme remarque “ce mod a l’air sympa, mais ils n’ont aucun serveur pour le tester”. En gros, le mod espère que des fans vont mettre en place des serveurs pour y jouer. Ceci est suicidaire car un mod multi est souvent très peu joué d’emblée, alors l’absence de serveurs existants et encore pire. J’ai donc pris conscience à un moment que je devrai investir dans des serveurs pour la promotion d’Unreal Safari. Or, en étant seul, louer des serveurs est loin d’être gratuit… Ce genre de préoccupation a un peu plomber les dernières semaines de développement. Cette idée me perturbait car je ne voulais pas non plus faire un mod injoué. Je ne faisais pas ça dans le but unique de faire un post-mortem après…

6ème raison : L’UDK apparaît

L’Unreal Development Kit est un véritable graal pour les moddeurs. Il donne accès au moteur Unreal Engine plus ou moins gratuitement (il y a quand même des royalties qui traînent). Je traiterai de cet outil plus en détails dans un prochain article.

Il faut comprendre que la sortie (surprise) de l’UDK a été une véritable bombe dans la communauté du modding et notamment du modding UT3. En effet, il devenait possible de faire passer son mod au statut de jeu complet, voire même de jeu complet payant. Toute Totale Conversion qui se respecte avait l’occasion d’élargir son public ! Et quand on connait la petitesse de la communauté UT3…

Je n’ai jamais eu l’envie de convertir mon mod UT3 en jeu UDK. Cependant, les grands mod UT3 (ceux du Make Something Unreal Contest) sont rapidement tous passés sur l’UDK. L’impression, vue de l’intérieur, était que la communauté se délitait.

L’UDK a précipité la chute d’Unreal Safari. En effet, je suivais à l’époque attentivement un jeu complet en développement : Exil. Son concepteur développait son propre moteur. Il abandonna cette idée et migra sur l’Unreal Engine à la sortie de l’UDK, l’aubaine était trop  belle. L’univers me plaisant et la programmation me gonflant de plus en plus, je proposais ma candidature et intégrais l’équipe en tant que mappeur/modeleur (il est difficile de n’être que mappeur sous l’Unreal Engine). Je pouvais ainsi mapper des endroits sombres et contrastés, dans un jeu solo ! Le bonheur fut de courte durée (quelques semaines avant que le projet s’arrête), mais mis une fin définitive à Unreal Safari.

http://www.udk.com/

http://www.makesomethingunreal.com/

http://www.moddb.com/games/exil

Mais alors, qu’aurais-je donc pu faire pour sauver Unreal Safari ?

Faire le post-mortem d’Unreal Safari m’a donné beaucoup de nostalgie et je regrette de ne pas l’avoir poussé plus loin. Cette série d’articles m’a apporté un recul que je n’avais pas imaginé à l’origine. En déterrant les bouts de code, les models, les maps et les concepts, je me suis aperçu que j’ai eu les yeux plus gros que le ventre. Tant que j’ai su rester simple, j’ai fait des releases de produits finis et honorables. Dès que j’ai décidé d’attendre une release plus complète, le travail restant est devenu trop grand. Si j’avais voulu faire une Totale Conversion, il fallait accepter l’idée de recruter des gens. Ce qui était pour moi inacceptable, ne voulant avoir à gérer des gens et des personnalités. C’est un choix de ma part et l’avenir me donnera (j’espère) raison.

Ce que j’aurais du faire, c’est développer le game type Safari. Ajouter un HUD plus personnalisé, des messages plus originaux, un écran en début de partie pour choisir son équipe… Cela m’aurait apporté beaucoup et le game type aurait gagné en personnalité et en originalité. Cela aurait été plus qu’une idée sympa.

L’autre idée (en lien avec la précédent) aurait été de développer des maps pour le game type Safari. Ces maps auraient pu être jouables aussi bien en Deathmatch par équipe qu’en mode Safari. L’occasion de faire jouer sur mes maps et de promouvoir mon game-type en quelque sorte.

Je tiens à préciser qu’en faisant le post-mortem du game-type Safari, il y a une part de moi qui me pousse à en reprendre le développement (notamment car j’ai beaucoup progressé en programmation et que ça me demanderait moins de temps). Mais il est vrai que la communauté UT3 étant tellement petite (et ça ne s’est pas arrangé avec le temps j’imagine), je ne pense pas que je reprendrai ce mode de jeu pour en faire une version 2.0.

Quel bilan en tirer ?

Unreal Safari fut une histoire fantastique et dura près d’un an et demi. Si le fait de vouloir faire une Totale Conversion fut une erreur évidente, elle m’a permis de toucher à tout et de pouvoir lancer mon projet suivant, Little God Story, en connaissance de cause ! De plus, l’apprentissage et l’amélioration de mes techniques lors du projet furent colossales. Je suis parti de très bas pour arriver à faire plein de choses, dans des domaines assez différents.

Même si Unreal Safari n’a pas eu un rayonnement énorme (c’est peu de le dire…), j’ai pu m’apercevoir au bout de plusieurs mois que les différentes releases m’ont permis de changer un peu mon statut dans la communauté, au moins francophone. Quand j’ai présenté mon nouveau projet, je n’étais pas un pauvre noob rêveur. J’avais une expérience concrète, prouvée par des réalisations correctes et surtout publiées. Faire un bout de map impressionnant, c’est à la portée de beaucoup. Faire une jolie map avec une gameplay qui tient la route sans que ça rame, c’est plus difficile. La plupart de mes maps sous Source avaient d’ailleurs fini à la poubelle pour des problèmes d’optimisation.

La sortie de l’UDK m’a permis également d’avoir un statut plus élevé du jour au lendemain. En effet, les développeurs UT3 étaient rares et quand l’UDK est sorti, beaucoup de projets ont vu le jour. Mais un nouvel outil demande un apprentissage. Du jour au lendemain, je devenais quelqu’un d’expérimenté ! Cette prise de conscience et ces réalisations m’ont fait prendre confiance en moi et c’est pour cela que j’ose, aujourd’hui, rédiger des tutoriaux sur l’Unreal Script.

Ce post-mortem est désormais terminé. J’espère que vous l’aurez trouvé intéressant et surtout pas trop narcissique. J’espère surtout qu’il servira aux personnes qui se lancent dans le modding. Car si j’ai fait des erreurs, j’ai fait également à des moments de bons choix qui m’ont permis d’avancer. Tout moddeur rêve de faire son jeu stand-alone qui déchire et qui surpassera Crysis et/ou Stalker. Il ne faut pas hésiter à être plus modeste et/ou plus original. L’industrie du jeu vidéo nous apporte de plus en plus de jeux formatés, alors si les moddeurs se formatent également, on peut dire adieu à l’originalité…

Unreal Safari : Post-mortem (5)

Jeudi 22 juillet 2010 à 13:35

unrealsafari

Depuis le début, on assiste dans ce post-mortem à des réalisations (modestes) mais le mod final est très loin d’être accompli. A partir de maintenant, plus aucune release ne sera faite. Commençons donc à nous intéresser à ce qui a été démarré et n’a jamais été terminé…

Map : SAF-Gizeh

Parlons d’abord mapping. Une fois le prototype de gameplay codé, j’ai pu m’atteler au level-design. Intelligemment, j’ai repris le thème de Gizeh en premier, histoire de réutiliser tout ce qui avait été fait auparavant. Contrairement à ce que j’avais prévu, la map WAR-Gizeh ne me sera d’aucun secours, le gameplay s’étant trop éloigné du mode Warfare d’Unreal Tournament III. En effet, en terme de level-design, l’une des particularités à exploiter est le (double) saut des gazelles. Cela me servira de référence pour construire les immeubles. L’idée est de faire des étages d’une hauteur telle que les gazelles puissent les atteindre et pas les hippopotames. Les premières ébauches sont très encourageantes. On peut sauter à travers les fenêtres, monter sur les toits… Sans être difficile, cela demande un minimum de prise en main (et donc du skill).

Le level-design doit donc comporter des ruelles et des petits immeubles pour être intéressant. De plus, je souhaite ajouter plus de passages intérieurs (où les gazelles seront désavantagées). Au final, je réutiliserai peu d’assets de WAR-Gizeh. D’autant plus que je me suis amélioré en terme de modélisation 3D. Je parviens à faire des modèles mieux texturés, plus fins. Je retouche donc certains modèles et refais entièrement d’autres.

improvement02 improvement03

Je me recentre aussi sur le monde d’Unreal Safari. J’ajoute un peu d’humour, un côté plus décalé et essaye de faire vivre le monde. Pour cela j’ajoute des petits objets colorés, des enseignes, des pancartes… Ceci me permet également de varier la palette de couleur (WAR-Gizeh était trop jaune dans l’ensemble). Sans revenir à l’idée d’un aspect cartoon, je donne un côté un peu rafraîchissant au mod, revenant aux idées de départ.

Cette map a atteint un niveau respectable. Je n’étais plus très loin d’une version beta testable. En tout cas, le gameplay fonctionnait bien et il y avait de quoi exploiter les caractéristiques des uns et des autres. Graphiquement également, elle a vu une amélioration nette de mes compétences. En effet, des gens ont commencé à s’intéresser à Unreal Safari pour son aspect graphique à partir de cette map. Ce n’était pas le cas avant.

gizeh_wip_15 gizeh_wip_14 gizeh_wip_11

Programmation

En terme de programmation, bien que le gameplay soit codé entièrement (jusqu’à nouveaux tests, ajustements et ajouts de features éventuelles), je n’étais pas en reste. Le game type Safari ayant atteint sa version finale, j’ai commencé à le modifier pour l’adapter à Unreal Safari. Ainsi, on n’était plus dans la “Heavy Team” mais chez les “Hippos”. De même, on ne passait plus “Niveau 4″ mais “Wild Beast”. Avec le recul, je me dis que j’aurais du intégrer ce genre de personnalisation directement dans Safari. Ce côté personnel, original, voire drôle aurait pu donner un coup de pouce par sympathie. En voulant faire quelque chose de générique, j’avais fait quelque chose de banal.

En terme de programmation, il me fallait faire également un HUD personnalisé. Contrairement à ce que l’on peut croire, c’est plus dur que l’on ne croit. En fait, pour faire un HUD, il faut avant tout supprimer tout ce qui existe. Par exemple, le score des bleus s’affiche en bleu. En fait, le moteur récupère une partie d’une texture blanc/gris puis la colore en bleu. Cela évite d’avoir des textures différentes pour chaque équipe. Cette optimisation est une bonne idée m’a posé le problème suivant : j’ai conçu mon HUD à partir de fruits (kiwi, oranges…) qui sont déjà colorés. Je devais donc trouver quelle partie du code colorait le HUD et la supprimer. Ceci n’est évidemment qu’un exemple parmi d’autres…

Un HUD est un bon moyen de personnaliser son jeu. Si j’aime les HUD discrets, je voulais ici apposer un côté cartoon. Le résultat n’était pas forcément de bon goût, mais il permettait au mod de se différencier. Je me suis aperçu qu’il est très difficile de faire quelque chose de plaisant pour tout le monde. Certains voulaient que tout soit affiché à l’écran (points d’XP, points d’XP restants pour le prochain niveau, équipe, score, frags, points de vie, munition, équipe…) et d’autres qu’il n’y ait rien et que l’on puisse tout afficher d’une pression d’une touche.

Autre point de programmation pas si évident à supprimer, ce sont tous les messages, annonces et voix intégrés au jeu. Par exemple, une voix annonce “il reste 5 frags avant la victoire”. Sauf que, techniquement, dans Unreal Safari on peut perdre des points (c’est ce qui en fait l’intérêt évidemment). Donc il peut arriver que cette annonce soit faite 3 fois en 30 secondes… C’est dans ces détails que la programmation devient désespérante. Comme dit sur le blog Conquérir le monde, quand on a fait 90% du travail, il reste 90% à faire. Et dans ce cas-là, c’est 90% qui n’apportent RIEN en terme de plaisir de jeu. Qui plus est, c’est souvent pénible à tester…

hud

http://conquerirlemonde.com/blog/category/creation-de-jeux-video/

Arme : L’AK-Banana

Avec l’AK-Banana, je suis persuadé d’avoir trouvé l’arme qui déchire et qui va faire le succès de mon mod. Le nom sonne bien, l’AK-47, l’arme originale, est très appréciée des joueurs et son design, avec deux banane à la place du chargeur est vraiment sympa. Le problème de cette arme, c’est qu’elle n’a pas d’équivalent. Je n’ai pas trouvé réellement de quoi faire d’autres armes sympas. La seule idée sympa était les grenades en noix de coco. J’avais vraiment envie de faire des armes originales .Mon influence originale était les armes de Prey qui m’avaient marqué par leur design. Même si je n’y avais pas joué à l’époque, Zeno Clash est dans la même veine avec ses armes classiques dans le fonctionnement mais originales dans leur design. Pour cet aspect-là d’Unreal Safari, j’ai simplement manqué de créativité. Peut-être que le fait de développer seul montrait ses limites.

Etant très moyen en modélisation, la création de l’AK-Banana fut douloureuse et n’atteindra pas les objectifs de départ. Cependant, son design décalé pouvait détourner (un peu) de la modélisation grossière. Il est intéressant de voir que sur mon projet actuel, c’est encore une fois l’arme qui pêche par sa modélisation.

Au niveau réussite, l’AK-Banana sera modélisé, animé et importé dans le jeu. Même si les animations sont extrêmement sommaires, sans les mains du joueurs et que l’arme n’est pas codé (cela reste un skin du Shockrifle), c’est une véritable victoire. C’est la première fois que j’arrive à importer une arme dans un jeu ! (et ce n’est pas faute d’avoir essayé, notamment quand j’essayais de modder sur Far Cry).

Au niveau échec, je n’arriverais jamais à me lancer dans le coding de l’arme (système de chargeur avec reloading, type d’impact, muzzleflash (étincelle et fumée au bout du canon). Techniquement, les armes d’UT3 étaient trop compliqué pour moi. Trop de fonctions, de paramètres à gérer, cela était incompréhensible à l’époque. Or, si je ne personnalisais pas un minimum mes armes, quel intérêt de faire une conversion totale ? En effet, il existe des mods qui reprennent le feeling du jeu original en opérant essentiellement une refonte graphique (Galactic Warfare pour Call of Duty 4 par exemple). Sans critiquer ce genre de mods, ce n’est pas ce que je recherchais.

akbanana_wip_02

http://www.moddb.com/mods/star-wars-mod-galactic-warfare

Personnage : L’Hippopotame

Je suis parvenu à faire un personnage assez simple : l’Hippopotame. Sa modélisation assez ronde était correcte même si son texturing l’aurait rendu très statique. Je pense que je me rapprochais de Bisounours Party dans le rendu. Je me voyais déjà avec une sorte de peluche mal articulée… Ceci n’arriva jamais puisque je n’ai jamais fait le rigging (c’est-à-dire le squelette du personnage) et donc encore moins l’animation.

hippo_wip_03a

http://www.moddb.com/mods/bisounours-party

Dans le prochain article, on verra les multiples (et surprenantes !) raisons qui m’ont poussé à arrêter le développement d’Unreal Safari.

Unreal Safari : Post-mortem (4)

Mercredi 21 juillet 2010 à 7:45

unrealsafari

Premier game type:  Safari

Pour information : la plupart des problèmes techniques que j’ai rencontré sur ce game type, je les ai traités par une série de tutoriels publiés sur ce même blog. Je conseille donc aux lecteurs de mes tutoriels de récupérer les sources de Safari afin de les lire. Elles seront un très bon compléments aux tutoriels.

Après avoir publié mon premier mutator, je me lance dans la conception de la deuxième partie du gameplay : la partie niveau/expérience et bonus/malus. Le but est, je le rappelle, de faire que les niveaux des joueurs influent sur le nombre de points qu’ils marquent lorsqu’ils fraggent quelqu’un. Schématiquement, quand un noob tue le meilleur joueur, il fait gagner 10 points à l’équipe, alors que quand le meilleur joueur tue un noob, il ne fait gagner qu’un point. Le tout avec 6 niveaux possibles de jeu, sachant que l’on peut perdre un niveau si on se fait fragger.

Très rapidement, je m’aperçois qu’intégrer deux mutators dans un même game type peut amener des problèmes de conflits entre eux. Je décidé alors de développer un game type, Safari, qui intègrera d’office le mutator Opposite Team. Contrairement à ce que l’on peut croire, cette histoire de niveau m’a posé beaucoup de problèmes. D’abord parce-que certaines fonctions que j’avais utilisé auparavant n’existaient que pour les mutators. De plus, ce système est beaucoup plus perméable aux bugs de fonctionnement (remise à niveau des points d’XP ou du score, problème dans le décompte des points…). Bref, plutôt qu’une adaptation d’un tutoriel existant, je me suis rapproché un peu du vrai boulot du programmeur : traquer les bugs ! Ce game type m’a aussi montré les problèmes inhérent au jeu multijoueur. En effet, la programmation ne se fait pas de la même façon pour un jeu solo ou un jeu multi. Ce côté plus complexe m’a obligé à comprendre un minimum ce que je faisais et j’ai commencé à mieux appréhender l’Unreal Script.

Autre problème : quand on fait un jeu avec des points d’expérience et des gains de niveau, on est un peu obligé de les afficher à l’écran. La première version de Safari (non publiée) était fonctionnelle mais opaque. Impossible de voir quoi que ce soit. J’ai donc commencé à travailler sur un HUD et un système de message. Pour simplifier, il me fallait :

1 - un affichage à l’écran permanent du niveau, des points d’XP, de l’équipe et du nombre de frags
2 - un message annonçant un changement de niveau (positif ou négatif)
3 - un message affichant le nombre de points d’XP gagné lors d’un frag

Ce genre d’aspect paraît relativement simple mais quand on est un débutant en programmation, tout est compliqué. Au niveau des messages, j’ai vite su faire deux messages différents : l’un disait qu’on avait gagné un niveau et s’affichait en vert, le deuxième disait qu’on avait perdu un niveau et s’affichait en orange. Très vite, il a paru essentiel de remplacer “Level Up !” par “You are Level 2 !” Après des difficultés, j’ai commencé par créer une classe par niveau. Ce qui me donnait en gros :

LevelUpOne.uc
LevelDownOne .uc
LevelUpTwo.uc
LevelDownTwo.uc

Et ainsi de suite pour les six niveaux. On voit très bien les problèmes. Car si multiplier les classes est déjà pénible et peu optimisé, c’est encore plus compliqué à l’intérieur du code (je vais essayer d’expliquer ça simplement). Quand on change de niveau (c’est détectable par du code assez simplement), le jeu envoie un message. Si les classes de messages sont séparées comme ici, on doit alors mettre des conditions :

Si je suis niveau 1 -> Message 1
Si je suis niveau 2 -> Message 2
Si je suis niveau 3 -> Message 3

Et ceci, une fois pour les gains de niveau, puis pareil pour les pertes de niveaux. Même avec seulement 6 niveaux, cela faisait des lignes de codes à n’en plus finir. Or, ajouter des lignes de code, c’est s’ajouter des risques de bugs. J’ai donc appris à optimiser un peu mes messages afin de faire :

Si je suis niveau X -> MessageUp (X)

Evidemment, il faut faire la même chose si on perd un niveau. Cette façon de faire est beaucoup plus souple également si l’on souhaite changer des choses plus tard (par exemple ajouter 5 niveaux supplémentaires !). Avec le recul, je pense qu’il est tout à fait possible d’intégrer la notion de perte/gain dans une classe de message générique, mais le gain n’était pas forcément énorme. Cette “optimisation” (car après tout faire le bourrin fonctionnait très bien !) me permettra plus tard de coder des messages qui affiche le nombre de points d’XP gagnés lors d’un frag. Pour information, le fait d’afficher le niveau qu’on a atteint lorsque l’on change de niveau n’arrivera qu’à la toute dernière version du game type !

Au niveau du HUD, je n’ai pas rencontré de difficulté fondamentale si ce n’est mon inexpérience. L’affichage d’un HUD permet aussi de débugguer le code car on a accès aux changements de données en temps réel (quand le HUD fonctionne en tout cas !). Avec le recul, c’est peut-être une des premières choses à faire quand on code un game type un peu différent.

La première beta de Safari souffre de quelques bugs que je considère comme mineurs mais qui seront abhorrés par les joueurs. Par exemple, quand on respawne, un freeze de l’écran dure une seconde. En arrivant à corriger ce genre de bugs, je me suis senti pour la première fois un programmeur.

Octobre 2009 : je publie la version 1.0 de Safari. La version est tellement proche du gameplay que je souhaite pour Unreal Safari que je décide d’apposer ma “marque” sur le nom. Ce game type intègre les deux composantes du gameplay final : expérience et équipes opposés. Techniquement, cette version est stable et fonctionnelle. Cette release aura un impact plus fort encore que les autres sur la visibilité d’Unreal Safari. En effet, en lui donnant un nom extrêmement proche, j’alimente la confusion entre le game type (=Safari) et le mod (=Unreal Safari). Résultat des courses : ModDB annonce la release de mon mod en première page et l’intègre dans les releases de sa newsletter. A ce moment là, j’atteins des pics de fréquentation sur la page d’Unreal Safari.

safari3 safari4

Malgré tout, le game play Safari reste très confidentiel (à cause d’une communauté restreinte) mais les retours sont plutôt positifs. Je travaille sur une version 1.1 publiée un mois plus tard et apportant des changements importants comme le support des bots ou l’affichage des points d’XP gagnés ou perdus lors d’un frag. J’en profite pour préciser que si une release est toujours un moment excitant, publier un correctif ou une nouvelle version est encore plus fort. En effet, on a vraiment l’impression de progresser en lisant la liste des améliorations apportées.

Au niveau des releases, j’ai impliqué une nouvelle fois la communauté française. J’ai ainsi publié le game-type sur les forums spécialisés. Une fois que j’ai pu constater qu’il n’y avait pas de bug majeur, je lançais une release plus large sur des forums et sites plus fréquentés (forums Epic, BeyondUnreal et bien sûr ModDB). J’en profite pour remercier une nouvelle fois la communauté Unreal.fr, dont les conseils en terme de gameplay sont toujours pertinents !

Au final, la mise en place du gameplay Safari m’a permis de vraiment comprendre comment fonctionnait le code de l’Unreal Script et m’a obligé à apprendre à la débugguer et surtout l’optimiser. La version 1.1, aboutie et fonctionnelle, est la preuve vivante que l’Unreal Script (contrairement à ce qu’on lit partout !) est facile d’accès si on est prêt à mettre les mains dans le cambouis. En partant de zéro, il m’aura fallu 4 mois environ pour coder un game type pas si simpliste qui fasse pas trop bidouillé (c’est-à-dire avec un habillage cosmétique cohérent et ergonomique).

Avec le recul, ce game type est peut-être mon plus grand accomplissement dans l’aventure Unreal Safari. Car j’ai ajouté une cartouche à mon fusil de moddeur : celle de programmeur. Et vu le manque de codeurs dans le paysage du modding, ce n’est pas rien !

http://www.moddb.com/mods/unreal-safari/downloads/safari-11-game-type

Unreal Safari : Post-mortem (3)

Mardi 20 juillet 2010 à 10:08

unrealsafari

Premier mutator : Opposite Team

Après avoir publié une map, j’ai pris la décision de me lancer dans la programmation. En effet, j’ai eu conscience à ce moment là que tant que je n’aurais pas un embryon de gameplay codé, je ne pourrais pas réellement faire du level-design. Un exemple simple pour illustrer ça : certains animaux sautent plus haut que les autres et un des intérêts est de pouvoir prendre des raccourcis auxquels les autres animaux n’ont pas accès. Mais tant que je ne sais pas à quelle hauteur saute tel animal, difficile de construire une map…

Dans le cadre d’une modification d’un jeu Unreal Tournament 3, il y a plusieurs niveaux :

1 - le mutator : change un aspect mineur du jeu (par exemple, les joueurs démarrent avec un seul point de vie)
2 - le game type : change les règles du jeu (par exemple, un capture the flag avec un seul flag central)
3 - le mod : change le game-type mais aussi des éléments du jeu (par exemple, de nouvelles armes)
4 - la totale conversion (TC): change entièrement le jeu (normalement, on ne doit plus voir que l’on joue à UT3)

Evidemment, comme beaucoup de modders, mon rêve était la TC. C’est la façon de modder la plus prestigieuse mais aussi la plus difficile. M’appuyant sur des tutoriaux, je décide de faire petit à petit, à savoir de faire d’abord un mutator, de le complexifier en game-type, puis d’ajouter les armes, puis de tout finaliser. Je pense que c’est à ce moment que j’ai pris la meilleure décision… En effet, en devant coder du gameplay, ça me poussait à fixer mon gameplay.

C’est à ce moment-là que j’ai finalisé mon gameplay. Au final, il était bien plus original qu’à l’origine. Il se basait sur deux équipes, les hippopotames et les gazelles. Deux idées principales fixaient le gameplay :

1 - Les deux équipes sont très différentes : les hippopotames sont lents mais résistants, les gazelles sont rapides, sautent haut mais meurent vite
2 - Quand un joueur fragge un autre, il gagne un certain nombre d’XP et le joueur fraggé en perd… De plus, tuer un bon joueur rapporte plus de points d’XP.

Pour la première idée, rien de très nouveau, cela a déjà été exploité, mais je préférais cette idée à un système de classe encore plus classique et utilisé dans 90% des mods existants… La deuxième idée, avec la perte d’un niveau, était selon moi plus originale. En effet, il devenait possible de perdre un niveau (qui représentait plutôt le skill plus que l’expérience d’ailleurs). De plus, le meilleur joueur devient clairement l’homme à abattre. Plutôt que de le fuir (oui, je suis comme ça, j’avoue), ça vaut le coup d’essayer de l’abattre. C’est valorisant pour un noob qui peut devenir utile à l’équipe (car plus on est nul, plus on rapporte de points quand on fraggue). Ce sentiment d’injustice est compensé par le fait qu’un gros joueur se sent une grosse responsabilité : il ne doit absolument pas mourir.

L’idée de départ était de développer un mutator pour chaque idée et de les mixer dans un game type. En effet, développer un mutator (simple) n’est pas trop compliqué avec les tutoriaux adaptés. Le tout est d’avoir une idée. Au final, je ferai différemment.

oppositeteam1-1

Je commençais donc à coder le premier mutator (avec les équipes antagonistes) : Opposite Team. Bien qu’annoncé comme une part d’une future Unreal Safari, j’avais alors prévu de le publier, afin de tester son effet réel, de me faire de la pub. En effet, une release, c’est toujours mieux qu’un screenshot (sauf si elle est bugguée à mort bien sûr). Je passe sur les difficultés pour un noob de la programmation Unreal Script (je n’avais codé qu’en Visual Basic des années avant et uniquement des choses très simples). Globalement, ce ne fut pas très compliqué, et j’ai pu ne publier qu’une version, car elle était fonctionnelle. Par contre, graphiquement, le tout était très limité. Peut-être ai-je négligé à ce moment-là l’aspect cosmétique (changer la phrase : “You are in Red Team” en “You are in Heavy Team”).

Une nouvelle fois, je m’appuyais sur la communauté pour tester et critiquer mon travail. Je publiais également le code du mutator afin d’aider les apprentis codeurs (je le conseille toujours d’ailleurs pour ceux qui se lancent là-dedans). La communauté a confirmé plusieurs choses très importantes

1 - pas de bug
2 - équilibrage correct
3 - idée sympathique et rafraîchissante

Certains détails inhérents à UT3 m’étaient complètement passé au-dessus de la tête. Ainsi, un joueur m’a dit que le gros avantage de l’équipe rapide était d’aller piquer les power-ups… Je n’y avais pas du tout pensé ! Encore une fois, il est essentiel de tester son jeu aussi bien avec des joueurs moyens qu’avec des joueurs aguerris.

Outre le fait de me prouver que j’étais capable de programmer, j’ai augmenté la visibilité de mon travail et eu un début de confirmation que les idées de gameplay d’Unreal Safari pouvaient être sympas. En revanche, en tant que mutator, Opposite Team n’a a priori pas eu de succès. Il faut dire que la promotion a été minimale. Ici, j’ai peut-être été pénalisé par le fait que je jouais peu à UT3. N’étant pas régulier sur certains serveurs, je n’ai pas eu l’occasion de le faire implanter afin d’élargir ma publication. Après, il faut aussi rappeler qu’UT3 étant peu joué, un mutator anecdotique a peu de chances de trouver un endroit où être joué !

En conclusion, aussi simpliste soit Opposite Team pour un codeur expérimenté, une fois encore j’ai publié quelque chose. J’ai finalisé une partie de mon projet. Je me suis prouvé que j’étais capable de programmer quelque chose tout comme je m’étais prouvé que je pouvais publier une map correcte. Et à force de publier des créations, on prend confiance. De façon plus narcissique, publier des produits finis permet aussi plus tard d’être pris au sérieux lorsque l’on veut intégrer une équipe (sérieuse). Avoir modélisé une salle ou avoir des bouts de code, ça ne sert pas à grand chose. Mieux vaut voir petit, faire simple et finir les choses. Car finir les choses, ça amène d’autres problèmes, comme la correction de bugs. On en avait parlé pour WAR-Gizeh, on en reparlera dans la prochaine partie !

http://www.moddb.com/mods/unreal-safari/downloads/opposite-team-mutator

Unreal Safari : Post-mortem (2)

Lundi 19 juillet 2010 à 16:12

unrealsafari

La première map : WAR-Gizeh

Après les premières hésitations, je me met à travailler sérieusement sur une map dans l’environnement Gizeh. Pour y aller petit à petit, je tente d’abord des maps uniquement extérieures, avec des temples ouverts sur le ciel. A force de recommencer, je commence à avoir une bibliothèque de modèles assez importante qui me permet, quand je redémarre une version de la map (ce qui arrive assez souvent) de ne pas passer des journées entières à tout refaire. Je travaille pas mal la modélisation modulaire qui permet de modéliser de façon plus souple.

Cependant, les brouillons de maps n’atteignant jamais une version suffisante. Je ne peux donc pas vraiment tester ces layouts en terme de gameplay. Lassé par la grande taille des maps Warfare, je décide alorsd’essayer de faire une version 100% dans un village. Le côté confiné est un désavantage certain, mais il me permet de mieux maîtriser les déplacement des joueurs. Avec le recul, cette idée était très mauvaise. Ce genre de map n’est pas du tout adaptée au mode de jeu. Je revenais à mes (mauvais) réflexes de level-designer pour Counter-Strike : Source.

Techniquement, les rendus rappellent UT2003/2004. J’apprends alors à utiliser à bien les textures de type normal maps (relief), specular maps (reflets) et shadow maps (ombres). Cela m’a pris du temps, me demande souvent plus de travail, mais j’obtiens enfin eu un rendu in-game supérieur à ce que je faisais sous Source. Il m’aura fallu des mois pour ça.

Une fois ces techniques maîtrisées, je redémarre une dernière fois WAR-Gizeh. Globalement, la réalisation de la map ne posera pas de problèmes particuliers. Mon idée ici est de publier une map Warfare (c’est-à-dire pour UT3) que je modifierai ensuite pour mon mode “Warfare pour animaux”. En effet, à ce stade, le mode de jeu prévu pour Unreal Safari est une Warfare sans véhicule. Pour ceux qui ont joué à ce mode de jeu, ils comprendront sans peine que :

1 - inutile de faire un mod pour ça
2 - les véhicules sont un des grands intérêts du mode Warfare

Cependant, l’idée de faire une map publiable est certainement la meilleure idée que j’ai eu ici. Car elle me permettait de me prouver que j’étais capable de faire une map avec 90% d’éléments custom sur l’Unreal Engine. Le layout est pas mal mis en cause et changera au fil des bétas. Très vite, j’apprend à écouter la communauté, même si ses exigences sont parfois décourageantes. Ajouter des points de contrôle par exemple demande énormément de boulot, car il ne faut qu’ils ne soient pas destructible de trop loin (donc il faut les protéger). De même, ajouter des véhicules implique un équilibrage pas toujours évident. Au final, en écoutant les remarques, la map a pris beaucoup en intérêt stratégique car au départ, il n’y avait pas beaucoup de possibilités de jeu et la map devenait vite répétitive. Il est à noter que la communauté m’a poussé à faire une version Necris en plus afin de plaire au plus grand nombre !

layout

WAR-Gizeh ne sera jamais utilisé pour Unreal Safari. Mais ce n’était pas une perte de temps car elle m’a permis de :

1 - Me faire connaître un peu dans la communauté
2 - Constituer une banque de modèles et de textures pour Unreal Safari
3 - Apprendre de nombreuses techniques supplémentaires
4 - Travailler le level-design d’un mode de jeu pour lequel je n’avais jamais mappé
5 - Me prouver que ma “patte” graphique était appréciée et considérée comme original

Il est à noter que plusieurs mois après la release, j’ai été contacté par des joueurs qui voulaient que je corrige les quelques soucis restant sur cette map. Contrairement à ce que je croyais, cette map a donc été jouée sur certains serveurs.

Je termine là-dessus afin de préciser l’importance des avis de la communauté. J’ai eu la chance de faire partie de communautés pertinentes (bien que peu nombreuses) qui m’ont soit aidé techniquement, graphiquement ou au niveau du gameplay. Sans eux, je ne serais pas allé loin. Ces communautés sont Mapping-Area, Unreal.fr et Unreal-Design.

beta_2_01 beta_2_07 beta_2_06

Liens : http://www.moddb.com/mods/unreal-safari/addons/war-gizeh

UnrealScripter #4

Lundi 19 juillet 2010 à 7:48

unrealscripter

VI. HUD

Attaquons-nous aujourd’hui à notre premier HUD. Comme je l’ai dit précédemment, j’ai codé le HUD avant tout pour contrôler que les modifications dans le code fonctionnaient ! Et cela a toujours été le cas dans mes projets. Il est important de savoir faire un HUD (même moche) afin de suivre en direct l’évolution des variables du jeu. Il est également possible, dans la même optique, d’ajouter des messages dans le console, mais ce n’est pas l’objet de ce tutoriel.

Une fois pris en considération qu’il n’y aura ici AUCUN souci esthétique, on va pouvoir se lancer. Avant tout, il existe désormais deux types de HUD dans l’UDK. Depuis la version de mai (attention à bien vérifier la version que vous utilisez) a été intégré Scaleform GFX, une technologie permettant l’affichage d’interfaces 3D interactives. L’avancée en termes graphiques est importante mais l’accessibilité est beaucoup moins évidente. Heureusement, il est toujours possible de créer des HUD à l’ancienne en ajoutant une simple ligne de code dans les defaultsproperties de TT_Game.uc :

bUseClassicHUD = true;

Surtout, n’oubliez pas de changer ça le jour où vous voulez faire une interface 3D !

Pour être honnête, je précise que l’on va ici utiliser une fonction qui ne vient pas de moi, DrawTexting(). Je l’ai adaptée à partir d’un tutoriel ou d’un exemple mais je ne sais plus d’où.

Commençons par créer le fichier, TT_HUD.uc :

TT_HUD extends UTHUD;

Je précise qu’il existe une classe UTTeamHUD qui prend en compte l’équipe dans laquelle on joue pour dessiner le HUD (simplement, ça permet de faire que si on est dans l’équipe bleue, certains textes et images du HUD se colorent en bleu). Je vous laisse donc adapter à ce que vous voulez faire. A ne pas oublier : dire à notre jeu qu’il doit utiliser ce HUD ! On doit doit ajouter la ligne suivante dans les defaultproperties de notre [b]TT_Game.uc[/b].

HUDType=Class’TT_HUD’

Ici, nous allons utiliser (comme toujours pour faire un HUD) des fonctions issues de Canvas.uc. Une nouvelle fois, je vous conseille d’aller jeter un coup d’oeil à cette classe pour voir un peu l’éventail de fonctions qui y existent.

simulated function DrawTexting (UTHUD H, float X, float Y, string Text)

{

if (H == None || H.Canvas == None) return;

// Simule une résolution de 1024*768

X = X * H.ResolutionScaleX;

Y = Y * H.ResolutionScale;

H.Canvas.Font = class’Engine’.static.GetMediumFont();

H.Canvas.SetPos (X, Y);

H.Canvas.DrawColor=WhiteColor;

H.Canvas.DrawText (Text, false);

}

En observant les variables de cette fonction, on a d’abord un HUD (pour savoir pour quel joueur on affichera le texte), des positions X et Y sur l’écran et le texte à écrire. La première condition (H == None || H.Canvas == None) vérifie si le HUD cité correspond à quelque chose et si ce n’est pas le cas, la fonction ne fait rien. Ensuite, la première partie simule un écran d’une taille donnée. En effet, chaque joueur ayant une résolution différente, il faut arriver à coder quelque chose de générique qui fonctionnera sur chaque écran. Globalement, l’idée est d’arriver à une notion de pourcentage plutôt que de nombre de pixels.
Les conditions suivantes sont celles qui vont déterminer la police d’écriture. On utilise ce genre de fonction pour les appeler :

class’Engine’.static.GetMediumFont()

On verra dans un autre tutoriel comment changer les polices d’écriture par défaut.

On utilise ensuite SetPos pour déterminer la position, DrawColor pour la couleur et DrawText pour dessiner le texte. On peut remarquer qu’une fonction, DrawText(), existe donc déjà. Cependant, en créant la notre, on la complexifie beaucoup (il suffit de voir déjà le nombre de variables) et on l’adapter à nos besoins. Il existe également une fonction qui dessine un texte en le centrant. Sans surprise, on trouve DrawTextCentered() dans Canvas.uc.

Pour le moment, on a codé notre base, c’est-à-dire la fonction qui nous permettra d’afficher du texte. Maintenant on va coder la fonction qui permettra d’exécuter cette fonction (un grand classique). Appelons la DrawLevel. Cette fonction a pour but d’afficher le niveau du joueur et son nombre de points d’expérience. Pour cela, on aura shématiquement deux lignes lançant deux fois la fonction DrawText. Reste à récupérer le niveau et points d’XP. Pour cela, on va créer deux nouvelles fonctions…

function int PickLevel(Controller c) //Récupère le Niveau

{

local int WhatLevel;

WhatLevel = TT_PRI(c.PlayerReplicationInfo).Level;

Return WhatLevel;

}

Encore une technique classique. Ici, la fonction PickLevel a pour variable un Controller, car on veut récupérer le niveau d’un joueur précis. On remarque dans la déclaration de la variable le “int”. Cela veut dire que quand je lance la variable, elle va me donner un nombre entier. Par exemple, si je fais PickLevel(Joueur); cela donnera 1, 2, 3 ou 4, etc. On peut évidemment déclarer des functions avec des floats, strings, booléens, etc.

Ici, on a donc déclaré une variable locale, on la définit comme égale au niveau du joueur. Et ensuite on retourne cette variable. Le résultat de la fonction est donc “WhatLevel”. Rien de bien compliqué ici. Je vous laisse faire la même fonction PickXP qui est exactement la même, il suffit de changer “Level” en “XP” (essayez de la refaire sans regarder l’autre, ce sera formateur !).

Maintenant que l’on a toutes nos fonctions, on peut passer à celle qui nous intéresse réellement !

simulated function DrawLevel(UTHUD H)

{

DrawTexting (H,10, 180, ” XP : ” @ PickXP(PlayerOwner));

DrawTexting (H,10, 200, ” Level : ” @ PickLevel(PlayerOwner));

}

A force de faire des fonctions annexes, notre fonction de base se trouve bien simplifiée ! Il faut comprendre que le fait de faire des sous-fonctions permet d’éviter de s’embrouiller dans les variables et surtout de les réutiliser ailleurs. Typiquement, une fonction comme DrawLevel sera certainement utilisable ailleurs (pour afficher des résultats par exemple). On remarque que j’ai décalé en hauteur (3ème variable, Y) les textes pour qu’ils ne soient pas l’un sur l’autre. La variable PlayerOwner est à retenir. C’est un PlayerController est défini dans HUD.uc (et donc aussi à UTHUD.uc qui en dérive) et désigne le joueur qui utilise ce HUD.

Terminé ? Pas du tout ! Nous n’avons pas lancé la fonction DrawLevel ! Pour cela, rien de compliqué, le tout c’est ne pas oublier de le faire !

function DisplayScoring()

{

Super.DisplayScoring();

DrawLevel (self);

}

La fonction DisplayScoring affiche le score (ha bon ?). On y ajoute discrètement notre fonction. Ici aussi, il est intéressant de voir la variable “self” qui dit donc que DrawLevel doit utiliser le HUD dans lequel il est lui-même. Cela peut paraître évident, mais ça ne l’est pas du tout. Par exemple, on pourrait très bien faire un jeu qui afficherait les points de vie de ses coéquipiers !

Voilà, c’est tout pour aujourd’hui. Notre HUD est très simple, voir moche mais permet de jouer en visualisant son niveau et ses points d’XP. Avec nos compétences actuelles, on peut très bien afficher également le nombre de points d’XP restants jusqu’au prochain niveau. N’hésitez surtout pas à utiliser la base du code pour l’adapter à vos besoins.

Dans le prochain tutoriel, on tentera (j’espère) le mode Furie !

UnrealScripter #3

Vendredi 16 juillet 2010 à 13:13

unrealscripter

IV. D’autres variables utilisables

PREREQUIS : il est important d’avoir lu les tutoriels correspondants précédents afin d’avoir la suite du code. Le code des anciens tutoriaux a été corrigé, il comportait quelques petites erreurs.

Certaines variables sont déjà dans le code de l’UDK et il n’est pas nécessaire de les réécrire dans votre propre code. Les plus utiles seront notamment :

GroundSpeed : vitesse de déplacement

JumpZ : hauteur de saut

Health : points de vie

Ces variables sont définies dans le fichier Pawn. Je Si on farfouille un peu dans le fichier Pawn.uc (dont dérive ensuite UTPawn.uc) on peut voir les multiples variables qui existent. Je vous laisse le faire car il y en a énormément. Inutile donc de s’embêter à tout refaire. Pour les définir, on utilise l’arborescence du code :

Controller -> Pawn -> Health

C.Pawn.Health = 100 ;

Pour notre jeu, nous allons faire en sorte que le joueur retrouve ses points de vie quand il gagne un niveau et qu’il gagne en vitesse et en hauteur de saut. Ceci, bien qu’apparemment très simple, va nous perdre de réfléchir un peu à la conséquence de nos actes. En effet, on aurait tendance à écrire simplement une ligne de code donnant 100 points de vie à notre joueur. Faux ! Si jamais le jeu a des power-ups permettant de dépasser cette limite, il faut vérifier avant que le joueur n’a pas déjà plus de 100 points de vie. Sinon, ça reviendrait à lui baisser la santé ! Comme récompense, il y a mieux…

Ici, on va utiliser deux variables OldLevel et NewLevel qui vont nous permettre, simplement, de vérifier si le joueur a changé de niveau. C’est une astuce toute bête, mais très pratique. Il suffit de définir OldLevel avant que l’on lance la fonction proprement dite, puis de définir NewLevel juste après et de les comparer.

Function CheckLevel(Controller C)

{

Local TT_PRI PRI ;

Local int OldLevel;

Local int NewLevel;

PRI = TT_PRI(C.PlayerReplicationInfo) ;

OldLevel = PRI.Level; //définissons le niveau actuel du joueur

if (PRI.XP <= 100)

{

PRI.Level = 0;

}

else if (PRI.XP <= 200)

{

PRI.Level = 1;

C.Pawn.GroundSpeed = 520.0000 ;

C.Pawn.JumpZ = 400 ;

}

else

{

PRI.Level = 2;

C.Pawn.GroundSpeed = 600.0000 ;

C.Pawn.JumpZ = 450 ;

}

NewLevel = PRI.Level;

if (NewLevel != OldLevel)

{

if (C.Health <= 100)

{

C.Health =100;

}

else

{

}

}

else

{

}

}

Ce code est intéressant car il comporte une condition (if, else if, else…) à l’intérieur d’une autre condition. D’où l’importance de hiérarchiser son code (avec des tabulations). Techniquement, cela ne change rien lors de la compilation, mais cela permet de mieux visualiser ce que l’on a fait. Imaginez vous reprendre un code écrit des mois auparavant qui fait 4 pages… Evitons donc de nous poser des problèmes !

V. Messages

Comme mon code ne marchait pas (il se compilait mais in-game, rien ne se passait), j’ai programmé en vitesse l’affichage d’un message afin de voir si les niveaux changeaient. Maintenant que c’est fait, autant l’intégrer dans le tutoriel !

Pour afficher des messages proprement, il nous faut une autre classe. Appelons là TT_MessageLevel.uc . On verra plus tard qu’il est tout à fait possible d’intégrer plusieurs types de messages dans une même classe. Une classe de messages dérivent la plupart du temps de LocalMessage.uc. Une bonne idée est d’ouvrir cette classe pour voir ce qu’elle comporte ! Ici on va utiliser uniquement la fonction GetString(), sans utiliser toutes ses options :

class TT_MessageLevel extends LocalMessage;

static function string GetString(

optional int Switch,

optional bool bPRI1HUD,

optional PlayerReplicationInfo RelatedPRI_1,

optional PlayerReplicationInfo RelatedPRI_2,

optional Object OptionalObject

)

{

return “Level UP”;

}

defaultproperties

{

bIsPartiallyUnique=True

bIsConsoleMessage=False

bBeep=False

Lifetime=5

DrawColor=(G=255,R=50,B=50)

PosY=0.9

FontSize=3

}

Rien de bien compliqué ! Pour information je vous ai laissé quelques propriétés par défaut très pratiques comme Lifetime (en secondes), bBeep (qui permet de faire du bruit lorsque le message s’affiche), PosY (qui ici indique que le message se affiché en bas de l’écran), FontSize (plus le nombre est grand, plus l’écriture est grande) et DrawColor (qui permet de définir la couleur du message). On voit qu’avec quelques propriétés, on a déjà de quoi personnaliser un peu son message ! Bien sûr, je n’ai pas inventé ces propriétés, il suffit d’ouvrir LocalMessage.uc pour les découvrir. Je me répète mais il est essentiel de lire (ou même juste parcourir) les classes dont dérivent les autres pour bien comprendre l’UnrealScript.

Cependant, il paraît évident que l’on préfèrerait un message qui nous précise notre niveau. Pour ça, on va utiliser la variable Switch de la fonction GetString(). Simplement, quand on va envoyer le message, on peut ajouter un nombre comme variable (=Switch).

static function string GetString(

optional int Switch,

optional bool bPRI1HUD,

optional PlayerReplicationInfo RelatedPRI_1,

optional PlayerReplicationInfo RelatedPRI_2,

optional Object OptionalObject

)

{

return “YOU ARE LEVEL ” @Switch;

}

Retenez bien le coup du “@” car c’est très important pour faire des HUD/Messages intéressants et personnalisés.

Reste maintenant à envoyer le message. On retourne donc dans TT_Game.uc. Un message se lance de la façon suivante :

PlayerController(C).ReceiveLocalizedMessage(class’TT_MessageLevel’, UnInteger);

Ici, “UnInteger” sera le niveau du joueur et définira le Switch du message. Avec la fonction complète, ça donne :

Function CheckLevel(Controller C)

{

Local TT_PRI PRI ;

Local int OldLevel;

Local int NewLevel;

PRI = TT_PRI(C.PlayerReplicationInfo) ;

OldLevel = PRI.Level; //définissons le niveau actuel du joueur

if (PRI.XP <= 100)

{

PRI.Level = 0;

}

else if (PRI.XP <= 200)

{

PRI.Level = 1;

C.Pawn.GroundSpeed = 520.0000 ;

C.Pawn.JumpZ = 400 ;

}

else

{

PRI.Level = 2;

C.Pawn.GroundSpeed = 600.0000 ;

C.Pawn.JumpZ = 450 ;

}

NewLevel = PRI.Level;

if (NewLevel != OldLevel)

{

if (C.Health <= 100)

{

C.Health =100;

}

else

{

}

PlayerController(C).ReceiveLocalizedMessage(class’TT_MessageLevel’, NewLevel);

}

else

{

}

}

Quand j’ai commencé à coder, j’avais créé un message pour chaque niveau et j’avais remis plein de conditions pour savoir quel message coder. Ici, le code est plus malléable et permet de fonctionner, quel que soit le nombre de niveaux.

Dans le prochain tutoriel, on verra comment ajouter un HUD très simple (je l’ai créé car le code ne marchait pas et que j’avais besoin de visualiser les XP/Level).

ps : pour les personnes déçues qui espéraient un mode Furie, j’ai eu des problèmes pour le coder. Quand on programme, on a beau être quasiment sûr de savoir faire quelque chose, on ne peut jamais être certain d’aller au bout…

Unreal Safari : Post-mortem (1)

Dimanche 11 juillet 2010 à 12:40

Introduction

En juin 2008, lassé par les problèmes d’optimisation de mes maps pour Counter-Strike : Source, fatigué d’être bridé pour les éclairages (notamment dynamiques), je décide d’acheter Unreal Tournament III pour pouvoir faire les maps de mes rêves. En substance, j’espère créer un mod, ayant toujours plein d’idées pour ça. Au départ, j’espère qu’un de mes concepts amènera du monde et que je ne serais “que” mappeur/level-designer/game-designer/leader. Bref, un grand classique du newbie qui va se planter.

Je pense qu’il est important de préciser mes compétences de l’époque.

Mapping (trois maps publiées)
gg_techcenter (version finale) : une map simple avec un design 90% custom, plutôt bien accueillie
cs_bladerunner (version beta) : une map à objectif bien accueillie, graphiquement originale et avec une gameplay qui tient la route
gg_paintball 69 (version beta) : une map sur commande, très incomplète et moche

Modeling
Beaucoup de bidouillages. Les modèles 3D sont souvent très simples et/ou comportant des défauts majeurs de modélisation. Quelques modèles simples (caisses, cylindres, tuyaux) ont été intégrés à mes maps et n’ont pas choqué.

Programmation
Des notions de base. Programmation sur calculatrice, maple (à visée purement mathématique) et programmation d’un casse-brique (très peu abouti) en Visual Basic.

A la vue de tout ceci, il paraît inconcevable que, quelques semaines plus tard, je décide de me lancer dans une Total Conversion (TC) pour Unreal Tournament III ! (je rappelle qu’une TC est un mod qui change absolument TOUT dans un jeu. On a l’impression que c’est un nouveau. Cela demande un travail colossal).

Le concept

Le concept de base d’Unreal Safari est assez ambitieux. Le jeu est multijoueur, 4 classes sont jouables, 3 modes de jeu, le tout dans plusieurs environnements différents.

Les classes : ce sont ici des animaux, chacun possédant ses caractéristiques (essentiellement la vitesse, hauteur de saut, armure, points de vie et mana), une arme de prédilection et une attaque spéciale.

Les modes de jeu : ils évolueront beaucoup, mais au départ l’idée est de faire une refonte du mode Warfare d’UT3, du Team Deathmatch et un mode Hunt où un joueur joue contre tous les autres. Tout ceci sera affiné par la suite. A ce moment là, j’ai plus un univers graphique en tête plus qu’un gameplay défini.

Les armes : Les armes sont des versions modifiées d’armes existantes. Toutes fonctionnent avec des bananes comme chargeur.

Les environnements : L’originalité ici est l’Afrique (même si Far Cry 2 l’a exploité). Les environnement prévus étaient Gizeh (désert et Afrique du Nord),  Madagascar (île luxuriante), Offshore (plateformes pétrolières) et Kilimandjaro (savane).

A cela, j’ajoute l’idée d’un graphisme cartoon pour compenser mes lacunes en modélisation et un aspect humour. Cet aspect humour, que j’intègre à la base à toutes mes productions, est souvent le plus difficile à garder pour plein de raisons. J’y reviendrai plus tard. Au final, Unreal Safari avait un concept assez proche de mods comme Bisounours Party.

Un game-design document est réalisé, assez précis, des concepts et des artworks sont dessinés. Tout est prêt. Il ne reste plus qu’à s’y mettre.

premier palmier, type cartoon !

premier palmier, type cartoon !

Les premiers pas

Rapidement je prends conscience que j’y arriverai jamais. Je décide alors de couper le mod en releases “par morceaux”. Dans la première, il n’y aura “que” deux personnages et armes jouables, sur une seule map, dans un seul mode de jeu. Cela peut paraître restrictif (et ça l’est !), mais il était essentiel de définir un objectif atteignable afin de garder la motivation. Cependant, aussi “petit” soit cet objectif, il était déjà démesuré étant donné que la plupart des choses à faire pour ce mod, je ne savais pas du tout comment les effectuer…

Comme c’est ce que je sais faire de mieux, je pars dans la conception des maps. C’était une erreur magistrale (comme on verra dans le détail plus tard). En effet, sans un embryon de gameplay ou de programmation, difficile de faire du level-design efficace.

Etant seul, je dois faire un choix et ne pas m’éparpiller. Je dois choisir un environnement, créer des modèles et textures correspondants et faire une map dans un mode de jeu donné. Evidemment, je vais rapidement changer mes choix et passer d’un environnement à l’autre. Si certaines choses pourront être récupérées (caisses, tables, ponton…), beaucoup sont trop typées pour cela (pyramides, obélisques…) .

Gizeh - première version

Gizeh - première version

A l’origine, je démarre par l’environnement Gizeh et ses pyramides. Le côté égyptien étant assez attractif, l’impact visuel est vite sympa. On remarque que dans les tous premiers modèles, j’essaie d’incorporer un côté fun. Cela doit détourner les éventuels joueurs du fait que mes modèles sont très (même trop) simples. Faire tous mes modèles 3D me prend beaucoup de temps pour des résultats pas toujours concluant. J’abandonne rapidement le fait de devoir faire un aspect cartoon (pour les maps en tout cas) qui est finalement plus difficile à faire que de faire quelque chose de réaliste.

Je finis par abandonner Gizeh et me lance dans l’environnement Kilimandjaro. Il en sort des trucs sympas, mais la map en elle-même, pour un mode typé Warfare, est beaucoup trop petite et trop plate. Cependant, je fais de gros progrès en ajoutant pas mal de features qui m’avaient incité à passer sur UT3 au départ : effets postprocess (bloom, deep of field), eau plus réaliste… Je travaille également sur les terrains et fais de gros progrès. Cela me semble plus intuitif que les displacements sous Source. Avec les textures made in UT3, ils rendent tout de suite de façon sympathique. Cependant, les défauts de level-design sont trop importants et je décide d’abandonner de nouveau cette map pour travailler sur une map TDM dans le milieu Offshore. Deux avantages pour cela : je peux utiliser les modèles d’UT3 et la map sera plus petite.

Kilimandjaro

WAR-Kilimandjaro

DM-Offshore m’a permis de comprendre beaucoup de choses sur le fonctionnement de l’UnrealEditor. Au lieu de focaliser sur la création d’assets, je pouvais faire du mapping pur (comme au temps où j’utilisais Source). Cela m’a permis de travailler notamment les éclairages (qui sont certainement l’un de mes points forts en mapping). Rapidement, je me suis aperçu que l’UnrealEngine n’était pas forcément l’eldorado tant attendu.

L’autre problème est que les modèles d’UT3 sont particulièrement beaux. Résultat : à côté des miens, on voit trop la différence. L’idée de pouvoir utiliser les modèles d’UT3 s’est vite estompée, à part pour des cas particulier, notamment naturels (eau, cascade, arbres, plantes, ciel, etc.).
A ce moment là, mon ordinateur a planté, m’obligeant à formater le tout. Je n’ai pas tout perdu pour autant (heureusement), mais cela m’a incité à tout reprendre. J’ai alors retravaillé entièrement les layers de mes maps et suis reparti sur l’environnement (jaune) de Gizeh. On pourrait croire que j’ai beaucoup tourné en rond en quelques mois (on est en février 2009, soit 6 mois après le début du projet), mais comme je ne connaissais rien à l’Unreal Editor et que je modélisais à la truelle, les avancées ont été importantes, bien que rien ne soit réellement utilisable pour un futur mod.
La suite au prochain épisode, avec les premières releases !

DM-Offhore

DM-Offshore

Quelques liens en rapport avec l’article :

Unreal Safari : http://www.moddb.com/mods/unreal-safari
Bisounours Party : http://www.moddb.com/mods/bisounours-party
gg_techcenter : http://www.fpsbanana.com/maps/51213
gg_paintball69 : http://www.fpsbanana.com/maps/55405
cs_bladerunner : http://www.fpsbanana.com/maps/55119

pageTracker._initData(); pageTracker._trackPageview(); } catch(err) {}