rapport de projet - ollopa.fr · ollopa.fr 1 rapport de projet 27 mai 2020 vernay rémi roussille...

54
ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

Upload: others

Post on 22-Sep-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 1

Rapport de projet 27 mai 2020

VERNAY Rémi

ROUSSILLE Philippe

PINGARD Adrien

VEYRE Thimot

LITOUX Pierre

DEPLAGNE Hugo

LLOMBART Lucas

Page 2: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 2

Table des matières :

1 – Introduction………………………………………………….……………………………………….……....3

2 – Cahier des charges………………………………………………………………………………………….4

3 – Réalisation…………………………..………………………………………..…………………………..….12

2.1 – Graphisme 2D……………………………………………..…………………………………....12

2.1.1 – Dessins………………………………………………………………………………12

2.1.2 – Fonctionnement animation…………………………………………………………13

2.2 – Le personnage…………………………………………………………………………….……..14

2.2.1 – les déplacements (y compris dans les liquides)…………………………………14

2.2.2 – différents modes…………………………………………………………………….15

2.2.3 – Autres…………………………………………………………………………………17

2.2.4 – placements des blocs……………………………………………………………….18

2.3 – Les bâtiments…………………………………………………………………………………….19

2.3.1 – Les différents bâtiments………………………………………………….19

2.3.1.1 – Panneau solaire………………………………………………19

2.3.1.2 – Générateur d’oxygène……………………………………….19

2.3.1.3 – Stockage………………………………………………………19

2.3.1.4 – Broyeur…………………………………………………………20

2.3.1.5 – Imprimante 3D…………………………………………………20

2.3.1.7 – Infirmerie……………………………………………………….20

2.3.1.8 – Puits de pétrole………………………………………………..20

2.3.1.9 – Raffinerie……………………………………………………….21

2.3.1.10 – Foreuse……………………………………………………….21

2.3.1.11 – Générateur thermique……………………………………….21

2.3.2 – Fonctionnement général……………………………………………………………..22

2.3.3 – Réseau énergétique………………………………………………………………….23

2.3.4 – Interface des bâtiments………………………………………………………………24

2.3.5 – Placement des bâtiments…………………………………………………………….25

2.3.6 – Fusée et fin du jeu……………………………………………………………………26

2.4 – Les ressources et les inventaires………………………………………………….………….…27

2.4.1 – Les ressources………………………………………………………………………..27

2.4.2 – Obtention des ressources……………………………………………………………28

2.4.3 – Inventaire du joueur………..…………………………………………………………30

2.5 – Environnement………………………………………………………………………………….…31

2.5.1 – Système jour/nuit……………………………………………………………………..31

2.5.2 – Paysages (Parallaxe) ………………………………………………………………..31

2.5.3 – Liquides………………………………………...……………...………………………32

2.5.4 – L’herbe…………………………………………………………………………………34

2.5.5 – Monde infini……………………………………………………………………………34

2.6 – La génération de l’environnement…………………………………….………………………....35

2.6.1 – génération du monde…………………………………………………………………35

2.6.2 – génération des minerais ……………………………………………………………..36

2.6.3 – génération des arbres………………………………………………………………...38

2.6.4 – génération des grottes………………………………………………………………..39

2.6.5 – génération des lacs……………………………………………………………………41

2.7 – Le pistolet laser……………………………………………………………………………...……..42

2.8 – Les ennemis………………………………………………………………………………………..44

2.9 – Interfaces utilisateurs……………………………………………………………………………...47

2.9.1 – Ajustement d’écrans……………………………………………..……………………47

2.9.2 – Menus….……………………………………………………………………………….47

2.10 – système de sauvegardes……………………………………………………………..…………48

2.11 – son……………………………………………………………………………………..…………..50

4 – Chronologie……………………………………………………………….……………………………..……...52

5 – Conclusion……………………………..…………………………………………………………...………..….53

Page 3: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 3

1 – Introduction :

Dans ce rapport nous allons vous présenter notre projet de jeu développé lors de cette

première année à l’EPITA Toulouse. Durant la dernière période de développement de notre jeu nous

avons pu rajouter beaucoup de nouveautés qui, on l’espère, plaira aux joueurs. Nous avons pensé à

beaucoup de détails pour démarquer notre projet des autres, malheureusement nous ne pouvions pas

tous réalisés et espérés être dans les temps, nous nous sommes donc focalisés sur les tâches les plus

importantes. Cependant, beaucoup de choses ont été rajoutés depuis la dernière soutenance pour finir

le projet et maintenant nous sommes fiers et heureux de vous présenter notre projet nommé Ollopa.

En effet, vous allez vous rendre compte que beaucoup de choses ont changé et avancé depuis

la dernière soutenance, tout ce que nous voulions faire après la deuxième soutenance a été fait et

même plus encore. Pour prendre des exemples, le laser a été complètement changé, beaucoup de

bâtiments ont été rajoutés et fonctionnent parfaitement, le contexte de notre astronaute devant réparer

sa fusés a été créé et les animations du joueur, des ennemis, de la fusée et de l’herbe a aussi été

rajouté. Le jeu est entièrement fonctionnel et offre un vrai amusement quand on y joue. On peut voir

dans cet avancement l’apprentissage de Godot par notre équipe entre le début et la fin du projet.

Dans ce qui suit nous vous présenterons en détail le jeu, ce qui a été fait, pour quelle raison et

comment on y joue. On y explique ce qui a ou n’a pas fonctionné et ce qu’on a dû faire pour optimiser

nos lignes de code pour que la plupart des joueurs puissent faire tourner le jeu.

Nous allons donc décrire les éléments composant notre jeu puis nous donnerons les tâches de

chacun de nos membres et enfin nous finirons par une conclusion sur ce projet.

Page 4: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 4

2 – Cahier des charges :

1 - Introduction

1.1 Présentation du groupe

13 est un groupe de quatre personnes de la promotion 2024 de l’EPITA Toulouse. Nous nous

sommes tous les quatre rencontrés à notre arrivée à l’EPITA en début d’année et sommes devenus amis. Il nous est donc paru naturel de former ce groupe pour le projet.

Notre projet est un jeux vidéo de type gestion survival en 2D, il se nomme Ollopa.

1.2 Nom du groupe

Le nom du groupe est 13, il fait référence à la mission Apollo 13, qui a rencontré de graves

avaries au cours de sa mission. De même, dans notre jeu, un astronaute se crashe sur une planète après avoir rencontré des problèmes importants sur son vaisseau. Le nom du jeu, Ollopa, le verlan d’Apollo, et le nom du groupe sont une référence à la mission éponyme.

1.3 Présentation des membres

• Adrien Pingard (chef de projet)

Adrien a été à l’unanimité choisi en tant que chef de projet car il possède déjà

des connaissances en programmation et a déjà eu l’occasion d’utiliser Unity. Il a également suivi la section S-SI spécialité ISN au lycée, ce qui lui confère des aptitudes supplémentaires pour la gestion de groupe.

• Lucas Llombart

Il est le moins expérimenté du groupe, mais sa motivation et sa volonté d’apprendre compenseront ce léger retard. En outre, Lucas est une personne consciencieuse, il ne s’arrêtera pas tant que le travail n’est pas correctement réalisé.

• Pierre Litoux

En première année dans le supérieur comme les autres, Pierre a lui aussi étudié la spécialité ISN au lycée, de plus il est volontaire mais assez peu organisé.

• Thimot Veyre

Comme Adrien, il a suivi la section S-SI spécialité ISN, associé aux nombreuses heures passées à apprendre sur l’informatique, cela lui confère une base de connaissance générale en informatique. Il pourra également apporter sa rigueur et son perfectionnisme au groupe.

• Hugo Deplagne Avant d’étudier à l’EPITA, Hugo était en classe préparatoire scientifique

(PCSI) ce qui lui a apporté beaucoup de rigueur dans son travail mais aussi une facilité dans les matières scientifiques. Ces qualités seront donc d’un grand avantage pour le projet.

Page 5: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 5

2 - Présentation du projet 2.1 Origines

Nous nous sommes rapidement mis d’accord que notre projet serait un jeu, mais il a été difficile

de se décider à quel genre appartiendrait celui-ci. Trouver une idée qui convenait à tous les membres du groupe a demandé de nombreuses propositions. L’idée de départ était un jeu en 2D, mais nous avons eu plusieurs concepts comme la création d’un Tower Defense ou d’un jeu de plateforme. Finalement, nous avons opté pour un jeu avec une génération procédurale, et nous nous sommes mis d’accord sur un style de jeu de gestion survival dans l’espace.

Le premier jeu de type space survival est Robinson's Requiem, un jeu vidéo de survie doté

d'éléments de jeu de rôle sorti en 1994 sur PC, 3DO, Amiga, Atari ST, Atari Falcon, Mac et en 2011 sur Atari Jaguar. Il a été développé et édité par Silmarils. Il est l'un des premiers space survival sorti. Il s'agit d'une simulation de survie dans laquelle le joueur est perdu sur une planète inexplorée et hostile et doit trouver un moyen de la quitter à l'aide des ressources présentes dans son environnement.

2.2 Inspiration

• Astroneer : Ce jeu a pour but d’explorer et de remodeler des mondes lointains. Il se déroule

durant une époque intergalactique. Les joueurs doivent évoluer dans des environnements hostiles pour faire des découvertes sur l’univers. Ce jeu est disponible sur Xbox et Playstation ainsi que sur PC.

