(Slick) Steuerung - mehrere Belegungen

staxx6

Mitglied
hi!,

ich programmiere eine Zeit lang schon mit Slick und hab jetzt nen kleinen Markel,
wenn man das mal so ausdrücken darf.
Mich stört seit längerem die Methode um ein bestimmten Tastendruck zu ermitteln:

if(input.isKeyDown(Input.KEY_A)) {}

Bei mehreren Belegungen müsste ich ne paar && ... anhängen was bei mehreren Aktionen
recht unübersichtlich wird und chaotisch, besonders wenn ich dran denke die Steuerung später
in eine Datei zu speichern (unterschiedliche mengen an .isKeyDown(...))

Da wollte ich euch mal fragen was ihr für Ideen dazu habt. Eine Idee von mir ist es
"Belegungen" in ein Array zu stecken. -> jumpList - UP, SPACE, W und alle andere Aktionen.
Würde so ca. so aussehen (hier mit nur einem Array)

Java:
	private boolean isKeyUp(Input input)
	{
		boolean isKeyPressed = false;
		
		ArrayList<Integer> keys = new ArrayList<Integer>();
		keys.add(new Integer(0xC8)); // TODO: load from file

		for(int i = 0; i < keys.size(); i++)
		{
			if(input.isKeyDown(keys.get(i).intValue()))
			{
				isKeyPressed = true;
				break;
			}
		}
		return isKeyPressed;
	}

Bin mir nicht so recht sicher ob es da nicht vielleicht noch bessere Ideen gibt.
 

Marco13

Top Contributor
Ich kenne mich mit Slick im speziellen nicht aus, aber ... meinst du den Fall, dass eine Aktion durch mehrere verschiedene Tasten ausgelöst werden kann? Das mit der Liste ist wohl eine Option, aber ob man sich da (für das Laden und Speichern, oder die Abfrage) noch mehr Infrastruktur drumrumbauen müßte (GROB im Sinne von InputMap/ActionMap, wie bei How to Use Key Bindings (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features) , auch wenn das nicht direkt übertragbar ist) kann ich gerade nicht einschätzen.
 
S

Spacerat

Gast
Ja, ich finde diese Tastaturabfragen mit Int-Zeigern in ein Boolean-Array auch sehr sinnig... deswegen findet man sie wohl auch überall :lol:.
Ne, im Ernst. Als ich ähnliche Probleme mit diesem Aufbau bekam, realisierte ich mir ähnliche Abfragen mit der Klasse BitSet. Mit "get(int index)" funktioniert die Abfrage einzelner Tasten weiterhin wie gewohnt und mit "and(BitSet x)" die Multi-Key-Abfragen. Multi-Keys können natürlich auch als BitSet-Konstanten definiert werden.
[EDIT]Wenn's aber um die Belegung freidefinierbarer Tastaturbelegungen in einem Spiel geht, ist die Idee mit der Liste gar nicht mal schlecht. Ich würde aber die Listindices wieder mit Konstanten benennen und die Abfrage wie dann gewohnt gestalten, sonst verliert man am Ende nur wieder den Überblick.[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

staxx6

Mitglied
hi!,

danke für die Antworten, sie haben mich zum nachdenken angeregt und auf eine noch andere Lösung gebracht. ;)

Ich hab eine Control Klasse mit einem Array, welches KeyMaps Klassen hält.
Ein KeyMap hat drei einfache Werte Name, Key1, Key2.

So lass ich einfach die Control klasse nach dem richtigen KeyMap suchen und dieser gibt wiederum an ob der input passt.

In der Game-Logik würde das dann auch einfach so aussehen:
Java:
if(control.isAction("Jump"))
{
     machWas();
}

Die Control Klasse welche später auch aus der Datei liest (das Drumherum gekürzt):
Java:
public class Control
{
	private Control()
	{
		keyMapList = new ArrayList<KeyMap>();
		addKeyMaps();
	}
	
	private void addKeyMaps()
	{
		// hier von der Datei laden
		keyMapList.add(new KeyMap("Jump", Input.KEY_UP, Input.KEY_W));
		keyMapList.add(new KeyMap("STRG", Input.KEY_LCONTROL, Input.KEY_LCONTROL));
	}
	
	public boolean isAction(final String actionName)
	{
		boolean isAction = false;
		
		for(KeyMap keyMap : keyMapList)
		{
			if(keyMap.getName().equals(actionName))
			{
				if(keyMap.checkEquality(INPUT))
				{
					isAction = true;
				}
			}
		}
		return isAction;
	}
}

Und die KeyMap Klasse:
Java:
public class KeyMap
{
	private final String name;
	private int key1 = 0, key2 = 0;
	
