From 1ee78ccdc4baa1f54fbf810c2e461529a0770e9d Mon Sep 17 00:00:00 2001 From: Salmi Eero Niilo Einari <eero.ss.salmi@student.jyu.fi> Date: Fri, 11 Apr 2025 08:53:31 +0300 Subject: [PATCH] =?UTF-8?q?P=C3=A4ivitetty=20harjoitusty=C3=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Ohjelma.cs" | 230 +++++++++++------- 1 file changed, 143 insertions(+), 87 deletions(-) diff --git "a/NukkuMatti -harjoitusty\303\266/NukkuMatti -harjoitusty\303\266/Ohjelma.cs" "b/NukkuMatti -harjoitusty\303\266/NukkuMatti -harjoitusty\303\266/Ohjelma.cs" index 68527dc..edabb83 100644 --- "a/NukkuMatti -harjoitusty\303\266/NukkuMatti -harjoitusty\303\266/Ohjelma.cs" +++ "b/NukkuMatti -harjoitusty\303\266/NukkuMatti -harjoitusty\303\266/Ohjelma.cs" @@ -2,13 +2,19 @@ using System.Collections.Generic; using Jypeli; -// Eero Salmen tekemä tasohyppelypeli osana ohjelmointi 1 -kurssia. Pelin nimi on NukkuMatti. -// Pelaajan tehtävänä on kuljettaa NukkuMattia tasolta toiselle tippumatta alas. +/// <summary> +/// Eero Salmen tekemä tasohyppelypeli osana ohjelmointi 1 -kurssia. Pelin nimi on NukkuMatti. +/// Pelaajan tehtävänä on kuljettaa NukkuMattia tasolta toiselle, tippumatta alas. +/// </summary> +/// <remarks> +/// @author Eero Salmi +/// @version 1 +/// </remarks> public class Tasohyppely : PhysicsGame { - // Muutama vakio arvo määritelty tähän, jotta ne on helpommin hallittavissa samassa paikassa - + // Muutama vakio arvo määritelty pelin mekaniikalle, jotta ne on helpommin hallittavissa samassa paikassa + private const double GravityStrength = -800; private const double HyppyVoima = 1100; private const double TasoLeveys = 100; @@ -17,80 +23,106 @@ public class Tasohyppely : PhysicsGame private const double PelaajaHeight = 100; private const double AlkuperainenHyppyNopeus = 1000; private const double TasoPoistoMarginaali = 200; - private const double StartingHeight = -20; - private const double FallThreshold = 1200; // Pelaaja saa pudota enintään 1200 yksikköä huippupisteestään - private double highestY; - -/// <summary> -/// Pelin keskeiset objektit ja tilamuuttujat -/// </summary> + private const double StartingHeight = -20; + + /// <summary> + /// Pelaaja-olio, jota käyttäjä ohjaa. + /// </summary> private PhysicsObject pelaaja; + + /// <summary> + /// Indikoidaan, onko peli käynnissä. + /// </summary> private bool peliKaynnissa = true; + + /// <summary> + /// Taustakuva, jota käytetään pelin visuaalisena taustana. + /// </summary> private GameObject taustakuva; + + /// <summary> + /// Näyttää game over -viestin pelin päättyessä. + /// </summary> private Label gameOverTeksti; + + /// <summary> + /// Näyttää pistemäärän pelin aikana. + /// </summary> + private Label scoreLabel; + + /// <summary> + /// Pistemäärä, joka päivitetään pelaajan edistymisen mukaan. + /// </summary> + private int score; + + /// <summary> + /// Lista kaikista peliin lisätyistä taso-olioista. Listalla seurataan ja poistetaan turhiksi muodostuneet tasot. + /// </summary> private List<PhysicsObject> tasot = new List<PhysicsObject>(); + /// <summary> - /// Aloitetaan peli. + /// Käynnistetään pääohjelma. /// </summary> public override void Begin() { // Asetetaan painovoima Gravity = new Vector(0, GravityStrength); - + + // Luodaan kentän elementit LuoKentta(); LisaaOhjaimet(); LuoGameOverTeksti(); - - // Ajastin sille, kyinka usein uusia tasoja ilmestyy pelikenttään + LuoPistelabel(); + + // Ajastin sille, kuinka usein uusia tasoja ilmestyy pelikenttään Timer tasoAjastin = new Timer(); - tasoAjastin.Interval = 1.4; + tasoAjastin.Interval = 0.8; tasoAjastin.Timeout += LuoTaso; tasoAjastin.Start(); - + // Hyppynopeus pelaaja.Velocity = new Vector(0, AlkuperainenHyppyNopeus); } - + /// <summary> - /// Luodaan peliin kenttä, joka sisältää taustan, pelaajan, - /// aloitustason ja törmäystenkäsittelijän + /// Luodaan kenttä ja asetetaan pelaajan ominaisuudet. + /// Luodaan aloitustaso, laitetaan kamera seuraamaan pelaajaa ja asetetaan törmäysominaisuus. /// </summary> private void LuoKentta() { LuoTausta(); LuoPelaaja(); - + // Asetetaan pelaajan ominaisuudet ja lisätään kentälle pelaaja.Position = new Vector(0, StartingHeight); - highestY = pelaaja.Y; pelaaja.CanRotate = false; pelaaja.Restitution = 0; Add(pelaaja); - + // Luodaan aloitustaso PhysicsObject aloitusTaso = PhysicsObject.CreateStaticObject(200, TasoKorkeus); aloitusTaso.Position = new Vector(0, -70); aloitusTaso.Color = Color.White; aloitusTaso.Tag = "taso"; Add(aloitusTaso); - + // Laitetaan kamera seuraamaan pelaajaa Camera.Follow(pelaaja); - + // Lisätään törmäysominaisuus AddCollisionHandler(pelaaja, "taso", OsuiTasoon); - + // Luodaan muutama aloitustaso for (int i = 0; i < 4; i++) LuoTaso(); } - + /// <summary> - /// Luodaan peliin tausta. + /// Määritetään pelin tausta. /// </summary> private void LuoTausta() { @@ -101,9 +133,22 @@ public class Tasohyppely : PhysicsGame Add(taustakuva, -1); } + + /// <summary> + /// Luodaan ja asetetaan pistenäyttö peliruudulle. + /// </summary> + private void LuoPistelabel() + { + scoreLabel = new Label("Pisteet: 0"); + scoreLabel.TextColor = Color.Red; + scoreLabel.Font = Font.Default; + scoreLabel.Position = new Vector(Level.Left + 100, Level.Top - 50); + Add(scoreLabel); + } + /// <summary> - /// Luodaan peliin lopetusteksti, joka ilmoittaa pelaajalla, että peli on päättynyt + /// Luodaan peliin Game over -teksti. /// </summary> private void LuoGameOverTeksti() { @@ -115,90 +160,88 @@ public class Tasohyppely : PhysicsGame gameOverTeksti.IsVisible = false; Add(gameOverTeksti); } - + /// <summary> - /// Luodaan pelaaja-olio ja määritellään sen perusasetukset + /// Luodaan pelaaja itse tekemän kuvan avulla. /// </summary> private void LuoPelaaja() { - //Luodaan hahmo + // Luodaan hahmo/pelaaja pelaaja = new PhysicsObject(PelaajaWidth, PelaajaHeight); pelaaja.Image = LoadImage("nukkumatti.png"); pelaaja.Restitution = 0; } - + /// <summary> - /// Luodaan peliin tasoja. + /// Asetetaan tasoja ilmestymään sattumanvaraisesti pelikentälle. + /// Määritellään niiden koko ja väri. Hyödynnetään silmukkaa tasojen luonnissa. /// </summary> private void LuoTaso() { - // Luodaan useampi taso yhdellä silmukalla - - for (int i = 0; i < 1; i++) - { - double x = RandomGen.NextDouble(Level.Left + 100, Level.Right - 100); - double y = Camera.ScreenToWorld(new Vector(0, Screen.Height / 2)).Y + RandomGen.NextDouble(10, 10); - - PhysicsObject taso = PhysicsObject.CreateStaticObject(TasoLeveys, TasoKorkeus); - taso.Position = new Vector(x, y); - taso.Color = Color.White; - taso.Tag = "taso"; - Add(taso); - tasot.Add(taso); - } - } + // Luodaan tasoja + double x = RandomGen.NextDouble(Level.Left + 100, Level.Right - 100); + double y = Camera.ScreenToWorld(new Vector(0, Screen.Height / 2)).Y + RandomGen.NextDouble(10, 20); + PhysicsObject taso = PhysicsObject.CreateStaticObject(TasoLeveys, TasoKorkeus); + taso.Position = new Vector(x, y); + taso.Color = Color.White; + taso.Tag = "taso"; + Add(taso); + tasot.Add(taso); + } + + /// <summary> - /// Määritellään näppäimistöohjaimet pelaajan liikkumiseen ja pelin lopettamiseen. + /// Asetetaan komennot näppäimistöltä. /// </summary> private void LisaaOhjaimet() { - // Asetetaan komennot näppäimistöltä Keyboard.Listen(Key.Left, ButtonState.Down, Liikuta, null, -400.0); Keyboard.Listen(Key.Right, ButtonState.Down, Liikuta, null, 400.0); Keyboard.Listen(Key.Escape, ButtonState.Pressed, Exit, "Poistu pelistä"); } - + /// <summary> - /// Muutetaan pelaajan vaakasuuntaista liikettä annetun nopeuden perusteella. + /// Asetetaan pelaajan vaakasuuntainen liike. /// </summary> - /// <param name="nopeus"></param> + /// <param name="nopeus">Vastaa pelaajan liikkumisen vaakasuuntaista nopeutta. Negatiivinen arvo siirtää pelaajaa vasemmalle ja positiivinen oikealle.</param> private void Liikuta(double nopeus) { if (peliKaynnissa) pelaaja.Velocity = new Vector(nopeus, pelaaja.Velocity.Y); } - + /// <summary> - /// Määritellään pelaajan ja tason törmäys. + /// Käsitellään törmäystilanne pelaajan ja tason välillä. /// </summary> - /// <param name="pelaaja"></param> - /// <param name="taso"></param> - private void OsuiTasoon(PhysicsObject pelaaja, PhysicsObject taso) + /// <param name="törmääväPelaaja">Hahmo, jota ohjataan ja jonka törmäystä tarkastellaan.</param> + /// <param name="taso">Objekti, jota käytetään ylöspäin liikkumisen mahdollistamiseksi törmäystilanteessa.</param> + private void OsuiTasoon(PhysicsObject törmääväPelaaja, PhysicsObject taso) { // Törmäys pelaajan ja tason välillä - if (pelaaja.Velocity.Y > 0 && pelaaja.Position.Y < taso.Top) + if (this.pelaaja.Velocity.Y > 0 && this.pelaaja.Position.Y < taso.Top) { - pelaaja.IgnoresCollisionResponse = true; + this.pelaaja.IgnoresCollisionResponse = true; return; } - - if (pelaaja.Velocity.Y <= 0 && Math.Abs(pelaaja.Bottom - taso.Top) < 5) + + if (this.pelaaja.Velocity.Y <= 0 && Math.Abs(this.pelaaja.Bottom - taso.Top) < 5) { - pelaaja.Y = taso.Top + pelaaja.Height / 2; - pelaaja.Velocity = new Vector(pelaaja.Velocity.X, HyppyVoima); + this.pelaaja.Y = taso.Top + this.pelaaja.Height / 2; + this.pelaaja.Velocity = new Vector(this.pelaaja.Velocity.X, HyppyVoima); } - + + this.pelaaja.IgnoresCollisionResponse = false; } - + /// <summary> - /// Poistetaan ne tasot, jotka poistuvat näkyvistä. + /// Määritellään marginaali, jolloin tasot poistuvat. /// </summary> private void PoistaPoistuvatTasot() { @@ -212,15 +255,26 @@ public class Tasohyppely : PhysicsGame } } } + + /// <summary> + /// Laskee pistemäärän pelaajan korkeuden perusteella. + /// Laskenta: jokaista 100 yksikköä pelaajan Y-koordinaatista kohden lisätään 1 piste. + /// </summary> + /// <param name="pelaajaY">Pelaajan Y-koordinaatti.</param> + /// <returns>Palauttaa laskettuna pistemäärän.</returns> + private int LaskePisteet(double pelaajaY) + { + return (int)(pelaajaY / 100); + } + /// <summary> - /// Lopetetaan peli, mikäli pelaaja on pudonnut liikaa korkeimmasta saavutetusta pisteestä. + /// Lopetetaan peli asettamalla peliKaynnissa-arvo epätodeksi, näytetään game over -teksti ja + /// ajastetaan pelin lopetus kolmen sekunnin kuluttua. /// </summary> private void LopetaPeli() { - // Pelin lopettamiskomento - if (peliKaynnissa) { peliKaynnissa = false; @@ -228,40 +282,42 @@ public class Tasohyppely : PhysicsGame Timer.SingleShot(3.0, Exit); } } - + /// <summary> - /// Päivitetään pelin tila jokaisella ruudunpäivityksellä, - /// mukaan lukien taustakuvan sijainti ja pelaajan pudotuksen valvonta. + /// Päivitetään pelin tila. Asetetaan taustakuvan sijainti kameran liikkeen mukaisesti, poistetaan turhat tasot, + /// lasketaan pistemäärä pelaajan Y-koordinaatin perusteella ja asetetaan pisteteksti. Tarkistetaan, + /// onko pelin lopetusehto täytetty. /// </summary> - /// <param name="time"></param> + /// <param name="time">Ajan hetkitetiedot, joita käytetään pelin tilan päivitykseen.</param> protected override void Update(Time time) { base.Update(time); - + // Taustakuva päivittyy kameran liikkeen mukaisesti taustakuva.Position = taustakuva.Position + (Camera.Position - taustakuva.Position) * 0.1; - + PoistaPoistuvatTasot(); - - if (pelaaja.Y > highestY) - highestY = pelaaja.Y; - - // Tarkista, onko pelaaja pudonnut liian pitkän matkan huipustaan - - if (highestY - pelaaja.Y > FallThreshold) - + + // Lasketaan pisteet ja päivitetään pistenäyttö + score = LaskePisteet(pelaaja.Y); + scoreLabel.Text = "Pisteet: " + score; + + if (pelaaja.Y < Level.Bottom - 100) LopetaPeli(); } } /// <summary> -/// Pääohjelman luokka, joka käynnistää pelin. +/// Käynnistetään ohjelma. /// </summary> +/// <remarks> +/// @author Eero Salmi +/// @version 1 +/// </remarks> public class Program { - // Päämetodi, joka luo pelin oliot ja käynnistää pelin. public static void Main() { using (var peli = new Tasohyppely()) -- GitLab