• Terraria : C’est un jeu en 2D de type action-aventure dont le système de jeu est basé sur l’exploration, la construction et l’action. IL est présent sur les plateformes de jeu Xbox, et Playstation et PC. Pour notre jeu, nous avons décidé d’imiter le système de construction et d’exploration pour créer des bâtiments et évoluer dans une planète inconnue.

• Starbound : Starbound se déroule dans un univers en deux dimensions. Le joueur doit explorer l’univers afin de trouver de nouvelles armes et armures ainsi que de trouver des objets divers pouvant être utile au joueur. Nous récupérons pour notre jeu l’univers spatial ainsi le système en 2D.

2.3 Histoire

Notre héros vit à une époque où le voyage spatial est démocratisé, il est aussi courant de

posséder un vaisseau qu’un avion de nos jours. Il est explorateur et de ce fait il voyage en terre inexploré. Lorsqu’il se crashe c’est donc sur une planète inconnue à la suite d’avaries sur son vaisseau. En outre, tous ses moyens de communications longues portées sont endommagés. Il ne peut donc compter que sur lui-même pour repartir.

Le personnage pourrait à des moments clés du jeu se remémorer des souvenirs mais cela reste très secondaire (voir optionnel) et ne sera implanté qu’en fin de développement si nous y trouvons un intérêt.

2.4 But et intérêt

Le but du jeu est de réparer son vaisseau pour retourner dans l’espace et finir son voyage. Il faut pour cela, récupérer différentes ressources (matières premières, électricité, pétrole...). Le joueur devra gérer les rendements de ses unités de productions pour ne pas dépenser plus d’énergie qu’il n’en produit.

Une partie doit durer au maximum une demi-heure. En effet pour une partie plus longue, il faut intégrer plus de contenu et nous ne pensons pas avoir assez de temps.

Page 6: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 6

2.5 Fonctionnalités

Toutes les fonctionnalités du jeu ne sont pas encore établies, certaines pourraient venir à être

modifiées ou supprimées ou bien même de nouvelles fonctionnalités pourraient venir au cours du développement du jeu.

Nous pouvons néanmoins faire une liste d’éléments qui seront implémentés dans le jeu :

• Le personnage est vu de côté, il peut se déplacer de gauche à droite ainsi que sauter et tomber. Il peut également interagir avec le terrain en cassant des blocs et en récupérant des ressources dans son inventaire. Le personnage doit gérer plusieurs variables (santé, oxygène, énergie).

• La carte est un terrain construit à l’aide de blocs, la génération de la carte est aléatoire.

• Des bâtiments (e.g raffinerie, panneau solaire) peuvent être posés sur la carte, chaque bâtiment a une utilité spéciale.

• Une arme/outil (e.g laser) permet de casser les blocs du monde et de se défendre contre d’éventuel ennemi. L’utilisation de cet outil fait perdre de l'énergie électrique au joueur.

• Une génération aléatoire de minerais dans la carte.

• Des matières premières (e.g bois, métaux) et des liquides (e.g eau, pétrole, fuel) pour permettre l’avancement dans le jeu.

• Un système d'énergie électrique qui permettra le fonctionnement de certains bâtiments mais servant aussi à la survie du joueur.

• Cycle jour/nuit permettant l’interaction avec certains bâtiments (e.g panneau solaire) et sur la vision du personnage.

• Système de mort partielle et permanente. La mort partielle est une mort du personnage après laquelle il peut revivre avec des malus. La mort permanente met fin à la partie.

• Un ennemi qui attaquera le joueur et lui fera perdre de la vie.

Page 7: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 7

3 - Réalisation projet 3.1 Outils utilisés et Moyens mis en œuvre

Moyens matériels et logiciels :

• Pour réaliser ce projet nous travaillerons avec Visual studio et plus précisément avec le langage de programmation C# complété par le framework GODOT. Visual studio et C# seront utilisés pour les scripts du jeu et GODOT pour la modélisation de celui-ci.

• Nous avons à notre disposition quatre ordinateurs (dont trois portables) ainsi que les ordinateurs de l’EPITA mis à notre disposition.

Moyens intellectuels : • En plus de nos connaissances actuelles en C# nous pouvons consulter sur internet des

tutoriels, des manuels numériques et des forums pour nous aider à avancer et à mieux comprendre le fonctionnement du framework GODOT. Nous avons aussi la possibilité de nous faire aider par les professeurs de l’EPITA et les étudiants des années supérieures.

• La communication étant importante dans un projet comme celui-ci, nous avons mis en place un serveur de chat vocal et écrit via l’application “Messenger” pour faciliter nos échanges durant toute la création de notre jeu. De plus, nous avons un groupe “Discord” permettant, tout comme “Messenger”, de communiquer avec le groupe entier via des messages ou encore des appels vocaux. Mais le plus gros avantage de “Discord” c’est que nous pouvons faire des partages d’écran vidéo, ce qui facilite la résolution des problèmes, comme un problème de code pour ne citer qu’un type de problème.

• Un git ainsi que des stockages cloud sont mis en place pour le partage des fichiers du projet.

• Nous avons également mis en place un système de gestion de projet, sur freedcamp, qui permet d’assigner des tâches à chacun en fonction de l’avancement du projet.

Page 8: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 8

3.2 Aspects économiques

Pour notre jeu, nous utilisons quatre ordinateurs dont trois portables. Chacun coûte aux

alentours de mille euros. De plus, nous louons, cinquante euros par an, un serveur afin de pouvoir héberger le site internet de notre jeu (ollopa.fr). Il servira à présenter le jeu et ainsi que l’équipe Ollopa. Nous pourrons implémenter, dans le futur, diverses fonctionnalités que nous ne souhaitons pas prendre en compte pour l’instant.

Il est possible que durant le projet nous ayons à réaliser des dépenses supplémentaires et nous avons donc prévu une enveloppe maximale de deux cents euros.

Nous souhaitons lancer notre jeu gratuitement sur différentes plateformes de jeu en ligne. En effet, étant notre premier jeu vidéo, nous serions déjà ravis que des gens y jouent.

3.3 Description des tâches

• Joueurs : Dans cette catégorie nous mettrons toutes les fonctionnalités que le joueur peut faire durant une partie dans le jeu, comme par exemple accéder à son inventaire pendant le jeu, ou encore placer différents bâtiments utilise au déroulement du jeu.

• Menu : Création d’un menu facile à utiliser mais comportant différentes fonctionnalités permettant au joueur une meilleure qualité de jeu.

• Génération de niveau : Génération d’une carte de jeu aléatoire pour chaque partie afin que le joueur n’ait pas l’impression de jouer tout le temps à la même partie. Création de forêts, d’eau et de montagne seront également crées de façon aléatoire.

• Environnement : Mise en place d’un environnement d’un planète spatiale inconnue contenant différentes ressources comme du bois spatial, ou de la roche spatiale. Création d’un environnement plus hostile grâce notamment aux ennemies se trouvant sur la planète et thèmes sonores liés aux ennemies.

• Site internet : Plateforme sur laquelle le jeu sera disponible au téléchargement. Mais aussi diverses informations sur le jeu comme des renseignements sur de futures mises à jour.

• Sons et musiques : Musique permettant au joueur de jouer dans une ambiance tranquille et détendue. Mais des thèmes sonores changeant selon la présence d’ennemie autour du joueur afin que le joueur puisse être dans l’ambiance du jeu.

Page 9: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 9

3.4 Répartition des tâches

Adrien Lucas Pierre Thimot Hugo

Développement

XX

X

X

X

X

Graphismes

X

XX

Musiques et

bruitages

XX

X

Site internet

XX

X

Gestion

XX

X

X

Tableau de répartition des taches

Adrien Lucas Pierre Thimot Hugo

Joueur

X

XX

X

Génération

XX

X

Bâtiments

XX

X

Interfaces

XX

X

Menus

X

X

XX

Equilibrage

X

XX

Ennemis

XX

X

Autre

X

X

X

X

X

Tableau des taches de la partie développement

Légende :

− Responsable : XX

− Suppléant : X

Page 10: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 10

3.5 Planning de développement

Pour l’organisation du planning de développement, nous utilisons Freedcamp.

Page 11: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 11

4 - Conclusion

En conclusion, Ollopa est pour tous notre plus gros projet à réaliser à ce jour. Nous avons

imaginé un jeu simple et rapide pour éviter car nous ne connaissons pas nos capacités. Ce choix nous permet également de rajouter du contenu si nous estimons être en avance. Il nous permettra d’acquérir des connaissances en développement et de l’expérience dans la gestion d'un projet.

Page 12: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 12

3 – Réalisation :

2.1 - Graphisme 2D

2.1.1 – Les dessins :

Les graphismes 2D ont été réalisés sur le logiciel “piskel” pour ce qui concerne la création des bâtiments

et les animations du joueur.

Broyeur Raffinerie Bâtiment de soin

Comme nous voulions que le jeu ait une allure plus « extraterrestre » nous avons aussi dessiné un ciel

qui rappelle l’espace et des montagnes violet clair en arrière-plan il en va de même pour l’allure des

arbres plutôt onirique.

Ciel en arrière-plan image feuillage et tronc d’arbre

Montagne en arrière-plan

Page 13: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 13

2.1.2 – Fonctionnement des animations

Plusieurs bâtiments du jeu sont animés à l’aide d’un nœud animationPlayer. Nous allons

présenter ici l’exemple du puits de pétrole. Celui-ci est divisé en deux partie le corps et la

tête.

Tête

Corps

Il n’y a que la tête du puits qui se met à osciller lorsque le bâtiment s’active et puise du

pétrole, le corps ne bouge pas. De la même manière nous avons animé la foreuse pour que

la tête se déploie et vibre lorsque le système s’active.