	public KeyMap(final String name, int key1, int key2)
	{
		this.name = name;
		this.key1 = key1;
		this.key2 = key2;
	}
	
	public boolean checkEquality(final Input input)
	{
		boolean isEqual = false;

		if(input.isKeyPressed(key1) || input.isKeyPressed(key2))
		{
			isEqual = true;
		}
		return isEqual;
	}
	
	public String getName()
	{
		return name;
	}
}

Nach längere Überlegung bin ich zum Entschluss gekommen, dass zwei Belegungen reichen pro "Aktion".
Weitere Funktionen wie die Tasten ändern in der Laufzeit sollte auch kein Problem darstellen und Taste gedrückt halten, etc.
 
S

Spacerat

Gast
Bei dir geht's definitiv doch um verschiedene Aktions-Belegungen, die womöglich auch noch zusammen benutzt werden sollen. Na herzlichen Dank für diese Inspiration... deswegen sieht meine Keyabfrage nun so aus:
Java:
public final class KeySet {
	private static final BitSet downKeys = new BitSet(256);

	private static final KeyListener listener = new KeyListener() {
		
		@Override
		public void keyTyped(KeyEvent e) {
			// nothing
		}
		
		@Override
		public void keyReleased(KeyEvent e) {
			int key = e.getKeyCode();
			if(key > 0 && key < 256) {
				downKeys.clear(key);
			}
		}
		
		@Override
		public void keyPressed(KeyEvent e) {
			int key = e.getKeyCode();
			if(key > 0 && key < 256) {
				downKeys.set(key);
			}
		}
	};

	private static Component activeComponent;

	public static boolean isKeyDown(int key) {
		if(key < 1 || key > 255) {
			throw new IllegalArgumentException("key out of range " + key);
		}
		return downKeys.get(key);
	}

	public static boolean isKeySetDown(KeySet action) {
		return action.and(downKeys);
	}

	public static boolean isAction(KeySet action) {
		return action.or(downKeys);
	}

	public static Component register(Component comp) {
		synchronized(KeySet.class) {
			Component rc = activeComponent;
			if(rc != null) {
				rc.removeKeyListener(listener);
			}
			activeComponent = comp;
			if(comp != null) {
				comp.addKeyListener(listener);
			}
			return rc;
		}
	}

	private final int[] keys;

	public KeySet(int ... keys) {
		for(int n = 0; n < keys.length; n++) {
			if(keys[n] < 1 || keys[n] > 255) {
				throw new IllegalArgumentException("key out of range " + keys[n]);
			}
		}
		this.keys = keys;
	}

	private boolean and(BitSet bs) {
		for(int n = 0; n < keys.length; n++) {
			if(!bs.get(keys[n])) {
				return false;
			}
		}
		return true;
	}

	private boolean or(BitSet bs) {
		for(int n = 0; n < keys.length; n++) {
			if(bs.get(keys[n])) {
				return true;
			}
		}
		return false;
	}
}
Evtl. kannst du ja auch etwas damit anfangen. Leider kann sie aber immer noch nicht zwischen linken und rechten STRG-, ALT- und/oder Windows-Tasten unterscheiden, aber immerhin schon mal Mehrfachbelegungen und Multikeys. Deine Control-Klasse könnte sie nun so verwenden:
Java:
class Control {
	public static final KeySet JUMP = new KeySet(VK_UP, VK_W);
	public static final KeySet STRG = new KeySet(VK_CONTROL);
	//... usw.
}
Im Prinzip kannst su so auch mehr als nur zwei Belegungen definieren. Das müsste aber auch bei deiner Methode klappen, wenn du wie ich den Array-Parameter (...) verwendest.
 

staxx6

Mitglied
In meiner ersten Version hatte ich in der KeyMap Klasse auch ein Array für die Belegung,
allerdings fand ich das doch übertrieben, da ich keine Situation kenne wo man mehr als zwei Tastenbelegung bräuchte.
Für Tastenkombos hab mir einfach eine isKeyDown() Methode ausgedacht, die dann mit der isKeyPressed() true liefert. Slick bietet da ja schon passende Methoden.

