Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: Oikea kuva matopelin käännöksiin

Sivun loppuun

Macro [17.03.2012 18:05:01]

#

Terve

Luon Javalla matopeliä, jossa ongelmana on kääntyminen. Kolmen sekunin mittainen videonäyte ongelmasta.

http://www.youtube.com/watch?v=9wdUu9Dk3xs

Kun matoa kääntää, kulmakohtaan pitäisi ilmestyä oikeanlainen kuva. Nyt mato ei jatku saumattomasti, vaan kulmapalikan tilalle tulee pala suoraa häntää.

Pään sekä muun vartalon asennon tarkistaminen toimii näin.

for(int i = 0; i < dots; i++) {
	if(i == 0) {
		// head
		if(direction == UP)
			draw = head_up;
		else if(direction == DOWN)
			draw = head_down;
		else if(direction == LEFT)
			draw = head_left;
		else if(direction == RIGHT)
			draw = head_right;
	} else if(i == dots - 1) {
		// tail
		int prevX = x[dots - 2];
		int prevY = y[dots - 2];

		if(prevY > y[dots - 1])
			draw = tail_down;
		if(prevY < y[dots - 1])
			draw = tail_up;
		if(prevX > x[dots - 1])
			draw = tail_right;
		if(prevX < x[dots - 1])
			draw = tail_left;
	} else {
		// body
		if(x[i] != x[i - 1])
			draw = body_horizontal;
		else
			draw = body_vertical;

		// if(suunta on ylhäältä alas ja sitten vasemmalle) draw = corner_rb;
	}

	g.drawImage(draw, x[i], y[i], this);
}

x ja y ovat taulukoita, jotka sisältävät kunkin madon palasen sijainnin laudalla. x[0] on madon pään sijainnin x-koordinaatti (pikseleissä etäisyys vasemmasta reunasta) ja y[0] on madon pään sijainti y-koordinaatistossa. Vastaavasti x[1] ja y[1] sisältävät seuraavan palan tiedot jne...

Millaisia vinkkejä löytyisi tuon käännöksen korjaamiseen?

Pekka Karjalainen [17.03.2012 22:18:15]

#

Macro kirjoitti:

Millaisia vinkkejä löytyisi tuon käännöksen korjaamiseen?

Ei tässä ole muuta tapaa kuin tarkistaa kaikki tapaukset. Käsittelet vain jokaisen eri mahdollisuuden ja valitset oikean madonpalan.

Tässä hieman pseudokoodia tavasta, joka minulle tuli ensimmäisen mieleen. Sinulla olisi luetelmatyyppi, joka luettelisi eri suunnat näin.

luetelma Suunta = {ylös, vasemmalle, oikealle, alas};

sitten madonpiirtosilmukka tähän malliin

toista (jokaiselle indeksille matotaulukossa)
  jos ei pää eikä häntä
    Suunta edellSuunta = // selvitä edellisen suunta
    Suunta seurSuunta = // selvitä seuraavan suunta
    Pala pala = valitsePiirrettäväPala(edellSuunta, seurSuunta)
    piirrä(pala, tähän)
  jos pää taikka häntä
    // tämän kohdan osaat jo

Tiedät, että edelliseen ja seuraavan paikkaan on aina mahdollista katsoa, kun kyseessä ei ole häntä eikä pää. Suunnanselvitys tapahtuu samalla tavalla kuin yllä selvitit hännän suunnan. Kahdesta naapuripalan suunnasta taas pitäisi olla helppo valita oikea piirrettävä pala esim. usean ehtolauseen avulla. Tämän operaation voi taulukoidakin, jos se tuntuu selkeältä siten tehtynä.

Macro [18.03.2012 13:22:26]

#

Jep, lisäsin kasan vertailuita koodiin niin kyllähän ne palat sai sinne paikalleen. Olin sitä ennenkin yrittänyt, mutta huomasimpa että olisi pitänyt jättää else if:n tilalle pelkästään if. Silloin piirrettiinkin vain suoria hännänpaloja, kun ensimmäinen tai toinen ehto toteutui aina.

Tommonen pala tuonne else-lohkoon niin alkoi toimia.

if((y[i] == y[i + 1] + 16 && x[i] == x[i - 1] + 16) || (x[i] == x[i + 1] + 16 && y[i] == y[i - 1] + 16))
	draw = corner_rb;

if((y[i] == y[i + 1] - 16 && x[i] == x[i - 1] - 16) || (x[i] == x[i + 1] - 16 && y[i] == y[i - 1] - 16))
	draw = corner_lt;

if((x[i] == x[i + 1] + 16 && y[i] == y[i - 1] - 16) || (x[i] == x[i - 1] + 16 && y[i] == y[i + 1] - 16))
	draw = corner_rt;

if((y[i] == y[i - 1] + 16 && x[i] == x[i + 1] - 16) || (x[i] == x[i - 1] - 16 && y[i] == y[i + 1] + 16))
	draw = corner_lb;

Grez [18.03.2012 14:21:54]

#

Pekka Karjalainen kirjoitti:

Ei tässä ole muuta tapaa kuin tarkistaa kaikki tapaukset. Käsittelet vain jokaisen eri mahdollisuuden ja valitset oikean madonpalan.

On niitä. Esimerkiksi käyttää binäärialgebraa ja numeroida ne 4 erinäköistä käännöspalaa sopivasti.

jalski [18.03.2012 15:17:32]

#

Itse tekisin Infernolle Limbolla jotakuinkin näin:

TILESZ : con 8 	# width and height of the map tile