De la même manière, les animations du joueur et de l’ennemi utilisent des nœuds

AnimationPlayer enregistrant différentes animations et étant jouées grâce à du code

implémenté aux scènes respectives.

Ci-dessous un exemple de l’animation de la mort du joueur :

Page 14: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 14

2.2 - Le personnage

Le personnage du joueur est au centre de tout le jeu car c’est lui qui va pouvoir casser des

blocs, se déplacer dans le monde, construire des bâtiments. Ce sera donc le représentant du joueur

dans le jeu c’est pourquoi la bonne réalisation de ce personnage est primordiale.

Il possédera 3 variables l’affectant directement qui est la vie, l’oxygène et l’énergie. Si sa vie tombe à

0 il meurt, si son oxygène vient à manquer il mourra lentement et si son énergie est nulle il ne pourra

plus utiliser son pistolet laser et sera donc vulnérable face aux ennemis. Il est à noter que la mort du

joueur entrainera une perte de ces ressources qu’il ne pourra pas récupérer.

Le joueur doit pouvoir utiliser plusieurs objets, poser des blocs, poser des bâtiments, se déplacer et

peut aussi mourir. Pour cela nous avons besoin de donner au personnage plusieurs états pour

différencier par exemple le moment où le personnage utilise le laser ou le moment ou il pose des

bâtiments.

Ici nous pouvons voir l’organisation des différents nœuds de la scène du personnage.

2.2.1 - Mouvements du personnage :

Dans la scène Player, le script attaché correspond aux mouvements basiques du joueur (le

saut et le déplacement de gauche à droite) accorder aux animations du joueur, mais il comprend aussi

la téléportation du joueur au début de la carte si celui-ci est à la fin.

Ce script s'occupe aussi de savoir si le joueur se trouve dans de l’eau et si oui, son mouvement

se doit d’être altéré. Nous avons donc créé la fonction booléenne “IsInWater()” pour savoir si une partie

du joueur est en contact avec de l’eau. Celle-ci passe en revue les positions de sa taille (y) et de sa

largeur (x) et regarde si une de ces positions (x,y) est dans de l’eau. Si le joueur arrive dans l’eau avec

une grande vélocité l’eau le ralentira soudainement puis ses mouvements seront ralenties.

Grâce aux nœuds “AnimationPlayer” et “Image” nous avons créé plusieurs animations du

joueur qui sont la mort, la course, le saut, et l’attente du joueur. Celles-ci sont jouées dans le script du

“Player”.

Page 15: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 15

2.2.2 - Différents modes pour le personnage :

Pour le Nœud 2D nommé « Inputs » nous donnons ce que peut faire le joueur en fonction des

différents états qui peuvent différer entre :

- Normal : Mode de base dans lequel le joueur peut

utiliser les outils et les blocs.

- Build : Mode dans lequel le joueur peut poser un

bâtiment.

- Inventory et BuildingInterface : Mode qui s’active

respectivement lors de la présence de l’inventaire et lors

de la présence de l’interface d’un bâtiment.

- Dead : Mode qui intervient à la mort du joueur.

- Link : Mode qui s’active lors d’une phase de liaison entre bâtiments, effectué par le joueur.

Nous nous occupons de savoir si nous pouvons poser des blocs, des bâtiments et faire des liens

entre les bâtiments. Par exemple :

public enum State

{

Normal,

Build,

Inventory,

Dead,

BuildingInterface,

Link

}

Page 16: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 16

Ici, la fonction ClickNormalState regarde si la position où nous voulons poser un bloc est valide (pas

trop loin du joueur), si la catégorie du bloc peut être placée, s’il nous reste ce type de bloc dans

l’inventaire et si nous avons pu placer le bloc. Avec toutes ces conditions remplies, on peut enlever un

bloc (du même type) de l’inventaire.

Enfin, on s’occupe aussi de savoir si le joueur a appuyé sur la touche Tab pour ouvrir l’inventaire ou

sur la touche Echap pour fermer n’importe quelle fenêtre ouverte dans le jeu, ou encore s’il a appuyé

sur le clic droit de la souris pour poser un objet ce qui peux activer la fonction précédente si le joueur

est à l’état Normal.

private void ClickNormalState()

{

Usable.Type type = Player.UsableSelected;

Usable.Category cat = Usable.category[(int)type];

if (MouseInRange(9,false))

{

if(cat==Usable.Category.Block)

{

int amount = Player.inventoryUsables.GetItemCount(type);

if (amount>0)

{

bool succeed =

PlaceBlock.Place((int)mousePos.x,(int)mousePos.y,

Usable.blocks[type]);

if (succeed)

{

Player.inventoryUsables.Remove(type, 1);

if (ToolBar.GetInstance() != null)

{

ToolBar.SendRefresh();

}

}

}

}

}

}

Page 17: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 17

2.2.3 - Autres :

Le nœud 2D « PlayerBuildingActions » sert à faire un lien entre le bâtiment stockant l’énergie

et le joueur afin de lui donner de l’énergie et aussi pour créer une animation entre les deux entités.

Le nœud « light » applique juste une lumière autour du joueur qui permet de mieux voir l’entourage du

personnage lors du cycle nuit.

Le nœud Area2D possède un CollisionShape2D qui est le même que celui du joueur seulement celui-

ci sert à savoir si les ressources représentées par des billes scintillantes jaunes sont arrivées au joueur.

Si oui, les ressources sont stockées dans l’inventaire ou détruites si on ne peut pas les ajouter à

l’inventaire, voir la fonction ci-dessous :

On remarque que même si on ne peut pas ajouter la ressource à notre inventaire, celle-ci disparaît à

notre rencontre.

Le nœud « Stream » sert à produire les bruits de pas du joueur et l’entré dans l’eau.

Enfin, le nœud Raygun possède toutes les fonctionnalités du pistolet laser pour que le joueur puisse

détruire des blocs. Lorsque le pistolet laser est utilisé il sera dans les mains du personnage (voir partie

2.7).

public void _on_Area2D_area_shape_entered(int id, Area2D area, int areaShape, int

selfShape)

{

/* REcuperation des loots*/

if (area.GetGroups().Contains("loot"))

{

/*On a un loot*/

Loot loot = area.GetNode<Loot>("..");

bool canAdd =

Player.inventoryItems.CanAdd(loot.GetLootType(),loot.GetLootAmount());

Player.inventoryItems.Add(loot.GetLootType(),

Player.inventoryItems.GetAmountCanAdd(loot.GetLootType(),

loot.GetLootAmount()));

area.RemoveFromGroup("loot");

if (canAdd)

{

loot.QueueFree();

}

else

{

loot.Explosion();

loot.dead = true;

loot.GetNode<Sprite>("img").Visible = false;

Delay.StartDelay(loot, 0.3f, () => loot.QueueFree());

}

}

}

Page 18: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 18

2.2.4 - Poser des blocs :

Pour poser un bloc dans le monde, le joueur doit le sélectionner, il passe alors dans un mode lui

permettant de poser le bloc sélectionné. Attention, le joueur ne peut poser des blocs que dans un

certain rayon, dans les limites des mondes, en dehors de sa personne, en dehors de la surface d’un

bâtiment et s’il lui reste encore des blocs.

Une zone carré rouge ou verte qui suit la souris, lui indique si le joueur peut poser ou non un bloc. S’il

peut poser un bloc la zone devient verte, sinon elle reste rouge.

Une fonction CanPlace () vérifie si un bloc peut être posé ou non.

public static bool CanPlace(int x, int y, out bool res)

{

res = y >= 0 && y <= Chunk.height ;

if (res)

{

Block b = World.GetBlock(x,y);

res = res && b.GetType==Block.Type.Air;

res = res && (b.isAutoGenerated || HasNeighbors(b));

res = res && !HasBuilding(x, y);

}

return res;

}

Page 19: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 19

2.3 - Les bâtiments :

2.3.1 - Les différents types de bâtiments :

2.3.1.1 Panneau solaire

Le premier bâtiment produisant de l’énergie, il la puise de

l’énergie de l’étoile, il ne fonctionne donc que la journée. Nous avons

intégré une fonction qui nous permet d’augmenter la puissance de

l’étoile en fonction de l’heure de la journée. La puissance atteint son

point culminant à midi.

Sur le graphique ci-contre, nous pouvons clairement

constater une variation de la production énergétique au cours de

la journée.

2.3.1.2 Générateur d’oxygène

Le joueur consommant en permanence de l’oxygène, il lui faut un

moyen de reconstituer sa réserve. C’est là qu’entre en jeu le générateur

d’oxygène qui produit de l’oxygène en utilisant de l’énergie et l’atmosphère

présente sur place.

2.3.1.3 Stockage

Le stockage est une batterie qui permet de stocker l’énergie. La

batterie peut recevoir et envoyer de l’énergie. Elle permet donc de faire un

tampon et de centraliser les connexions entre les générateurs et les

consommateurs. Sa fonction secondaire est de recharger l’énergie du joueur.

Le rechargement du joueur est prioritaire sur tout autre transfert d’énergie et

s’effectue dès que le joueur est assez proche du stockage.

Nuit Jour

Page 20: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 20

2.3.1.4 Broyeur

Ce bâtiment utilise différentes ressources pour les transformer en

composite, matériau obligatoire pour réparer la fusée.

2.3.1.5 Imprimante 3D

L’imprimante 3D est un bâtiment essentiel, il permet au joueur

d’imprimer les autres bâtiments présents dans le jeu. Chaque bâtiment

est imprimable et demande des ressources, un temps de production et

une quantité d’énergie particuliers.

Une fois toutes les conditions réunis le joueur peut lancer

