Tai rekisteröidy jo tänään!
Sivuja: [1]

Easy Autotile

0 jäsentä ja 1 Vieras katselee tätä aihetta.
Aloitusviesti: 26. Maaliskuu 2016, 14:38Peukku ylös +2Peukku alas -0
Hetken asiaa mietittyäni keksi erittäin helpon tavan toteuttaa autotiletys gridin pohjalta. Eli ensin luodaan Grid jossa on on arvoja eri materiaaleille esim. Perlin noisella tai Diamond algoritmillä (Ei kuulu tähän tutoriaaliin  :D). Gridin numerot on tässä tutoriaalissa asetettu-2:sta 5:seen korkeuksien mukaan. Nämä pitää myös katso että vastaavat Gridisi arvoja.
Lisätään peliin background kuvia jossa yksi kuva on aina yksi maaperä tämän kuvan muottia käyttäen:

Kuvat siis pitää olla toisissaan kiinni ja neljä ensimmäistä tileä on variaatioita sellaisesta tilestä jossa ei ole reunoja. Tämä siksi että saadaa tasaisiin alueisiin vähän vaihtelua. Poikkeuksena kivet joille pitaa tehda viel neljä extra kuvaa kulma kosketuksia varten ja tuo pohjamaankuva johon riittaa neljä kuvaa. Kuvat pitaa tietenkin nimeta oikein myös koodiin. Itse olen kayttanyt bck_dirt, bck_water jne... Ovat koodin loppuosassa.

Nimetään scripti: src_autotile

Scriptin sisältö:
//AUTOTILE
//Tarkistetaan huoneen koko ja tiletetaan sen mukaan
rw = room_width/16
rh = room_height/16

