ebSkola

4.6 Noslēguma projekts: Top-down šautene

Stundas uzdevums: Apvienot datu struktūras, AI un object pooling pilnvērtīgā top-down šautenē.

SR 2.4.1. Problēmu dekompozīcija SR 2.4.16. Datu struktūras SR 2.4.18. OOP SR 2.4.19. Algoritmu efektivitāte

80 min plāns: Ievads un kritēriju pārruna (~10 min) · 1. uzdevums (~20 min) - spēlētājs ar kustību un mērķēšanu · 2. uzdevums (~25 min) - divi ienaidnieku tipi ar AI · 3. uzdevums (~20 min) - viļņu sistēma un rezultāts · Iesniegšana (~5 min).

Pirms sāc: šis ir 4. tēmas noslēguma projekts. Izmanto visu apgūto: sarakstus, vārdnīcas, stāvokļu mašīnu, pathfinding un lādiņu krātuvi. Sāc ar VIENU ienaidnieka tipu.

Teorija: Spēles apraksts un arhitektūra

Top-down šautene ar šādām funkcijām:

  • Spēlētājs ar 8 virzienu kustību un mouse-aimed šaušanu.
  • 3 ienaidnieku tipi ar dažādu AI uzvedību.
  • Pathfinding ap šķēršļiem.
  • Wave system: ienaidnieku viļņi ar augošu sarežģītību.
  • Pickup sistēma: HP, ammo, power-ups.
  • Score un wave skaitītājs.
// Klašu hierarhija
public partial class Player : CharacterBody2D { /* WASD + shoot */ }
public partial class Enemy : CharacterBody2D { /* state machine + pathfinding */ }
public partial class FastEnemy : Enemy { /* fast, light */ }
public partial class Brute : Enemy { /* slow, strong */ }
public partial class Shooter : Enemy { /* keeps distance, shoots */ }
public partial class Bullet : Area2D { /* pooled */ }
public partial class WaveManager : Node { /* spawns waves */ }

Kā šo izmantot projektā

Atceries: ar redzamu efektu editorā nepietiek. Paskaidro, kura C# klase glabā stāvokli, kura metode to maina un kā Godot node struktūra izmanto šo kodu.

Pārbaudi: C# kodā pamatoti izvēlēti List, Dictionary vai HashSet, AI stāvokļi ir skaidri, un sarežģītākas sistēmas var profilēt vai atkļūdot.

public class AiDataCheckpoint
{
    public string Lesson = "4.6 Noslēguma projekts: Top-down šautene";
    public bool UsesCSharp = true;
    public bool ChoosesContainer = true;
    public bool SeparatesAiState = true;
    public bool HandlesRemovalSafely = true;
}

Praktiskie uzdevumi

1. uzdevums -

Spēlētājs ar kustību un mērķēšanu

Beigās spēlētājs pārvietosies ar WASD un šaus peles virzienā.

  1. Izveido spēlētāja klasi ar 8 virzienu kustību un normalizētu vektoru.
  2. Paņem peles pozīciju ar GetGlobalMousePosition().
  3. Pagriez spēlētāju pret peli ar LookAt(...).
  4. Pievieno šaušanu no 4.5 stundas ar lādiņu krātuvi.
  5. Izšauj lādiņu spēlētāja skatīšanās virzienā.
  6. Būvē un pārbaudi kustību visos virzienos un šaušanu.
  7. Pārliecinies, ka diagonālā kustība nav ātrāka.

Gatavs, kad: spēlētājs kustas visos virzienos, vienmēr skatās uz peli un šauj tieši tajā virzienā.

2. uzdevums -

Divi ienaidnieku tipi ar AI

Beigās ienaidnieki uzvedīsies atšķirīgi.

  1. Izveido bāzes klasi Enemy ar stāvokļu mašīnu no 4.3 stundas.
  2. Izveido bērna klasi Chaser, kas dzenas ar pathfinding.
  3. Izveido otru bērna klasi Shooter, kas apstājas un šauj no attāluma.
  4. Glabā visus ienaidniekus vienā List<Enemy>.
  5. Uzraksti vienu ciklu, kas atjaunina visus ienaidniekus.
  6. Pievieno ienaidniekiem HP un dzēšanu, kad tie tiek nošauti.
  7. Pārbaudi, ka abi tipi uzvedas atšķirīgi.

Gatavs, kad: viens ienaidnieku tips dzenas pakaļ, otrs apstājas un šauj, un abus apstrādā viens cikls.

3. uzdevums -

Viļņu sistēma un rezultāts

