Pour une app dans ce genre, j'utiliserais plutot un tableau qu'une liste chainée car on connait le nombre de cases qui sont de tailles et d'espacement constants donc il est très simple de trouver la case sur laquelle est le crayon sans avoir à toute les tester.
J'utiliserais simplement WindowMouseX/Y() aussi plutot que MouseX/Y() ce qui faciliterai le passage screen <-> window
Je te fais un exemple en vitesse, mais c'est juste comment je verais la chose, libre à toi de programmer comme tu le veux
Code : Tout sélectionner
;----------------
;- Window Constants
;
Enumeration
#Fenetre
EndEnumeration
;- MenuBar Constants
;
Enumeration
#MenuBar_0
EndEnumeration
Enumeration
#MENU_OUVRIR
#MENU_SAUVEGARDE
#MENU_QUITTER
#MENU_JEU
#MENU_CONSTRUCTION
#MENU_ABOUT
EndEnumeration
;- Gadget Constants
;
Enumeration
#Text_Largeur
#Spin_Largeur
#Text_Mode
#Text_Longueur
#Spin_Longueur
#Frame3D_0
EndEnumeration
;- StatusBar Constants
;
Enumeration
#StatusBar_0
EndEnumeration
;- Sprites Constants
;
Enumeration
#Fond
#Grille
#Indication_Horiz
#Indication_Vert
#Crayon
#Cross
EndEnumeration
;- Autres Constants
#Max_Cross = 10 ; nombre maxi de cases
;----------------
;- Structures
;----------------
Structure Cross
x.f ; stocke position en x
y.f ; stocke position en y
Sprite.b ; stocke le sprite
EndStructure
;- Declarations globales
;
Global Dim Cross.Cross(#Max_Cross, #Max_Cross) ; tableau des cases
Global MaxCrossX.l, MaxCrossY.l ; nombre maxi de cases en x/y de la partie en cour (ne pas confondre avec le nombre maxi de case d'une partie en général)
Global CrayonX.l, CrayonY.l ; stock la position du crayon
Global CrayonCrossX.l, CrayonCrossY.l ; Stock la cases sur laquelle est le crayon
Global SwitchCursor.b ; va nous permetre d'afficher / cacher le curseur seulement s'il y a besoin et non à chaque boucle
Declare.b Generer_Cross()
;- Initialistions
;
InitSprite()
InitSprite3D()
SwitchCursor = #True
MaxCrossX = 5 : MaxCrossY = 5 ; nombre de cases de la premieres partie à 5x5
; On génère le premier tableau
Generer_Cross()
;- Creation fenetre / gadgets / ecran
;
OpenWindow(#Fenetre, 0, 0, 622, 522, "Exemple cases", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateMenu(#MenuBar_0, WindowID(#Fenetre))
MenuTitle("Fichier")
MenuItem(#MENU_OUVRIR, "Ouvrir un Purecross")
MenuItem(#MENU_SAUVEGARDE, "Sauvegarder un Purecross")
MenuBar()
MenuItem(#MENU_QUITTER, "Quitter")
MenuTitle("Mode")
MenuItem(#MENU_JEU, "Mode Jeu")
MenuItem(#MENU_CONSTRUCTION, "Mode Construction")
MenuTitle("Aide")
MenuItem(#MENU_ABOUT, "A propos de PureCross ")
EndIf
If CreateStatusBar(#StatusBar_0, WindowID(#Fenetre))
AddStatusBarField(180)
StatusBarText(#StatusBar_0, 0, "Purecross par Hackotedelaplaque")
EndIf
If CreateGadgetList(WindowID(#Fenetre))
TextGadget(#Text_Largeur, 430, 100, 130, 20, "Largeur du PureCross : ")
SpinGadget(#Spin_Largeur, 570, 100, 40, 20, 5, 20,#PB_Spin_ReadOnly | #PB_Spin_Numeric)
SetGadgetState(#Spin_Largeur, MaxCrossX)
TextGadget(#Text_Mode, 0, 20, 630, 30, "Mode construction", #PB_Text_Center)
SetGadgetFont(#Text_Mode, FontID1)
SetGadgetColor(#TEXT_MODE,#PB_Gadget_FrontColor,RGB(0, 0, 255))
TextGadget(#Text_Longueur, 430, 160, 120, 20, "Longueur du PureCross :")
SpinGadget(#Spin_Longueur, 570, 160, 40, 20, 5, 20,#PB_Spin_ReadOnly | #PB_Spin_Numeric)
SetGadgetState(#Spin_Longueur, MaxCrossY)
Frame3DGadget(#Frame3D_0, 420, 50, 200, 420, "Paramètres du PureCross")
EndIf
OpenWindowedScreen(WindowID(#Fenetre), 5, 70, 400, 400, 0, 0, 0)
;- Chargement / creation sprites
; On peut très bien utiliser le même identifiant pour un sprite normal et un sprite3D
UsePNGImageDecoder()
TransparentSpriteColor(#PB_Default, RGB(255, 0, 255))
LoadSprite(#Fond, "back.png")
LoadSprite(#Grille, "case_vierge.png", #PB_Sprite_Texture)
LoadSprite(#Cross, "cross.png", #PB_Sprite_Texture)
LoadSprite(#Crayon, "crayon.png", #PB_Sprite_Texture)
CreateSprite(#Indication_Horiz, 92, 12,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(#Indication_Horiz))
Box(0, 0, 92, 12,RGB(157, 255, 98))
Line(0, 0, 92, 0,RGB(91, 199, 107))
StopDrawing()
CreateSprite(#Indication_Vert, 12, 92, #PB_Sprite_Texture)
StartDrawing(SpriteOutput(#Indication_Vert))
Box(0, 0, 12, 92,RGB(0, 0, 255))
Line(0, 0, 0, 92,RGB(2, 2, 153))
StopDrawing()
;- Sprites3D
CreateSprite3D(#Grille, #Grille)
CreateSprite3D(#Cross, #Cross)
CreateSprite3D(#Indication_Horiz, #Indication_Horiz)
CreateSprite3D(#Indication_Vert, #Indication_Vert)
CreateSprite3D(#Crayon, #Crayon)
Repeat
; On recupère la position du crayon sur l'ecran (sur la fenetre on s'en fou un peut...)
CrayonX = WindowMouseX(0) - 5
CrayonY = WindowMouseY(0) - 70
; On verifi que les positions restent dans l'écran
If CrayonX < 0 : CrayonX = 0 : EndIf
If CrayonX > 400 : CrayonX = 400 : EndIf
If CrayonY < 0 : CrayonY = 0 : EndIf
If CrayonY > 400 : CrayonY = 400 : EndIf
; On calcul sur quelle case est le crayon
CrayonCrossX = Round((CrayonX - 200) / 12 + MaxCrossX / 2, 1) - 1
CrayonCrossY = Round((CrayonY - 200) / 12 + MaxCrossY / 2, 1) - 1
; on verifi qu'il sagit bien d'une case du tableau sinon on met à -1 ce qui permetre de ne pas change une case qui "n'existe" pas
If CrayonCrossX < 0 : CrayonCrossX = -1 : EndIf
If CrayonCrossX > MaxCrossX -1 : CrayonCrossX = -1 : EndIf
If CrayonCrossY < 0 : CrayonCrossY = -1 : EndIf
If CrayonCrossY > MaxCrossY -1 : CrayonCrossY = -1 : EndIf
; Si le curseur est dans l'écran, on le cache
CursorInScreen = WindowMouseX(0) >= 5 And WindowMouseX(0) <= 405 And WindowMouseY(0) >= 70 And WindowMouseY(0) <= 470
If CursorInScreen And SwitchCursor = #True
ShowCursor_(#False)
SwitchCursor = #False
ElseIf Not CursorInScreen And SwitchCursor = #False
ShowCursor_(#True)
SwitchCursor = #True
EndIf
;- Evenements sur la fenetre
;
wEvent = WindowEvent()
If wEvent ; S'il y a un evenement
Repeat ; Il peut y en avoir donc un boucle pour ne pas en perdre
Select wEvent
Case #WM_CLOSE ; La croix a été clikée
Quit = #True
Case #PB_Event_Gadget
Select EventGadget()
Case #Spin_Largeur
; on verifi que le nombre de cases n'est pas supérieur à #Max_Cross
If GetGadgetState(#Spin_Largeur) > #Max_Cross : SetGadgetState(#Spin_Largeur, #Max_Cross) : EndIf
MaxCrossX = GetGadgetState(#Spin_Largeur)
; on recreer le tableau
Generer_Cross()
Case #Spin_Longueur
; on verifi que le nombre de cases n'est pas supérieur à #Max_Cross
If GetGadgetState(#Spin_Longueur) > #Max_Cross : SetGadgetState(#Spin_Longueur, #Max_Cross) : EndIf
MaxCrossY = GetGadgetState(#Spin_Longueur)
; on recreer le tableau
Generer_Cross()
EndSelect
Case #WM_LBUTTONUP ; Si le bouton droit est relacher sur une case, on la change si ce n'est pas -1, -1
If CrayonCrossX > -1 And CrayonCrossY > -1
Cross(CrayonCrossX, CrayonCrossY)\Sprite = #Cross
EndIf
EndSelect
wEvent = WindowEvent() ; On regarde s'il y a un autre evenement
Until wEvent = #Null ; Sinon on sort
EndIf
;- Dessin sur l'écran
;
; Affichage du fond
DisplaySprite(#Fond, 0, 0)
Start3D() ; Surtout appeler Start3D() avant les boucle quand on est sur d'afficher que des sprite3d, ça evite les appels inutiles
; Affichage du tableau
For y = 0 To MaxCrossY - 1
For x = 0 To MaxCrossX - 1
; affichage des cases
DisplaySprite3D(Cross(x, y)\Sprite, Cross(x, y)\x, Cross(x, y)\y, 125)
Next
Next
; Affichage du crayon s'il est dans l'écran
If CursorInScreen
DisplaySprite3D(#Crayon,CrayonX, CrayonY, 220)
EndIf
Stop3D()
FlipBuffers()
Until Quit = #True
;- Procedures
;
Procedure.b Generer_Cross()
For y = 0 To MaxCrossY - 1
For x = 0 To MaxCrossX - 1
Cross(x, y)\Sprite = #Grille
; on calcul la postion en x/y de la case
Cross(x, y)\x = 200 + ((x - MaxCrossX / 2) * 12)
Cross(x, y)\y = 200 + ((y - MaxCrossY / 2) * 12)
Next
Next
EndProcedure
J'ai essayé de commenté les points "délicats" mais si tu as des questions, n'hesites pas
Et encor une foi, je ne dis pas qu'il faut faire comme ça absolument, je te montre juste comment je ferais