ebSkola

1.5 Spēles laukuma izveide

Stundas uzdevums: Pabeigt Pong laukumu un ieviest abu rakešu vadību, bumbas kustību un atlēkšanu.

SR 2.4.7. Lietotāja saskarne (UI) SR 2.4.13. Datu tipi

80 min plāns: Ievads (~10 min) · laukuma robežas (~20 min) · rakešu vadība (~25 min) · bumbas atlēkšana (~20 min) · saglabāšana (~5 min).

Pirms sāc: vajadzīgas 1.4 scēnas un Paddle.cs ar Speed un ievades nosaukumiem. Šodien laukums kļūs kustīgs: pārbaudīsi raketes un bumbu. Punktu uzskaite un spēles vadība būs 1.6 stundā.

Darba ritms: pēc katra uzdevuma saglabā un pārbaudi rezultātu. Kad projektam pievienots C# skripts, pirms palaišanas nospied Build. Kļūdu gadījumā sāc ar pirmo sarkano kļūdu, nevis nākamo uzdevumu.

Teorija: koordinātes, ātrums un sadursme

1280 × 720 laukumā centrs ir (640,360). X pieaug pa labi, Y — uz leju. Saknes Position novieto objektu laukumā, bet tās bērnu Visual un CollisionShape2D pozīcijas paliek (0,0). Fizikas saknes Scale atstāj (1,1); izmēru maina formā.

Velocity glabā ātrumu pikseļos sekundē. Raketei MoveAndSlide() laiku ņem vērā pats. Bumbai MoveAndCollide(Velocity * (float)delta) nododam viena soļa pārbīdi. Tāpēc delta šajās divās metodēs lieto atšķirīgi.

Ja MoveAndCollide atgriež sadursmi, Velocity.Bounce(collision.GetNormal()) aprēķina atlēkušo ātrumu. Bez sadursmes rezultāts ir null. Fizikas kustība notiek _PhysicsProcess. Godot kustības un atlēkšanas dokumentācija.

ObjektsLayer ķeksīšiMask ķeksīši
WallTop, WallBottom (StaticBody2D)tikai 1neviens
PaddleLeft, PaddleRight (CharacterBody2D)tikai 2tikai 1
Ball (CharacterBody2D)tikai 31 un 2

Tabulā ir Inspector ķeksīšu numuri. .tscn failā 3. slāņa bitu vērtība ir 4. Ball Mask 1 un 2 bitu vērtība ir 3. Raketēm bumbas slāni Mask neieslēdzam: bumba pati nosaka sadursmi ar raketi.

1. uzdevums -

Izveido redzamas laukuma robežas

  1. Atver Main.tscn. Pārbaudi PaddleLeft (60,360), PaddleRight (1220,360), Ball (640,360). Main sakne paliek (0,0).
  2. Main pievieno StaticBody2D bērnu WallTop, Position = (640,10). Tam pievieno CollisionShape2D ar New RectangleShape2D, Size = (1280,20); formas mezgla Position = (0,0).
  3. WallTop pievieno Polygon2D bērnu Visual ar punktiem (-640,-10), (640,-10), (640,10), (-640,10) un redzamu krāsu. Sienas fizikas forma viena pati spēlē nav redzama.
  4. Dublē visu WallTop par WallBottom, saknes Position = (640,710). Abām sienām Layer tikai 1, Mask neviena ķeksīša. No dublēšanas kopīgs Shape ir derīgs, kamēr abām vajadzīgs vienāds izmērs.
  5. Pievieno Main bērnu Line2D ar nosaukumu CenterLine, Points = (640,20) un (640,700), Width = 2, neuzkrītošu krāsu. Tā ir dekorācija un nedrīkst apturēt bumbu.
  6. Pārbaudi visu objektu Layer un Mask pēc tabulas. Palaid F5: redzamas divas sienas, raketes un bumba. Šim fiksētajam laukumam Camera2D nav vajadzīga.

Gatavs, kad: attēls un sadursmes ir vienā vietā, sienas iet gar augšu un apakšu, sānu malas paliek atvērtas punktiem.

2. uzdevums -

Pievieno vadību abām raketēm

  1. Project → Project Settings → Input Map ar Add izveido visas sešas tabulas darbības; ar + pievieno attiecīgo taustiņu. Pārbaudi mazos burtus un pasvītrojumus.
  2. Paddle.cs saglabā _Ready un esošos laukus. Klases iekšpusē pievieno _PhysicsProcess no pilnā faila zemāk. Ja izmanto visu failu, aizstāj esošo saturu, neveido otru Paddle klasi.
  3. Saglabā un Build. Main scēnā PaddleRight Input Up/Down joprojām jābūt p2_up/p2_down, kreisajai — p1_up/p1_down; Speed abām 420.
  4. Ar F5 pārbaudi W/S un ↑/↓ atsevišķi un vienlaikus. Turot abus viena spēlētāja pretējos virzienus, rakete apstājas. Atlaižot taustiņus, tai arī jāapstājas.
  5. Turi katru raketi pret augšējo un apakšējo sienu. Tām jāpaliek laukumā: raketes centra Y robežas ir aptuveni 80 un 640 (siena 20 px + raketes pusaugstums 60 px).
DarbībaTaustiņš
p1_upW
p1_downS
p2_up↑
p2_down↓
serveSpace — izmantosim 1.6
restartR — izmantosim 1.6
1.5 Paddle.cs ar kustību — pilns fails salīdzināšanai

Lejupielādēt Paddle.cs. Aizstāj tikai atbilstošā faila saturu; neveido otru tāda paša nosaukuma klasi.

using Godot;

public partial class Paddle : CharacterBody2D
{
    [Export] public float Speed = 420.0f;
    [Export] public string InputUp = "p1_up";
    [Export] public string InputDown = "p1_down";
    public bool IsActive { get; set; } = true;

