Chronospatium

Ce projet de conception de jeu à été réalisé en équipe de 4 contenant 2 artistes et 2 programmeurs. Lors de ce travail d’équipe, mes tâches étaient de :
- Concevoir la mécanique de génération d’une carte sur une grille donnant l’impression d’être aléatoire.
- Permettre la téléportation du personnage.
- Gérer l’affichage des différents éléments de UI (Charges de téléportation et affichage des effets négatifs dans le UI).
- Programmer le fonctionnement des ennemis dans le mon « futuriste ».
- Programmer le changement des bonus / malus lors de l’activation d’un interrupteur.
- Sonoriser certaines interactions.
Exemples de code conçus lors de ce projet
Fonction de patrouille des ennemis du monde « futuriste ».
private IEnumerator CoroutinePatrouille()
{
// initialisation d'un compteur pour determiner chaque point a atteindre
int iCible = 0;
while (true) //pour toujours
{
// attend une duree avant de commencer le mouvement
yield return new WaitForSeconds(_dureePause);
// augmente la valeur de la cible pour aller a un prochain marqueur ou retour a zero si la valeur est trop grande
iCible++;
if (iCible >= _lPos.Count) iCible = 0;
// tant que la distance entre le gameobject et le marqueur n'est pas assez petite
while (Vector2.Distance(_rb.position, _lPos[iCible]) > _toleranceDestination)
{
// Modifie les coordonnes du point a atteindre pour empecher que l'ennemi se mette a voler
//Haut et Bas
if(_orientationEnnemi == SensObjet.haut || _orientationEnnemi == SensObjet.bas)
{
// prend le y de l'ennemi au lieu de la valeur du marqueur si l'ennemi doit etre a l'horizontale
_lPos[iCible] = new Vector2(_lPos[iCible].x, transform.position.y);
}
//Gauche
else if(_orientationEnnemi == SensObjet.gauche || _orientationEnnemi == SensObjet.droite)
{
// prend le x de l'ennemi au lieu de la valeur du marqueur si l'ennemi doit etre a la verticale
_lPos[iCible] = new Vector2(transform.position.x, _lPos[iCible].y);
}
// calcule la position pour que le gameobjectse rapproche de sa cible (marqueur)
Vector2 nouvPos = Vector2.MoveTowards(transform.position, _lPos[iCible], _vitesse * Time.deltaTime); //fixedDeltaTime
// approche le gamobject (deplacement)
_rb.MovePosition(nouvPos);
// retour a l'execution
yield return new WaitForFixedUpdate();
}
_rend.flipX = !_rend.flipX;
}
}
Fonction nécessaire au fonctionnement du lance portail.
/// <summary>
/// #tim Jeremie
/// Genere le projectile portail si le joueur possede les charges necessaires
/// </summary>
private void LancerPortail()
{
// instancie le prefab de portail a la position du perso
_goProjPortail = Instantiate(_prefabProjPortail, transform.position, Quaternion.identity);
// enregistre la reference du gameobject de portail sur la scene dans le SO InfosPerso
_iPerso.projectilePortail = _goProjPortail;
// obtient la composante du script du projectile portail
ProjectilePortail scriptProjectilePortail = _goProjPortail.GetComponent<ProjectilePortail>();
// envoie la direction vers laquelle le joueur se deplace (0 s'il ne bouge pas)
scriptProjectilePortail.directionHorizontale = _srPerso.flipX; // retourne la valeur de la direction vers laquelle le joueur "regarde"
scriptProjectilePortail.directionVerticale = Input.GetAxisRaw("Vertical"); // retourne la valeur de deplacement horizontal
_existeProjPortail = true; // enregistre le fait qu'un portail est sur la scene
}
/// <summary>
/// #tim Jeremie
/// Teleporte le personnage sur l'instance du portail present sur la scene
/// (Utilise par le lance portail pour forcer le joueur a retourner a sa position apres son delais
/// + par le lance portial lui meme)
/// </summary>
public void TeleporterSurPortail()
{
// obtient la composante de script du projectile portail enregistre en reference
ProjectilePortail scriptProjectilePortail = _goProjPortail.GetComponent<ProjectilePortail>();
// si le delais necessaire a attendre entre l'apparition et la teleportation est atteint
if(scriptProjectilePortail.peutTeleporter)
{
// deplace le joueur sur le projectile de portail
transform.position = _goProjPortail.transform.position;
// enregistre le fait qu'aucun portail n'est sur la scene
_existeProjPortail = false;
// detruit le projectile portail enregistre en reference dans les SO infosPerso
Destroy(_iPerso.projectilePortail);
// joue le son de teleportation
GestAudio.instance.JouerSon(_sonTeleportation);
}
}
Système d’inventaire complet conçus grâce à des « Scriptable Object ». (Pratique d’utilisation de « Scriptable Objects », un inventaire beaucoup plus simple aurait été possible)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Classe du bonus donnant des points en forme bonus ou qui inverse les commandes du joueur en mode malus
/// Auteurs du code: Jeremie Genier
/// Auteur des commentaires: Jeremie Genier
/// </summary>
[CreateAssetMenu(menuName="Infos du perso",fileName="InfosDuPerso")] //consigne de creation du menu de creation de l'asset
public class InfosPerso : ScriptableObject
{
[Header("Valeurs initiales")] //Entete de section pour les valeurs initiales avant la partie
[SerializeField] private string _nomIni; //nom par defaut
[SerializeField] private int _vieIni = 10; // nombre de vie initial
[SerializeField] private int _nbPtsIni = 0; // nombre de points initial
[SerializeField] private int _multiPtsIni = 1; // multiplicateur de points initial
[SerializeField] private int _nbChargesPortailIni = 0; // nombre de charges du lance portail initial
private Dictionary<string,int> _dEffetsIni = new Dictionary<string,int>(); // effets initiaux sur le perso (aucun)_projectilePortail
private GameObject _projectilePortailIni = null;
[Header("Valeurs en cours")] //Entete de section pour les valeurs durant la partie
[SerializeField] private string _nom; //nom durant la partie
[SerializeField] private int _vie; // nombre de vie durant la partie
[SerializeField] private int _nbPts; // nombre de points durant la partie
[SerializeField] private int _multiPts; // multiplicateur de points durant la partie
[SerializeField] private int _nbChargesPortail = 0; // nombre de charges du lance portail durant la partie
private Dictionary<string,int> _dEffets; // effets sur le perso durant la partie
private GameObject _projectilePortail;
[HideInInspector] public string _nomIntermediaire =""; //nom intermediaire, correspond au nom inscrit dans le champ par le joueur (avant le jeu)
public string nom { get => _nom; set => _nom = value; } //accesseur et mutateur du nom
public int vie { get => _vie; set => _vie = value; } // accesseur et mutateur du nombre de vies en cours de partie
public int nbPts { get => _nbPts; set => _nbPts = value; } // accesseur et mutateur du pointage en cours de partie
public int multiPts { get => _multiPts; set => _multiPts = value; } // accesseur et mutateur du multiplicateur de pointage en cours de partie
public int nbChargesPortail { get => _nbChargesPortail; set => _nbChargesPortail = value; } // accesseur et mutateur du nombre de charges de portail durant la partie
public string nomIntermediaire { get => _nomIntermediaire; set => _nomIntermediaire = value; } //accesseur et mutateur du nom intermediaire
public Dictionary<string,int> dEffets { get => _dEffets; } // accesseur au dictionnaire des effets
public GameObject projectilePortail { get => _projectilePortail; set => _projectilePortail = value; }
/// <summary>
/// Initialisation des valeurs par defaut
/// </summary>
public void Initialiser()
{
if(_nomIntermediaire != "") _nom = _nomIntermediaire; //si le nom inter n'est pas vide, changer le nom selon le nom inter
else { _nom = _nomIni; } //sinon, changer le nom pour le nom par defaut
_nomIntermediaire = ""; //vider le nom inter, pour la prochaine fois!
_vie = _vieIni; // La vie obtient sa valeur initiale
_nbPts = _nbPtsIni; // Le nombre de points obtient sa valeur initiale
_multiPts = _multiPtsIni; // Le multiplicateur de score obtient sa valeur initiale
_dEffets = _dEffetsIni; // Vide le dictionnaire des effets
_projectilePortail = _projectilePortailIni; // efface la reference au projectile si il en as une
}
/// <summary>
/// Enregistre un effet sur le personnage (peut avoir plusieurs fois le meme effet en cours)
/// </summary>
/// <param name="nomEffet">Nom de l'effet a ajouter</param>
/// <param name="quantite">Quantite a ajouter</param>
public void AjouterEffet(string nomEffet, int quantite)
{
// si l'effet existe deja dans le dictionnaire
if(_dEffets.ContainsKey(nomEffet)){
// agmente le nombre d'effet
_dEffets[nomEffet] += quantite;
}
else
{
// Ajoute l'effet au dictionnaire
_dEffets.Add(nomEffet,quantite);
}
}
/// <summary>
/// Reduit l'effet sur le personnage (plusieurs effets en quantite = plusieurs fois le meme effet en cours sur le perso)
/// </summary>
/// <param name="nomEffet">Nom de l'effet a reduire</param>
/// <param name="quantite">Quantite a retirer</param>
public void ReduireEffet(string nomEffet, int quantite)
{
if(_dEffets.ContainsKey(nomEffet)){
// si la reduction ne reduit pas l'effet en bas de 0
if((_dEffets[nomEffet] - quantite) >= 0)
{
// reduit l'effet de la quantite obtenue en parametre
_dEffets[nomEffet] -= quantite;
}
// sinon, l'effet tombe a zero
else
{
// met la valeur de l'effet a 0 (donc aucun effet)
_dEffets[nomEffet] = 0;
}
}
else
{
// message d'erreur
Debug.Log("Réduction d'effet impossible : Effet non existant");
}
}
}
// Cette fonctionest contenue dans le contrôleur du personnage
/// <summary>
/// #tim jeremie
/// Fonction activee lors d'un changement a propos des effets sur le personnage.
/// Reduction ou Augmentation.
/// </summary>
private void MiseAJourEffets()
{
//EFFET INVERSEMENT
// Si le dictionnaire contient le champ "Inversement" avec une valeur plus grande que 0, (donc inversement actif)
if(_iPerso.dEffets["Inversement"] > 0){
// Sers à inverser la valeur de deplacement horizontal GetAxis
_inversementCommandes = true;
// Affichage icone de l'effet
GestUI.instance.AfficherEffet("Inversement",1);
}
else{
_inversementCommandes = false; // Desactive l'effet si la valeur est 0 (inactif)
// Retire l'icone de l'effet
GestUI.instance.EffacerEffet("Inversement");
}
}
Logiciels utilisés
- Unity
- Blender
- Photoshop
Crédits et sources
- Modèles 3D, musique, composants UI et textures crées par Alex Tremblay et Xavier Coursol
- La programmation à été réalisée avec l’aide de Vincent Chalifoux
- Effets sonores provenant de opengameart.org