wiki:TileMap
Last modified 3 years ago Last modified on 2014-06-11 11:45:08

Jypelin käyttöohjeet » Ruutukentän luominen

  1. Kentän tekeminen kuvatiedostosta
    1. 1. Kentän piirtäminen Paint.NETillä
    2. 2. Kenttätiedoston lisääminen Visual Studioon
    3. 3. Kentän luominen Visual Studioon lisätystä kuvatiedostosta
  2. Kentän tekeminen tekstitiedostosta
    1. 1. Kenttätiedoston tekeminen ja muokkaaminen ConText-tekstieditorilla
    2. 2. Kenttätiedoston lisääminen Visual Studioon
    3. 3. Ruutukartan luominen
    4. 4. Merkit / pikselit vastaamaan olioita
    5. 4.1 Isojen kenttien optimointi
    6. 5. Kentän lisääminen peliin
    7. 6. Valmis esimerkki
  3. Tekstuurin lisääminen
  4. Optimointi (jos peli on hidas)

Jypelissä on mahdollista luoda kenttä kuvatiedostoon tai tekstitiedostoon "piirretyn" mallin mukaisesti.

Tällöin puhutaan, että tehdään ns. ruutukenttä, sillä kuvatiedoston jokainen pikseli tai tekstitiedoston jokainen merkki asetetaan vastaamaan tietyn kokoista ruutua pelikentässä.

Kentän tekeminen kuvatiedostosta

Kentän voi luoda kuvasta niin, että yksi kuvapiste eli pikseli vastaa yksittäistä oliota pelikentällä.

Eriväriset pikselit vastaavat siten eri olioita, joten vaikkapa mustat pikselit voivat olla seiniä, vihreät pelaajia ja keltaiset kerättäviä tähtiä. Värien merkityksen voi itse päättää.

1. Kentän piirtäminen Paint.NETillä

Mikroluokissa piirtämiseen on käytössä Paint.NET -niminen ohjelma. Voit piirtää ruutukentän muullakin ohjelmalla, tärkeintä on että kuvan yksittäisiä pisteitä eli pikseleitä pääsee muokkaamaan ja niiden väriarvot ovat helposti nähtävissä.

Avataan ensin Paint.NET Käynnistä-valikosta tai työpöydältä. Näkyville pitäisi tulla seuraavanlainen ikkuna:

Valitse File-valikosta New... luodaksesi uuden kuvan. Avautuvaan ikkunaan kirjoita kentälle haluttu koko Width- ja Height-kohtiin.

HUOM. Kentän koko on olioina, ei pikseleinä, joten vältä 80x80 suurempia kuvakokoja!

Kuvan zoomaustasoa voi säätää painamalla Ctrl pohjaan ja käyttämällä hiiren rullaa tai + ja - -näppäimiä.

Poista vielä valkoinen tausta valitsemalla kaikki (Ctrl+A) ja painamalla Delete-näppäintä. Nyt kuvan pitäisi näyttää tältä:

Tallenna kuva pelin Content-hakemistoon (mikroluokissa C:\MyTemp\tunnus\Peli\PeliContent missä Peli on pelisi nimi).

Kuva kannattaa tallentaa png-muodossa, jotta läpinäkyvyys säilyy. (Ks. myös Miten teen kuvaan läpinäkyviä osia.)

Nyt voit aloittaa kentän piirtämisen. Valmis kenttä voi näyttää vaikkapa tältä:

Voit itse päättää, mitä oliota mikäkin väri vastaa. Esimerkiksi mustat pikselit voivat olla seiniä, vihreät pelaajia, keltaiset kerättäviä tähtiä ja punaiset vihollisia.

2. Kenttätiedoston lisääminen Visual Studioon

Kentän lataamiseksi kuvasta lisätään kenttätiedosto content-projektiin, jonka jälkeen kenttä voidaan ladata koodissa.

Lisää content-projektiin tekemäsi tiedosto klikkaamalla content-projektia hiiren kakkospainikkeella, ja sen jälkeen valitsemalla Add ja Existing Item...

Etsi piirtämäsi kuvatiedosto (kentta1.png) ja valitse Add.

Kenttätiedosto tulee näkyviin Solution Explorer -ikkunaan.

3. Kentän luominen Visual Studioon lisätystä kuvatiedostosta

Kun kuva on liitetty Content-projektiin, voimme ottaa sen käyttöön koodissa.

Sopiva paikka kentän luomiseksi on aliohjelma, joka luo kentän (esim. LuoKentta).