l’impression du nouveau bâtiment, une barre de progression ainsi qu’une

animation lui indique l’avancée de l’impression. Il peut aussi décider de mettre l’impression en

pause pour arrêter de consommer de l’énergie. Il peut également annuler l’impression, il

récupère alors toutes les ressources mais pas l’énergie dépensée.

2.3.1.6 Compacteur

Ce bâtiment permet la création des différents blocs utilisable par

le joueur. Chaque bloc possède une composition précise d’item (par

exemple, il faut l’item pierre pour confectionner un bloc de pierre).

2.3.1.7 Infirmerie

Le joueur peut utiliser ce bâtiment pour régénérer sa vie, le

bâtiment consomme de l’énergie et des items.

2.3.1.8 Puits de pétrole

Comme son nom l’indique, le puits de pétrole puise du pétrole

du sol de la planète.

Page 21: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 21

2.3.1.9 Raffinerie

C’est un bâtiment complémentaire du puit de pétrole. Il permet au

joueur de raffiner le pétrole en carburant pour la fusée.

2.3.1.10 Foreuse

La foreuse est un bâtiment permettant la récupération des minéraux

enfuis dans le sous-sol de la planète. Elle évite au joueur d’aller chercher des

ressources lui-même.

2.3.1.11 Générateur thermique

Ce générateur permet de créer de l’énergie en utilisant des

matériaux combustibles comme le bois ou le pétrole. Ce bâtiment fonctionne

jour et nuit contrairement au panneau solaire qui ne fonctionne que le jour.

Page 22: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 22

2.3.2 – Fonctionnement général :

La plupart des bâtiments fonctionnent autour du système d’énergie c’est-à-dire qu’il y a des bâtiments

qui vont produire l’énergie comme le panneau solaire ou le générateur thermique. Des bâtiments qui

stockent comme le stockage et enfin ceux qui utilisent l’énergie comme l’imprimante 3D, le compacteur

ou le broyeur.

Pour fonctionner, tous les bâtiments ont donc une réserve d’énergie qu’ils peuvent alimenter en

produisant/recevant de l’énergie et qu’ils peuvent soit consommer directement soit partager à d’autre

bâtiments.

L’écran de droite permet d’avoir toutes les informations utiles sur l’état du bâtiment :

La réserve d’énergie permet de connaitre la quantité d’énergie actuelle et maximum du bâtiment.

Les deux flèches permettent de savoir si le bâtiment donne ou consomme (flèche rouge) ou reçoit

(flèche verte) de l’énergie en ce moment.

Enfin les trois graphiques qui permettent de savoir dans l’ordre :

- jaune : connaitre la quantité d’énergie par rapport au temps

- vert : connaitre la quantité d’énergie par seconde reçus dans le temps

Page 23: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 23

- rouge : connaitre la quantité d’énergie par seconde consommée dans le temps

2.3.3 – Réseau énergétique :

Le système de passage et transfert d’énergie se fait grâce au « link ». Cette fonction permet de lier les

bâtiments de production et de stockage à d’autre bâtiments du même types ou des bâtiments qui

utilisent l’énergie.

Ces bâtiments disposent donc d’un menu « link » permettant de choisir à quel bâtiment ils vont être

liés.

Un fois en mode « link » on peut sélectionner les différents bâtiments qui ont désormais un code couleur

qui les enveloppe.

- Le bâtiment violet est celui que l’on veut lier avec d’autre bâtiments.

- Un bâtiment rouge signifie qu’il ne peut pas recevoir d’énergie

- Un bâtiment jaune est un bâtiment déjà lié au bâtiment d’origine

- Un bâtiment vert est un bâtiment que l’on peut lier

Il suffit de cliquer/recliquer pour lier/délier un bâtiment et d’appuyer sur la touche échap pour quitter le

mode « link ».

Page 24: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 24

2.3.4 – Interface des bâtiments :

Chaque bâtiment possède une interface personnelle. Celle-ci est divisé en deux partie, une première

partie sur son énergie qui est identique sur tous les bâtiments, puis une deuxième qui lui est propre.

Chaque interface est une scène entière qui est chargée lorsque l’on clique sur le bâtiment et qui est

déchargé lors de la fermeture de l’interface.

Celles-ci sont conçues pour toujours rester au milieu de l’écran peu importe la taille ou le ratio de de

ce dernier.

Ces interfaces sont principalement constituées de bouton, de label et de shader (pour l’affiche de

l’énergie, de l’oxygène, du pétrole et du carburant).

Ci-dessous vous pouvez voir l’interface la plus compliquée du jeu, celle de l’imprimante 3D.

On retrouve la partie énergique à droite, identique sur tous les bâtiments. La partie de gauche est

constitué de plusieurs boutons qui sont activés selon certaines circonstances. Nous avons ensuite

une description, au milieu, du bâtiment sélectionné, à gauche, celle-ci doit être modifié pour chaque

bâtiment car chaque information affichée est spécifique à un seul bâtiment (temps de construction,

ressources nécessaires, etc.).

Page 25: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 25

2.3.5 – Placement des bâtiments :

Dans le jeu le placement des bâtiments suit plusieurs règles pour être cohérent avec l’environnement.

En effet le placement des bâtiments suit certaines règles :

-Il est de dimension 4 par 4 blocs

-il doit être placé sur quatre blocs pleins

-il ne peut pas être placé par-dessus un bloc ou un autre bâtiment

-il ne peut pas être placé en dehors des limites de jeux

Afin que le placement soit facile d’utilisation une fonction isplacable est constamment vérifié et un

carré de 4*4 de couleur verte ou rouge en fonction de si on peut placer le bâtiment est affiché à

l’emplacement de la souris.

Page 26: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 26

2.3.6 – Le vaisseau spatial

Le vaisseau spatial est un bâtiment spécial, il est posé dès le début de la partie et ne peut

pas être imprimé avec l’imprimante 3D. Il ne peut pas non plus être raccordé au réseau énergétique.

Pour placer le vaisseau spatial, nous construisons une plateforme faite de blocs de fer et de

warningBloc. Pour se créer, le script de la plateforme prend en entrée une position “X” et une

longueur. De ces de valeurs, le script va déterminer la hauteur maximale sur toute la longueur

donnée à partir de la position “X”. Il va ensuite poser une rangée de bloc de fer deux bloc plus haut

par rapport à la hauteur maximale. Le système pose ensuite des warningBloc en guise de poteau à

intervalle régulier entre la plateforme et le sol.

Ci-dessous deux exemples de génération

A la suite de ça, deux lumières sont placées à chaque bout de la plateforme de manière à éclairer le

vaisseau. Enfin le vaisseau spatial est placé sur la plateforme terminée.

Le vaisseau de nuit

En ouvrant l’interface, nous pouvons trouver les trois objectifs à remplir pour terminer le jeu.

Nous devons réparer le vaisseau avec du composite, remplir son énergie ainsi que son réservoir de

carburant. Une fois tout ceci fait, le bouton Launch devient accessible, en cliquant dessus le joueur

Page 27: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 27

fini la partie et le jeu affiche le temps total de jeu. Un objectif secondaire est fini le jeu le plus vite

possible.

Pour transférer des ressources au vaisseau, le joueur clique sur un bouton en dessous de la jauge de

la ressource de son choix. Le jeu transverse en continue tant que le joueur ne l’arrête pas, que

l’interface n’est pas fermée, que le joueur à de la ressource ou que la quantité n’est pas suffisante.

L’interface du vaisseau spatial

2.4 - Les ressources et les inventaires :

2.4.1 – Les ressources :

Dans notre jeu, nous pouvons classifier les ressources dans 3 catégories différentes : les

matière premières (« Items »), les utilisables (« Usables ») et les liquides.

Les matières premières :

- Le composite est la principale matière première. Cette matière est essentielle pour le

déroulement de la partie, elle est à la base de la construction de quasiment tous les

bâtiments du jeu. Le composite est aussi nécessaire pour gagner la partie en réparant le

vaisseau spatial du joueur.

- Les autres matières premières servent également à la construction de certains bâtiments.

Par exemple il faut du bois pour la construction du générateur d’oxygène.

Des catégories au sein même des matières premières sont créée tel que les combustibles et les

cristaux .

Les combustibles (bois) permettront de faire fonctionner certain bâtiment comme le générateur

thermique.

Les cristaux et le bois permettront de soigner le joueur si ce dernier les utilise dans le bâtiment de

soin.

Les utilisables :

Deux catégories se trouve dans les utilisables, les outils et les blocs.

Les outils ne sont pas accumulables contrairement aux blocs. Notre jeu ne possède qu’un outil qui est

le laser qui permet de casser et d’infliger des dégâts.

Page 28: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 28

2.4.2 – Obtention des ressources :

Tous d’abord, le système d’obtention des ressources se fait grâce à un système de « loot » qui

nous permet de récupérer la matière première directement lorsque l’on casse des blocs.

Celui-ci possède un type (bois, pierre, terre, etc) et une quantité représentant le nombre d’objet du type

« type » que nous avons dans ce « loot » (par exemple 3 pierres), enfin le booléen « hasLoot » vérifie

si la variable « amount » passe en dessous de 0. Si c’est le cas, cette variable passera à « false ».

Les « loot » ont plusieurs caractéristiques pour simplifier la vie du joueur et diminuer le lag dû à

l’affichage :

- Ils sont attirés par le joueur si celui-ci se trouve à proximité.

Ces deux fonctions présentent dans le _PhysicProcess de « loot » permettent cette attraction, le corps

du « Player » est tout d’abord recherché et s’il se trouve dans une zone définie on actualise la position

