2013-04-08 21 views
15

Tôi mới ở Libgdx và tôi đang gặp sự cố khi sử dụng cơ sở dữ liệu trên trò chơi của mình.Sử dụng cơ sở dữ liệu SQLite trong Libgdx

Tôi đã tìm kiếm hướng dẫn về cách làm cho SQLite hoạt động trên cả ứng dụng Android và Máy tính để bàn bằng cách sử dụng Libgdx nhưng tôi không tìm thấy dễ dàng.

Lần cuối cùng tôi sử dụng cơ sở dữ liệu trong Android, tôi đã tạo một lớp mở rộng từ SQLiteOpenHelper.

Có cách nào đơn giản để thực hiện tương tự bằng cách sử dụng Libgdx không? Hoặc ít nhất, bất cứ ai có thể chỉ cho tôi một hướng dẫn từng bước hoặc một cái gì đó tương tự?

EDIT

Tôi quên nói rằng tôi đang tìm kiếm cái gì đó cho tôi quản lý phiên bản như SQLiteOpenHelper. Nói cách khác, tôi muốn tạo lại cơ sở dữ liệu của mình trong Android khi cài đặt apk, khi tôi thay đổi phiên bản DB của mình trên mã.

SOLUTION

Sau @42n4 câu trả lời, tôi được quản lý như thế nào để kết nối với cơ sở dữ liệu SQLite sử dụng SQLiteOpenHelper trên Android Application và JDBC trên Desktop Application.

Trước tiên, tôi đã tạo ra một "lớp học chung" cho cả máy tính để bàn và ứng dụng Android:

//General class that needs to be implemented on Android and Desktop Applications 
public abstract class DataBase { 

    protected static String database_name="recycling_separation"; 
    protected static DataBase instance = null; 
    protected static int version=1; 

    //Runs a sql query like "create". 
    public abstract void execute(String sql); 

    //Identical to execute but returns the number of rows affected (useful for updates) 
    public abstract int executeUpdate(String sql); 

    //Runs a query and returns an Object with all the results of the query. [Result Interface is defined below] 
    public abstract Result query(String sql); 

    public void onCreate(){ 
     //Example of Highscore table code (You should change this for your own DB code creation) 
     execute("CREATE TABLE 'highscores' ('_id' INTEGER PRIMARY KEY NOT NULL , 'name' VARCHAR NOT NULL , 'score' INTEGER NOT NULL);"); 
     execute("INSERT INTO 'highscores'(name,score) values ('Cris',1234)"); 
     //Example of query to get DB data of Highscore table 
     Result q=query("SELECT * FROM 'highscores'"); 
     if (!q.isEmpty()){ 
      q.moveToNext(); 
      System.out.println("Highscore of "+q.getString(q.getColumnIndex("name"))+": "+q.getString(q.getColumnIndex("score"))); 
     } 
    } 

    public void onUpgrade(){ 
     //Example code (You should change this for your own DB code) 
     execute("DROP TABLE IF EXISTS 'highscores';"); 
     onCreate(); 
     System.out.println("DB Upgrade maded because I changed DataBase.version on code"); 
    } 

    //Interface to be implemented on both Android and Desktop Applications 
    public interface Result{ 
     public boolean isEmpty(); 
     public boolean moveToNext(); 
     public int getColumnIndex(String name); 
     public float getFloat(int columnIndex); 
     [...] 
    } 
} 

Sau đó, tôi đã tạo ra một lớp DatabaseDesktop cho Desktop Application:

public class DatabaseDesktop extends DataBase{ 
    protected Connection db_connection; 
    protected Statement stmt; 
    protected boolean nodatabase=false; 

    public DatabaseDesktop() { 
     loadDatabase(); 
     if (isNewDatabase()){ 
      onCreate(); 
      upgradeVersion(); 
     } else if (isVersionDifferent()){ 
      onUpgrade(); 
      upgradeVersion(); 
     } 

    } 

