Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java, Limbo: Matopelikysymyksiä

Sivun loppuun

Macro [05.03.2012 15:12:57]

#

Terve

Mulla on JFrame, johon olen lisännyt luokan, joka periytyy JPanelista sekä toteuttaa ActionListener-luokan. Kun lisään sen sen JFrameen (add(new Board())), tämän lisätyn luokan ActionListener ei toimi.

Koodit näyttävät yksinkertaistettuna tältä.

class Board extends JPanel implements ActionListener {
  Board(...) {
    addKeyListener(new KListener());
  }

  public void actionPerformed(ActionEvent e) {
    if(playing) {
      ...
    }

    repaint();
  }

  private class KListener extends KeyAdapter {
    @Override
    public void keyPressed(KeyEvent e) {
      ...
    }
  }
}
public class Snake extends javax.swing.JFrame {
  private Board board;
  public void startGame() {
    board = new Board(...);
    this.getContentPane().add(board);
    this.revalidate();
  }
}

Miten ylempi luokka saisi kuunneltua noita näppäimenpainalluksia, jotta se tietäisi mihin suuntaan matopelin matoa pitäisi liikutella?

Triton [05.03.2012 15:51:57]

#

Minun silmääni tossa on jotain todella outoa. Ensinnäkin kiinnostaisi, että missä kohtaa näkyy ActionListener-rajapinnan ainut toteutettava metodi actionPerformed() ? Niin, ja mikä idea on käyttää tässä kohtaa sisäkkäisiä luokkia? Oikeastaan mihin sä ylipäätään tarvitset koko ActionListeneriä eikös KeyListener olisi sopivampi?

Edit. Eli jotenkin näin:

class Board extends JPanel implements KeyListener {

	public Board() {
		this.addKeyListener( this );
	}

	public void keyPressed( KeyEvent e ) {}
	public void keyReleased( KeyEvent e ) {}
	public void keyTyped( KeyEvent e ) {}

}

Macro [05.03.2012 16:12:32]

#

Lisäsin sen actionPerformed-metodin sinne alkuperäiseen viestiin. Unohtui laittaa tonne, kun tiivistin koodista jonkin järkevän tiivistelmän.

Tossa on siksi ActionListener eikä KeyListener, kun sen pitää reagoida myös Timerin aiheuttamiin tapahtumiin.

Triton [05.03.2012 16:19:10]

#

Voithan sä toteuttaa molemmat rajapinnat...

Macro [05.03.2012 16:41:02]

#

Lopputulos olisi kumminkin sama, vain vähän eri tavalla toteutettuna.

What about the real problem?

Triton [05.03.2012 17:05:17]

#

Minkälainen tuo sinun pelisi main-metodi on? Eli miten käytät tuota Snake-luokasta luotua oliota?

Macro [05.03.2012 17:10:47]

#

Halusit tietää varmaan, että mitä sille tehdään, ja se ei kyllä valitettavasti löytynytkään noista kahdesta, joten tässä nämä..

public void startGame() {
	board = new Board(paljon parametrejä);
	this.getContentPane().remove(mainmenu);
	this.getContentPane().add(board);
	this.revalidate();
}

public void endGame() {
	this.getContentPane().remove(board);
	this.getContentPane().add(mainmenu);
	this.revalidate();
	board.endGame();
	updateStats();
}

Metabolix [05.03.2012 17:55:07]

#

Suosittelen, että luet alkajaisiksi Java-oppaat aiheista Key Listener ja Key Bindings. Sinun tulisi mahdollisesti käyttää näistä tavoista jälkimmäistä. Jos kuitenkin välttämättä haluat yrittää ensimmäisellä, lisää paneelille ainakin setFocusable(true) ja tarpeen mukaan myös requestFocusInWindow() tai setFocusTraversalKeysEnabled(false).

Macro [05.03.2012 18:24:43]

#

Kiitos. Ymmärsinköhän kumminkin jotain väärin, kun lopputulos oli tämmöistä kauheaa toistoa? Lopputuloksesta tuli kumminkin ihan toimiva.

this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke((KeyEvent.VK_DOWN), 0, false), "DOWN");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke((KeyEvent.VK_UP), 0, false), "UP");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke((KeyEvent.VK_RIGHT), 0, false), "RIGHT");
...