du « loot » pour le rapprocher du « Player »

public void setLoot(Item.Type type, int amount) {

this.type = type; this.amount = amount; this.hasLoot = true;

}

var bodies = area.GetOverlappingBodies();

Node2D Player = null; foreach (var body in bodies) {

if (((Node2D)body).GetGroups().Contains("Player")) { Player = (Node2D) body; } } if (Player != null) { Vector2 vec = Player.Position - Position;

Position = Position + (vec.Normalized() * speed);

}

Page 29: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 29

- Les « loot » du même type peuvent se compacter c’est-à-dire que casser dix blocs de

pierre ne fera apparaitre qu’un seul « loot » au lieu d’avoir dix « loot ».

Cette fonction permet à un premier « loot » de donner le plus de quantité possible a un deuxième

« loot ». Ainsi, si les quantités sont petites et inférieures à STACKSIZE, exécuter de nombreuse fois

cette fonction permet de compacter plein de petits « loot » en un seul.

- Ils ont une durée de vie limitée pour libérer la mémoire.

Cette simple fonction dans le _PhysicProcess de l’objet « loot » s’exécute à chaque tic de jeux et gère

la disparition du « loot » en temps voulu.

Une fois les matières premières obtenue il faudra la transformer soit :

- En blocs avec le compacteur

- En composite avec le broyeur

- Créer des bâtiments grâce à l’imprimante 3D

public void GiveLoot(Loot l)

{

int r = STACKSIZE - l.GetLootAmount(); int amount = 0; if (GetLootAmount() <= r) { amount = GetLootAmount(); } else { amount = r; } this.amount -= amount; l.AddLoot(amount); l.ResetTime(); }

public int GetLootAmount() => amount;

if (dead)

return; time += delta; if (time >= LIFETIME)

{

Explosion(); dead = true; Delay.StartDelay(this, 0.3f, () => QueueFree()); }

Page 30: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 30

2.4.3 – L’inventaire :

Pour que notre joueur puisse interagir avec les objets et ressources qu’il transporte, nous avons créé

un inventaire. Celui-ci peut s’afficher en appuyant sur la touche tabulation. Ce dernier est divisé en

cinq. Il y a une partie pour les items, les blocs, les bâtiments, les liquides ainsi que les statistiques du

joueur (santé, oxygène, énergie).

Pour réaliser l’inventaire nous utilisons un nœud « Control » qui contient trois listes correspondant aux

zones items, blocs et bâtiment. A droite, nous trouvons une section affichant la quantité de liquide

(pétrole et carburant) et en dessous les statistiques du joueur (énergie, oxygène et vie).

De base, ce nœud n’est pas visible, il le devient lorsque nous appuyons sur la tabulation. Une mise à

jour des éléments est faite dans chaque liste pour que l’inventaire puisse être toujours à jour. Et l’état

du joueur devient « Inventory ».

Lorsque que le joueur appuie à nouveau sur tabulation ou sur le bouton en haut de l’inventaire cela

rend le nœud à nouveau invisible et change l’état du joueur sur celui présent avant d’ouvrir l’inventaire.

Ci-dessous une capture d’écran de l’inventaire, nous pouvons également sélectionner un item dans

l’inventaire, cela ferme alors automatiquement l’inventaire et met l’item dans la « main » du joueur.

Un compteur affiche également le nombre d’éléments pour chaque item.

Page 31: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 31

2.5 – Environnement :

2.5.1 – Système jour/nuit :

Pour ce système jour/nuit nous utilisons toujours le paramètre “delta” de la fonction _Process

en guise d’horloge du jeu et un « CanvasModulate » (outil pour assombrir ou éclaircir les objets) associé

à un « Tween » (outil qui sert à animer une propriété au fil du temps) pour faire effet jour/nuit. Nous

avons changé le laps de temps entre le jour et la nuit et nous avons rajouter du brouillard par moment.

Il existe actuellement deux fonctions contrôlant le cycle, une pour le jour et une pour la nuit.

Voyons celle pour le jour :

Dans cette fonction la première condition donne les propriétés du CanvasModulate, la deuxième donne

les propriétés du brouillard et la troisième active la lampe du joueur en fonction du jour et de la nuit.

Le brouillard et la lumière du joueur sont actifs tout le temps mais sont visibles surtout la nuit.

2.5.2 – Paysages (parallaxe) :

Pour rendre notre jeu plus beau, nous avons décidé d’ajouter un décor de fond. Pour le rendre

plus réaliste nous l’avons animé en suivant les règles de la parallaxe.

Le paysage du jeu fonctionne avec un système de parallaxe sur trois plans pour donner un effet de

distance avec les montagnes et le ciel en arrière-plan.

Le principe est simple lorsque le joueur se déplace sur le premier plan a une certaine vitesse les deux

plans en arrière-plan (la montagne et le ciel) se déplacent à une vitesse différente de celle du joueur.

En effet pour donner l’impression que les montagnes sont lointaines celles-ci se déplacent moins vite

que le joueur, de même, pour ne pas donner l’impression que le ciel et les montagnes sont sur le même

plan ces deux plans n’ont pas la même vitesse. Cet effet est appliqué à la fois sur les mouvements

horizontaux et verticaux.

Page 32: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 32

2.5.3 – Liquides :

Notre jeu étant un monde en 2D et fait de blocs, nous avions le choix d’intégrer les liquides

sous forme réaliste (infinités de position possible) ou sous forme de subdivision de bloc. Nous avons

choisi la seconde option qui nous semblait être la plus simple à mettre en place et la moins gourmande

en performance.

Pour la réaliser, nous avons dû trouver un équilibre entre nombre de subdivision et performances. En

effet plus le bloc est subdivisé plus les mouvements des liquides sont fluides mais cela amène un

réalisme qui ne correspond pas forcement au style graphique du jeu. Nous sommes donc parties sur 8

subdivisions par bloc, ceux-ci faisant 16 pixels. Ils nous seraient possible de monter à 16 subdivisions,

car cela nous permet de visuellement bien voir comment réagit le fluide.

Pour concevoir les liquides nous avons créé une

scène contenant un compte à rebours et une

grille contenant des images appelée TileMap.

Pour chaque type de liquide pouvant être sur la

carte (actuellement l’eau et le pétrole) mais le

processus d’ajout d’un liquide est assez simple.

Prenons un exemple avec l’eau, tout autre liquide se comporte exactement pareil, lors du lancement

de jeux un objet LiquidMove de type eau va être créé et ajouté à un dictionnaire permettant de l’appeler

par son type. L’objet que nous venons de créer contient une matrice de la taille de la carte et une liste

contenant la position des blocs contenant de l’eau. Lorsque le TimerWater, atteint 0, il appelle la

fonction Move de notre objet eau. Cette fonction a pour but comme son nom l’indique de déplacer l’eau.

Lors d’un mouvement, nous vérifions d’abord que l’objet

LiquidMove eau a fini de s’initialiser, nous avons dû utiliser

un thread donc nous vérifions que le thread est mort. Nous

calculons dans un premier temps le déplacement vertical de

chaque bloc, puis son mouvement horizontal. Enfin nous

redessinons notre liste de blocs sur la TileMap

correspondant à celle de l’eau.

Pour réaliser ces mouvements, nous avons dû réaliser trois versions différentes avant d’avoir quelque

chose d’utilisable.

Dans la première version nous avons utilisé uniquement la matrice du monde, pour chaque fonction

sur l’image ci-dessus nous parcourions toutes la matrice pour mettre à jour chaque case de cette

dernière seulement si elle contenait de l’eau. Nous faisions un quatrième parcours au début également

public void Move()

{

if (!init.IsAlive)

{

VerticalWater();

HorizontalWater();

DrawWater();

}

}

Page 33: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 33

pour mettre à jour les blocs ne pouvant contenir de l’eau (si le joueur en supprime ou ajoute un bloc de

terre par exemple).

Cette version bien que fonctionnelle consommait beaucoup trop de performance et ne nous permettais

pas de dépasser les vingt images par seconde. De plus les performances dépendaient en train grande

partie de la taille du monde, la présence de bloc d’eau avait une influence négligeable.

Nous nous sommes donc attelés à créer une deuxième version n’utilisant cette fois ci plus qu’une liste

contenant de la position des blocs d’eau. Bien que plus performante, nous ne sommes jamais arrivés

à un résultat totalement fonctionnel. Nous avons donc décidé de créer une troisième version, utilisant

une matrice et une liste de blocs contenant de l’eau.

Celle-ci ne fait plus aucun parcours de matrice, en effet toutes les fonctions ne s’exécutent plus que

sur la liste contenant de l’eau. Cette version a d’excellentes performances mais peut néanmoins

consommer beaucoup de mémoire, jusqu’à 250Mo de RAM.

Il reste des améliorations possibles, dans un premier temps sur les règles pour les mouvements des

liquides qui pourrait être perfectionnées. Dans un second temps, il faudrait faire un travail de

simplification du code pour qu’il soit plus clair et plus court. Pour la complexité, nous pensons avoir

atteints le maximum que nous sachions faire, donc nous ne n’allons pas essayer de réduire encore la

complexité.

Tests de performances :

Version 1 : uniquement une matrice, les performances dépendent de la taille du monde

Version 2 : pas de test car jamais fonctionnelle

Version 3 : matrice et liste contenant les positions du liquide, les performances dépendent du nombre

de bloc de liquide

La taille du monde est de 100 blocs de hauteur et fera environ 500 blocs de largeur (peut-être sujet à

des modifications). Ce qui donne un monde d’environ 50 000 blocs. Nous souhaitons que les