LEFT, RIGHT, UP, DOWN: con iota; 	# 0, 1, 2, 3

# Snake node
SPoint: adt
{
	pos: Point; 	# position (x, y)
	rot: int; 		# LEFT, RIGHT, UP or DOWN
};

headImages: array [4] of ref Image; # All possible image rotations
tailImages: array [4] of ref Image; # All possible image rotations
bodyImages: array [4] of ref Image; # All possible image rotations

Eli siis käärme koostuisi paloista, joihin olisi tallennettu tieto paikasta ja kulkusuuntaa vastaava kuvan rotaatio.

Tallentaisin käärmeen taulukkoon siten, että taulukon ensimmäinen alkio (0) on häntä, viimeinen alkio (len snake - 1) on pää. Taulukon alkiot ensimmäisen ja viimeisen alkion välissä ovat luonnollisesti vartaloa.

Käärmeen liikuttaminen on helppoa:

snake[0:] = snake[1:];
np := (snake[len snake - 2].pos.add(dir), rot);
snake[len snake - 1] = np;

Edellisessä siis:

snake = array of SPoint;
dir = suuntavektori (x, y)
rot = suuntavektoria vastaava rotaatio (LEFT, RIGHT, UP tai DOWN)

Käärmeen pirto onnistuu yksinkertaisesti ilman vertailuja:

# draw tail
buffer.draw(tailImages[snake[0].rot].r.addpt((snake[0].pos.x * TILESZ, snake[0].pos.y * TILESZ)), tailImages[snake[0].rot], nil, Point(0, 0));

# draw body
for (i := 1; i < len snake - 2; i ++)
	buffer.draw(bodyImages[snake[i].rot].r.addpt((snake[i].pos.x * TILESZ, snake[i].pos.y * TILESZ)), bodyImages[snake[i].rot], nil, Point(0, 0));


# draw head
buffer.draw(headImages[snake[len snake - 1].rot].r.addpt((snake[len snake - 1].pos.x * TILESZ, snake[len snake - 1].pos.y * TILESZ)), headImages[snake[len snake - 1].rot], nil, Point(0, 0));

Pekka Karjalainen [18.03.2012 17:07:56]

#

Grez kirjoitti:

Pekka Karjalainen kirjoitti:

Ei tässä ole muuta tapaa kuin tarkistaa kaikki tapaukset. Käsittelet vain jokaisen eri mahdollisuuden ja valitset oikean madonpalan.

On niitä. Esimerkiksi käyttää binäärialgebraa ja numeroida ne 4 erinäköistä käännöspalaa sopivasti.

Laskisin itse oikein toimivan binäärilogiikan käytön kaikkien tapausten tarkistamiseksi, vaikka siinä ei tarvitakaan eksplisiittisiä ehtorakenteita. En jaksaisi kuitenkaan saivarrella tällaisesta sanavalinnasta sen enempää. Olisiko Grez onnellisempi, jos sanoisin, että kaikki mahdolliset tapaukset pitää käsitellä?

On kuitenkin hyvä huomata, että mato voi mennä suoraankin, joten joka ruutuun ei välttämättä pidä piirtää käännöspalaa. Minä laskisin minimissään vaadittavan kuusi erilaista madon keskipalaa, joista kaksi on suoran madonpalan kääntöjä ja neljä mutkallisen.

Grez [18.03.2012 17:31:59]

#

No joo, suhteutin ehkä vastaustasi liikaa tuohon Macron toteutukseen.

jalski [18.03.2012 17:52:43]

#

Pekka Karjalainen kirjoitti:

Minä laskisin minimissään vaadittavan kuusi erilaista madon keskipalaa, joista kaksi on suoran madonpalan kääntöjä ja neljä mutkallisen.

Olet oikeassa... Jotenkin itse huomioin esimerkissäni vain mahdolliset eri hännän tai pään suuntien rotaatiot.

Esimerkkiini tuo madon vartalopalojen käännöspalojen piirron toteutus on tosin helpohko toteuttaa lisäämällä rotaatiot: UPLEFT, UPRIGHT, DOWNLEFT, DOWNRIGHT, LEFTUP, LEFTDOWN, RIGHTUP, RIGHTDOWN.

Vertaamalla vanhaa ja uutta suuntavektoria pystytään päättelemään käännöspalalle oikea kuva. Tämä kuvan "rotaatio" siis asetetaan madon vanhalle päälle ennen uuden pään lisäämistä, jos vanha ja uusi suuntavektori eroavat toisistaan.

Pekka Karjalainen [18.03.2012 18:40:54]

#

Jos vielä saa huomauttaa yhdestä erikoistapauksesta, niin yhden ruudun pituinen mato pitää käsitellä erikseen, jos sellaisen syntyminen on pelin sääntöjen mukaan mahdollista. Lisäksi se tarvinnee vielä omat neljä graafista kuvaa, koska siinä häntä ja pää pitäisi mahduttaa yhteen ruutuun.

Ja jos todella ryhdyn spekuloimaan, niin välttämättä samojen kuvien peilaaminen tai kääntäminen ei riitä, jos grafiikassa on varjostuksia tai niistä näkyy madon kulkusuunta (esim. jos mato on käärme ja kuviin on piirretty suomut). Mutta tämä menee jo vähän liialliseksi tässä vaiheessa.

Yritän taas varoa liian ehdottomia ilmauksia tyyliin "ei ole muuta tapaa" tilanteissa, joissa en kirjoita asioista tällaisen ilmauksen vaatimalla tarkkuudella.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta