Comme vous le savez on peut trié une liste, mais pas une map. Par contre on ne peux placer aucun filtre ni sur l'une ni sur l'autre.
Le langage Sql quant à lui permet tout cela avec une grande facilité, dans cette exemple de petit jeux Atéroide je vous montre comment utilisé un base de données en lieu et place d'une liste.
(Ps: Pour ne pas rendre un code inutilement grand je ne gérè pas les collisions)
Code : Tout sélectionner
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
Code : Tout sélectionner
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