performances ne diminuent pas avant d’avoir 500 blocs de liquides présents sur le monde. Notre ban

de test a été le suivant : Intel i7, 16 Go RAM, Nvidia 1050 Ti.

Version 1 Hauteur (blocs) Largeur (blocs) Total (blocs) Images par seconde

Test 1 100 48 4800 ̴ 50

Test 2 100 96 9600 ̴ 30

Test 3 100 160 16 000 ̴ 10

Test 4 100 500 50 000 < 5

Version 3 Nombres de blocs de liquide Images par seconde

Test 1 < 500 ̴ 110

Test 2 1000 ̴ 90

Test 3 2500 ̴ 80

Test 4 4000 ̴ 70

Test 5 5000 ̴ 50

Test 6 6000 ̴ 100

Avec la version 3, lorsque nous somme en 6000 et 7000 blocs image par seconde remontent comme

au départ, nous n’avons pas trouvé pourquoi mais nous pensons atteindre une limite de taille sur la

liste de position car le nombre d’élément se bloque entre 6000 et 7500.

Page 34: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 34

2.5.4 – L’herbe :

Pour rajouter du contenu et de l’interaction avec l’environnement du jeu, nous avons décidé

de créer de l’herbe à la surface des blocs d’herbe.

Pour ce faire, nous avons désigné deux images, une pour l’herbe à l’état normale et une autre

lorsque cette dernière est écrasée par le joueur.

De plus pour rajouter du dynamisme à l’herbe, nous avons utilisé un « shader » (programme qui

paramètre le processus de rendu) qui simule l’ondulation de l’herbe face au vent.

Pour l’apparition de l’herbe sur le monde, nous avons créé une fonction qui pose l’herbe à la surface

du relief et qui vérifie que le bloc en dessous soit bien un bloc d’herbe :

Chaque image (« Sprite ») de l’herbe sur le monde possède son propre script qui vérifie plusieurs

choses. Premièrement, le script vérifie les changements de blocs :

- Le bloc en dessous de l’herbe

- Le bloc au niveau de l’herbe

Si les types de blocs ne correspondent pas respectivement à un bloc d’herbe et un bloc d’air, l’herbe

est supprimée du monde.

Dernièrement, le script détecte si le joueur se trouve sur l’herbe et modifie en fonction son image

entre les deux ci-dessus.

L’herbe n’est pas entièrement terminée car il reste à intégrer la gestion de fin de monde, car pour

l’instant l’herbe n’apparait pas aux bornes du monde.

2.5.5 - Monde Infini

Nous avons décidé que le joueur devait pouvoir faire le tour du monde et revenir à son point de

départ. Pour ce faire nous téléportons le joueur en position 0 lorsqu’il atteint la fin du monde ou en fin

de monde lorsqu’il atteint la position 0.

public static void GrassGenerate();

public static void GrassGenerate()

{

for (int x = 0; x < World.size * Chunk.size; x++)

{

Chunk c = GetChunk(x);

int yground = c.GetGroundY(Chunk.GetLocaleX(x));

if (World.GetBlock(x, yground - 1).GetType == Block.Type.Grass)

{

Grass.Spawn(x,yground);

}

}

}

Page 35: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 35

Néanmoins l’affichage des éléments « au-delà » de la fin du monde (donc ceux du début) ne

s’affichait pas avant la téléportation. Nous avons donc mis en place un système d’affichage qui

affiche tous les éléments « au-delà » du monde.

2.6 - La génération de l’environnement :

Pour la génération de l’environnement du jeu, nous avons décidé de créer un algorithme qui

génère le terrain du jeu de façon aléatoire mais contrôlé (alias procédurale).

Nous avons également mis en place un système de graine (« Seed ») de la carte du jeu pour que les

utilisateurs puissent jouer sur la même génération de carte. Cela pourra permettre aux joueurs de jouer

plusieurs fois sur une certaine génération ou bien même d’imaginer un système de compétition en

limitant l’aspect aléatoire du jeu.

2.6.1– génération du monde :

La génération du monde correspond à celle du relief du monde.

La génération du relief est procédurale (aléatoire contrôlé).

Pour créer un relief qui correspond à celui d’une planète tel que la nôtre, nous avons décidé d’utiliser

un « Simplex noise » qui est une texture de bruit qui permet d’avoir des nuances de gris qui peuvent

être contrôlé en fonction de plusieurs variables tel que : les octaves, la période, la persistance et la

lacunarité.

Après de nombreux essais nous avons déterminé les valeurs associer aux variables ci-dessus :

- Octaves = 3

- Période = 20

- Persistance = 0.1

- Lacunarité = 3.5

Apres l’obtention de nos valeurs de nuances de gris, nous avons déterminé les variables de

délimitation de notre monde :

« chunkMax » : l’ordonné maximale de notre monde

« chunkMin » : l’ordonné minimale de notre monde

« height » : La hauteur de notre monde

« seaLevel » : correspond au niveau de la mer théorique

« minYGeneration » : l’ordonné minimale de la génération de la surface du monde

« maxYGeneration » : l’ordonné maximale de la génération de la surface du monde

Ainsi avec les valeurs « minYGeneration », « maxYGeneration » et les valeurs du bruit simplex, nous

avons pu générer le relief de notre monde.

public const int chunkMax = 100;

public const int chunkMin = 0;

public const int height = (chunkMax-chunkMin)+1;

public const int seaLevel = chunkMin + 30;

public const int minYGeneration = seaLevel - 12;

public const int maxYGeneration = seaLevel + 20;

Page 36: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 36

2.6.2 –

génération

des minerais :

Pour la génération des minerais nous avons créé une nouvelle classe statique « Ore ». Cette classe

possède :

- Une liste « ores » qui contient les types des blocs correspondant à un minerai

- Un Dictionnaire « probabilities » qui associe une probabilité d’apparition a un minerai

- Un Dictionnaire « heights » qui associe une hauteur à un minerai, la hauteur représente

une hauteur en dessous de laquelle le minerai peut apparaitre

La classe « Ore » possède également une liste de couples composés d’un flottant et d’une chaine de

caractères « veins » qui permet à partir d’un nombre flottant compris entre 0.0 et 1.0 d’obtenir la

forme d’un filon.

Pour obtenir la forme du filon à partir d’une chaine de caractère de la forme « ___,___,___ » avec ‘_’

égale ‘0’ ou ‘X’, il faut voir la chaine de charactère comme un tableau de 3 colonnes et de 3 lignes qui

public static List<Block.Type> ores = new List<Block.Type>

{

Block.Type.SonarOre,

Block.Type.OspiritOre

};

public static Dictionary<Block.Type, float> probabilities = new

Dictionary<Block.Type, float>

{

{Block.Type.SonarOre, 0.15f},

{Block.Type.OspiritOre, 0.02f}

};

public static Dictionary<Block.Type, int> heights = new Dictionary<Block.Type, int>

{

{Block.Type.SonarOre, 15},

{Block.Type.OspiritOre, 10}

};

Page 37: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 37

représente la position spatiale des minerais dans le filon. Ainsi, il faut parcourir de gauche à droite la

chaine caractère sachant qu’un ‘X’ correspond à un minerai du filon.

Exemple : pour « 0XX,XXX,XX0 » on a :

Ainsi, grâce à ces données on peut générer les minerais en fonction de leur rareté et de leurs couches

d’apparition et ils peuvent apparaitre sous différente forme de filon.

La génération des minerais se déroule juste après la génération du relief du terrain à travers la

fonction :

Cette fonction parcourt le terrain de gauche à droite, blocs par blocs. A chaque valeur de x du terrain

elle calcule un flottant pour chaque minerai, et si celui-ci correspond à la probabilité d’apparition du

minerai en question alors un filon aléatoire sera créé à une hauteur aléatoire en dessous de la hauteur

d’apparition du minerai.

0 X X

X X X

X X 0

public static List<(float, string)> veins = new List<(float, string)>

{

(0.1f, "000,0XX,000"),

(0.2f, "0X0,0X0,000"),

(0.3f, "0X0,0X0,X00"),

(0.4f, "0XX,0XX,000"),

(0.5f, "0X0,0XX,000"),

(0.6f, "0XX,0XX,XX0"),

(0.7f, "0XX,XXX,XX0"),

(0.8f, "0XX,X00,XXX"),

(1.0f, "XX0,0X0,000")

};

private static void OreGenerate();

Page 38: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 38

2.6.3 – Génération des arbres :

Nous avons ajouté les arbres pour créer les prémices d’une biodiversité avec laquelle le joueur

pourra interagir. Les arbres sont constitués de deux éléments, le tronc et le feuillage, actuellement il

existe deux types d’arbres, les « verts » et les « roses ».

Un monde possède un paramètre de densité moyenne d’arbre par chunk (subdivisons du monde) qui

permet de régler la densité d’arbre présente sur le monde. Tous les arbres générés sont ensuite stockés

dans une liste

Chaque arbre, généré aléatoirement, peut avoir une infinité de tailles. Il possède également plusieurs

paramètres comme de la vie, ses ressources et sa position.

La vie d’un arbre dépend de sa taille, plus il est grand plus il aura de vie. Il en est de même avec les

ressources (ce qu’il donne au joueur lorsqu’il est détruit), les ressources étant toujours du bois.

Le joueur peut détruire un arbre de deux manières. Soit en le détruisant avec le pistolet laser, une

animation est présente sur l’arbre pour montrer qu’il perd de la vie. Lorsque l’arbre est détruit il tombe

sur le sol et donne ses ressources. Soit en détruisant le bloc sur lequel repose l’arbre, à ce moment-là

