2017-12-18 8 views
0

Wir sind eine Gruppe von Französisch Studenten. Wir entwickeln ein Spiel, das eine Datenbank benötigt. Um den Code zu vereinfachen, verwenden wir LibGdx. Aber es scheint, dass Sugar ORM nicht an die Anwendung gebunden ist. Wir können SugarRecord nicht erweitern.Wie kann ich Sugar ORM in LibGDX implementieren

Ich habe den Code von AndroidManifest.xml und Build.gradle (Modul: Android). Wie können wir das bitte beheben?

EDIT: Wir erstellen unsere Klassen in Android-Ordner. Sugar Orm ist nicht im Kern definiert.

<application 
    android:name="com.orm.SugarApp" 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/GdxTheme"> 
    <meta-data 
     android:name="DATABASE" 
     android:value="AppName.db" /> 
    <meta-data 
     android:name="VERSION" 
     android:value="1" /> 
    <meta-data 
     android:name="QUERY_LOG" 
     android:value="true" /> 
    <meta-data 
     android:name="DOMAIN_PACKAGE_NAME" 
     android:value="com.AppName" /> 

Die build.gradle (Modul: Android):

dependencies { 
    compile 'com.github.satyan:sugar:1.3' 
    //other dependencies 
} 

Vielen Dank!

+0

wie dies scheint, ist, was Sie wollen: https://github.com/ libgdx/libgdx/wiki/Interface-mit-Plattform-spezifischen Code – Arctic45

Antwort

0

Bonjour! Ich werde ein paar Annahmen treffen (korrigiert mich wenn sie falsch sind, und wir werden die Antwort unten verfeinern):

  1. Das Problem ist, dass Sie versuchen, SugarRecord<T> und Compiler/IDE erweitern können Ich sehe diese Klasse nicht.
  2. 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; 
    } 
} 
+0

Danke dir John! Effektiv haben wir nicht viel Zeit! Also, wir reparieren den Code mit Ihrer einfachen Lösung. Tschüss –

Verwandte Themen