# Mehr Abstraktion bei Spieleinstellungen



## Haave (27. Mrz 2011)

Hallo,

ich programmiere momentan ein kleines Spiel und habe dort ein Menü, in dem sich verschiedene Einstellungen vornehmen lassen (Feldgröße, Spieldauer, Mischgeschwindigkeit etc.). Die vom Spieler eingetragenen Werte werden mit diesem Code in die Einstellungen übernommen (ignorieren wir dabei mal, dass die Eingaben momentan ungeprüft übernommen werden):

```
private void applyChanges() {
	gameSettings.setGridLength(Integer.parseInt(textFields[0].getText()));
	gameSettings.setRemainingTime(Integer.parseInt(textFields[1].getText()));
	gameSettings.setShuffleSpeed(Integer.parseInt(textFields[2].getText()));
	gameSettings.setButtonSizeX(Integer.parseInt(textFields[3].getText()));
	gameSettings.setButtonSizeY(Integer.parseInt(textFields[4].getText()));
	gameSettings.setHorizontalGap(Integer.parseInt(textFields[5].getText()));
	gameSettings.setVerticalGap(Integer.parseInt(textFields[6].getText()));
}
```

Mit diesem Code bin ich nicht gerade zufrieden, da er zu wenig abstrahiert ist und ich ihn immer wieder händisch anpassen muss, wenn es Änderungen gibt (z.B. neue Einstellmöglichkeiten hinzu, nicht benötigte weg). Ich hätte lieber eine Schleife, mit der zum einen durch die Textfelder und zum anderen (hoffentlich werde ich jetzt nicht geknüppelt) durch die aufzurufenden Methoden iteriert wird.
Reflection mag ich nicht benutzen (falls das in diesem Fall überhaupt helfen würde - wobei… mit dem Holzhammer ist sicher einiges möglich ).
Ansonsten fällt mir nur ein, das ganze über Interfaces zu machen: Dabei würde jede Klasse, die das Interface Settable (oder so) implementiert, eine Einstellung repräsentieren. Dann könnte man deren Instanzen in ein Settable[] tun. Irgendwie scheint mir das aber auch Overkill/Overobjectizing zu sein. Weiteres Problem: Die Einstellungen sind nicht immer nur ints, image_path ist z.B. ein String, also müsste trotz Abstraktion auch auf Sonderfälle Rücksicht genommen werden

Für den Import und Export von Einstellungen verwende ich java.util.Properties, wo ich den ganzen Schmus dann nochmal habe:

```
props.put("game_duration", Integer.toString(remainingTime));
props.put("grid_gap_horizontal", Integer.toString(horizontalGap));
props.put("grid_gap_vertical", Integer.toString(verticalGap));
props.put("grid_length", Integer.toString(gridLength));
props.put("shuffle_speed", Integer.toString(shuffleSpeed));
props.put("vermin_button_size_x", Integer.toString(buttonSizeX));
props.put("vermin_button_size_y", Integer.toString(buttonSizeY));
props.put("image_path", imagePath);
```



… Öhm, ja. Weiß jemand Rat, wie man das schöner machen könnte?


----------



## Haave (1. Jun 2011)

Nach zwei Monaten mal: *schubs*


----------



## Tomate_Salat (1. Jun 2011)

Naja, ein wenig was sparen kannst du dir, wenn du es direkt in den Properties speichern würdest. Schau dir mal das hier an: Map-->Interface. Vllt hilft dir das ja weiter. Du kannst mit einem Objekt arbeiten, welches die Daten in deinen Properties immer aktuell hält. Leider unterstützt er noch kein Parsern der Werte über den Setter, aber der Code ist offen und du könntest es notfalls selbst implementieren oder warten, bis ich das nachgeholt habe =)
-----
*Edit* Support habe ich geschrieben. Will das noch ein wenig testen und werde es dann im laufe des Tages uploaden, hier ein kleines Beispiel:

```
import java.util.Properties;
import javax.swing.JTextField;
import de.jfruit.factory.CFactory;
import de.jfruit.factory.ILinkParser;
import de.jfruit.factory.Link;
import de.jfruit.factory.MethodType;

public class GameSettings 
{
	JTextField textField;
	Properties props=new Properties();
	
	public static void main(String[] args) {
		new GameSettings();
	}
	
	public GameSettings() 
	{
		textField=new JTextField("800");
		
		MyConfig config=CFactory.createFromMap(props, MyConfig.class);
		config.setStoreWidth(textField);
		System.out.println("Width: " + config.getStoreWidth());
	}
}

interface MyConfig
{
	@Link(key="game_width",parser=JTFParser.class,type=MethodType.SETTER) public void setStoreWidth(JTextField field);
	@Link(key="game_width") public int getStoreWidth();
}

class JTFParser 
	implements ILinkParser
{

	@Override
	public Object defValue() {
		return null; // diese Methode spielt beim Setter keine Rolle
	}

	@Override
	public Object parse(Object o) {
		if(!(o instanceof JTextField))
			return 0;
						
		return Integer.parseInt(((JTextField)o).getText());
	}
}
```

Augabe

```
Width: 800
```

*--- Habe das update hochgeladen ---*


----------

