Comme d'hab' sur Gamasutra, la rubrique
Game Design Deep Dive (Soit plus ou moins « Plongée dans les eaux profondes de la conception d'un jeu ») nous propose une nouvelle fois l'exploration d'une mécanique de jeu particulière. Aujourd'hui c'est le tout récent
Cities: Skyline,
dispo sur PC/Mac/Linux qui passe sur le grill.
Si vous souhaitez lire un test du jeu, le lien vers le
test de GK. Et pour ceux qui préfère la VO, ça se passe
ici.
Qui: Antti Lehto (programmeur), Damien Morello (programmeur) et Karoliina Korppoo (conceptrice principale)
Nous travaillons à
Colossal Order, un studio de jeu indépendant basé en Finlande spécialisé dans les jeux de simulation PC. Colossal Order fut fondé en 2009 et nous avons publié à ce jour 3 jeux :
Cities in Motion, un jeu de simulation de transports publics,
Cities in Motion 2, la suite du précédent et
Cities : Skylines, un jeu de construction urbaine vieille école. Nous avons une équipe de 13 personnes seulement et sommes particulièrement friands de gâteaux et de petits oiseaux bleus.
Alors que les jeux
Cities in Motion furent créés pour un assez petit mais très fidèle public,
Skylines a touché une cible bien plus large et attire aussi des personnes moins expérimentées dans le genre simulation. Nous sommes très fiers que les fans de construction urbaine aient été ravis du jeu et sommes heureux de voir des
modders créer du contenu à un rythme soutenu. Nous voulions encourager le
modding et brouiller les frontières entre le jeu et la création, afin que les gens puissent vraiment être le propriétaire du jeu.
Quoi : le système de trafic dans Cities : Skylines
Gérer la circulation est l'une des dernières étapes dans le jeu, probablement la plus importante. Il existe de nombreux types de routes différents et ils doivent tous être utilisables et des choix intéressants. L'outil route est flexible pour permettre aux joueurs de construire des intersections complexes afin de gérer les flux de circulation mais aussi suffisamment simple pour ne pas transformer en corvée la construction de routes simples.
Il y a une limite au nombre de citoyens et véhicules qui peuvent être simulés dans les rues simultanément. Si la limite n'est pas atteinte, les citoyens peuvent décider de voyager. Les citoyens dans le jeu ont un éventail de destinations qu'ils veulent visiter. Ces endroits peuvent se remplir, ce qui entraîne plus de demandes pour ces sites. Lorsqu'un citoyen se dirige vers un de ces lieux, il choisit la route la plus rapide jusqu'à là-bas.
[Les citoyens] prennent en compte si ils ont leur propre véhicule, si il y a des routes embouteillées et si des transports publics sont disponibles. Selon ces facteurs ils [décident] de marcher, d'utiliser les transports publics ou leur propre véhicule. Les piétons peuvent emprunter les voies piétonnes, séparées des routes. Les piétons ne peuvent pas marcher sur les autoroutes.
Lorsque les véhicules planifient leur route, ils ne s'en détournent pas. Ils ne recalculeront pas leur trajet en plein milieu de leur voyage à moins que quelque chose sur leur chemin ait été modifié. Si pour une raison ou une autre ils ne trouvent de routes vers l'endroit qu'ils ont choisi, le véhicule se téléportera à son point de départ.
Les véhicules appartiennent aux citoyens ou à des bâtiments, ils ont donc tout le temps un endroit où retourner. Quelques véhicules arrivent de l'extérieur de la carte mais y retournent si ils se perdent. Les véhicules choisissent leur voie assez rapidement et ils restent dans celle qui leur permet de tourner dans la direction vers laquelle ils se dirigent.
Pourquoi?
Le but dès le début du projet était d'avoir des villes avec un million de citoyens au maximum. Ce n'est pas une limite immuable, c'est ce que nous avons estimé être le maximum pour une ville pleinement développée et ca a été une ligne directrice interne pour équilibrer les systèmes de la ville. Avec un million de citoyens potentiels, il était clair que tous ne pouvaient se trouver dans la rue simultanément si nous voulions garder les configurations machine requises raisonnables. Ca signifie que nous devions créer le système des travailleurs afin que les travailleurs qui ne se rendent pas réellement physiquement à leur lieu de travail n'entraîne pas une pénalité pour le joueur.
Nous avons passé beaucoup de temps à travailler et reprendre le système du trafic. Ca a été le plus grand défi du jeu et c'est un système avec lequel tous les joueurs interagissent, c'est donc l'un des plus importants systèmes. Durant le développement nous avons essayé par exemple de permettre aux voitures de changer de voie plus souvent, ce qui donnait un chaos total de la circulation avec les voitures qui essayaient de rejoindre des voies bondées, bloquaient par la même deux voies et entraînaient ainsi un arrêt du trafic.
La téléportation fut créée comme fonction de sécurité lorsque les tests démontrèrent que les joueurs moins expérimentés rencontraient de gros problèmes lorsque leur système routier tout entier devenait un seul gigantesque embouteillage et que les informations routières affichées ne pouvaient identifier le véritable goulot d'étranglement quand toutes les routes étaient pleines de voitures en attente et encombrées. Ca signifiait que les joueurs ne pouvaient localiser l'endroit problématique si ils n'avaient pas ou peu d'expériences ou si ils n'étaient pas vraiment intéressés par cet aspect.
Comme solution nous avons créé un système qui téléporte les véhicules à leurs points de départ si ils rencontrent un bouchon. Le goulot d'étranglement originel est toujours là et les véhicules y sont stoppés ou progressent mètre par mètre mais le bouchon ne croît pas de manière incontrôlable. Ca permet au système d'infos contextuelles d'identifier la zone problèmatique, de la peindre en rouge et ainsi d'indiquer clairement au joueur quelle partie du système routier doit être inspectée.
Comment
Sans routes il n'y aurait pas de circulation. Commençons donc par la vision d'ensemble quant à la création des routes.
Lorsqu'un joueur construit une route, il place des nœuds fondamentalement. Deux d'entre eux crée un segment et une route est créé à partir d'un segment (ou plusieurs). Les segments ont une taille maximale, une longue route sera donc découpée en plusieurs segments. L'une des motivations derrière cette approche est que les routes doivent suivre la typologie du terrain, et même une route rectiligne aura donc besoin de plusieurs segments afin qu'elle ne soit pas entrecoupée par le terrain. Une autre motivation est que de petits segments sont mieux optimisés pour la détection des collisions, le rendu et autres.
Les nœuds (connus comme points de contrôle) contiennent la position initiale et finale d'un segment alors qu'un segment contient une direction initiale et finale. Cette structure est ensuite ''convertie'' en
courbe de Bézier en générant deux points de contrôle supplémentaires utilisant ces positions et directions.
Des courbes de Bézier
La géométrie routière est ensuite créée en utilisant un modèle 3D [NdT:
Static mesh en VO] à tesselation définie combiné à un
vertex shader [NdT : plus d'infos
ici ] qui transformera le modèle selon les données
spline [NdT: Cerce]. C'est efficace étant donné que les données
vertex pour les routes peuvent être partagées entre routes du même type, les systèmes
UV sur la direction et longueur sont aussi calculés dans le
vertex shader basé sur la longueur
spline (1).
Les intersections sont créées en utilisant une approche similaire et les segments enregistrent leurs connections aux segments voisins en même temps que leur type routier. Chaque segment peut ensuite connaître ses voies disponibles utilisant leur type routier, ce qui définit le nombre de lignes et leur
offset on the mesh.
Avec l'information décrite ci-dessus, les voitures et camions savent où ils peuvent se positionner sur les routes. Au lieu d'utiliser une interpolation naïve le long de la
spline, les véhicules sont de simples objets physiques avec une vélocité propre et de multiples points d'objectifs le long de la
spline qu'ils veulent suivre. Ca permet de prédire les courbes serrées et les intersections en approche afin que le véhicule puisse ralentir ou freiner selon les circonstances. Les véhicules règlent leur limite de vitesse à partir du type de route du segment sur lequel ils sont en train de circuler.
Lorsqu'un citoyen veut atteindre une nouvelle destination, un chemin sera calculé à partir de sa position initiale jusqu'à la destination finale, que ce soit pour marcher, conduire, utiliser les transports publics.... Ce qui au passage est vraiment cool étant donné que ça explique les citoyens marchant d'un arrêt de bus à un autre afin de changer de bus. Durant ce processus, ''l'explorateur de chemin'' [NdT :
pathfinding] détermine le meilleur chemin possible pour le véhicule en calculant un résultat à partir des données de segments/voies en prenant en compte le niveau d'embouteillage, la vitesse maximum autorisée et la direction.
Le trafic est simulé en utilisant la logique du « premier arrivé, premier servi ». Les véhicules utilisent les points cibles mentionnés précédemment pour créer un segment ''attention !'' ; lorsque deux segments de véhicules différents se croisent, nous savons qu'il y aura une collision et la vélocité et la distance jusqu'au point d'intersection sont utilisées pour déterminer qui a la priorité et qui doit freiner. Il y a une exception à cette règle avec les feux de circulation qui empêchent simplement les points ciblent d'entrer dans l'intersection, ce qui amène les véhicules à ralentir et s'arrêter jusqu'à ce que le feu passe au vert.
Il y a bien sûr plusieurs autres facteurs qui impactent la circulation mais, fondamentalement, ça tourne autour de ces quelques simples démarches.
En terme de performances il est impossible de simuler ce qui est décrit ci-dessus en l'appliquant à chaque véhicule pour chaque image calculée. Le secret d'une performance décente est de distribuer les calculs autant que possible. Dans notre cas, le mouvement des voitures est simulé environ 4 fois par seconde tandis que le rendu utilisera deux de ces images simulées pour en retirer une position régulière à partir de ses données de vélocité, de rotation et de position. Des décisions plus compliquées peuvent être calculées moins fréquemment encore mais en utilisant la même approche régulière, [le mouvement] semblera être constamment mis à jour.
Les résultats
Quelques joueurs ressentent le jeu comme trop facile à cause de la téléportation. Ca rend le jeu beaucoup plus facile que le trafic embouteillé mais c'est vraiment nécessaire pour garder la courbe d'apprentissage raisonnable. Si elle n'existait pas, le temps de réaction requis pour s'occuper des problèmes de circulation avant qu'ils n'empirent serait simplement trop court.Il y a un mode utilisateur disponible pour désactiver la téléportation et les joueurs qui aiment les gros défis peuvent l'obtenir facilement. Au final le nombre de joueurs mentionnant les problèmes de circulation est relativement bas, ce qui nous mènent à penser que la solution fonctionne plutôt bien.
La circulation est cependant encore la partie la plus exigeante du jeu pour la plupart des joueurs. Le fait de choisir les voies tôt entraîne occasionnellement des aberrations visuelles dans le jeu. Les véhicules peuvent s'entasser sur une seule voie alors que les autres semblent vides (le trafic sur ces dernières est simplement rapide). Techniquement une voie embouteillée indique toujours au joueur que quelque part plus loin dans la ville, une intersection empêche la circulation d'être régulière mais certains joueurs pensent que c'est un bug lorsqu'ils voient seulement la longue ligne de véhicules.
Le principal défi maintenant est d'apprendre aux utilisateurs comment construire des systèmes de circulation fonctionnels mais en regardant les discussions des joueurs sur le forum c'est un sujet intéressant auquel les gens aiment contribuer. Après avoir saisi les bases du système de trafic, beaucoup de joueurs semble le trouver fascinant et passent des heures dessus à s'éclater en optimisant et gérant la circulation.
(1) : je vous mets la VO étant donné qu'en dehors de Kayama, des physiciens, mathématiciens, programmeurs et autres scientifiques spécialisés du site, c'est du charabia (rien compris perso

) :
The road geometry is then created by using a static mesh with a set tesselation combined with a vertex shader which will transform the mesh accordingly to the spline data. This is efficient as the vertex data for roads can be shared between same road types, uvs on the length direction are also calculated in the vertex shader based on the spline length.