if(control.actionHold("LSTRG") && control.action("JUMP")) {//mach was }
 

staxx6

Mitglied
Ich hab mal dein Rat mit
Code:
public static final KeySet JUMP = new KeySet(VK_UP, VK_W);
beherzigt und das daraus gemacht:


Java:
public final class Control
{	
	/* Static list for the KeyMap */
	
	/* Player actions */
	public static KeyMap MOVE_JUMP = new KeyMap("moveJump", Input.KEY_UP, Input.KEY_W);;
	public static KeyMap MOVE_LEFT = new KeyMap("moveLeft", Input.KEY_A, Input.KEY_LEFT);
	public static KeyMap MOVE_RIGHT = new KeyMap("moveRight", Input.KEY_D, Input.KEY_RIGHT);
	
	public static KeyMap RESET_POSITION = new KeyMap("ResetPosition", Input.KEY_R, Input.KEY_F5);
	
	/* Additional keys */
	public static KeyMap L_CONTROL  = new KeyMap("LSTRG", Input.KEY_LCONTROL, Input.KEY_LCONTROL);
	
	private Control()
	{
		logger.info("loading controls");
	}
	
	public static boolean isAction(final KeyMap keyMap, final boolean holdingKey)
	{
		if(holdingKey == true) {
			if(keyMap.checkEqualityHolding(INPUT))
			{
				return true;
			}
		} else if(keyMap.checkEquality(INPUT))
			{
				return true;
			}
		return false;
	}
}

Java:
public class KeyMap
{
	private final String name;
	private int key1 = 0, key2 = 0;
	
	public KeyMap(final String name, int key1, int key2)
	{
		this.name = name;
		this.key1 = key1;
		this.key2 = key2;

                //TODO: Von Datei Laden
	}
	
	public boolean checkEquality(final Input input)
	{
		if(input.isKeyPressed(key1) || input.isKeyPressed(key2))
		{
			return true;
		} else { return false; }
	}
	
	public boolean checkEqualityHolding(final Input input)
	{
		if(input.isKeyDown(key1) || input.isKeyDown(key2))
		{
			return true;
		} else { return false; }
	}
	
	public String getName()
	{
		return name;
	}
}

So kann ich sogar total auf ein Array verzichten. Ich schätze mal das ich das jetzt so lasse, wenn nicht was noch besseres kommt. :)
 
S

Spacerat

Gast
Was besseres wäre, wenn meine Implementation noch die Location unterscheiden könnte - man arbeitet dran, allerdings ohne Slick, für eigene Zwecke.
Was dich betrifft... wozu benötigst du nun noch die Strings in KeyMap?
Das Array wäre allerdings noch 'ne Möglichkeit einige Belegungen mehr inkl. einer benutzerdefinierten anzubieten, wie man es von diversen Spielen schon kennt.
 
Zuletzt bearbeitet von einem Moderator:

staxx6

Mitglied
Was meinst du genau mit Location?
Die Strings halte ich, damit ich die später in den Optionen anzeigen kann und damit man die von der Datei lesen kann.

Kommt jetzt drauf an was du noch mehr an Benutzerdefinierte Testen haben möchtest. Kenne da nur das höhste in WoW z.B., Laufen: Belegung1; Belegung2 :)
Für Springen z.B. kannst du ja diese einfach ändern Ingame. (steht oben noch nicht im Code..) Doch das sollte ja kein Problem sein, sprich:
Code:
Control.MOVE_JUMP.changeKey("key1", Input.KEY_X);
etc.

Wenn du solche eigen definierte Belegung wie z.B. STRG+W meinst, kann ich die KeyMap erweitern um zwei "Keys".
 
S

Spacerat

Gast
Was meinst du genau mit Location?
Unterscheiden ob STRG-Links oder STRG-Rechts gedrückt wurde. Bei KeyEvents ist das die Location.

Kommt jetzt drauf an was du noch mehr an Benutzerdefinierte Testen haben möchtest. Kenne da nur das höhste in WoW z.B., Laufen: Belegung1; Belegung2 :)
Für Springen z.B. kannst du ja diese einfach ändern Ingame. (steht oben noch nicht im Code..) Doch das sollte ja kein Problem sein, sprich:
Code:
Control.MOVE_JUMP.changeKey("key1", Input.KEY_X);
etc.
Das hört sich nach vorbelegten KeySets an aus denen man auswählen kann. Ich meinte eher eine benutzerdefinierte Belegung ala The Elder Scrolls oder Need for Speed, wo man einer Aktion einzelne Tasten bzw. Tastenkombis zuweisen kann.
 

staxx6

Mitglied
Aso, Slick hat schon die Links-Rechts Unterscheidung.

Ich bin mir immer noch nicht so recht sicher was du meinst. :oops:
Die Aktionen sind klar vordefiniert "JUMP". Die Belegungen der Aktionen sind vorgeladen, sagen wir mal
"start-settings", welche man später dann durch eigene Tasten verändern kann.

Input.KEY_X war nur Exemplarisch, welche Taste genau gedruckt wurde, ist klar zu ermitteln oder halt Tasten (strg..).
 
S

Spacerat