Kentän luomisen vaiheet:

  1. Luodaan uusi ColorTileMap nimeltä ruudut, johon kuvatiedosto luetaan.
    • HUOM. Älä kirjoita kuvatiedoston nimen perään sen tiedostopäätettä .png.
  1. Kerrotaan ColorTileMapille mitä aliohjelmaa kutsutaan, kun tietyn värinen pikseli tulee vastaan kuvatiedostossa. (Ja toteutetaan tarvittavat aliohjelmat.)
    • Aliohjelmassa luodaan olio, sijoitetaan se oikeaan paikkaan ja lisätään peliin
    • Aliohjelmille tulee parametrina vektori, joka kertoo olion paikan pelikentällä.
    • Lisäksi parametreina tulevat yhdelle pikselille varatun ruudun leveys ja korkeus pelikentällä.
    • Listan väreistä ja nimet Paint.netin väreille näet allaolevasta linkistä.

Lista Paint.NETin valmiista väreistä.

  1. Luodaan kenttä Execute-komennolla.
    • Parametreina annetaan yhden pikselin leveys ja korkeus pelikentällä.

Esimerkki:

void LuoKentta()
{
  //1. Luetaan kuva uuteen ColorTileMappiin, kuvan nimen perässä ei .png-päätettä.
  ColorTileMap ruudut = ColorTileMap.FromLevelAsset("kentta1");
  
  //2. Kerrotaan mitä aliohjelmaa kutsutaan, kun tietyn värinen pikseli tulee vastaan kuvatiedostossa.
  ruudut.SetTileMethod(Color.Green,  LuoPelaaja);
  ruudut.SetTileMethod(Color.Black,  LuoTaso);
  ruudut.SetTileMethod(Color.Yellow, LuoTahti);
  
  //3. Execute luo kentän
  //   Parametreina leveys ja korkeus
  ruudut.Execute(20, 20);
}

void LuoPelaaja(Vector paikka, double leveys, double korkeus)
{
  pelaaja = new PlatformCharacter(10, 10);
  pelaaja.Position = paikka;
  AddCollisionHandler(pelaaja, "tahti", TormaaTahteen);
  Add(pelaaja);
}

void LuoTaso(Vector paikka, double leveys, double korkeus)
{
  PhysicsObject taso = PhysicsObject.CreateStaticObject(leveys, korkeus);
  taso.Position = paikka;
  taso.Image = groundImage;
  taso.CollisionIgnoreGroup = 1;
  Add(taso);
}

void LuoTahti(Vector paikka, double leveys, double korkeus)
{
  PhysicsObject tahti = new PhysicsObject(5, 5);
  tahti.IgnoresCollisionResponse = true;  
  tahti.Position = paikka;
  tahti.Image = tahdenKuva;
  tahti.Tag = "tahti";
  Add(tahti, 1);
}

HUOM! Execute-komento muuttaa kentän kokoa! Jos siis lisäät kenttään reunoja tai zoomaat kameran näyttämään koko kentän, tee se vasta tämän jälkeen.

Vinkki: Mikäli teet kentän, jossa on paljon samoja staattisia olioita (maasto, seinät, jne.), lisää seuraava rivi olion luovaan aliohjelmaan:

    palikka.CollisionIgnoreGroup = 1;

Tämän rivin vaikutus on se, että kaikki oliot, joilla on sama CollisionIgnoreGroup eivät törmää keskenään. Pelissä vierekkäiset tasot törmäilevät muuten huomaamattamme keskenään, ja näiden törmäysten käsittely syö tietokoneen laskentatehoa.

Kentän tekeminen tekstitiedostosta

Kentän voi luoda tekstitiedostosta niin, että jokainen merkki vastaa yksittäistä oliota. Voit itse päättää, minkälaista merkkiä mikäkin olio vastaa. Esimerkiksi '#' voisi olla seinä tai muu kiinteä kappale ja '*' vaikkapa tähti.

1. Kenttätiedoston tekeminen ja muokkaaminen ConText-tekstieditorilla

Helpoin tapa on tehdä ruudukko erilliseen tekstitiedostoon, josta se sitten luetaan. Vaihtoehtoinen tapa on määrittää ruudut suoraan koodissa.

Mikroluokissa tekeminen ja muokkaaminen onnistuu helpoiten ConText-ohjelmalla. Avaa ConText käynnistä-valikosta, tai klikkaamalla Win + R ja kirjoittamalla context ja paina Enter.

Luo uusi tiedosto ConTextiin. Tekstitiedostoon voi nyt "piirtää" kirjoitusmerkeillä haluamansa kentän. Ruudukon leveydeksi tulee tiedoston pisimmän rivin pituus ja korkeudeksi tiedoston rivien määrä. Käytä tyhjien ruutujen merkitsemiseen välilyöntiä, älä käytä Tab-näppäintä.