this.getActionMap().put("DOWN", new AbstractAction() {
	@Override
	public void actionPerformed(ActionEvent e) {
		...
	}
});

this.getActionMap().put("UP", new AbstractAction() {
	@Override
	public void actionPerformed(ActionEvent e) {
		...
	}
});

...

qeijo [05.03.2012 18:30:58]

#

KeyListener, keyPressed ?

http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html

...

		int keyCode = e.getKeyCode();

		switch (keyCode) {

			case 37:
				//Vasen
			break;

			case 38:
				//Ylos
			break;

			case 39:
				//Oikea
			break;

			case 40:
				//Alas
			break;

            default:
                 //Muu mikä..
            break;
		}

...

Triton [05.03.2012 18:42:11]

#

Minusta silti tuntuu, että teet tuon nyt vaikeamman kautta... ts. itse olen ainakin toteuttanut matopelin ohjauksen huomattavasti helpommalla...

Macro [05.03.2012 18:52:45]

#

Ohjaus on toteutettu niin, että loopissa tarkistetaan mikä muuttujista (right, left, up, down) on tosi ja liikutaan siihen suuntaan. Ohjaus on oikeastaan tehty tämän oppaan perusteella. Se toimii, mutta se kyllä tuntuu vähän erikoiselta.

Jos matopelitoteutuksesi on nähtävillä, niin olisin halukas näkemään jos voisin tehdä jotain paremmin.

Metabolix [05.03.2012 19:12:37]

#

Eikö olisi helpompaa pitää vain yhtä muuttujaa, josta selviäisi suunta?

void lisaaNappi(String nimi, int vk, final Suunta uusiSuunta) {
	this.getInputMap(...).put(KeyStroke.getKeyStroke(vk, 0, false), nimi);
	this.getActionMap().put(nimi, new AbstractAction() {
		@Override
		public void actionPerformed(ActionEvent e) {
			suunta = uusiSuunta;
		}
	});
}

// ...
lisaaNappi("DOWN", KeyEvent.VK_DOWN, Suunta.ALAS);
lisaaNappi("UP", KeyEvent.VK_UP, Suunta.YLOS);

Tai jopa suunta suoraan vektorimuodossa (dx, dy).

jalski [06.03.2012 09:55:54]

#

Metabolix kirjoitti:

Tai jopa suunta suoraan vektorimuodossa (dx, dy).

Itse kallistuisin täman ratkaisun kannalle. En tiedä Javan valmiita luokkia, mutta esim. Infernolla löytyy Point adt, mikä soveltuu tämän tyyppiseen touhuun erinomaisesti.

esim. Infernolla tuo suunnan muutos ja 180° käännöksen estäminen sujuisi:

if (!newdir.eq(dir) && !newdir.eq(dir.mul(-1))) { 	# don't allow 180° turn.
	dir = newdir;
}

Macro [06.03.2012 13:44:59]

#

Nyt kun eksyttiin jo sivuraiteille, niin muokkasin otsikkoa sopivammaksi ja kysyn lisää.

Mikä sitten olisi hyvä tapa liikkumiseen? Mainitsit vektorit, mutta minulla ei ole mitään käsitystä niiden käytöstä edes Ohjelmointiputkan oppaan lukemisen jälkeen (ehkä niitä tulee vasta myöhemmin koulussa..).

jalski [06.03.2012 16:01:12]

#

Tässä tapauksessa vektori olisi vain (x, y) pari ja matematiikka normaalia peruskoulun laskuoppia...

Otetaan esimerkki:

Olet kartalla koordinaateissa (x = 5, y = 5) ja haluat liikkua ruudun verran vaakasuorassa vasemmalle.

Tarvittava suuntavektori olisi tuolloin: (x = -1, y = 0)

Arvasit varmaan, että laskemalla sijaintivektorin ja suuntavektorin x -ja y-komponentit yhteen saat uuden sijainti vektorin: (x = 4, y = 5).

Macro [07.03.2012 16:25:25]

#

Tyydyin kumminkin tähän nykyiseen tapaan, kun sainkin sen viritettyä toimimaan.

Kiitos vastauksista.


Sivun alkuun

Vastaus

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

Tietoa sivustosta