Gast
Bei einigen Spielen hat man diverse Belegungsvorgaben, zwischen denen man wählen kann. Von diesen bieten widerum einige die Möglichkeit einer individuellen "pro Spielerprofil"-Belegung.
Also eigentlich das was du geschrieben hast. Weil du deine Control-Klasse so fest verdrahtest hattest, bin ich davon ausgegangen, dass du nur verschiedene Belegungsvorgaben anbieten wolltest.
 

staxx6

Mitglied
Ach-so meinst du das. Das was du als Belegungsvorgaben siehst soll nur die Standard Konfig. sein.
Wie ich Post drüber schrieb sollte auf jeden Fall noch eine Methode folgen, um die Belegungen zu ändern.
Sowie diese zu speichern und laden. Ggf. auch in einem Spieler Profil speichern für ganze unterschiedliche Profile.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
coolian slick lwjgl text darstellen mit UnicodeFont funktoniert nicht? Spiele- und Multimedia-Programmierung 11
S 2D mit Slick - Anfänger sucht Hilfe Spiele- und Multimedia-Programmierung 4
Hercules Slick - .fon Dateien benutzen? Spiele- und Multimedia-Programmierung 6
N [SLICK] Rectangle in Array Speichern Spiele- und Multimedia-Programmierung 3
X Android Slick AE Anmation Spiele- und Multimedia-Programmierung 2
X Android Slick AE Image Pfad Spiele- und Multimedia-Programmierung 3
X Slick in Android Apps einsetzten Spiele- und Multimedia-Programmierung 6
Rayo Slick Applet Spiele- und Multimedia-Programmierung 12
CookieSoft Slick und LWJGL Texture lag Spiele- und Multimedia-Programmierung 13
CookieSoft Slick Texture laden Fehler Spiele- und Multimedia-Programmierung 6
D Slick Lib - Bilder einlesen funktioniert nicht Spiele- und Multimedia-Programmierung 2
L Slick-Image aus byte-array erzeugen Spiele- und Multimedia-Programmierung 2
M BlueJ Schach Steuerung programmieren Spiele- und Multimedia-Programmierung 28
A Spracherkennung/steuerung Spiele- und Multimedia-Programmierung 12
C Bluetooth Helikopter steuerung Spiele- und Multimedia-Programmierung 6
T Problem mit JnR-Steuerung / KeyListener Spiele- und Multimedia-Programmierung 6
D java 3d Steuerung (mit KSKB) Spiele- und Multimedia-Programmierung 9
L iTunes-Steuerung / Ereignisse abfangen Spiele- und Multimedia-Programmierung 2
A Steuerung des Bewegungsflusses bei einem Netzwerkspiel Spiele- und Multimedia-Programmierung 18
R Problem Steuerung Spiele- und Multimedia-Programmierung 3
L 2 Spieler Steuerung Spiele- und Multimedia-Programmierung 4
B Mehrere Klassen auf JFrame Spiele- und Multimedia-Programmierung 3
N Mehrere Rechtecke in großes Quadrat einzeichnen Spiele- und Multimedia-Programmierung 5
J mehrere Listener für einen Button / Label Spiele- und Multimedia-Programmierung 1
M Applets - mehrere Tasten gleichzeitig abfragen Spiele- und Multimedia-Programmierung 3
E [LWJGL] Karusell, mehrere Objekte drehen sich um einen Mittelpunkt Spiele- und Multimedia-Programmierung 31
B GameGrid Probleme mit mehrere Actors Spiele- und Multimedia-Programmierung 5
R Mehrere Shader in einem Program Spiele- und Multimedia-Programmierung 8
B GameGrid Probleme mit mehrere Actors Spiele- und Multimedia-Programmierung 2
S Ein Thread für alle Animationen oder mehrere? Spiele- und Multimedia-Programmierung 2
S Mehrere Steine gleichzeitig setzen und bewegen Spiele- und Multimedia-Programmierung 4
V Java3D: mehrere ViewingPlaforms in Sonnensystem Spiele- und Multimedia-Programmierung 8
A Mehrere geometrische Objekte in JPanel zeichnen Spiele- und Multimedia-Programmierung 4
hdi mehrere Threads/Tasks in einem synchronisieren -> TaskPoo Spiele- und Multimedia-Programmierung 36
S Java3D - mehrere Instanzen eines Geometrieobjektes erzeugen Spiele- und Multimedia-Programmierung 3
V Ein oder mehrere GIF-Grafiken zusammenfügen Spiele- und Multimedia-Programmierung 3
M mehrere PNG in eine Datei Spiele- und Multimedia-Programmierung 3
L Wie kann ich mehrere Texturen auf ein Object File mappen Spiele- und Multimedia-Programmierung 4
D mehrere Graphiken erstellen und ihre Position definieren Spiele- und Multimedia-Programmierung 4

Ähnliche Java Themen

Neue Themen


Oben