Bonjour! Ich werde ein paar Annahmen treffen (korrigiert mich wenn sie falsch sind, und wir werden die Antwort unten verfeinern):
- Das Problem ist, dass Sie versuchen,
SugarRecord<T>
und Compiler/IDE erweitern können Ich sehe diese Klasse nicht.
- Die Klasse Sie versuchen, ist zu haben, zu erweitern
SugarRecord<T>
in core/src/...
befindet, nicht android/src/...
Was ist das Problem?
Wenn Sie Software schreiben (egal, ob es Spiele sind), sollten Sie darauf achten, wie Sie Ihre Software in Teile aufteilen und wie diese Teile interagieren. Insbesondere möchten Sie wissen, wann eine Änderung an einem Teil einen anderen bricht.
Libgdx trennt seinen Code in Teilen auf der Plattform basiert (das ist, warum Sie ein Kern Projekt und eine Desktop Projekt und ein android Projekt). Kern soll den gesamten Code haben, der plattformunabhängig ist (d. H. Das Gleiche, egal ob Sie auf einem PC oder einem mobilen Gerät sind), und Ihre anderen Projekte kümmern sich um plattformspezifische Dinge.
Zucker ORM ist ein Android-spezifische Sache, so dass Sie (richtig) es in Ihre android Gradle Projektabhängigkeiten setzen. Das bedeutet jedoch, dass nur Ihr Code unter dem Ordner android/src
über Sugar ORM bekannt ist und es verwenden kann. Ich bin mir ziemlich sicher, dass das Ihr Problem verursacht. Problem ist, die Klassen, die Sie speichern möchten, sind fast sicher unter core/src
, und sie gehören dort, so wie wir es beheben?
Der einfache Weg
Fix Wenn Sie Ihr Programm nur die Absicht, für immer auf Android zu laufen (und Sie haben einen engen Zeitplan für Ihr Projekt: wink:), können Sie die Abhängigkeit von Ihrem Android gradle Projekt bewegen zu deinem Core-Großprojekt. Dies ermöglicht es Ihnen, diese Klassen überall zu verwenden, aber es wird Probleme geben, wenn Sie versuchen, die Desktop/iOS/HTML-Projekte zu erstellen.
Der richtige Weg
zu beheben, wenn Sie es den Recht Weg (und vielleicht auch beeindrucken Sie Ihren Professor mit Ihren verrückt Codierung Fähigkeiten) beheben wollen, müssen Sie etwas Dependency Injection genannt verwenden. Dependency Injection ist, wenn wir etwas nehmen, das unser Code benötigt, und wir stellen es dem Code zur Laufzeit zur Verfügung. Das bedeutet, wir können im laufenden Betrieb entscheiden, ob wir eine android Datenbank oder eine iOS Datenbank übergeben. Wie @ Arctic45 sagte in den Kommentaren, die libGDX Wiki hat einen kurzen Überblick über diese Technik, aber wir werden ein wenig mehr ins Detail gehen.
Für dieses Beispiel werde ich ein einfaches Spiel mit einem Monster
Klasse zu übernehmen, die etwa wie folgt aussieht:
// Lives in core
public class Monster {
public String name; // prénom
public int hitpoints; // points de dommage
public Monster() {
this.name = "Tim the Unnamed";
this.hitpoints = 1;
}
public Monster(String name, int hitpoints) {
this.name = name;
this.hitpoints = hitpoints;
}
@Override
public String toString() {
return String.format("{name: '%s', hitpoints: %n}", this.name, this.hitpoints);
}
public void attack(Monster other) {
// Game specific logic...
}
}
Nun ist diese eine Datenbank wir wollen in der Lage zu retten, aber wir don Ich weiß nicht, ob es sich um eine Android-Datenbank oder eine iOS-Datenbank oder vielleicht sogar um eine Datenbank handelt, die irgendwo im Web ist (wie Firebase). Wie gehen wir damit um?
Was wir tun, geben wir Kern eine DatabaseWrapper
Schnittstelle. Diese Schnittstelle bietet die Methoden, die wir brauchen, aber nicht, wie sie implementiert sind - es verhält sich wie ein Versprechen. Kern kann planen, diese Methoden zu verwenden, und dann werden wir sie später bereitstellen, sobald wir wissen, auf welcher Plattform wir sind. Hier ist ein Beispiel-Anwendung, unter der diese Technik veranschaulicht:
// Lives in core
// Replace with your application
public class LibGDXTestbed extends ApplicationAdapter {
DatabaseWrapper database;
public LibGDXTestbed() { } // For platforms that don't have databases to inject.
public LibGDXTestbed(DatabaseWrapper database) {
this.database = database;
}
/**
* For demo purposes, add a new randomized monster to the database, then log a list of all the
* monsters created to date.
*/
@Override
public void create() {
if(database != null) {
createMonster();
printMonsters();
} else {
Gdx.app.error("WARNING", "No database provided. Load/Save Functionality Disabled.");
}
}
// Helper method
private void createMonster() {
// Create a set of names we can use for new monsters.
String[] names = {"Fred", "Mary", "Jean", "Tim"};
String randomName = new Array<String>(names).random();
int randomHP = MathUtils.random(100);
database.saveMonster(new Monster(randomName, randomHP));
}
// Helper method
private void printMonsters() {
for(Monster monster : database.getMonsters()) {
Gdx.app.log("DEBUG", monster.toString());
}
}
}
Beachten Sie, dass die oben nichts zu Sugar ORM weiß oder keine Annahmen darüber, wie die Datenbank funktioniert.
Der Wrapper selbst sieht ungefähr so aus:
// Located in core
public interface DatabaseWrapper {
public void saveMonster(Monster monster);
public List<Monster> getMonsters();
}
Nun ist dies ein wenig gekünstelt (und Refactoring könnte mehr generisch sein), aber es zeigt den Punkt.
Als nächstes erstellen wir den Android-spezifischen Code, den wir brauchen, um diese Datenbank zu implementieren. Zuerst werden wir schaffen eine SugarMonster
Klasse, die SugarRecord
erstreckt (da wir mit unseren Kern Monster
Klasse selbst nicht tun wollen, dass):
// Lives in android/src
public class SugarMonster extends SugarRecord<SugarMonster> {
public String name; // prénom
public int hitpoints; // points de dommage
public SugarMonster() {
}
public SugarMonster(Monster monster) {
this.name = monster.name;
this.hitpoints = monster.hitpoints;
}
}
Wir werden auch eine SugarWrapper
Klasse benötigen welche implementiert unsere DatabaseWrapper
Klasse mit Zucker ORM hinter den Kulissen:
// Lives in android/src
public class SugarWrapper implements DatabaseWrapper {
@Override
public void saveMonster(Monster monster) {
SugarMonster data = new SugarMonster(monster);
data.save();
}
@Override
public List<Monster> getMonsters() {
List<SugarMonster> records = SugarMonster.listAll(SugarMonster.class);
ArrayList<Monster> monsters = new ArrayList<>();
for(SugarMonster record : records) {
monsters.add(new Monster(record.name, record.hitpoints));
}
return monsters;
}
}
Schließlich müssen wir unsere AndroidLauncher
Klasse aktualisieren unsere Datenbank-Wrapper injizieren:
// Lives in android/src
public class AndroidLauncher extends AndroidApplication {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new LibGDXTestbed(new SugarWrapper()), config);
}
}
Bonus
Eine andere kühle Sache ist, dass, wenn Sie diese die „richtige“ Art und Weise implementieren, es Optionen ein paar coole Möglichkeiten zum Testen auf.Wenn Sie Unit-Tests gegen Ihren Code schreiben möchten, können Sie eine TestWrapper
schaffen, die DatabaseWrapper
und ahmt die Datenbank-Funktionalität mit statischen Daten implementiert:
public class TestWrapper implements DatabaseWrapper {
List<Monster> monsters;
public TestWrapper() {
this.monsters = new ArrayList<>();
this.monsters.add(new Monster("Tim the Tester", 123));
}
@Override
public void saveMonster(Monster monster) {
this.monsters.add(monster);
}
@Override
public List<Monster> getMonsters() {
return this.monsters;
}
}
wie dies scheint, ist, was Sie wollen: https://github.com/ libgdx/libgdx/wiki/Interface-mit-Plattform-spezifischen Code – Arctic45