Omenasoturi - vaihe 3

Tässä vaiheessa opetellaan kuuntelemaan hiiren liikettä ja klikkauksia, jotta hedelmiä voidaan alkaa silppuamaan. Lisätään näytölle hiiren vetäisyn mukainen viiva, joka puolittaa ne omenat, joihin se osuu. Tässä vaiheessa joudutaan hieman pyörittelemään kulmia ja vektoreita, joten ole tarkkana.

Aloitetaan esittelemällä apumuuttujat niille paikoille, missä pelaajan hiiri on klikattaessa ja päästettäessä irti. Ideana on piirtää näiden pisteiden välille omenia silppuava viiva. Viiva on Jypeli-pelissä tavallinen GameObject, joten esitellään se tässä samalla. Nämä rivit tulevat ohjelmakoodin alkuun, aliohjelmien yläpuolelle, samaan paikkaan missä kuvat esiteltiin.

Vector alku, loppu;
GameObject viiva;


Seuraavaksi luodaan tynkä tälle viivalle, jotta oliota ei tarvitse luoda uudestaan aina kun hiirtä liikutetaan. Myöhemmin laitetaan viivan paikka ja koko muuttumaan pelaajan klikkauksien ja hiiren liikkeen mukaan. Lisää Begin-aliohjelman loppuun seuraava rivi.

Add(viiva = new GameObject(2, 0));


Nyt keskelle pelikenttää syntyy viiva. Älä huoli, jos et vielä näe kentällä mitään, sillä viivan kuuluukin olla tässä vaiheessa näkymätön. Se nimittäin piirretään kentän keskipisteestä keskipisteeseen, eli viivan pituus on 0.

Seuraavaksi aletaan kuuntelemaan hiiren klikkausta, jolloin viivan piirtäminen oikeasti aloitetaan. Lisätään siis Begin-aliohjelman loppuun seuraava rivi:

Mouse.Listen(MouseButton.Left, ButtonState.Pressed,
    () => alku = Mouse.PositionOnWorld, "Aloittaa viivan piirtämisen");


Nyt viivan alkupiste päivittyy aina, kun pelaaja klikkaa hiiren vasemmalla napilla. Lisätään äskeisen rivin perään vielä toinen kuuntelija, joka päivittää viivan paikkaa ja suuntaa niin kauan, kun nappi on painettuna.

Mouse.Listen(MouseButton.Left, ButtonState.Down, PiirraViiva, "Piirtää viivan");


Sitten kirjoitetaan äskeisellä rivillä mainittu PiirraViiva-aliohjelma. Aliohjelmassa päivitetään viivan loppupiste hiiren nykyiseen paikkaan ja asetetaan viivan pituudeksi alku- ja loppupisteen välimatka. Koska viiva syntyy alunperin alkupisteen paikalle, siirretään se vielä puoleenväliin kohti loppupistettä ja käännetään se alku- ja loppupisteen välisen kulman suuntaiseksi. Yhdessä nämä rivit saavat aikaan sen, että viiva piirtyy oikeaan paikkaan ja oikean suuntaisena.

void PiirraViiva()
{
    viiva.Color = Color.Black;
    loppu = Mouse.PositionOnWorld;

    viiva.Height = Vector.Distance(alku, loppu);
    viiva.Position = (alku+loppu)/2;
    viiva.Angle = (alku-loppu).Angle + Angle.FromDegrees(90);
}


Nyt pelikentälle pitäisi pystyä vetelemään mustia viivoja, kun hiiren vasen nappi on painettuna. Seuraavaksi haluttaisiin, että viiva häviää jonkin ajan kuluttua, kun napista päästetään irti. Samaan aikaan viivan kohdalla olevat omenat pitäisi pilkkoa puoliksi. Lisätään siis vielä yksi hiirenkuuntelija muiden alle:

Mouse.Listen(MouseButton.Left, ButtonState.Released, Silppua, null);


Sitten kirjoitetaan tuo Silppua-aliohjelma, jonka tarkoitus on puolittaa kaikki viivan kohdalla olevat omenat. Aliohjelma häivyttää ensin viivan pois näkyvistä. Sitten ruudulta etsitään kaikki alku- ja loppupisteen välillä olevat omenat, tuhotaan ne ja kutsutaan toista aliohjelmaa, joka lisää entisen omenan paikalle kaksi puolikasta. Jo puolitettuja omenoita tai viivaa ei kuitenkaan haluta tuhota, joten tarkistetaan silmukan sisällä, onko olio kokonainen omena ennen kuin tuhotaan se.

void Silppua()
{
    viiva.FadeColorTo(Color.Transparent, 0.25);

    List<GameObject> omenat = GetObjectsBetween(alku, loppu);
    foreach (GameObject omena in omenat)
    {
        if (omena == viiva || !omena.Tag.Equals("omena"))
            continue;
        LisaaPuolikkaat(omena);
        omena.Destroy();
    }
}


Puolikkaiden lisäämiseen tarvitaan LisaaPuolikkaat-aliohjelma. Tämä aliohjelma laskee puolikkaiden omenoiden paikat ja kulmat alkuperäisen omenan paikan ja kulman perusteella. Sitten kutsutaan kahteen kertaan aliohjelmaa, joka osaa lisätä yhden puolikkaan.

