| |||||||
Das Thema "Meine Gedanken zur Spieleprogrammierung - Teil 2 - Spielstandsdaten" befindet sich unter Android Codeschnipsel auf Android-Hilfe.de.
|
| | Themen-Optionen | Ansicht |
| | #1 (permalink) |
| Android-Hilfe.de Mitglied Registriert seit: 25.06.2009
Beiträge: 51
Abgegebene Danke: 0
Erhielt 5 Danke für 4 Beiträge
| Jetzt möchte ich gern zeigen, wie man auf einfache Weise seinen Spielstand vorhalten, laden und speichern kann. Gehen wir mal davon aus, dass wir ein Spiel haben (wie das dann funktioniert, folgt in einem weiteren Teil) in dem z.B. wir die Informationen Spielername, Level, Punktzahl und Lebensenergie speichern wollen. Wenn man sich nicht noch über Dateiformate Gedanken machen möchte, gibt es eine sehr einfache Möglichkeit in Java, Daten vorzuhalten: die Klasse Properties. Sie besteht prinzipiell aus einer Map, die Schlüssel-Wertpaare beinhaltet, hat aber noch eine entscheidene Eigenschaft: Sie kann ihren Inhalt in Text- oder XML-Dateien schreiben und diesen wieder auslesen. Sicherlich wären Spieldaten im Zugriff schneller, wenn wir sie als Klassenhierarchie aufbewahren, aaber dann müssten wir dieses selbst tun. Wie arbeite ich jetzt aber damit? Zuallererst einmal müssen meine Spieleviews wissen, dass es einen Spielstand gibt. Dieser wird zentral verwaltet und den Views übergeben. Dazu erweitern wir unser IGameView Code: public interface IGameView {
/**
* @return game data object
*/
public Properties getGameData();
/**
* @param data game data object
*/
public void setGameData(Properties data);
/**
* @param setter Instance of the program setting the active view
*/
public void setViewSetter (IViewSetter setter);
} Code: public class MainActivity extends Activity implements IViewSetter {
// Die Spielstandsdaten- Neudeutsch: Geschäftsobjekt
Properties gameData = new Properties();
public void setView(String, viewName) {
...
// mache den ViewSetter bekannt
view.setViewSetter(this);
// mache der View den Spielstand bekannt.
view.setGameData(gameData);
// setze die neue View
setContentView ((View) view);
} Code: public class MainMenu extends LinearLayout implements IGameView,
OnClickListener {
IViewSetter setter = null;
Properties gameData = new Properties();
Button startGame = null;
Button loadGame = null;
Button saveGame = null;
Button exit = null;
private Button createMenuButton(String name) {
Button b = new Button(getContext());
b.setText(name);
b.setVisibility(VISIBLE);
b.setPadding(2, 2, 2, 2);
b.getBackground().setAlpha(0x80);
b.setClickable(true);
b.setOnClickListener(this);
this.addView(b);
return b;
}
public MainMenu(Context context) {
super(context);
try {
// set visibility
this.setVisibility(VISIBLE);
// gravity is bottom
this.setOrientation(VERTICAL);
this
.setGravity(Gravity.CENTER_VERTICAL
| Gravity.CENTER_HORIZONTAL);
startGame = this.createMenuButton("Start Game");
loadGame = this.createMenuButton("Load Game");
// wenn Daten im Spieleobjekt enthalten sind,
// stelle den save-button dar
if (!this.gameData.isEmpty()) {
saveGame = this.createMenuButton("Save Game");
}
exit = this.createMenuButton("Exit");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Properties getGameData() {
return gameData;
}
@Override
public void setGameData(Properties data) {
this.gameData = data;
}
@Override
public void setViewSetter(IViewSetter setter) {
this.setter = setter;
}
@Override
public void onClick(View v) {
Log.d("TraderGame", "item click");
if (v == startGame) {
this.setter.setView("gameloop");
} else if (v == loadGame) {
this.setter.setView("loadgame");
} else if (v == saveGame) {
this.setter.setView("savegame");
} else if (v == exit) {
this.setter.setView("exit");
}
}
} Code: public abstract class FileListView extends LinearLayout implements IGameView,
OnItemClickListener, OnClickListener {
protected IViewSetter setter = null;
protected Properties gameData = new Properties();
protected File directory = null;
protected ListView list = null;
protected EditText filename = null;
protected Button go = null;
/**
* @param context
*/
public FileListView(Context context) {
super(context);
// Savegame-Verzeichnis erstellen
createDirectory(context);
// set visibility
this.setVisibility(VISIBLE);
// gravity is bottom
this.setOrientation(VERTICAL);
this.setGravity(Gravity.TOP | Gravity.LEFT);
LinearLayout view2 = new LinearLayout(context);
view2.setOrientation(HORIZONTAL);
view2.setGravity(Gravity.LEFT);
// add filename textfield
this.filename = new EditText(context);
this.filename.setWidth(250);
view2.addView(filename);
// add run button
this.go = new Button(context);
this.go.setText("go");
this.go.setOnClickListener(this);
view2.addView(go);
this.addView(view2);
// add ListView
this.list = new ListView(context);
this.list.setId(R.id.ListView01);
this.list.setOnItemClickListener(this);
String fileList[] = directory.list();
this.list.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, fileList));
this.addView(this.list);
}
/**
* create data directory
*
* @param context
*/
private void createDirectory(Context context) {
directory = new File("/sdcard/."
+ context.getResources().getString(R.string.app_name));
// Erstelle das Unterverzeichnis für die Savegames, falls nötig
if (!directory.isDirectory()) {
directory.mkdir();
}
}
/*
* (non-Javadoc)
*
* @see de.docjunior.gameengine.IGameView#getGameData()
*/
@Override
public Properties getGameData() {
return this.gameData;
}
/*
* (non-Javadoc)
*
* @see de.docjunior.gameengine.IGameView#setGameData(java.util.Properties)
*/
@Override
public void setGameData(Properties data) {
this.gameData = data;
}
/*
* (non-Javadoc)
*
* @see
* de.docjunior.gameengine.IGameView#setViewSetter(de.docjunior.gameengine
* .IViewSetter)
*/
@Override
public void setViewSetter(IViewSetter setter) {
this.setter = setter;
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int item, long arg3) {
this.filename.setText(this.list.getItemAtPosition(item).toString());
}
/**
* gets the created file
* @return
*/
protected File getFile() {
File f = null;
if (!this.filename.getText().equals("")) {
String dir = this.directory.getAbsolutePath();
dir += "/" + this.filename.getText();
dir.replace(" ", "_");
Log.d(getContext().getString(R.string.app_name), "File:" + dir );
f = new File (dir);
}
return f;
}
} Code: public class LoadGame extends FileListView {
/**
* @param context
*/
public LoadGame(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
if (v == this.go) {
InputStream is;
try {
is = new FileInputStream(getFile());
this.gameData.load(is);
this.setter.setView("gameloop");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} Code: public class SaveGame extends FileListView {
/**
* @param context
*/
public SaveGame(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
/*
* (non-Javadoc)
*
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
if (v == this.go) {
OutputStream os;
try {
os = new FileOutputStream(getFile());
this.gameData.store(os, "save game at" + new Date());
this.setter.setView("mainmenu");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} Code: public void setGameData(Properties gameData) {
// TODO Auto-generated method stub
this.gameData = gameData;
if (gameData.isEmpty()) {
InputStream in;
try {
in = getContext().getAssets().open("newgame.properties");
gameData.load(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} Ich hoff, ich hab euch ein wenig was Interessantes erzählen können. Kritik und Anregungen sind wie immer erwünscht. |
| | |
| | #2 (permalink) | |
| Erfahrener Benutzer Registriert seit: 25.06.2009
Beiträge: 212
Abgegebene Danke: 4
Erhielt 13 Danke für 11 Beiträge
| Zitat:
Für Android gibt's auch die Klasse Preference: Preference | Android Developers Sie speichert ihre Daten in einer sqlite Datenbank. Vorteil ist, dass man von überall aus zugreifen kann, ohne sich Gedanken über Dateienamen oder Speicherorte machen zu müssen. Vermutlich ist sie auch ein wenig schneller, da nicht jedesmal ein XML file geladen und geparst werden muss. Man holt sich einfach eine SharedPreferences editor Instanz und kann dann ganz bequem alles reinschreiben. | |
| | |
| | #3 (permalink) |
| Android-Hilfe.de Mitglied Registriert seit: 25.06.2009
Beiträge: 51
Abgegebene Danke: 0
Erhielt 5 Danke für 4 Beiträge
|
ja, aaaber dann kannst du meines Wissens nur einen Spielstand laden. Es muss ja auch nicht xml sein. So, wie's im Code steht, speichert er einfache Schlüssel = Wert - Paar in Textdateien. Ansonsten ists aber auch Auffassungsfrage hab ja gesagt, bin nicht der Weisheit letzter Schluss.Edit: Hab mir gerade die Preferences genauer angeschaut. Sie arbeiten auch über einen XML-Baum, sind aber im Gegensatz zu Properties hierarchisch aufbaubar. Sogar im- und exportieren kann man. Bei komplexeren Daten sicher garnicht so schlecht. Ich kenn halt die Android-API noch nicht soo gut und beschreibe eben auch nur meine Gedankengänge, als JavaSEler Geändert von DocJunioR (16.07.2009 um 12:45 Uhr) |
| | |
| | #4 (permalink) |
| Android Guru Registriert seit: 09.05.2009
Beiträge: 2.389
Abgegebene Danke: 36
Erhielt 307 Danke für 289 Beiträge
|
kleiner tipp: von dateien ist generell abzuraten. ( in sehr seltenen fällen mögen sie ja sinnvoll sein, aber ganz ganz ganz selten ) es gibt diese shared preferences und die sqlite db. die datenbank liegt ja direkt am händy, wodurch der zugriff ja extrem schnell ist ( im vergleich natürlich )
__________________ App Entwicklung Latest apps: Media Streamer BETA | DailyCash | MoneyManager ( PRO | HD ) |
| | |
| | #5 (permalink) |
| Android-Hilfe.de Mitglied Registriert seit: 25.06.2009
Beiträge: 51
Abgegebene Danke: 0
Erhielt 5 Danke für 4 Beiträge
|
naaja, ich weiß nicht, ob es sich wirklich lohnt, für sowas ne datenbank zu entwickeln und eigenlich wird die datei ja nur zum lade- und speicherzeitpunkt angefasst, der rest läuft im ram ab . insofern ist performance eher unkritisch. prinzipiell ist es aber egal, wie persistiert wird. der transport des geschäftsobjekts- wie auch immer dieses aussieht- bleibt gleich ![]() Ich persönlich bleibe vorerst bei dateien. |
| | |
| | #6 (permalink) |
| Android Guru Registriert seit: 09.05.2009
Beiträge: 2.389
Abgegebene Danke: 36
Erhielt 307 Danke für 289 Beiträge
|
ja war auch nur ein hinweis, wie man es in der android welt eher bevorzugen sollte db entwickeln ist dafür schon ein wenig hoch gegriffen einfach eine tabelle mit paar werten und passtaber viele wege führen nach rom , das ist klar
__________________ App Entwicklung Latest apps: Media Streamer BETA | DailyCash | MoneyManager ( PRO | HD ) |
| | |
![]() |
|
| Themen-Optionen | |
| Ansicht | |
| |
| ||||
| Thema | Autor | Forum | Antworten | Letzter Beitrag |
| Die beliebtesten Android Apps aus dem Android Market | philipp_weide | Foto und Multimedia | 290 | 04.09.2011 17:59 |
| Meine Gedanken zur Spieleprogrammierung - Teil 1 - Spielstrukturen | DocJunioR | Android Codeschnipsel | 3 | 16.07.2009 11:31 |
| wo ist meine app im market? | swordi | Android App Entwicklung | 7 | 04.06.2009 13:02 |
| Meine meinung zum G1 | markus90 | Smalltalk und Offtopic | 3 | 21.03.2009 11:52 |