Vinkki: Laita päälle sarake- ja rivinumeroiden näyttö, sekä tyhjien merkkien näyttö:

  • Sarakkeet: View » Ruler
  • Rivit: Options » Environment options » Editor » Line Numbers
  • Tyhjät merkit: View » Show Special Characters

Vinkki: Kentän muokkaaminen voi olla helpompaa, kun painat Insert-näppäintä (tekstin korvaustila). Paina Insert-näppäintä uudelleen päästäksesi takaisiin normaaliin kirjoitustilaan.

Vinkki: Käytä merkkeinä pelkästään isoja ja pieniä kirjaimia sekä numeroita. Erikoismerkit (Esim £) eivät välttämättä toimi oikein.

Kun olet piirtänyt kentän, klikkaa tallennuskuvaketta, tai mene File » Save (Ctrl + S) ja anna tiedostolle nimeksi esimerkiksi "kentta1.txt" (ilman lainausmerkkejä), jos teit ensimmäisen kentän.

Kun kenttä on valmis, palaa Visual Studioon.

2. Kenttätiedoston lisääminen Visual Studioon

Ruudukon lataamiseksi tiedostosta lisätään kenttätiedosto Content-projektiin, jonka jälkeen kenttä voidaan ladata koodissa.

Lisää Content-projektiin tekemäsi tiedosto klikkaamalla Content-projektia hiiren kakkospainikkeella, ja sen jälkeen valitsemalla Add ja Existing Item...

Etsitään ja valitaan dialogista tekemästi tekstitiedosto (kentta1.txt) tai kuvatiedosto (kentta1.png) ja lisätään tiedosto content-projektiin valitsemalla Add

Jos tiedostoa ei näy, varmista että File name: tekstilaatikon oikealla puolella olevassa pudotusvalikossa lukee All files (*.*)

Kenttätiedosto tulee näkyviin Solution Explorer -ikkunaan.

HUOM! Kenttien tekstitiedostot eivät kopioidu automaattisesti käännöskansioon (debug), jolloin peli kaatuu. Ratkaisu: Muuta kenttien tekstitiedostojen asetuksia seuraavasti:

Klikkaa hiiren oikealla napilla kenttätiedostoa ja valitse Properties.

Properties-ikkunassa muuta asetuksia seuraavasti:

Output: Copy if newer

3. Ruutukartan luominen

Ruutukentän luomista varten tarvitsee koodissa luoda ruutukartta-olio (TileMap). Sopiva paikka ruutukartan luomiseksi on aliohjelma, joka luo kentän (esim. LuoKentta()).

Ruutukartta-olio luodaan seuraavasti (vaihda nimen kentta tilalle tiedosto, jonka liitit projektiin, ilman .txt päätettä):

TileMap ruudut = TileMap.FromLevelAsset("kentta1");

4. Merkit / pikselit vastaamaan olioita

Tarkoitus on, että jokaista erilaista kirjoitusmerkkiä tai pikseliä vastaa joku tietynlainen olio. Jokainen käyttämäsi merkki tai pikseli liitetään sitä vastaavan olion luovaan aliohjelmaan seuraavalla tavalla:

Tekstitiedostolle:

ruudut.SetTileMethod('=', LuoPalikka);
ruudut.SetTileMethod('*', LuoTahti);

LuoPalikka sekä LuoTahti ovat joita kutsutaan jokaisen annetun merkin kohdalla, joita kenttätiedostosta löytyy. Tällaisessa aliohjelmassa voidaan esimerkiksi luoda uusi olio.

Nyt täytyy vielä kirjoittaa oliot luovat aliohjelmat. Esimerkiksi LuoPalikka voisi olla seuraavanlainen:

void LuoPalikka(Vector paikka, double leveys, double korkeus)
{
    PhysicsObject palikka = PhysicsObject.CreateStaticObject(leveys, korkeus);
    palikka.Position = paikka;
    palikka.Shape = Shape.Rectangle;
    palikka.Color = Color.Gray;
    Add(palikka);
}

Jos teet paljon samantyyppisiä elementtejä, jotka eroavat toisistaan vain vähän, esimerkiksi kuvan tai värin suhteen, voit antaa muuttuvat tiedot parametrina. Samoin voit toimia toki muidenkin ominaisuuksien kanssa. Alla esimerkki kahden eri värisen palikan tekemisestä samalla aliohjelmalla, sama toimii kuville kun pistät parametriksi Imagen.

public override void Begin()
{
    TileMap kentta = TileMap.FromLevelAsset("kentta1");
    kentta.SetTileMethod('$', LisaaTaso, Color.White);
    kentta.SetTileMethod('#', LisaaTaso, Color.Blue);
    kentta.Execute();
}

