Little Blog Story

Game-Design & Modding le blog de belzaran.

Articles taggés avec ‘game type’

Making-of : Hunt

Mardi 17 août 2010

Introduction

Little God Story est un projet passionnant mais particulièrement long à mettre en place. Ayant été habitué ces dernières années à publier du contenu régulièrement (maps, mutator, game type…), je me sens quelque peu frustré par cet aspect-là du développement. Ayant progressé fortement en programmation suite à mes travaux sur Little God Story, j’ai décidé de programmer un game-type pour Unreal Tournament III  : Hunt. Ce game-type était prévu pour Unreal Safari à l’origine (cf le post-mortem consacré au mod). J’ai décidé de le développer tranquillement et de publier ici les différentes avancées, sous forme d’un making-off. Quand j’aurais terminé (si je termine), je publierai les sources annotées pour aider les personnes souhaitant de mettre à l’UnrealScript.

L’idée ici est d’aller vite. Il n’est pas du tout prévu de développer des maps pour ce game-type ou de reprendre le développement d’Unreal Safari.

Concept du mode

Le mode Hunt est assez simple dans son fonctionnement. Un joueur est la cible. Tant qu’il n’est pas tué, il accumule des points. Quand il est fraggé, le tueur devient la cible et ainsi de suite. Il me semble que ce mode existe déjà dans plusieurs jeux mais je suis bien incapable de dire lesquels. N’hésitez pas à combler cette lacune culturelle dans les commentaires…

Une autre particularité (héritée d’Unreal Safari) est que la cible est très fragile. Elle a peu de points de vie mais court vite et saute très haut, pouvant prendre des raccourcis. Les tueurs sont lents mais très résistants. Si bien que la cible a intérêt à fuir plutôt qu’à chercher le combat.

A ce niveau, la question de l’équilibrage ne se pose pas encore. L’idée est de séparer les différentes façons de faire des points et de rendre leur changement aisé. Ici, il y a trois façons de faire des points :

  • Être la cible
  • Tuer la cible
  • Être la cible et tuer un chasseur

On peut également envisager un malus :

  • Être un chasseur et tuer un chasseur

Conception du code

Ici, je parle de la conception du code avant de plonger les mains dans le bousin. Rien ne dit donc que ça va marcher. A l’époque d’Unreal Safari, j’avais commencé à bosser sur ce mode. En fait, il y a une façon dont je l’ai envisagé qui me paraît mauvaise et compliqué : construire le mode comme un jeu d’équipe. L’équipe rouge chasse, l’équipe bleu est chassé. Si la cible est tué, elle passe dans l’équipe rouge et le tueur passe dans l’équipe bleu. Cela permet également de gérer simplement les friendly fire. Cependant, il faut bien prendre en compte que le mode Hunt n’est pas un feu d’équipe ! Chacun joue pour lui et seul le premier sera vainqueur. C’est une variante du mode Deathmatch. Changer le TDM posait d’autres problèmes tout simples :

  • Le HUD montre un score par équipe
  • La table des scores montre un score par équipe
  • Changer d’équipe nécessite de mourir (imaginez la frustration quand le joueur fraggue et qu’il meurt : il ne sait pas tout de suite s’il a été fraggué ou s’il est devenu la cible).
  • Une cible est définie dès le deuxième joueur connecté aléatoirement (c’est-à-dire qu’un joueur va faire des points sans avoir rien fait en début de partie)
  • Le message “VOUS ÊTES ROUGE” à changer pour “VOUS ÊTES LA CIBLE” (il est toujours plus facile d’ajouter simplement un message plutôt que d’en changer)

J’ai donc décidé de tout articuler sur la fonction ScoreKill (qui gère les frags). Elle se lance quand un joueur est tué et permet d’agir sur le tueur et le tué. Ainsi, je pourrais définir par une variable un changement de cible (certainement un booléen : bTarget). Plutôt que de mettre un système d’équipe complet, j’ajoute une variable à chaque joueur qui définit s’il est la cible ou non. L’idée est de faire :

Si le tué est la cible, alors le tueur devient la cible.

Rien de bien compliqué sur le papier, dans la pratique il y aura deux/trois choses à prendre en compte (notamment le friendly fire). Il faut également permettre aux joueurs de reconnaître la cible rapidement (même si elle saute deux fois plus haut que les autres et court comme Usain Bolt). Pour cela, une lumière dynamique suivra la cible pour qu’elle soit reconnaissable (en cela, utiliser un système d’équipe avait l’avantage de bien séparer visuellement les deux types de joueurs).

Dernière chose importante dans la conception pre-code : quand est-ce que je j’ajoute une cible ? En effet, si deux joueurs se retrouvent seuls sur un serveur, quel intérêt de mettre une cible ? Difficile ici de définir correctement. De toute manière, un joueur qui arrive en milieu de partie est toujours désavantagé pour du deathmatch. L’idée est de faire que la partie démarre sans cible. Dès qu’un joueur tue, il devient la cible.

Autres aspects du mode

Contrairement au game type Safari, ce mode demande beaucoup moins de personnalisation visuelle. Safari prenait en compte des niveaux et des points d’expérience qui avaient un impact important sur le jeu. Ici, quelques messages uniquement à afficher au bon moment :

  • Message : “Vous êtes la cible !” (avec un bruit reconnaissable)
  • Message : “Vous êtes un chasseur !” (lors du respawn)
  • Message : “Vous avez tué un chasseur !” (lors d’un friendly fire)

J’ai envie de faire quelque chose de plus personnalisé et fun avec plutôt des phrases du type : “Accident de chasse, arrêtez de boire !” ou “Vous êtes la cible, faites gaffe à vos fesses”. Le tout avec des sons enregistrés pour l’ambiance. Mais là, on parle déjà de finalisation du mode !

Sinon, le game-type Hunt a un nom pourri bien que représentant bien le principe. J’aimerais en trouver un de plus sympa. Hunting Safari sonne mieux je trouve mais je pense que vous voyez le problème…

C’est tout pour aujourd’hui. N’hésitez pas à donner votre avis sur le mode en lui-même. S’il y a des choses qui vous chiffonnent et qui vous paraissent rédhibitoires.

Unreal Safari : Post-mortem (4)

Mercredi 21 juillet 2010

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