l’arbre se détruit instantanément mais ne donne aucune ressource au joueur.

La génération de l’arbre elle se fait donc par chunk car une fois un chunk généré il va ensuite générer

ses arbres.

private static void OreGenerate()

{

for (int x = 0; x < World.size * Chunk.size; x++)

{

foreach (var ore in Ore.ores)

{

float p = (float)random.NextDouble();

if (p <= Ore.probabilities[ore])

{

int height = random.Next(1, Ore.heights[ore] + 1);

if (World.GetBlock(x, height).GetType == Block.Type.Stone)

{

Ore.CreateVein(ore, x, height);

}

}

}

}

}

Page 39: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 39

A chaque coordonnée “x” du chunk on va juste rendre aléatoire le fait que nous allons oui ou non placer

un arbre en fonction de la TREE_FREQUENCY , les arbres seront alors simplement placés à la

coordonnée “y” du sol.

2.6.4 – Génération des grottes :

Le jeu comporte aussi un système aléatoire de génération des grottes.

Pour cela on utilise un automate cellulaire simple semblable à celui du “jeu de la vie” de John Horton

Conway.

La génération s’effectue en deux étapes tout d’abord sur une matrice de booléens représentant le

monde :

1) En utilisant les nombres aléatoires de la graine on initialise aléatoirement chaque case du

monde en « vrai » (bloc plein) ou en « faux » (bloc d’air)

2) Ensuite on effectue plusieurs générations, ici 7, de l’automate cellulaire pour former des

grottes.

private void TreesGeneration()

{

for (int x = 0; x < size; x++)

{

float r = (float)World.random.NextDouble();

if (r <= TREE_FREQUENCY)

{

int y = GetGroundY(x);

Tree.SpawnTree(new Vector2(x+id*size,y));

}

}

}

Page 40: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 40

A chaque génération on applique les règles de génération sur chacune des cases en fonction de leur

nombre de voisins « vrai », qui sont les suivantes :

- Si un bloc est « vrai » alors s’il a moins de 4 voisins il devient « faux » sinon il reste vrai.

- Si un bloc est « faux » alors s’il a moins de 4 voisins il devient « vrai » sinon il reste faux.

Chacune des générations est effectuée pas en place et demande la création d’une nouvelle matrice.

Une fois les générations effectuées on applique la dernière matrice au monde et on remplace par de

l’air tous les blocs de roches de la carte qui sont à une coordonnée « faux » de la matrice.

Page 41: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 41

2.6.5 – Génération des lacs :

La génération des lacs se base sur un niveau d’océan qui est la hauteur maximum d’apparition de

l’eau. Tous les blocs d’air en dessous de ce niveau et au-dessus du sol sont remplacés par de l’eau.

private static void CaveGenerate()

{

bool[,] cellmap = Cave.InitCave();

for (int i = 0; i < World.size * Chunk.size; i++)

{

for (int j = 0; j < Chunk.maxYGeneration; j++)

{

if (!(cellmap[i, j]))

{

int yWorld = j;

Chunk c = GetChunk(i);

int xChunk = i % Chunk.size;

Block.Type t = World.GetBlock(i, j).GetType;

if (t == Block.Type.Stone)

c.AddBlock(xChunk, yWorld,

Block.Type.Air);

}

}

}

}

Page 42: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 42

Les blocs de terre avec de l’herbe sont remplacé par un bloc de terre si de l’eau est dessus.

La fonction qui génère les lacs

Un exemple de génération

2.7 – Le pistolet laser :

Le pistolet laser, nommé « Raygun » dans la plupart du projet, sert à se défendre face à des

ennemis mais aussi à récupérer des ressources en cassant des blocs par exemple. Il sera l’outil le plus

private static void SeasGenerate()

{

for (int x = 0; x < World.size * Chunk.size ; x++)

{

Chunk c = GetChunk(x);

int yground = c.GetGroundY(Chunk.GetLocaleX(x));

if (yground <= Chunk.seaLevel)

{

GetChunk(x).AddBlock(Chunk.GetLocaleX(x), yground-1,

Block.Type.Dirt);

}

for (int y = Chunk.seaLevel; y >= yground; y--)

{

Liquid.PlaceLiquid(x, y, Liquid.Type.Water);

GetChunk(x).GetBlock(Chunk.GetLocaleX(x), y).isAutoGenerated =

true;

}

}

}

Page 43: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 43

utilisé par notre personnage et sera vital à sa survie, il est donc impératif qu’il soit fonctionnel et qu’il

donne au joueur une bonne sensation quant à son utilisation.

Il sera en tout temps dans les mains du joueur et se focalisera sur l’emplacement de la souris mais

n’aura qu’une certaine rangé d’action.

La scène du laser utilise un nœud RayCast2D pour pouvoir savoir ce qui rentre en collision

avec son rayon.

La fonction shoot(float delta) nous montre bien que si le RayCast2D rentre en collision avec un

bloc, un arbre ou un ennemi cela appelle respectivement les fonctions BlockCollision, TreeCollision et

EnemyCollision qui vont faire des dégâts à l’objet concerné jusqu’à ce qu’il n’ait plus de vie et

disparaisse. Pour que cela fonctionne le laser possède un taux de dégât et les objets ont une vie limitée.

L’animation du rayon laser se fait grâce à deux images begin et beam chacune dans un sprite

différent. L’image begin sert à faire un cercle à la sortie du canon du pistolet laser, puis beam fait la

continuité du laser jusqu’à la fin. Ceci est possible en agrandissant l’image beam avec la RegionRect

d’un sprite qui contrôle la taille d’une image. En donnant pour celle-ci la longueur entre le canon et la

collision ou s’il n’y a pas de collision entre le canon et la fin du Raycast2D. Pour que cette image

suive le RayCast2D elle va prendre la rotation du celui-ci. Enfin, si le rayon collisionne avec un objet

cela crée une Particule2D à l’endroit de la collision. Nous pouvons donc remarquer ces configurations

dans la fonction shoot du dessus présent au début après la première condition et à la fin lors de la

condition contraire.

Page 44: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 44

public void shoot(float delta)

{

begin.Visible = true;

beam.Visible = true;

if (raycast.IsColliding())

{

end.GlobalPosition = raycast.GetCollisionPoint();

float collision = (raycast.GetCollisionPoint()-

raycast.GlobalPosition).Length()*500/120;

beam.Rotation = raycast.CastTo.Angle();

var beamRegionRect = beam.RegionRect;

var vector2 = beamRegionRect.End;

vector2.x = collision;

beamRegionRect.End = vector2;

beam.RegionRect = beamRegionRect;

var hit_collider = raycast.GetCollider();

// Collide with a block

if (hit_collider is TileMap)

{

BlockCollision(delta);

}

else if (hit_collider is StaticBody2D)

{

// Collide with a tree

StaticBody2D s = (StaticBody2D) hit_collider;

if (s.GetGroups().Contains("tree"))

{

TreeCollision(delta);

}

}

else if (hit_collider is Ennemy_Fly)

{

EnemyCollision(delta);

}

}

else

{

end.GlobalPosition = raycast.CastTo;

beam.Rotation = raycast.CastTo.Angle();

var beamRegionRect = beam.RegionRect;

var vector2 = beamRegionRect.End;

vector2.x = raycast.CastTo.Length();

beamRegionRect.End = vector2;

beam.RegionRect = beamRegionRect;

}

particule.Emitting = true;

}

}

Page 45: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 45

2.8 – Les ennemis :

Les ennemis rajoutent de la difficulté au jeu et est un bon moyen de faire apprécier le jeu à la

personne qui y joue. Quoi de mieux que de tuer des ennemis avec un laser ?

Nous avons donc créé des ennemis volants ressemblant à ceci :

Ils vont un peu moins vite que le joueur et sont attiré par lui

lorsque celui-ci est proche. A la collision du joueur il lui inflige des

dégâts et recule pour réattaquer par la suite.

Les mouvements de ces ennemis sont basés sur le même

principe que celui du joueur à la différence près qu’ils ont des mouvements aléatoires lorsque le

joueur n’est pas proche et vont vers le joueur lorsqu’il est d’eux. Tous cela grâce à la fonction

« MoveAndSlide() » de Godot.

La fonction booléenne PlayerNear() indique si le joueur est près de l’ennemi.

private bool Player_Near()

{

var bodies = proximity.GetOverlappingBodies();

bool verif = false;

int i = 0;

int n = bodies.Count;

while (!verif && i < n)

{

if (((Node2D)bodies[i]).GetGroups().Contains("Player"))

{

verif = true;

}

i++;

}

return verif;

}

Page 46: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 46

La fonction Random_moves() donne sur l’axe x une vitesse et une direction aléatoire à

l’ennemi et le garde en l’air.

private void Random_moves()

{

if (EnemyDirection == 1)

{

Enemy_fly.FlipH = true;

}

else

{

Enemy_fly.FlipH = false;

}

if (IsOnWall() || IsOnFloor())

{

vel.y += JUMP_power;

vel.x = 0;

}

else

{

vel.y = 0;

}

if (!IsOnWall())

{

vel.x = EnemyDirection * rand.Next((int) (Speed/5),(int)(Speed));

}

MoveAndSlide(vel, up);

}

Page 47: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 47

La fonction Get_To_Player() fait bouger l’ennemi vers le joueur en le faisant glisser sur les

parois pour ne pas qu’il se bloque.

Lorsque la nuit tombe et toutes les 45 secondes un ennemi apparaît près du joueur en

« tombant du ciel » puis se relève et entreprend ces mouvements habituels.

Cet ennemi apparait car il a été instancié à la scène principale du jeu. Il ne peut pas y avoir plus de 5