    public override void _Ready()
    {
        GD.Print($"{Name}: ātrums {Speed}, vadība {InputUp}/{InputDown}, aktīva {IsActive}");
    }

    public override void _PhysicsProcess(double delta)
    {
        if (!IsActive)
        {
            Velocity = Vector2.Zero;
            return;
        }

        float direction = Input.GetAxis(InputUp, InputDown);
        Velocity = new Vector2(0, direction * Speed);
        MoveAndSlide();
    }
}

Gatavs, kad: divi spēlētāji vienlaikus vada savas raketes un neviena neiziet cauri sienām.

3. uzdevums -

Pievieno bumbas kustību un atlēkšanu

  1. Atver Ball.tscn un tās saknei pievieno res://Scripts/Ball.cs. Aizstāj saturu ar pilno failu zemāk. Base Speed = 420, Motion Mode = Floating. Saglabā un Build.
  2. Palaid Main ar F5. Ball _Ready sāk bumbas kustību pa labi ar nelielu nejaušu vertikālo komponenti. Normalized saglabā kopējo ātrumu 420 px/s.
  3. Pārbaudi atlēkšanu no abām raketēm un abām sienām. Redzamā viduslīnija bumbu neaptur. Ja vajag, atkārto F5 vairākas reizes, lai novērotu abus vertikālos virzienus.
  4. Ļauj bumbai iziet aiz labās vai kreisās malas. Kad tā pilnībā atstāj laukumu, tā apstājas; ExitSide kļūst par 1 vai -1. Šajā stundā turpināšanai apturi un palaid F5 no jauna. Nākamajā stundā šo vērtību nolasīs Game, piešķirs punktu un sagatavos jaunu servi.
  5. README.md pieraksti, kāpēc bumbai pārbīdi reizina ar delta, bet raketes Velocity pirms MoveAndSlide — ne. Saglabā video ar vadību un atlēkšanu.
1.5 Ball.cs — pilns fails salīdzināšanai

Lejupielādēt Ball.cs. Aizstāj tikai atbilstošā faila saturu; neveido otru tāda paša nosaukuma klasi.

using Godot;

public partial class Ball : CharacterBody2D
{
    [Export] public float BaseSpeed = 420.0f;
    public bool IsMoving { get; private set; } = false;
    // -1: bumba izgājusi pa kreisi; 1: pa labi; 0: nav iziešanas.
    public int ExitSide { get; private set; } = 0;

    public override void _Ready()
    {
        ResetBall();
        Serve(1); // 1.5 stundā bumba sāk kustēties pati.
    }

    public void ResetBall()
    {
        Stop();
        Position = new Vector2(640, 360);
        ExitSide = 0;
    }

    public void Serve(int horizontalDirection)
    {
        float verticalDirection = (float)GD.RandRange(0.25, 0.6);
        if (GD.Randf() < 0.5f) verticalDirection = -verticalDirection;
        Velocity = new Vector2(horizontalDirection, verticalDirection).Normalized() * BaseSpeed;
        IsMoving = true;
    }

    public void Stop()
    {
        IsMoving = false;
        Velocity = Vector2.Zero;
    }

    public override void _PhysicsProcess(double delta)
    {
        if (!IsMoving) return;

        KinematicCollision2D collision = MoveAndCollide(Velocity * (float)delta);
        if (collision != null)
            Velocity = Velocity.Bounce(collision.GetNormal());

        if (Position.X < -10)
        {
            ExitSide = -1;
            Stop();
        }
        else if (Position.X > 1290)
        {
            ExitSide = 1;
            Stop();
        }
    }
}

Gatavs, kad: abas raketes kustas, bumba atlec un pēc iziešanas apstājas; punktu sistēmai ir skaidri definēts ExitSide.

Papildu uzdevums — izmēģini spēles tempu

Ball instancei pamēģini Base Speed 350 un 500, katru reizi izspēlējot vairākas atlēkšanas. Pieraksti, kuru ātrumu ir vieglāk spēlēt. Pirms nākamās stundas atjauno 420; vēlāk savu izvēli vari pamatot kā dizaina lēmumu.

Ko sagatavo

Stundas mērķis: pirms noslēguma stundas fizika un ievade jau ir pārbaudītas.

GitHub krātuvē jābūt:

  1. Paddle.cs, Ball.cs, atjauninātas scēnas un Input Map.
  2. Video ar abām vadībām un atlēkšanām; README.md delta un sānu iziešanas skaidrojums.

Saglabā projekta iestatījumus, izveidotās scēnas un resursus; no 1.3 stundas arī C# skriptus un projekta failus (.csproj u.c.). .gitignore ieraksti .godot/, bin/ un obj/ katru savā rindā.

Kā iesniedz: veic commit un push. Skolotāja norādītajā vietā iesniedz GitHub krātuves saiti; README.md un pārbaudes pierādījumiem jābūt krātuvē.

Ja kaut kas nestrādā

PazīmeKo pārbaudīt
Rakete vai bumba iziet cauri sienaiPārbaudi CollisionShape2D Shape, izmēru, Layer/Mask un to, vai pozīcija piešķirta saknei tikai vienreiz.
Abas raketes vada W/SMain scēnā PaddleRight ievades laukus maini uz p2_up/p2_down.
Rakete ļoti lēnaVelocity pirms MoveAndSlide papildus ar delta nereizina.
Bumba pazūd pēc iziešanas1.5 posmā tas ir paredzēts: tā gaida punktu apstrādi, ko pievienosi 1.6. Pārbaudi ar jaunu F5 palaišanu.
Izmēri vai pozīcijas neatbilstPārbaudi 1280 × 720, sakņu Scale (1,1) un bērnu Position (0,0).