Avaruuden sankari

Tehtävän kuvaus

Tarkoitus on tehdä pieni Space Invaders-tyyppinen ammuskelupeli. Pelaaja ohjaa alusta joko oikealta vasemmalle tai ylhäältä alas. Pelaaja kerää pisteitä ampumalla vastustajia, kun pelaaja kuolee näytetään lopetusruutu. Lopetusikkunalla kerrotaan pelaajan pisteet sekä kaikkien aikojen paras tulos. Peli voi myös perustua painovoimaan.

  • GameController
    • Kokeillaan tässä pelissä samaa ideaa kuin Ping Pong-sovelluksessa. On yksi pääluokka jonka sisällä luodaan alus ja vastustajat.
  • Alus ja liikkuminen
    • Tehdään pelaajan alus joka voi liikkua ylös ja alas (tai oikealle ja vasemmalle)
  • Ampuminen
    • Katso miten Ruby's 2D RPG:ssä tehtiin ampuminen. Tarkoitus on, että aluksella pystyisi ampumaan kohti vihollisia.
  • Viholliset
    • Viholliset ilmestyvät satunnaisesti ruudun toiseen reunaan ja liikkuvat kohti pelaajaa.
  • Liikkuva tausta
    • Tarkoitus on kokeilla miten saadaan taustalle esimerkiksi tähtikartta joka liikkuu pelin kulun ajan.
    • Youtube: Liikkuva tausta

1. Suunnittelu

Tässä harjoituksessa on tehtävänä ensin tehdä kevyt suunnitelma.

  1. Markdown-tiedostona kevyt suunnitelma pelistä. Tähän kootaan suunnittelun aikana tehtävä sisältö.
  2. Yleiskuvaus: kerro lyhyesti millainen sinun pelisi olisi. Mitä olet lähdössä tekemään.
  3. Yksinkertainen mockup pelistä. Sinun ei tarvitse käyttää pirtoohjelmaa vaan tee Unityssa ulkoasu aloitus-, lopetus- ja pelinäkymästä. Mieti mitä mahdollisia valmiita Asset Storen assetteja hyödyntäisit.
  4. Luokkakaavio pelin luokista. Tässä harjoituksessa palautetaan mieleen miten luokkakaavio piirretään. Käytetään Vision kaaviota "Staattinen UML-rakenne".
    • Ensin luokat kaaviolle.
    • Luokkien muuttujat (attribuutit)
    • Luokkien toiminnot (metodit)
    • Luokkien väliset yhteydet. Yhteyksissä kannattaa käyttää Koostetta (Composition) tai Kytkentää (Assosiation), yhteys on silloin kun toinen luokka, esimerkiksi GameManager, käyttää toista luokkaa. (Lisätietoa esimerkiksi Class Diagram Relationships).

  5. Esittele suunnitelma ennen toteuttamisen aloittamista!

2. Toteutus

Liikkuminen

Kun olet tehnyt kevyen suunnitelman niin kannattaa aloittaa pelaajan koodaamisesta

  • hahmo (itse piirretty, asset -paketista tai googlen kuvahausta)
  • skripti hahmolle
  • miten hahmo liikkuisi esim. vasemmalle - oikealle

Hahmon liikkuessa voi lähteä miettimään ampumista tai vastustajia

Ammus

Ammus kannattaa toteuttaa samaan tapaan kuin Ruby's 2D RPG:ssä. Ammus tarvitsee oman skriptin, liitä tämä ammuksen prefabille. Lisää ammukselle RigidBody2D, älä laita Kinematic vaan Dynamic ja Mass arvolle 0.

  1. Aseta ammukselle private-attribuutti rigidbody:
    Rigidbody2D rigidbody2d;
  2. RigidBody asetetaan Awake()-metodissa:
    void Awake()
    {
    	rigidbody2d = GetComponent<Rigidbody2D>();
    }
    
  3. Lisätään ammukselle metodi joka käynnistää liikkeen
    public void Shoot(Vector2 direction, float force)
    {
    	rigidbody2d.AddForce(direction * force);
    }
    
  4. Osuminen tarkistetaan OnCollisionEnter2D-metodissa:
    void OnCollisionEnter2D(Collision2D other)
    {
    	Debug.Log("Osuttiin " + other.gameObject);
    	Destroy(gameObject);
    }
    
  5. Pelaaja suorittaa ampumisen, pelaaja-luokassa tehdään uuden ammuksen luonti.
    • Lisää aluksi uusi GameObject:
      public GameObject laserPrefab;
      Rigidbody2D rigidbody2d;
      

      Rigidbody2D määritellään samaan tapaan kuin ammuksella Awake() tai Start()-metodissa. Raahaa laserPrefab:n kohdalle editorissa ammuksesi Prefabs-kansiosta.

    • void Shoot()
      {
      GameObject laser = Instantiate(laserPrefab, rigidbody2d.position + Vector2.up * 1.5f, Quaternion.identity);
      
      LaserController projectile = laser.GetComponent<LaserController>();
      projectile.Shoot(new Vector2(0,1), 0.2f);
      
      }
    • Kun painetaan välilyöntiä niin ammutaan, lisää Update()-metodille:
      if (Input.GetKeyDown(KeyCode.Space))
      {
      	Shoot();
      }
      
Vastustajien luominen

Vastustajia voi tehdä monella tapaa, kokeile hakea verkosta erilaisia ratkaisuja ja mieti mikä voisi toimia sinun pelissäsi.

Yksi yksinkertainen malli: EnemySpawnScript.cs

Tekstin päivittäminen
  1. Tässä ohjelmassa teksti ei ole sidottu mihinkään Prefab-objektiin vaan ammuksen pitäisi osata kertoa GameManagerille koska pisteitä lisätään. Lisää aluksi tuttuun tapaan skenelle uusi Canvas ja TMP_Text.
  2. Lisää GameManager:lle julkinen TMP_Text-muuttuja, raahaa editorissa TMP_Text-kenttä tämän arvoksi.
    using TMPro;
    
    Esittele muuttujat:
    public TMP_Text txtScore;
    public int score;
    

    Raahaa Text-objekti julkisen muuttujan kohdalle Inspector-ikkunassa:

  3. Lisää GameManagerille julkinen aliohjelma joka kasvattaa pisteitä:
    public void AddScore()
    {
    	this.score += 1;
    	this.txtScore.text = "Score ny: " + score;
    }
    
  4. Ammus osuu vastustajaan ja silloin pisteiden pitäisi kasvaa. Lisää aluksi uusi muuttuja ammukselle:
    public GameManager gm;
    

    Raahaa GameManager tähän muuttujaan editorissa (sinun tarvitsee ehkä tehdä GameManagerista Prefab jos se ei vielä ollut).

    Aseta gm Awake()-metodissa:

     gm = GameObject.Find("GameManager").GetComponent<GameManager>();
    
    Kun osutaan vastustajaan niin kutsutaan gm:n AddScore()-aliohjelmaa:
    gm.AddScore();