    public void execute(String sql){ 
     try { 
      stmt.execute(sql); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 

    public int executeUpdate(String sql){ 
     try { 
      return stmt.executeUpdate(sql); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
     return 0; 
    } 

    public Result query(String sql) { 
     try { 
      return new ResultDesktop(stmt.executeQuery(sql)); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    private void loadDatabase(){ 
     File file = new File (database_name+".db"); 
     if(!file.exists()) 
      nodatabase=true; 
     try { 
      Class.forName("org.sqlite.JDBC"); 
      db_connection = DriverManager.getConnection("jdbc:sqlite:"+database_name+".db"); 
      stmt = db_connection.createStatement(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void upgradeVersion() { 
     execute("PRAGMA user_version="+version); 
    } 

    private boolean isNewDatabase() { 
     return nodatabase; 
    } 

    private boolean isVersionDifferent(){ 
     Result q=query("PRAGMA user_version"); 
     if (!q.isEmpty()) 
      return (q.getInt(1)!=version); 
     else 
      return true; 
    } 

    public class ResultDesktop implements Result{ 

     ResultSet res; 
     boolean called_is_empty=false; 

     public ResultDesktop(ResultSet res) { 
      this.res = res; 
     } 

     public boolean isEmpty() { 
      try { 
       if (res.getRow()==0){ 
        called_is_empty=true; 
        return !res.next(); 
       } 
       return res.getRow()==0; 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
      return false; 
     } 

     public boolean moveToNext() { 
      try { 
       if (called_is_empty){ 
        called_is_empty=false; 
        return true; 
       } else 
        return res.next(); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
      return false; 
     } 

     public int getColumnIndex(String name) { 
      try { 
       return res.findColumn(name); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
      return 0; 
     } 

     public float getFloat(int columnIndex) { 
      try { 
       return res.getFloat(columnIndex); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
      return 0; 
     } 

     [...] 

    } 

} 

Và một DatabaseAndroid dành cho Android Ứng dụng

public class DatabaseAndroid extends DataBase{ 
    protected SQLiteOpenHelper db_connection; 
    protected SQLiteDatabase stmt; 

    public DatabaseAndroid(Context context) { 
     db_connection = new AndroidDB(context, database_name, null, version); 
     stmt=db_connection.getWritableDatabase(); 
    } 

    public void execute(String sql){ 
     stmt.execSQL(sql); 
    } 

    public int executeUpdate(String sql){ 
     stmt.execSQL(sql); 
     SQLiteStatement tmp = stmt.compileStatement("SELECT CHANGES()"); 
     return (int) tmp.simpleQueryForLong(); 
    } 

    public Result query(String sql) { 
     ResultAndroid result=new ResultAndroid(stmt.rawQuery(sql,null)); 
     return result; 
    } 

    class AndroidDB extends SQLiteOpenHelper { 

     public AndroidDB(Context context, String name, CursorFactory factory, 
       int version) { 
      super(context, name, factory, version); 
     } 

     public void onCreate(SQLiteDatabase db) { 
      stmt=db; 
      DatabaseAndroid.this.onCreate(); 
     } 

     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      stmt=db; 
      DatabaseAndroid.this.onUpgrade(); 
     } 

    } 

    public class ResultAndroid implements Result{ 
     Cursor cursor; 

     public ResultAndroid(Cursor cursor) { 
      this.cursor=cursor; 
     } 

     public boolean isEmpty() { 
      return cursor.getCount()==0; 
     } 

     public int getColumnIndex(String name) { 
      return cursor.getColumnIndex(name); 
     } 

     public String[] getColumnNames() { 
      return cursor.getColumnNames(); 
     } 

     public float getFloat(int columnIndex) { 
      return cursor.getFloat(columnIndex); 
     } 

     [...] 

    } 

} 

Cuối cùng, tôi là cha nged các lớp chính của cả Android và máy tính để bàn Ứng dụng:

public class Main extends AndroidApplication { 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     initialize(new MyGame(new DatabaseAndroid(this.getBaseContext())), false); 
    } 
} 

public class Main { 

    public static void main(String[] args) { 
     new LwjglApplication(new MyGame(new DatabaseDesktop()), "Example", MyGame.SCREEN_WIDTH, MyGame.SCREEN_HEIGHT,false); 
    } 

} 

Lưu ý rằng:

tôi đã thực hiện một quản lý phiên bản như một trong đó xảy ra trong SQLiteOpenHelper sử dụng PRAGMA user_version. Bằng cách này, tôi chỉ thay đổi phiên bản của lớp DataBase khi tôi cần nâng cấp nó.

Tôi đã không đặt tất cả các phương pháp mà tôi đã thực hiện trên Result nhưng, tôi đặt những cái mà tôi cho rằng quan trọng hơn. Điều đó quan trọng hơn.

Trả lời

3

http://marakana.com/techtv/android_bootcamp_screencast_series.html Class 4, Phần 1: Android Bootcamp - statusData, cho libgdx: http://code.google.com/p/libgdx-users/wiki/SQLite

EDIT: tôi nên đề cập đến khoảng hai khóa học mới về trò chơi libgdx tại Udacity: https://github.com/udacity/ud405

https://github.com/udacity/ud406

+0

Vì vậy, cho cả Android và máy tính để bàn, tôi tạo ra một lớp có tên 'StatusData' phải không? Trong Android, tôi có thể sử dụng 'SQLiteOpenHelper' như tôi đã sử dụng trước đây. Nhưng còn ứng dụng Desktop thì sao? Làm thế nào tôi có thể, ví dụ, làm cho ứng dụng Desktop tạo lại DB khi phiên bản DB thay đổi trên 'StatusData'? –

+0

Có lẽ nó sẽ giúp: http://code.google.com/p/libgdx-users/wiki/SQLite – 42n4

+0

Vì vậy, chỉ cần rõ ràng, tôi có thể sử dụng 'SQLiteOpenHelper' trên Android và trong Desktop tôi có thể thực hiện tương tự điều sử dụng 'JDBC' và cả hai đều được tạo ra trên một lớp có tên là' StatusData' hoặc một cái gì đó tương tự. Đúng? –

6

Có một phần mở rộng (được gọi là gdx-sqlite) mà tôi đã viết sẽ thực hiện hầu hết công việc bạn yêu cầu. Bạn có thể tải xuống phiên bản mới nhất của tiện ích mở rộng này từ here.Mã nguồn và đọc tôi được đặt tại: https://github.com/mrafayaleem/gdx-sqlite

Tiện ích này hiện hỗ trợ nền tảng Android và Máy tính để bàn. Ngoài ra, không có hỗ trợ để mở cơ sở dữ liệu nằm trong thư mục tài sản của ứng dụng Android. Tuy nhiên, đây là một tính năng đang chờ xử lý và sẽ sớm được bổ sung.

Làm theo hướng dẫn trong đọc cho tôi để thiết lập các dự án của bạn để xử lý cơ sở dữ liệu. Sau đây là một ví dụ mã:

package com.mrafayaleem.gdxsqlitetest; 

import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.sql.Database; 
import com.badlogic.gdx.sql.DatabaseCursor; 
import com.badlogic.gdx.sql.DatabaseFactory; 
import com.badlogic.gdx.sql.SQLiteGdxException; 

public class DatabaseTest { 

    Database dbHandler; 

    public static final String TABLE_COMMENTS = "comments"; 
    public static final String COLUMN_ID = "_id"; 
    public static final String COLUMN_COMMENT = "comment"; 

    private static final String DATABASE_NAME = "comments.db"; 
    private static final int DATABASE_VERSION = 1; 

    // Database creation sql statement 
    private static final String DATABASE_CREATE = "create table if not exists " 
      + TABLE_COMMENTS + "(" + COLUMN_ID 
      + " integer primary key autoincrement, " + COLUMN_COMMENT 
      + " text not null);"; 

    public DatabaseTest() { 
     Gdx.app.log("DatabaseTest", "creation started"); 
     dbHandler = DatabaseFactory.getNewDatabase(DATABASE_NAME, 
       DATABASE_VERSION, DATABASE_CREATE, null); 

     dbHandler.setupDatabase(); 
     try { 
      dbHandler.openOrCreateDatabase(); 
      dbHandler.execSQL(DATABASE_CREATE); 
     } catch (SQLiteGdxException e) { 
      e.printStackTrace(); 
     } 

     Gdx.app.log("DatabaseTest", "created successfully"); 

     try { 
      dbHandler 
        .execSQL("INSERT INTO comments ('comment') VALUES ('This is a test comment')"); 
     } catch (SQLiteGdxException e) { 
      e.printStackTrace(); 
     } 

     DatabaseCursor cursor = null; 

     try { 
      cursor = dbHandler.rawQuery("SELECT * FROM comments"); 
     } catch (SQLiteGdxException e) { 
      e.printStackTrace(); 
     } 
     while (cursor.next()) { 
      Gdx.app.log("FromDb", String.valueOf(cursor.getString(1))); 
     } 

     try { 
      dbHandler.closeDatabase(); 
     } catch (SQLiteGdxException e) { 
      e.printStackTrace(); 
     } 
     dbHandler = null; 
     Gdx.app.log("DatabaseTest", "dispose"); 
    } 
}