ennemis à la fois et l’ennemi disparaît au bout d’un certain temps.

Pour rendre l’ennemi plus vivant on lui à ajouter une animation lorsqu’il vole (battement

d’ailes) et lorsqu’il meurt (désintégration).

Le joueur peut tuer un ennemi en maintenant son rayon laser dessus et il disparaitra au bout

d’un certain temps en tombant par terre et se désintégrant.

private void Get_To_Player()

{

Position_Player = new Vector2(PlayerMouvements.GetX(),

PlayerMouvements.GetY());

Position_Player = Convertion.World2Location(Position_Player);

Vector2 direction = (-this.GlobalPosition

+Position_Player).Normalized();

vel = direction * Speed;

if (vel.x >= 0)

{

Enemy_fly.FlipH = true;

}

else

{

Enemy_fly.FlipH = false;

}

MoveAndSlide(vel, up);

}

Page 48: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 48

2.9 – Interfaces utilisateur :

2.9.1 – Ajustement d’écrans :

Dès le début du jeu, nous avons fait face à un problème majeur, les différentes définitions et

de tailles de nos écrans. Nous avons donc ajouté un nœud au jeu chargé de ce problème.

Nous voulions que la fenêtre s’adapte aux écrans plus grands mais surtout plus petits. Pour cela nous

maximisons la fenêtre à la taille de l’écran au lancement du jeu et nous redéfinissons notre maximum

comme étant la taille de la fenêtre actuelle à ce moment-là. De cette manière le fenêtre du jeu ne peux

pas être plus grande que l’écran sauf si le joueur l’agrandit manuellement.

Si nous voulons utiliser le jeu dans une fenêtre plus petite, celle-ci passe automatiquement à quatre-

vingt-dix pourcents de la taille maximale lorsque nous cliquons sur le bouton pour passer en mode

fenêtre.

Nous avons décidé que notre jeu serait généré en 1920*1080 car c’est la définition d’écran la plus

courante selon “Steam”. Nous n’allons cependant pas nous adapter aux autres définitions car trop

compliqué à mettre en place et à tester. De plus, nous ne pensons pas avoir le temps de le faire. Le

jeu sera néanmoins jouable dans toute sorte de définition, si la définition est plus élevée, le viewport

(fenêtre générée par le jeu) affichera plus de bloc car il sera plus grand. Pour les résolutions inférieures,

cela sera l’inverse et nous verrons moins de bloc à l’écran.

2.9.2 – Menus :

Les menus prennent une place importante dans le jeu puisqu’ils permettent au joueur de gérer

ses sauvegardes.

Le menu d’accueil nous permet de lancer une partie avec une « seed » prédéfinie ou avec une « seed »

aléatoire. Le “seed” spécifique permet de générer une carte précise.

Un menu de gestion des sauvegardes est implémenté pour permettre de charger des parties, de les

sauvegarder et de les supprimer pour permettre au joueur de garder son avancée et d’étendre sa

session de jeux sur une vaste période de temps.

Page 49: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 49

2.10 – Système de sauvegardes :

La sauvegarde d’une partie est un point essentiel de notre jeu, notamment dû à longueur

d’une partie qui peut s’étendre sur plusieurs heures. Nous avons rencontré plusieurs difficultés

puisque nous avons commencé le jeu sans vouloir faire de système de sauvegarde, et donc celui-ci

n’était pas conçu pour.

Les sauvegardes de notre jeu se trouve dans les fichiers locaux de l’utilisateur

(« home/$USER/.Godot/app_userdata/ThirteenProject» sur linux et

« %appdata%/Godot/app_userdata/ThirteenProject » sur windows).

Un dossier de sauvegarde est composé de plusieurs fichiers, qui contienne toutes les informations

d’une partie.

Chaque fichier .data du dossier de sauvegarde est un fichier qui contient des informations au format

JSON.

Pour la sauvegarde :

Pour chaque fichier .data, on sérialise une classe au format JSON est on écrit le texte JSON

dans le fichier correspondant.

Pour le chargement :

Pour chaque fichier .data, on désérialise le texte du fichier pour obtenir la classe

correspondante avec les variables contenues dans la sauvegarde.

Exemple de la classe de sauvegarde du fichier « Environnement.data » :

Architecture d’une sauvegarde

Page 50: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 50

La classe « EnvironementDataModel » possède trois variables, ce sont les variables qui vont être

sauvegardées dans le fichier « Environnement.data ». La fonction « GetValues() » a pour but d’aller

récupérer les informations dans le jeu pour les stocker dans les variables de la classe avant que la

classe soit sérialiser pour obtenir un fichier JSON.

A l’inverse, la fonction « SetValues() » a pour but de mettre à jour les valeurs du jeu en fonction des

variables de la classe de sauvegarde.

public class EnvironementDataModel

{

public float time { get; set; }

public List<float> sunPowerhistory { get; set; }

public float timePlayed { get; set; };

public void GetValues()

{

time = Environement.time;

sunPowerhistory = Environement.sunPowerhistory;

timePlayed = Game.timePlayed;

}

public void SetValues()

{

Environement.time = time;

Environement.sunPowerhistory = sunPowerhistory;

Game.timePlayed = timePlayed;

}

}

Page 51: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 51

2.11 – Son :

Tous les sons du jeu attachés au joueur sont joués grâce à la fonction « PlayStream » présente dans

le script « PlayerMouvements.cs ».

Celle-ci permet de diffuser un grand nombre de son différents simultanéments.

Pour chaque son, un nouveau AudioStreamPlayer2D est créé, le son est joué puis le nœud est

détaché.

Les sons sont regroupés dans un dictionnaire dans le script « Sound.cs » pour rendre leur utilisation

plus pratique, leur nom, leur chemin d’accès et le niveau de décibel à lequel on veut les jouer est

ainsi stocké.

public async void PlayStream(Sounds.Type sound)

{

AudioStreamPlayer2D Sound = new AudioStreamPlayer2D();

Sound.Stream = Sounds.sounds[sound];

Sound.VolumeDb = Sounds.soundAjust[sound];

AddChild(Sound);

Sound.Play();

await ToSignal(Sound, "finished");

Sound.QueueFree();

}

Page 52: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 52

public enum Type

{

PlayerDeath,

PlayerGetloot,

PlayerLaser,

BlockBreak,

PlayerHurt,

PlayerStep,

PlayerPlouf,

PlayerLanding

}

public static Dictionary<Type, AudioStream> sounds = new Dictionary<Type,

AudioStream>

{

{Type.PlayerDeath,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Player/player_death.wav")},

{Type.PlayerGetloot,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Player/player_getloot.wav")},

{Type.PlayerLaser,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Player/player_laser.wav")},

{Type.BlockBreak,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Blocks/BlockBreak.wav")},

{Type.PlayerHurt,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Player/player_hurt.wav")},

{Type.PlayerStep,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Blocks/BlockBreak.wav")},

{Type.PlayerPlouf,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Player/player_plouf.wav")},

{Type.PlayerLanding,

GD.Load<AudioStream>("res://Assets/Ressources/Sounds/Blocks/BlockBreak.wav")},

};

public static Dictionary<Type, float> soundAjust = new Dictionary<Type, float>

{

{Type.PlayerDeath, -15},

{Type.PlayerGetloot, -25},

{Type.PlayerLaser, -15},

{Type.BlockBreak, -20},

{Type.PlayerHurt, -15},

{Type.PlayerStep, -37},

{Type.PlayerPlouf, -20},

{Type.PlayerLanding, -28}

};

Page 53: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 53

3 - Chronologie :

Dans cette partie, nous détaillons la liste des choses faites depuis le début du projet, pour

chaque section le nombre d’heure indique le temps approximatif passé dessus.

Adrien Pierre Hugo Lucas Thimot

Documentation 30h 20h 20h 45h 25h

Dessins 2h 30h 30h 3h

Le joueur 18h 20h

Bâtiments 35h 12h 10h 50h

Ressources 25h

Environnement 25h 80h

Génération du monde 30h 5h

Ennemi 1h 2h 15h

Interface utilisateur 20h 5h

Son 1h 5h

Sauvegardes 20h

Equilibrage 5h 4h 2h 15h

Site 4h 30h 8h

Corrections de bug 20h 5h 2h 4h

Détails mineurs 10h 5h 3h 5h

Total 246h 83h 94h 91h 192h

Page 54: Rapport de projet - ollopa.fr · ollopa.fr 1 Rapport de projet 27 mai 2020 VERNAY Rémi ROUSSILLE Philippe PINGARD Adrien VEYRE Thimot LITOUX Pierre DEPLAGNE Hugo LLOMBART Lucas

ollopa.fr 54

4 - Conclusion : En conclusion de ce rapport, nous sommes fiers de notre jeu même s’il n’est pas parfait. Nous ne

pensions pas avoir quelque chose d’aussi amusant au départ, sachant que c’était notre premier

véritable projet en équipe. Lors des phases d’équilibrages nous avons eu d’excellent retour de la part

d’amis qui le trouvaient amusant, ce à quoi nous ne nous attendions pas vraiment.

De plus, ce projet nous a permis d’apprendre énormément en informatique mais également en gestion

de planning, préparation de soutenances et gestion de groupe.

Les points que nous n’avons pas réaliser ou modifier par rapport au cahier des charges sont des

adaptations pour rendre le jeu meilleur. Après la dernière soutenance, nous souhaitons continuer le jeu

et peut-être le mettre gratuitement sur une plateforme de jeu.

En définitive, ce jeu nous a beaucoup apportés et nous espérons qu’il vous amusera.