Aller au contenu principal

Responsabilités du code

Regarde ton code validé du Projet 02. Il tourne parfaitement et valide tous les tests de la checklist. Mais si tu regardes l'intérieur de SpawnOne(), remarque combien de tâches différentes cette unique méthode prend en charge :

  1. Elle vérifie si un ped est déjà actif.
  2. Elle valide le modèle et le demande au moteur avec un délai d'attente.
  3. Elle calcule les coordonnées et l'orientation relative au joueur.
  4. Elle manipule le moteur avec World.CreatePed.
  5. Elle envoie des retours visuels à l'écran.

Tant que tes scripts font moins de cinquante lignes, regrouper toutes ces responsabilités reste tolérable. Mais dès le Stage 4, tu vas donner à ce PNJ des armes, des tâches de combat et des logiques de faction. Si tout ce code est entassé dans une seule méthode, modifier un détail cassera immanquablement le reste.

Les quatre responsabilités fondamentales d'un mod

Tout script de jeu se découpe naturellement en quatre couches de responsabilités distinctes :

+------------------------------------------------------+
| 1. Saisie & Cadence (KeyDown, chronomètres Tick) |
+------------------------------------------------------+
|
+------------------------------------------------------+
| 2. Validation & État (clauses de garde, limites) |
+------------------------------------------------------+
|
+------------------------------------------------------+
| 3. Opérations moteur (streaming, apparitions, tâches)|
+------------------------------------------------------+
|
+------------------------------------------------------+
| 4. Cycle de vie & Nettoyage (suppression, remise à 0)|
+------------------------------------------------------+

Refactoriser le Projet 02 par rôle

Refactorisons le spawner pour que chaque méthode n'ait qu'une seule raison d'évoluer :

Rôle 1 : La gestion des entrées

Décide uniquement de quand agir :

private void OnKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.NumPad1)
{
TenterApparitionPed();
}
else if (e.KeyCode == Keys.NumPad0)
{
SupprimerPedCourant();
}
}

Rôle 2 : La validation d'état

Décide uniquement de si l'action est permise :

private void TenterApparitionPed()
{
if (EstDejaActif())
{
GTA.UI.Notification.PostTicker("Un PNJ est déjà présent.", false);
return;
}

Ped player = Game.Player.Character;
if (player == null || !player.Exists())
{
return;
}

Vector3 pointSpawn = CalculerPositionDevant(player);
_spawned = CreerPedA(PedHash.Trevor, pointSpawn, player.Heading);
}

private bool EstDejaActif()
{
return _spawned != null && _spawned.Exists();
}

Rôle 3 : Les opérations moteur

S'occupe exclusivement du streaming et de la création :

private Vector3 CalculerPositionDevant(Ped reference)
{
return reference.Position + reference.ForwardVector * 2.0f;
}

private Ped CreerPedA(PedHash hash, Vector3 position, float heading)
{
Model model = new Model(hash);
if (!model.IsValid || !model.IsInCdImage || !model.Request(2000))
{
model.MarkAsNoLongerNeeded();
return null;
}

try
{
return World.CreatePed(model, position, heading);
}
finally
{
model.MarkAsNoLongerNeeded();
}
}

Rôle 4 : Le nettoyage

Remet le monde dans son état d'origine :

private void SupprimerPedCourant()
{
if (_spawned != null && _spawned.Exists())
{
_spawned.Delete();
}
_spawned = null;
}

Pourquoi cette discipline change tout

Remarque le gain immédiat :

  • Tu veux changer la distance d'apparition de 2 mètres à 4 mètres ? Tu modifies uniquement CalculerPositionDevant. Le reste ne peut pas casser.
  • Tu veux faire apparaître Michael au lieu de Trevor ? Tu passes un argument différent à CreerPedA.
  • Tu veux ajouter une minuterie de disparition automatique ? Tu appelles SupprimerPedCourant() depuis OnTick sans réécrire la logique de suppression.

Tu as validé le Stage 3 Fondations. Tu comprends la boucle de simulation, l'espace 3D, les entités, leur validité et l'architecture modulaire. Dans le Stage 4 Systèmes de jeu, nous allons donner vie à ces acteurs avec de l'intelligence artificielle, des conduites de véhicules, des événements dynamiques et des sauvegardes persistantes.