Pong-peli, vaihe 4

Tässä oppaassa teemme toisenkin mailan.

1. Miten tehdään peliin toinen maila?

Maila tehtiin edellisessä vaiheessa, metodissa LuoKentta, seuraavasti:

        PhysicsObject maila = PhysicsObject.CreateStaticObject(20.0, 100.0, Shape.Rectangle);
        maila.X = Level.Left + 20.0;
        maila.Y = 0.0;
        maila.Restitution = 1.0;
        Add(maila);

Kutsu PhysicsObject.CreateStaticObject(20.0, 100.0); luo sellaisen fysiikkaobjekti, johon törmääminen ei liikuta itse mailaa, mutta pallo voi kimmota siitä. Mikäli olisi luotu tavallinen fysiikkaobjekti, lähtisi maila kääntymään ja liikkumaan pallon osumasta.

Toisen mailan voisimme tehdä tietysti samaan tapaan kuin ensimmäisenkin. Voisimme kopioida ensimmäisen mailan luovat rivit ja vaihtaa joka riville muuttujan maila tilalle maila2 sekä muuttaa toisen mailan koordinaatit.

Jos myöhemmin peliin haluttaisiin vielä lisää mailoja, voisimme jälleen kopioida rivit, vaihtaa muuttujien nimet ja tarvittavat ominaisuudet...

Mutta kun mailat kerran tehdään ihan samaan tapaan, eikö tässä tehdä sama työ moneen kertaan?

Voitaisiinko mailan luominen ohjelmoida kerran niin, että ainoastaan mailan paikka kerrotaan kummallekin mailalle erikseen?

Kyllä voidaan! Mailan tekeminen voisi olla oma aliohjelma, jolle ainoastaan kerrotaan mihin halutaan tehdä uusi maila. Näin samalla aliohjelmalla voitaisiin tehdä monta eri mailaa.

2. Mailoja luova aliohjelma ja parametrit

Tehdään aliohjelma, jota kutsumalla tietokone tekee aina uuden mailan ja lisää sen peliin haluamaamme paikkaan.

Koska eri mailoille tarvitaan eri koordinaatit, täytyy tämä pystyä jotenkin kertomaan aliohjelmalle. Annetaan koordinaatit aliohjelmalle parametreina.

  • Aliohjelman parametrit luetellaan aliohjelman nimen jälkeen sulkujen sisällä.
  • Ensin kerrotaan parametrin tyyppi ja sen jälkeen parametrin nimi.
  • Useammat parametrit erotetaan pilkulla toisistaan.
  • Kun aliohjelmaa kutsutaan, sille täytyy antaa juuri sellaiset parametrit mitä se haluaa.

Lisää siis seuraavanlainen funktio joka on ihan vastaava kuin LuoPallo ja tee lisäys vaikka LuoPallon jälkeen:

    public static PhysicsObject LuoMaila(PhysicsGame peli, double x, double y)
    {
        PhysicsObject maila = PhysicsObject.CreateStaticObject(20.0, 100.0, Shape.Rectangle);
        maila.X = x;
        maila.Y = y;
        maila.Restitution = 1.0;
        peli.Add(maila);
        return maila;
    }

LuoMaila-funktion parametrit x ja y ovat tyyppiä double. Tyyppiä double käytetään desimaalilukujen esittämiseen.

Poista punaisella merkityt mailan luomiseen liittyvät koodirivit koska ne laitettiin LuoMaila-funktioon:

   private void LuoKentta()
    {
        PhysicsObject maila = PhysicsObject.CreateStaticObject(20.0, 100.0, Shape.Rectangle);
        maila.X = Level.Left + 20.0;
        maila.Y = 0.0;
        maila.Restitution = 1.0;
        Add(maila);

        Level.CreateBorders(1.0, false);
        Level.Background.Color = Color.Black;
        
        Camera.ZoomToLevel();
    }


Voit kokeilla ajaa pelin, mutta yhtään mailaa ei vielä näy. Funktiota LuoMaila ei vielä kutsuta missään, eli sen koodirivejä ei koskaan suoriteta.

3. Mailoja luovan aliohjelman kutsuminen ja parametrien välittäminen

Aliohjelman avulla mailoja on helppo tehdä useampikin. Äsken siirrettyjen rivien tilalle kirjoitetaan kaksi aliohjelmakutsua:

   private void LuoKentta()
    {
        LuoMaila(this,Level.Left + 20.0, 0.0);
        LuoMaila(this,Level.Right - 20.0, 0.0);

        Level.CreateBorders(1.0, false);
        Level.Background.Color = Color.Black;
        
        Camera.ZoomToLevel();
    }


Aliohjelman kutsussa aliohjelmalle annettavat parametrit annetaan samassa järjestyksessä kuin ne aliohjelmassa otetaan vastaan. Tässä tapauksessa siis ensin x-koordinaatti ja sitten y-koordinaatti.

Kutsussa ei luetella parametrien tyyppejä (kuten double).

Alla oleva kuva havainnollistaa sitä, miten parametrit välittyvät funktion kutsusta mailan koordinaateiksi. Vaikka LuoMaila palauttaa luomansa mailan (matkittu LuoPallo-funktiosta), ei paluuarvoa "oteta kiinni" vielä tässä vaiheessa kun sillä ei ole vielä käyttöä.

# dimaila

Huomaa, että parametri voi olla myös laskutoimituksen tulos. Esimerkiksi lasku

    Level.Left + 20.0

suoritetaan ennen aliohjelman kutsua ja siitä saatava tulos annetaan aliohjelmalle parametriksi.

Nyt pelissä pitäisi näkyä kaksi mailaa!

4. Lopputulos

Pong-peli kahdella mailalla näyttää nyt tältä:

using Jypeli;

namespace Pong;

/// @author vesal
/// @version 20.09.2024
/// <summary>
/// Peli jossa kaksi palaajaa yrittää saada pallon toisen päätyyn. 
/// </summary>
public class Pong : PhysicsGame
{
    public override void Begin()
    {
        PhysicsObject pallo = LuoPallo(this, -200, 0);
        
        LuoKentta();

        AloitaPeli(pallo);
        
        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
    }
    
    
    private void LuoKentta()
    {
        LuoMaila(this,Level.Left + 20.0, 0.0);
        LuoMaila(this,Level.Right - 20.0, 0.0);

        Level.CreateBorders(1.0, false);
        Level.Background.Color = Color.Black;
        
        Camera.ZoomToLevel();
    }
    
    
    public static PhysicsObject LuoPallo(PhysicsGame peli, double x, double y)
    {
        PhysicsObject pallo = new PhysicsObject(40.0, 40.0, Shape.Circle);
        pallo.X = x;
        pallo.Y = y;
        pallo.Restitution = 1.0;
        pallo.KineticFriction = 0.0;
        pallo.MomentOfInertia = double.PositiveInfinity;
        peli.Add(pallo);
        return pallo;
    }

    
    public static PhysicsObject LuoMaila(PhysicsGame peli, double x, double y)
    {
        PhysicsObject maila = PhysicsObject.CreateStaticObject(20.0, 100.0, Shape.Rectangle);
        maila.X = x;
        maila.Y = y;
        maila.Restitution = 1.0;
        peli.Add(maila);
        return maila;
    }    
    
    
    private static void AloitaPeli(PhysicsObject pallo)
    {
        Vector impulssi = new Vector(500.0, 0.0);
        pallo.Hit(impulssi * pallo.Mass);
    }
}

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.