# Gleichzeitiges Steuern von 2 Objekten über Tastatur



## TeacherMC (10. Mai 2007)

Hallo,

wir arbeiten an einem Spiel "Breakout"

in dem Spiel soll mit 2 "Schägern", welche einfach Buttons sind ein Ball hin und her gespielt werden.
Das ansteuern der JButtons mithilfe des KeyListeners und das setzen der neuen Position
ist kein Problem.

Das einzige Problem ist, wenn beide Spieler eine Taste festhalten.
Dann wird eine Taste im Tastaturpuffer gehalten, und die andere kommt erst zum Zug, wenn der
erste Spieler die Taste kurz los läßt.

Hat jemand eine Idee?


----------



## doctus (10. Mai 2007)

Ich würds mal mit Multihread versuchen.

lg doctus


----------



## Bradan (10. Mai 2007)

Doctus: Multithreading allein bringt nicht viel bei dem Konzept des KeyListeners. Java ist in dieser Hinsicht für mich sowieso keine Ideale Sprache. In jeder anderen (Nativ WinAPI fähigen) Sprache würde man standardmäßig GetAsyncKeyState(int VirtualKeycode) verwenden.

Eine Lösung wäre das hier:


```
import java.awt.BorderLayout;
import javax.swing.JPanel;
import java.awt.GraphicsConfiguration;
import java.awt.HeadlessException;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class GUI extends JFrame implements KeyListener, Runnable {

	private JPanel jContentPane = null;
	private boolean[] action;
	private Thread derThread;

	public GUI() {
		super();
		action = new boolean[256];
		for (int i = 0; i < action.length; i++) {
			action[i] = false;
		}
		initialize();
		
		addKeyListener(this);
		
		derThread = new Thread(this);
		derThread.start();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(0, 200);
		this.setContentPane(getJContentPane());
		this.setTitle("JFrame");
		this.addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent e) {
				System.exit(0);
			}
		});
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
		}
		return jContentPane;
	}

	public void keyTyped(KeyEvent e) {
	}

	public void keyPressed(KeyEvent e) {
		action[e.getKeyCode()] = true;
	}

	public void keyReleased(KeyEvent e) {
		action[e.getKeyCode()] = false;
	}

	public void run() {
		while(true) {
			
			for (int i = 0; i < action.length; i++) {
				if(action[i] == true) {
					System.out.println("Taste: "+KeyEvent.getKeyText(i));
				}
			}
			
			try {
				Thread.sleep(1000 / 3);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}
```

Bei keyPressed() wird der Wert für den Tastencode auf "true" gesetzt bis zum keyReleased. Der Thread aktualisiert die Nachrichten auf der Konsole 3 mal pro Sekunde. Ein großes Problem bei der Sache ist, dass wenn das Fenster den Fokus verliert und ein keyReleased noch offen steht, es den Tastendruck trotzdem weiterhin als gedrückt wahrnimmt.
Eine andere Lösung wäre das einbinden von org.eclipse.... (alternativ auch NativeCall) mit der abstrakten Klasse OS. Dann könnte man direkt mit OS.GetAsyncKeyState() die Taste überprüfen.


----------



## Quaxli (11. Mai 2007)

Der oben beschriebene Code funktioniert in Java wunderbar und diese Lösung ist im Prinzip eine Standardvorgehensweise im Rahmen der Spieleprogrammierung.
Allerdings würde ich für die benötigten 4 - 6 Tasten jeweils einen Boolean definieren.
Das oben gezeigte, 256 Felder große, Boolean-Array wäre mir (außer zu Demo-Zwecken) zu umständlich.


----------



## Bradan (11. Mai 2007)

Quaxli hat gesagt.:
			
		

> Der oben beschriebene Code funktioniert in Java wunderbar und diese Lösung ist im Prinzip eine Standardvorgehensweise im Rahmen der Spieleprogrammierung.
> Allerdings würde ich für die benötigten 4 - 6 Tasten jeweils einen Boolean definieren.
> Das oben gezeigte, 256 Felder große, Boolean-Array wäre mir (außer zu Demo-Zwecken) zu umständlich.



 Klar, für die paar Tasten könnte man einfach einzelne Variablen nutzen, aber bei mehreren wirds unübersichtlich und umständlich, gerade wenn man die Steuerung anpassbar halten will. :autsch: Außerdem hab ich das in mehreren Spielen schon mit einzelnen Variablen gemacht und jedes mal musste ich nachschauen wie ich nun die Variable genannt hab (Sowas wie IntelliSense Autovervollständigung hat leider nicht jeder). In meinen neuen Projekten sieht es schön übersichtlich aus. Das nervt sonst tierisch, wenn man den VK-Code weiß, aber nicht die Variable.


----------



## TeacherMC (14. Mai 2007)

Vielen Dank für den Lösungsvorschlag.

Das funktioniert natürlich super, Danke.
Werde ich gleich an meine Schüler so weitergeben.

Einfach Klasse Leute.

Gruß

Niko


----------



## André Uhres (14. Mai 2007)

TeacherMC hat gesagt.:
			
		

> ..Einfach Klasse Leute..


Ich finde diesen Thread auch sehr gut, muss ich mir merken


----------



## fl3xX (6. Jun 2007)

hab mir den code auch mal angesehen. funktionier an sich auch sehr gut. nun will ich jedoch, dass wenn "s" gedrück wird eine variable erhöht wird und bei Druck auf "a" soll die variable kleiner werden. jedoch macht er das nicht. hilfe von nöten..

```
public void run() {
	      while(true) {
	         
	         for (int i = 0; i < action.length; i++) {
	            if(action[i] == true) {
	            	panel.label2.setText("Taste: >"+KeyEvent.getKeyText(i)+ "<");
		        if(KeyEvent.getKeyText(i) == "A" ){
		            	canvas.p1x -= 5;
		        }
		        if(KeyEvent.getKeyText(i) == "S"){
		            	canvas.p1x += 5;
		        }
	            }
	         }
	      }
	   }
```


----------



## SlaterB (6. Jun 2007)

string.equals(string)

statt 

string == string


----------

