Pong-peli, vaihe 6
Tässä vaiheessa parantelemme mailojen liikuttelua ja tutustumme if
-lauseeseen.
1. Rajojen tarkistus
Edellisessä oppaassa laitoimme mailat liikkumaan, mutta pieni puute mailojen liikuttamiseen jäi. Nimittäin mailaa voi liikutella ylös- ja alaspäin rajattomasti! Ei ole varmaankaan hyödyllistä eikä toivottavaa, että mailat voivat mennä pelikentän ulkopuolelle. Tämän korjaamiseksi mailaa pitäisi voida liikuttaa ylöspäin vain silloin, kun se ei ole mennyt kentän yläreunan yli. Vastaavasti alaspäin liikuttaminen pitäisi olla mahdollista vain, kun maila ei ole mennyt alarajan ali.
1.1 Yläreunan tarkistus
Mietitään algoritmi eli ohje, jolla saisimme mailan pysymään kentän sisäpuolella. Käsitellään ongelmaa ensin vain kentän yläreunalle ja mietitään alareunaa myöhemmin.
Pitäisi lisätä ohjelmakoodiin ehto, jonka mukaan:
- Jos maila on yläreunan yli,
- niin pysäytetään maila.
- Muuten liikutetaan mailaa normaalisti.
Tällainen tietyllä ehdolla suoritettava koodi voidaan toteuttaa ohjelmoinnissa if-lauseella. If-lause muodostuu ehdosta, ja koodiriveistä jotka suoritetaan vain jos ehto on totta. If-lauseen perässä olevien aaltosulkujen väliin kirjoitetaan ne koodirivit, jotka halutaan suorittaa vain jos annettu ehto toteutuu.
Jotta meillä olisi käytössä tason (Level
) reunat, pitää joko luopua static
määreestä koska tasoon viitataan oikeasti this.Level
tai sitten peli pitäisi tuota parametrina. Valitaan tällä kertaa tuo että poistetaan static
, jolloin meillä on this
käytössä.
Muokkaa AsetaNopeus
-aliohjelmaasi olemaan seuraavanlainen:
Mailan ja kentän yläreunojen y-koordinaatit saadaan niiden Top
-ominaisuudesta.
Ehdossa katsotaan, onko mailan yläreuna kentän yläreunan yläpuolella:
- Jos on, niin pysäytetään maila ja return-lauseella tullaan pois aliohjelmasta.
- Jos ei, niin if-lauseen perässä olevien aaltosulkujen välissä olevia koodirivejä ei suoriteta vaan asetetaan mailalle nopeus normaaliin tapaan.
Pysähtyykö maila yläreunaan? Taitaa kyllä pysähtyä, mutta...
Miksi maila ei enää liiku kun se kerran saavuttaa yläreunan? Mieti hetki, ennen kuin jatkat eteenpäin.
1.2 Toinen yritys
Mailat lopettivat liikkumisen, kun ne saavuttivat kentän yläreunan. Vaikka yritämme yläreunan saavuttamisen jälkeen liikuttaa mailaa alaspäin, mailan yläreuna on yhä kentän yläreunan yläpuolella. If-lauseemme ehto siis toteutuu yhä ja maila pysäytetään.
Täytyy siis lisätä vielä yksi ehto edelliseen algoritmiimme:
- Jos nopeuden suunta on ylöspäin ja jos maila on yläreunan yli,
- niin pysäytetään maila.
- Muuten liikutetaan mailaa normaalisti.
Lisätään toinen ehto samaan if-lauseeseen AsetaNopeus
-aliohjelmaan:
Tässä käytettiin if
-lauseessa merkintää (nopeus.Y > 0) && (maila.Top > Level.Top)
. Tässä merkit &&
voi lukea sanana "ja".
Ehdon voisi nyt lukea: "Nopeuden y-koordinaatti on suurempi kuin nolla JA mailan yläreunan y-koordinaatti on suurempi kuin kentän yläreunan y-koordinaatti".
Täältä lisätietoa ehtolauseisiin liittyen. TODO: TIMIIN
2. Alareunan tarkistus
Nyt kun mailan liikuttelu ylöspäin on kunnossa, tee sama alaspäin liikuttamiselle.
Nyt vastaavasti tarkistetaan, onko suunta alaspäin ja onko mailan alareunan y-koordinaatti pienempi kuin kentän alareunan y-koordinaatti.
AsetaNopeus
näyttää muutosten jälkeen tältä:
3. 3. XBox-ohjainten lisääminen (valinnainen)
Jos haluat, voit lisätä ohjauksen XBox-360-ohjaimille seuraavasti. Muuten voit hypätä tutoriaalin seuraavaan vaiheeseen.
XBox-ohjainten napit voidaan asettaa helposti käyttämällä samantapaista Listen
-aliohjelmaa kuin näppäimistön nappien asettamisessa. Ainoa ero on, että tällä kertaa ei kutsuta Keyboard.Listen
-aliohjelmaa vaan ControllerX.Listen
-aliohjelmaa. (X:n paikalle ohjaimen numero: One
, Two
, Three
tai Four
), esimerkiksi ControllerOne.Listen
kutsuu ohjainta, joka on asetettu ykkösohjaimeksi. ControllerOne.Listen
ottaa ensimmäisenä parametrina XBox-ohjaimen napin, jota halutaan kuunnella, esimerkiksi Button.X
tarkoittaa ohjaimen X-nappia.
Tässä tapauksessa voidaan käyttää samaa AsetaNopeus
-aliohjelmaa myös XBox-ohjaimille.
Lisää XBox-ohjainten asetus samaan AsetaOhjaimet
-aliohjelmaan:
private void AsetaOhjaimet(PhysicsObject maila1, PhysicsObject maila2)
{
Keyboard.Listen(Key.A, ButtonState.Down, AsetaNopeus, "Pelaaja 1: Liikuta mailaa ylös", maila1, nopeusYlos );
Keyboard.Listen(Key.A, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
Keyboard.Listen(Key.Z, ButtonState.Down, AsetaNopeus, "Pelaaja 1: Liikuta mailaa alas", maila1, nopeusAlas );
Keyboard.Listen(Key.Z, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
Keyboard.Listen(Key.Up, ButtonState.Down, AsetaNopeus, "Pelaaja 2: Liikuta mailaa ylös", maila2, nopeusYlos );
Keyboard.Listen(Key.Up, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
Keyboard.Listen(Key.Down, ButtonState.Down, AsetaNopeus, "Pelaaja 2: Liikuta mailaa alas", maila2, nopeusAlas );
Keyboard.Listen(Key.Down, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
Keyboard.Listen(Key.F1, ButtonState.Pressed, ShowControlHelp, "Näytä ohjeet" );
Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli" );
ControllerOne.Listen(Button.DPadUp, ButtonState.Down, AsetaNopeus, "Liikuta mailaa ylös", maila1, nopeusYlos );
ControllerOne.Listen(Button.DPadUp, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
ControllerOne.Listen(Button.DPadDown, ButtonState.Down, AsetaNopeus, "Liikuta mailaa alas", maila1, nopeusAlas );
ControllerOne.Listen(Button.DPadDown, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
ControllerTwo.Listen(Button.DPadUp, ButtonState.Down, AsetaNopeus, "Liikuta mailaa ylös", maila2, nopeusYlos );
ControllerTwo.Listen(Button.DPadUp, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
ControllerTwo.Listen(Button.DPadDown, ButtonState.Down, AsetaNopeus, "Liikuta mailaa alas", maila2, nopeusAlas );
ControllerTwo.Listen(Button.DPadDown, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
ControllerOne.Listen(Button.Back, ButtonState.Pressed, ConfirmExit, "Lopeta peli" );
ControllerTwo.Listen(Button.Back, ButtonState.Pressed, ConfirmExit, "Lopeta peli" );
}
4. Lopputulos
Tähän asti pelimme näyttää 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
{
private readonly Vector nopeusYlos = new Vector(0, 200);
private readonly Vector nopeusAlas = new Vector(0, -200);
public override void Begin()
{
PhysicsObject pallo = LuoPallo(this, -200, 0);
PhysicsObject maila1 = LuoMaila(this,Level.Left + 20.0, 0.0);
PhysicsObject maila2 = LuoMaila(this,Level.Right - 20.0, 0.0);
LuoKentta();
AsetaOhjaimet(maila1, maila2);
AloitaPeli(pallo);
}
private void LuoKentta()
{
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);
}
private void AsetaOhjaimet(PhysicsObject maila1, PhysicsObject maila2)
{
Keyboard.Listen(Key.A, ButtonState.Down, AsetaNopeus, "Pelaaja 1: Liikuta mailaa ylös", maila1, nopeusYlos );
Keyboard.Listen(Key.A, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
Keyboard.Listen(Key.Z, ButtonState.Down, AsetaNopeus, "Pelaaja 1: Liikuta mailaa alas", maila1, nopeusAlas );
Keyboard.Listen(Key.Z, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
Keyboard.Listen(Key.Up, ButtonState.Down, AsetaNopeus, "Pelaaja 2: Liikuta mailaa ylös", maila2, nopeusYlos );
Keyboard.Listen(Key.Up, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
Keyboard.Listen(Key.Down, ButtonState.Down, AsetaNopeus, "Pelaaja 2: Liikuta mailaa alas", maila2, nopeusAlas );
Keyboard.Listen(Key.Down, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
Keyboard.Listen(Key.F1, ButtonState.Pressed, ShowControlHelp, "Näytä ohjeet" );
Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli" );
ControllerOne.Listen(Button.DPadUp, ButtonState.Down, AsetaNopeus, "Liikuta mailaa ylös", maila1, nopeusYlos );
ControllerOne.Listen(Button.DPadUp, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
ControllerOne.Listen(Button.DPadDown, ButtonState.Down, AsetaNopeus, "Liikuta mailaa alas", maila1, nopeusAlas );
ControllerOne.Listen(Button.DPadDown, ButtonState.Released, AsetaNopeus, null, maila1, Vector.Zero );
ControllerTwo.Listen(Button.DPadUp, ButtonState.Down, AsetaNopeus, "Liikuta mailaa ylös", maila2, nopeusYlos );
ControllerTwo.Listen(Button.DPadUp, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
ControllerTwo.Listen(Button.DPadDown, ButtonState.Down, AsetaNopeus, "Liikuta mailaa alas", maila2, nopeusAlas );
ControllerTwo.Listen(Button.DPadDown, ButtonState.Released, AsetaNopeus, null, maila2, Vector.Zero );
ControllerOne.Listen(Button.Back, ButtonState.Pressed, ConfirmExit, "Lopeta peli" );
ControllerTwo.Listen(Button.Back, ButtonState.Pressed, ConfirmExit, "Lopeta peli" );
}
private void AsetaNopeus(PhysicsObject maila, Vector nopeus)
{
if ((nopeus.Y < 0) && (maila.Bottom < Level.Bottom))
{
maila.Velocity = Vector.Zero;
return;
}
if ((nopeus.Y > 0) && (maila.Top > Level.Top))
{
maila.Velocity = Vector.Zero;
return;
}
maila.Velocity = nopeus;
}
}
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.