Use Database instead of list

Share your advanced PureBasic knowledge/code with the community.
User avatar
microdevweb
Enthusiast
Enthusiast
Posts: 179
Joined: Fri Jun 13, 2014 9:38 am
Location: Belgique

Use Database instead of list

Post by microdevweb »

My idea come this http://www.purebasic.fr/french/viewtopi ... =1&t=15535 falsam show than use a database in memorys.
As you know, we can sort a list but not a map. However, we can not filter this.
With sql we can make this to easily.

In this sample asteroid game i show you wen use database instead of list.

(Ps: to shorten the code i don't manage the collisions)

Code: Select all

EnableExplicit
UseSQLiteDatabase()
Enumeration 
      #MainForm
      #Ship
      #Bulet
      #Asteroid
      #Db
EndEnumeration
; La structure pour le joueur
Structure player
      X.i
      Y.i
EndStructure
Global myPlayer.player

InitSprite()
InitKeyboard()
OpenWindow(#MainForm,0,0,800,600,"Teste Db",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(#MainForm),0,0,800,600)
; Creation des sprites
;{ Le sprite pour le vaiseau un simple réctangle vert
CreateSprite(#Ship,50,80)
StartDrawing(SpriteOutput(#Ship))
Box(0,0,SpriteWidth(#Ship),SpriteHeight(#Ship),$00FF00)
StopDrawing()
; On place le joueur au centre de l'écran
myPlayer\X=400-(SpriteWidth(#Ship)/2)
myPlayer\Y=580-SpriteHeight(#Ship)
;}
;{ Le sprite pour les bales un simple cercle rouge
Define W=5
CreateSprite(#Bulet,W*2,W*2,#PB_Sprite_AlphaBlending|#PB_Sprite_PixelCollision)
StartDrawing(SpriteOutput(#Bulet))
Circle(W,W,W,$0000FF)
StopDrawing()
;}
;{ Le sprite pour les astéroides un simple cercle bleu
W=15
CreateSprite(#Asteroid,W*2,W*2,#PB_Sprite_AlphaBlending|#PB_Sprite_PixelCollision)
StartDrawing(SpriteOutput(#Asteroid))
Circle(W,W,W,$FFFF00)
StopDrawing()
;}
;{ Création de la base de données en mémoire qui va remplocer nos listes ou nos maps
If OpenDatabase(#Db,":memory:","","")=0
      MessageRequester("DataBase Error","Can not create DataBase")
      End
EndIf
; Création de la table pour nos bales
Define query$
query$="CREATE TABLE bulet ("
query$+"X INTEGER,"
query$+"Y INTEGER"
query$+")"
If DatabaseUpdate(#Db,query$)=0
      MessageRequester("DataBase Error",DatabaseError())
      End
EndIf
; Création de la table pour nos astéroides
Define query$
query$="CREATE TABLE asteroid ("
query$+"X INTEGER,"
query$+"Y INTEGER"
query$+")"
If DatabaseUpdate(#Db,query$)=0
      MessageRequester("DataBase Error",DatabaseError())
      End
EndIf
;}
;{ Ajout de plusieurs astéroides dans la table
Define N
For N=1 To 20
      query$="INSERT INTO asteroid (X,Y) VALUES ("
      query$+Str(Random(800,0))+"," ; La position X dans l'écran
      query$+Str(0-Random(800,0))+")"
      If DatabaseUpdate(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
Next
;}
Define Event
Define TireOn.b=#True
Define TimeElapset
Repeat
      Repeat
            Event=WindowEvent()
            If Event=#PB_Event_CloseWindow :End :EndIf
      Until Event=0
      ; On fait descendre les asteroide
      query$="UPDATE asteroid SET Y=Y+1"
      If DatabaseUpdate(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
      ClearScreen(RGB(0,0,0))
      ; On affiche les astéroides uniquement les visibles
      query$="SELECT * FROM asteroid WHERE Y>=-50"
      If DatabaseQuery(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
      While NextDatabaseRow(#Db)
            DisplayTransparentSprite(#Asteroid,GetDatabaseLong(#Db,0),GetDatabaseLong(#Db,1))
      Wend      
      FinishDatabaseQuery(#Db)
      ; On supprime les astéroides hors écran
      query$="DELETE FROM asteroid WHERE Y>650"
      If DatabaseUpdate(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
      ; On affiche le vaiseau
      DisplaySprite(#Ship,myPlayer\X,myPlayer\Y)
      ; Déplacement du vaiseau
      ExamineKeyboard()
      If KeyboardPushed(#PB_Key_Left) And myPlayer\X>5
            myPlayer\X-5
      EndIf
      If KeyboardPushed(#PB_Key_Right) And myPlayer\X<(795-SpriteWidth(#Ship))
            myPlayer\X+5
      EndIf
      ; Gestion du tir
      If KeyboardPushed(#PB_Key_Space) And  TireOn
            TireOn=#False ;Decative le tir
            TimeElapset=ElapsedMilliseconds(); pour lancer le chrone
            ; On ajoute la bale à la table
            query$="INSERT INTO bulet (X,Y) VALUES ("+Str(myPlayer\X+20)+","
            query$+Str(myPlayer\Y-10)+")"
            If DatabaseUpdate(#Db,query$)=0
                  MessageRequester("DataBase Error",DatabaseError())
                  End
      EndIf
      EndIf
      ; Gestion du chrone
      If Not TireOn
            If (ElapsedMilliseconds()-TimeElapset)>100
                  TireOn=#True
            EndIf
      EndIf
      ; Affichage des bales
      query$="SELECT X,Y FROM bulet ORDER BY Y DESC"
      If DatabaseQuery(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
      While NextDatabaseRow(#Db)
            DisplayTransparentSprite(#Bulet,GetDatabaseLong(#Db,0),GetDatabaseLong(#Db,1))
      Wend  
      FinishDatabaseQuery(#Db)
      ; On fait avancer les bales
       query$="UPDATE bulet SET Y=Y-6"
      If DatabaseUpdate(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
      ; On supprime les bale hors ecran
      query$="DELETE FROM bulet WHERE Y<-10"
      If DatabaseUpdate(#Db,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            End
      EndIf
      FlipBuffers()
ForEver
Use Pb 5.73 lst and Windows 10

my mother-language isn't english, in advance excuse my mistakes.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Use Database instead of list

Post by IdeasVacuum »

Code: Select all

OpenDatabase(#Db,":memory:","","")
That's a great tip, I had no idea it could be so simple. 8)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
microdevweb
Enthusiast
Enthusiast
Posts: 179
Joined: Fri Jun 13, 2014 9:38 am
Location: Belgique

Re: Use Database instead of list

Post by microdevweb »

for complete this post i'm create a procedure for saving the memory Db in file Db

Code: Select all

Procedure SaveDb(IdDb,FileName$)
      Structure column
            Index$
            name$
            type$
            not_nul$
            default_value$
            primaryKey$
      EndStructure
      Structure Table
            name$
            List myColumn.column()
      EndStructure
      Protected NewList myTable.Table()
      Protected query$="Select * From sqlite_master order by type Desc, name Asc"
      Protected Db,IdFile,N
      If DatabaseQuery(IdDb,query$)=0
            MessageRequester("DataBase Error",DatabaseError())
            ProcedureReturn #False
      EndIf
      ; Sauvegarde des tables
      While NextDatabaseRow(IdDb)
            If GetDatabaseString(IdDb,0)="table"
                  AddElement(myTable())
                  With myTable()
                        \name$=GetDatabaseString(IdDb,1)
                  EndWith
            EndIf
      Wend
      FinishDatabaseQuery(IdDb)
      ForEach myTable()
            With myTable()
                  ; Relevé des infos des colonnes des tables
                  query$="PRAGMA table_info('"+\name$+"')"
                  If DatabaseQuery(IdDb,query$)=0
                        MessageRequester("DataBase Error",DatabaseError())
                        ProcedureReturn #False
                  EndIf
                  While NextDatabaseRow(IdDb)
                        AddElement(\myColumn())
                        \myColumn()\Index$=GetDatabaseString(IdDb,0)
                        \myColumn()\name$=GetDatabaseString(IdDb,1)
                        \myColumn()\type$=GetDatabaseString(IdDb,2)
                        \myColumn()\not_nul$=GetDatabaseString(IdDb,3)
                        \myColumn()\default_value$=GetDatabaseString(IdDb,4)
                        \myColumn()\primaryKey$=GetDatabaseString(IdDb,5)
                  Wend
                  FinishDatabaseQuery(IdDb)
            EndWith
      Next
      ; La nouvelle base de donnée
      IdFile=CreateFile(#PB_Any,FileName$)
      If IdFile=0
            MessageRequester("File Error","Can not create file "+FileName$)
            ProcedureReturn #False
      EndIf
      CloseFile(IdFile)
      Db=OpenDatabase(#PB_Any,FileName$,"","")
      If Db=0
            MessageRequester("DataBase Error","Can not open DataBase")
            ProcedureReturn #False
      EndIf
      ; Transfert des donnée
      ForEach myTable()
            With myTable()
                  query$="CREATE TABLE "+\name$+"("
                  N=0
                  ForEach \myColumn()
                        N+1
                        If N>1
                              query$+","
                        EndIf
                        query$+\myColumn()\name$+" "
                        query$+\myColumn()\type$+" "
                        If \myColumn()\not_nul$<>"0"
                              query$+" NOT NULL "
                        EndIf
                        If \myColumn()\primaryKey$="1"
                              query$+ "PRIMARY KEY"
                        EndIf
                  Next
                  query$+")"
                  If DatabaseUpdate(Db,query$)=0
                        MessageRequester("DataBase Error",DatabaseError())
                        ProcedureReturn #False
                  EndIf
            EndWith
      Next
      ForEach myTable()
            With myTable()
                  query$=" SELECT * FROM "+\name$
                  If DatabaseQuery(IdDb,query$)=0
                        MessageRequester("Database Error",DatabaseError())
                        ProcedureReturn #False
                  EndIf
                  While NextDatabaseRow(IdDb)
                        query$="INSERT INTO "+\name$+"("
                        N=0
                        ForEach \myColumn()
                              N+1
                              If N>1
                                    query$+","
                              EndIf
                              query$+\myColumn()\name$
                        Next
                        query$+") VALUES ("
                        For N=0 To DatabaseColumns(IdDb)-1
                              If N>0
                                    query$+","
                              EndIf
                              Select DatabaseColumnType(IdDb,N)
                                    Case #PB_Database_String
                                          query$+"'"+GetDatabaseString(IdDb,N)+"'"
                                    Case #PB_Database_Long
                                          query$+Str(GetDatabaseLong(IdDb,N))
                                    Case #PB_Database_Float
                                          query$+StrF(GetDatabaseFloat(IdDb,N))
                                    Case #PB_Database_Double
                                          query$+StrD(GetDatabaseDouble(IdDb,N))
                                    Case #PB_Database_Quad
                                          query$+Str(GetDatabaseQuad(IdDb,N))
                              EndSelect
                        Next
                        query$+")"
                        If DatabaseUpdate(Db,query$)=0
                              MessageRequester("Database Error",DatabaseError())
                              ProcedureReturn #False
                        EndIf
                  Wend  
            EndWith
      Next
      ProcedureReturn #True
EndProcedure
Use Pb 5.73 lst and Windows 10

my mother-language isn't english, in advance excuse my mistakes.
User avatar
Kiffi
Addict
Addict
Posts: 1504
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Use Database instead of list

Post by Kiffi »

microdevweb wrote:for complete this post i'm create a procedure for saving the memory Db in file Db [...]
You can use this code to save a :memory:-Database to disk: http://www.purebasic.fr/english/viewtop ... 43#p368143

Greetings ... Peter
Hygge
User avatar
microdevweb
Enthusiast
Enthusiast
Posts: 179
Joined: Fri Jun 13, 2014 9:38 am
Location: Belgique

Re: Use Database instead of list

Post by microdevweb »

Thank's Kiffi,

It's vey nice and really more easy, but i'm modified this code look at her

Code: Select all

Procedure.i SQLite_BackupSqliteDatabase(sourceDB, FileName$)
      Protected result, backUp,IdFile,destinationDB
      IdFile=CreateFile(#PB_Any,FileName$)
      If IdFile=0
            MessageRequester("Acces file Error","Can not create this file "+FileName$)
            ProcedureReturn #False
      EndIf
      CloseFile(IdFile)
      destinationDB=OpenDatabase(#PB_Any,FileName$,"","")
      If destinationDB=0
            MessageRequester("DataBase Error","Can not open this DataBase "+FileName$)
            ProcedureReturn #False
      EndIf
      If IsDatabase(sourceDB) And IsDatabase(destinationDB)
            backUp = sqlite3_backup_init(DatabaseID(destinationDB), "main", DatabaseID(sourceDB), "main")
            If backUp
                  sqlite3_backup_step(backUp, -1)
                  If sqlite3_backup_finish(backUp) = 0 ;#SQLITE_OK
                        result = #True   
                  EndIf
            EndIf
      EndIf
      ProcedureReturn result
EndProcedure
Use Pb 5.73 lst and Windows 10

my mother-language isn't english, in advance excuse my mistakes.
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2139
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Use Database instead of list

Post by Andre »

The theme and so the example seems to have the potential to become very useful for me.

Unfortunately it doesn't run properly on my MacOS 10.6.8 - I can only move the green sprite to left/right, but don't see anything else!?
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Use Database instead of list

Post by wilbert »

Andre wrote:Unfortunately it doesn't run properly on my MacOS 10.6.8 - I can only move the green sprite to left/right, but don't see anything else!?
I can confirm this on OSX 10.11 .
I have the impression that there's a bug with the combination of #PB_Sprite_AlphaBlending and DisplayTransparentSprite but am not very familiar with this.
If you are familiar with it, maybe you can check if it really is caused by this and post a bug report if it is.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
microdevweb
Enthusiast
Enthusiast
Posts: 179
Joined: Fri Jun 13, 2014 9:38 am
Location: Belgique

Re: Use Database instead of list

Post by microdevweb »

Hello Andre, wilbert,

Id don't no know why this code don't run with macOs, perhaps macOs don't manage the memorys database, you can try with debuger for see if your variable it's right. But i don't have Mac so i don't try that.
Use Pb 5.73 lst and Windows 10

my mother-language isn't english, in advance excuse my mistakes.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Use Database instead of list

Post by wilbert »

microdevweb wrote:perhaps macOs don't manage the memorys database
That was my initial thought but the database works fine and the coordinates to display the sprites are retrieved properly.
It's just that the sprites aren't visible.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
microdevweb
Enthusiast
Enthusiast
Posts: 179
Joined: Fri Jun 13, 2014 9:38 am
Location: Belgique

Re: Use Database instead of list

Post by microdevweb »

it's amazing... I don't know what for. But the interest of this message it's not for the sprite management, it's main for use the memory Database for another aplication.
Use Pb 5.73 lst and Windows 10

my mother-language isn't english, in advance excuse my mistakes.
Post Reply