void LisaaPuolikkaat(GameObject omena)
{
    Vector siirros = Vector.FromLengthAndAngle(omena.Width/2, viiva.Angle);
    Angle kulma = viiva.Angle - Angle.FromDegrees(90);

    LisaaPuolikas(omena, -siirros, -kulma, puolikas1);
    LisaaPuolikas(omena,  siirros,  kulma, puolikas2);
}


Kirjoitetaan vielä tämä LisaaPuolikas-niminen aliohjelma yksittäisen puolikkaan lisäämiselle. Aliohjelmalle tuodaan parametrina kaikki sen tarvitsema tieto puolikkaan omenan paikasta, kulmasta ja kuvasta. Aliohjelma myös tönäisee luomansa puolikkaan liikkeelle poispäin alkuperäisen omenan paikasta, jotta pelatessa näyttää siltä, että omenat oikeasti lyödään puoliksi.

void LisaaPuolikas(GameObject omena, Vector siirros, Angle kulma, Image kuva)
{
    PhysicsObject puolikas = new PhysicsObject(omena.Width/2, omena.Height);
    puolikas.Position = omena.Position + siirros;
    puolikas.Image = kuva; puolikas.Angle = viiva.Angle;
    puolikas.Hit(Vector.FromLengthAndAngle(200, kulma));
    Add(puolikas);
}


Huh, huh. Nyt peli alkaa olla siinä vaiheessa, että omenoita pystyy pilkkomaan hiirellä. Jos myös oma versiosi toimii näin, voit siirtyä seuraavaan vaiheeseen, missä peliin lisätään vielä piste- ja elämälaskurit sekä hieman räjähdyksiä.


Siirry seuraavan vaiheeseen



Koko koodin pitäisi näyttää kolmannen vaiheen lopuksi suurinpiirtein tältä:

using System;
using System.Collections.Generic;
using Jypeli;
using Jypeli.Assets;
using Jypeli.Controls;
using Jypeli.Effects;
using Jypeli.Widgets;    

public class Omenasoturi : PhysicsGame
{
    Image omena = LoadImage("omena_k");
    Image puolikas1 = LoadImage("omena_p1");
    Image puolikas2 = LoadImage("omena_p2");    

    Vector alku, loppu;
    GameObject viiva;
    PhysicsObject alareuna;    


    public override void Begin()
    {
        Level.Height = Level.Width = Window.Height = Window.Width = 800;
        alareuna = Level.CreateBottomBorder();
        Gravity = new Vector(0, -200);
        Level.Background.Color = Color.Beige;    

        LuoHedelmia();
        Add(viiva = new GameObject(2, 0));    

        Mouse.Listen(MouseButton.Left, ButtonState.Pressed,
            () => alku = Mouse.PositionOnWorld, "Aloittaa viivan piirtämisen");
        Mouse.Listen(MouseButton.Left, ButtonState.Down, PiirraViiva, "Piirtää viivan");
        Mouse.Listen(MouseButton.Left, ButtonState.Released, Silppua, null);    

        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
    }    

    void LuoHedelma()
    {
        double koko = RandomGen.NextDouble(20, 100);
        PhysicsObject hedelma = new PhysicsObject(koko, koko, Shape.Circle);    

        hedelma.X = RandomGen.NextDouble(Level.Left, Level.Right);
        hedelma.Y = RandomGen.NextDouble(Level.Bottom + 50, Level.Top);    

        hedelma.Image = omena;
        hedelma.Tag = "omena";
        hedelma.Hit(new Vector(RandomGen.NextDouble(-50, 50), RandomGen.NextDouble(100, 500)));
        hedelma.AngularVelocity = RandomGen.NextDouble(-10, 10);    

        Add(hedelma);
    }    

    void LuoHedelmia()
    {
        Timer t = new Timer();
        t.Interval = 1;
        t.Timeout += () => {
            LuoHedelma();
            if (t.Interval > 0.1) t.Interval -= 0.01;
            Level.Background.FadeColorTo(RandomGen.NextLightColor(), 5);
        };
        t.Start();
    }    

    void PiirraViiva()
    {
        viiva.Color = Color.Black;
        loppu = Mouse.PositionOnWorld;    

        viiva.Height = Vector.Distance(alku, loppu);
        viiva.Position = (alku + loppu) / 2;
        viiva.Angle = (alku - loppu).Angle + Angle.FromDegrees(90);
    }    

    void Silppua()
    {
        viiva.FadeColorTo(Color.Transparent, 0.25);    

        List<GameObject> omenat = GetObjectsBetween(alku, loppu);
        foreach (GameObject omena in omenat)
        {
            if (omena == viiva || !omena.Tag.Equals("omena"))
                continue;
            LisaaPuolikkaat(omena);
            omena.Destroy();
        }
    }    

    void LisaaPuolikkaat(GameObject omena)
    {
        Vector siirros = Vector.FromLengthAndAngle(omena.Width / 2, viiva.Angle);
        Angle kulma = viiva.Angle - Angle.FromDegrees(90);    

        LisaaPuolikas(omena, -siirros, -kulma, puolikas1);
        LisaaPuolikas(omena, siirros, kulma, puolikas2);
    }    

    void LisaaPuolikas(GameObject omena, Vector siirros, Angle kulma, Image kuva)
    {
        PhysicsObject puolikas = new PhysicsObject(omena.Width / 2, omena.Height);
        puolikas.Position = omena.Position + siirros;
        puolikas.Image = kuva; puolikas.Angle = viiva.Angle;
        puolikas.Hit(Vector.FromLengthAndAngle(200, kulma));
        Add(puolikas);
    }
}

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