void LisaaTaso(Vector paikka, double leveys, double korkeus, Color vari)
{
    PhysicsObject taso = PhysicsObject.CreateStaticObject(leveys, korkeus);
    taso.Position = paikka;
    taso.Color = vari;
    Add(taso);
}

4.1 Isojen kenttien optimointi

Mikäli teet kentän, jossa on paljon samoja staattisia olioita (maasto, seinät, jne.), lisää seuraava rivi yllä olevann aliohjelmaan.

    palikka.CollisionIgnoreGroup = 1;

Tämän rivin vaikutus on se, että kaikki oliot, joilla on sama CollisionIgnoreGroup eivät törmää keskenään. Tässä tapauksessa yksikään palikka olio ei törmää toiseen palikka olioon.

5. Kentän lisääminen peliin

Kun ruudut ovat taulukossa ja merkkien merkitys kerrottu, kentän voi vihdoin luoda peliin seuraavanlaisella komennolla:

ruudut.Execute(20, 20);

Tässä yhden ruudun kooksi tulisi (20, 20).

HUOM! Tämä komento muuttaa kentän kokoa! Jos siis lisäät kenttään reunoja tai zoomaat kameran näyttämään koko kentän, tee se vasta tämän jälkeen.

Toinen vaihtoehto on antaa kirjaston laskea edellämainitut attribuutit jolloin kentän koko ei muutu. Tällöin käytä komentoa:

ruudut.Execute();

6. Valmis esimerkki

Tässä eräs ratkaisu ruutukentän tekemiseen, kun kenttä on tehty erilliseen tekstitiedostoon nimeltä "kentta.txt":

void LuoKentta()
{
  TileMap ruudut = TileMap.FromLevelAsset("kentta1");
  ruudut.SetTileMethod('P', LuoPelaaja);
  ruudut.SetTileMethod('#', LuoPalikka);
  ruudut.SetTileMethod('*', LuoTahti);
  ruudut.Execute(20, 20);
}

void LuoPelaaja(Vector paikka, double leveys, double korkeus)
{
  pelaaja = new PlatformCharacter(10, 10);
  pelaaja.Position = paikka;
  AddCollisionHandler(pelaaja, "tahti", TormaaTahteen);
  Add(pelaaja);
}

void LuoPalikka(Vector paikka, double leveys, double korkeus)
{
  PhysicsObject taso = PhysicsObject.CreateStaticObject(leveys, korkeus);
  taso.Position = paikka;
  taso.Image = groundImage;
  Add(taso);
}

void LuoTahti(Vector paikka, double leveys, double korkeus)
{
  PhysicsObject tahti = new PhysicsObject(5, 5);
  tahti.IgnoresCollisionResponse = true;  
  tahti.Position = paikka;
  tahti.Image = tahdenKuva;
  tahti.Tag = "tahti";
  Add(tahti, 1);
}

Tekstuurin lisääminen

Ruutukentän luomille olioille halutaan usein asettaa jokin kuva eli tekstuuri. Koska samaa kuvaa käytetään monta kertaa, se kannattaa ladata muuttujaan pelin alussa. Sitten samaa kuvaa voi helposti käyttää samanlaisia olioita luovassa aliohjelmassa.

Piirrä tekstuuri kuvankäsittelyohjelmalla ja katso sitten ohjeet sisällön tuomisesta projektiin.

Kun kuva on olemassa ja tuotu projektiin sitä voidaan käyttää seuraavasti:

Ladataan kuva muuttujaan luokan alussa:

using System;
using Jypeli;

public class Peli : PhysicsGame
{
    Image palikanKuva = LoadImage("palikka");

    public override void Begin()
    {
        //...

Asetetaan ladattu kuva olioille:

void LuoPalikka(Vector paikka, double leveys, double korkeus)
{
    PhysicsObject palikka = PhysicsObject.CreateStaticObject(leveys, korkeus);
    palikka.Position = paikka;
    palikka.Image = palikanKuva;
    Add(palikka);
}

Optimointi (jos peli on hidas)

Jos kenttä on iso ja siinä on paljon staattisia olioita kuten seiniä vierekkäin, sitä voidaan nopeuttaa antamalla Jypelin yhdistellä vierekkäisiä olioita. Tämä onnistuu kirjoittamalla ruutukentän luontiin ennen Execute-riviä

kentta.Optimize(Color.Black);

tai tekstikentälle

kentta.Optimize('x');

Huom. älä käytä esim. kerättäville esineille, pelaajille tai muille joiden lukumäärällä on merkitystä