Beigās spēle kļūs arvien grūtāka un skaitīs punktus.

  1. Izveido klasi WaveManager ar lauku int wave = 1;.
  2. Radi katrā vilnī vairāk ienaidnieku nekā iepriekšējā.
  3. Pārej uz nākamo vilni, kad visi ienaidnieki iznīcināti.
  4. Pievieno punktu skaitītāju un HUD ar vilni, punktiem un HP.
  5. Pievieno spēles beigas, kad spēlētāja HP sasniedz nulli.
  6. Izspēlē vismaz trīs viļņus.
  7. Veic commit un push.

Gatavs, kad: spēle pāriet no viļņa uz vilni, katrā ir vairāk ienaidnieku, un beidzas, kad spēlētājs zaudē HP.

Papildu uzdevums - Pievieno savācamos bonusus

Ja pamatdarbs ir gatavs, ļauj spēlētājam atjaunot HP un munīciju.

  1. Izveido Area2D bonusa scēnu ar veidu HP vai AMMO.
  2. Radi bonusu nejaušā vietā pēc katra viļņa.
  3. Palielini attiecīgo vērtību, kad spēlētājs to savāc.
  4. Ierobežo HP, lai tas nepārsniegtu maksimumu.
  5. Pārbaudi abus bonusa veidus.

Gatavs, kad: bonusi parādās pēc katra viļņa un atjauno HP vai munīciju, nepārsniedzot maksimumu.

Ko sagatavo

Stundas mērķis: Tev ir izspēlējama top-down šautene: spēlētājs ar 8 virzienu kustību un mērķēšanu pret peli, vismaz divi ienaidnieku tipi ar atšķirīgu AI, viļņu sistēma ar augošu grūtību un HUD ar punktiem un HP.

GitHub krātuvē jābūt:

  1. Viss projekts ar C# skriptiem, scēnām un projekta failiem.
  2. README.md ievietota video saite, kurā izspēlē vismaz divus viļņus un redzami abi ienaidnieku tipi.
  3. Faili Player.cs, Enemy.cs, abu ienaidnieku tipu klases un WaveManager.cs.
  4. README.md: kā tavi divi ienaidnieku tipi atšķiras un kāpēc abus var apstrādāt vienā ciklā.

Kā iesniedz: Veic commit un push. Skolotāja norādītajā vietā ievieto tikai GitHub krātuves saiti; visiem prasītajiem failiem, README.md pierakstiem un pierādījumiem jābūt pašā krātuvē.

Biežākās kļūdas

  • Lag ar daudziem enemies: Pārliecinies, ka NavigationAgent2D update_freq ir saprātīgs.
  • Bullets sit savus: Pārbaudi collision layers - Player bullets jāignore Player.
  • Wave neuzsākas: Timer vai counter sajaucies - debug ar print statements.

Godot ekrānuzņēmumi

Top-down šautenes spēles aina: spēlētājs centrā, 8 ienaidnieki dažādos virzienos, lādiņu trajektorijas, HP bāris.
Top-down šautenes spēles aina: spēlētājs centrā, 8 ienaidnieki dažādos virzienos, lādiņu trajektorijas, HP bāris.
Spēles UI: 'Wave 3' augšā, 'Enemies: 8/12' centrā, 'Score: 1240' apakšā, HP bāris, ammo skaitītājs.
Spēles UI: 'Wave 3' augšā, 'Enemies: 8/12' centrā, 'Score: 1240' apakšā, HP bāris, ammo skaitītājs.

Koda piemērs (paplašināts)

using Godot;
using System.Collections.Generic;

public enum EnemyType { Fast, Brute, Shooter }

public partial class WaveManager : Node
{
    private int currentWave = 0;
    private float waveTimer = 0.0f;
    private readonly List<Enemy> activeEnemies = new();

    private record Wave(int FastEnemies, int Brutes, int Shooters);

    private readonly List<Wave> waves = new()
    {
        new Wave(3, 0, 0),      // wave 1
        new Wave(5, 1, 0),      // wave 2
        new Wave(6, 2, 1),      // wave 3
        new Wave(8, 3, 2),      // wave 4
        new Wave(10, 5, 3)      // wave 5 + boss
    };

    public override void _Process(double delta)
    {
        waveTimer -= (float)delta;
        if (activeEnemies.Count == 0 && waveTimer <= 0)
        {
            StartNextWave();
        }
    }

    private void StartNextWave()
    {
        if (currentWave >= waves.Count)
        {
            GD.Print("All waves complete!");
            return;
        }

        Wave wave = waves[currentWave];
        for (int i = 0; i < wave.FastEnemies; i++) Spawn(EnemyType.Fast);
        for (int i = 0; i < wave.Brutes; i++) Spawn(EnemyType.Brute);
        for (int i = 0; i < wave.Shooters; i++) Spawn(EnemyType.Shooter);
        currentWave++;
        waveTimer = 30.0f;
    }
}
Pilnvērtīga top-down šautene ar 5 viļņiem, 3 ienaidnieku tipiem, pathfinding un boss.