for(yy=1; yy<rh-1; yy+=1)
    {
    for(xx=1; xx<rw-1; xx+=1)
      {
      count=0 //Muuttuja joka laskee mika palikka valitaan
      arpa=0 // arpa muuttuja jotta saadaan vaihtelua tasaiseen maastoon
      target=ds_grid_get(argument0,xx,yy)
      //Katsotaan mita ymparilla on
      if ds_grid_get(argument0, xx+1, yy)!=target {count+=1}
      if ds_grid_get(argument0, xx, yy-1)!=target {count+=2}
      if ds_grid_get(argument0, xx-1, yy)!=target {count+=4}
      if ds_grid_get(argument0, xx, yy+1)!=target {count+=8}
      if target=5 && count=0 //Tama kohta muuttaa tilen myos silloin kun kysessa kylma kosketus eli jos halutaan saada koholla maasta olevat kivet elavimmiksi
        {
        if ds_grid_get(argument0, xx+1, yy-1)!=target {count=16}
        if ds_grid_get(argument0, xx-1, yy-1)!=target {count=17}
        if ds_grid_get(argument0, xx-1, yy+1)!=target {count=18}
        if ds_grid_get(argument0, xx+1, yy+1)!=target {count=19}
        }
      //Lopuksi piirretaan valittu aine
      if count=0 {arpa=choose(1,2,3)}
      if target=-2 {tile_add(bck_lava,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      if target=-1 {tile_add(bck_water,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      if target=0 {tile_add(bck_dirt,(3-arpa)*16,0,16,16,xx*16,yy*16, 10)} //pohja maa
      if target=1 {tile_add(bck_ice,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      if target=2 {tile_add(bck_snow,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      if target=3 {tile_add(bck_sand,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      if target=4 {tile_add(bck_grass,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      if target=5 {tile_add(bck_stone,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      }
    }


Käyttö (Gridin luonnin jälkeen esim create eventtiin):
src_autotile(GRIDIN_NIMI)

GRIDIN_NIMI pitää tietysti muuttaa samaksi kuin se grid johon numerot on tallennettu.

Lopputulos:


Laittakaa ihmeessä palautetta ja kuvia jos joskus kokeilette :) Ja kysymyksiäkin voi laittaa jos jokin jäi epäselväksi :D (Typojakin saattaa esiintyä kun hieman siistin koodia tänne postaamista varten)
4x
Tykkään
#1: 01. Kesäkuu 2016, 19:57Peukku ylös +0Peukku alas -0
Moi

Tsekkasin koodia läpi, tällä pitäisi saada pieni performance boost tuohon palaan:



//AUTOTILE
//Tarkistetaan huoneen koko ja tiletetaan sen mukaan
rw = room_width/16
rh = room_height/16

for(yy=1; yy<rh-1; yy+=1)
    {
    for(xx=1; xx<rw-1; xx+=1)
      {
      count=0 //Muuttuja joka laskee mika palikka valitaan
      arpa=0 // arpa muuttuja jotta saadaan vaihtelua tasaiseen maastoon
      target=ds_grid_get(argument0,xx,yy);
     
      //Katsotaan mita ymparilla on
      if (ds_grid_get(argument0, xx+1, yy) != target) {count+=1}
      if (ds_grid_get(argument0, xx, yy-1) != target) {count+=2}
      if (ds_grid_get(argument0, xx-1, yy) != target) {count+=4}
      if (ds_grid_get(argument0, xx, yy+1) != target) {count+=8}
     
     
      //Mikäli tämän oikein tulkitseen ei ole tarvetta käydä if lausekkeella kaikkia läpi vaan saada tieto jos tärppää kerrankin? (Muussa tapauksessa täytyy olla if ilman else)
      if (target=5 && count=0) //Tama kohta muuttaa tilen myos silloin kun kysessa kylma kosketus eli jos halutaan saada koholla maasta olevat kivet elavimmiksi
        {
            if ds_grid_get(argument0, xx+1, yy-1)!=target {count=16}   
            else if ds_grid_get(argument0, xx-1, yy-1)!=target {count=17}
            else if ds_grid_get(argument0, xx-1, yy+1)!=target {count=18}
            else if ds_grid_get(argument0, xx+1, yy+1)!=target {count=19}
        }
      //Lopuksi piirretaan valittu aine //++Tässä kannattaa käyttää else rakennetta tai switch ettei aiheuta turhaa prosessointia (riippuu compilerista kumpi on nopeampi).
      if count=0 {arpa=choose(1,2,3)}
      else if (target=-2) {tile_add(bck_lava,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      else if (target=-1) {tile_add(bck_water,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      else if (target=0) {tile_add(bck_dirt,(3-arpa)*16,0,16,16,xx*16,yy*16, 10)} //pohja maa
      else if (target=1) {tile_add(bck_ice,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      else if (target=2) {tile_add(bck_snow,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      else if (target=3) {tile_add(bck_sand,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      else if (target=4) {tile_add(bck_grass,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      else if (target=5) {tile_add(bck_stone,(count+3-arpa)*16,0,16,16,xx*16,yy*16, 10)}
      }
    }
Tykkään
#2: 01. Kesäkuu 2016, 21:27Peukku ylös +0Peukku alas -0
Korvasin nuo if lausekkeet switch case:lla jonka pitäisi olla tehokkaampi. Tuleeko muuta mieleen?
Tykkään
#3: 01. Kesäkuu 2016, 23:21Peukku ylös +0Peukku alas -0
Hmm.. riippuu hieman mutta parhaassa tapauksessa korvaa nipun if lausekkeita ja pienentää koodia 1/2.


ds_grid_value_exists(argument0, xx-1, yy-1, xx+1, yy+1, target)

Tykkään
#4: 02. Kesäkuu 2016, 11:14Peukku ylös +0Peukku alas -0
Koodi toimiin niin että se katsoo viereiset laatat ja lisää counttia 1,2,4,8,16,17,18 tai 19 sen mukaan mistä ruudussa osuma löytyy (eli counttia ei kasvateta vain yhdellä per osuma vaan noilla potenssi arvoilla) joka ei onnistu tuolla ds_grid_value_exists functiolla ja scriptin toimivuuden kannalta on errittäin tärkeää että count muutujan arvo on oikea :). Mutta hyvä kun mainitsit sillä tuon ds_grid_value_exists:n sillä se on se mitä todennäköisesti tarvitsen nyt kun koodailen AI:n rakennus scriptiä.
Tykkään
#5: 02. Kesäkuu 2016, 15:56Peukku ylös +0Peukku alas -0
Jep, tuolta game makerin syntaxista puuttuu tähän oleellinen funtio joka laskee kuinka monta kertaa tietty arvo esiintyy alueella.

Raapustin vihkoon tällaisen tänään palaverissa, en testannut mutta pitäisi toimia, tällä siis korvataan ds_grid_get rivit kun tarkastetaan alueita jotka suurempia kuin 1x1:


Scriptin kutsuminen:

count = power(2, scr_ds_grid_value_count(xx,yy,1,target,argument0));


Scripti : scr_ds_grid_value_cout


x_pos = argument0;
y_pos = argument1;
v_radius = argument2;
v_value = argument3;
v_grid = argument4;
v_count = 0;

//Tarkastetaan että tarkastettavalta alueelta löytyy arvo, mikäli ei palautetaan suoraan 0

if (ds_grid_value_exists(v_grid, xpos-v_radius, y_pos-v_radius, x_pos+v_radius, y_pos+v_radius, v_value))
{
    for (i = y_pos-v_radius; i < y_pos+v_radius; i += 1)//Liikutaan neliö muodostelmassa vasemmasta yläkulmasta alaspäin.
    {
        for (j = x_pos-v_radius; j < x_pos+v_radius; j += 1)//Liikutaan neliö muodostelmassa vasemmalta oikealle.
        {
            if (ds_grid_get(v_grid, j, i) = v_value){v_count+=1;}//Jos tarkistettava alue on gridin ulkopuolella, funktio palauttaa nollan tarkastukseen.
        }
    }
}

return v_count;


/*

Esimerkki grid tarkastus jossa v_radius = 1:

1. x_pos ja y_pos koordinaatit viittaavat ruudukkoon jossa numero 5 (keskipiste).
2. Ruudukossa näkyy tarkastettava alue tarkastus järjestyksessä (aloitetaan numerosta 1).
3. Jos tarkastettaisiin löytyykö arvoa 5, scripti palauttaa numeron 1 koska se löytyi kerran.

[1][2][3]
[4][5][6]
[7][8][9]

*/

Tykkään
#6: 02. Kesäkuu 2016, 21:18 (muokannut Dart 02. Kesäkuu 2016, 21:35)Peukku ylös +0Peukku alas -0
Jep, mutta sciptin ei sinänsä ole tarkoitus laskea montako saman suuruista arvoa on ruudun eripuolilla vaan olennaisempaa on tietää millä sivulla arvo sijaitsee esim. jos ruudun ylä ja ala puolella on sama arvo niin countin täytyy olla 10 muuten oikea tile ei piirry.

edit.
eikä siten siis vain kertoa counttia kahden potenssilla :)

Tykkään
#7: 03. Kesäkuu 2016, 14:25Peukku ylös +0Peukku alas -0
Kyllä, tuota ei pysty käyttämään tuossa koodissa muuttamatta suurempaa kokonaisuutta.

Tarkastus tuossa alkuperäisessä on järjestyksessä 2,8,4,6 kun taas tuossa area tarkastuksessa (jos tarkastetaan vain round numberit) 2,4,6,8.

[1][2][3]
[4][5][6]
[7][8][9]

Scriptien / funktioiden tekeminen riippuu aina kuinka suuri projekti on kyseessä (kuinka monta kertaa samoja asioita joutuu pyörittämään).
Jos tuon tarkastuksen joutuu tekemään vain kerran / kaksi niin parempi käyttää suoria kyselyitä optimoidusti.
Tykkään
#8: 04. Kesäkuu 2016, 09:14Peukku ylös +0Peukku alas -0
Tämä koko maailman tiletys tehdään minun pelissä vain kerran ja jos muutoksia tapahtuu niin silloin tilitetään vain muuttuneet ruudut ja niiden naapurit.

Eikös tuossa sinun koodissa count ole sama esim. (4,2), (4,6), (8,6) tai missä tahansa parissa, komikoissa jne.. miten tuo erottaa millä sivulla kosketus tapahtuu?

Tykkään
#9: 07. Kesäkuu 2016, 17:49Peukku ylös +0Peukku alas -0
Kyllä, palauttaa vain kuinka monta kertaa ko. arvo löytyy.

Jos haluaa kasvattaa counttia tarkan sijainnin mukaan niin pitää for loopin keskelle tehdä ehto joka katsoo missä kohtaa (i & j).

Mikäli tarkastus halutaan tehdä vain pysty ja vaaka tasossa niin ensimmäinen ehto for loopin keskellä : if ((v_radius = i) || ( v_radius = j)){}


Mutta tosiaan jos koodi rullataan vain kerran luomisessa läpi on dynaamisten scriptien teko turhaa.

Tykkään

Sivuja: [1]
 

Powered by SMF 2.0.11 | SMF © 2006–2009, Simple Machines LLC