Voici donc le code initial de défilement 2D suffisamment fluide pour s'amuser.
Mode emploi: appuyez sur les 4 touches de direction.
Tout est modifiable à volonté. S'il y a des difficultés à trouver où est-ce qu'on doit faire une modif pour voir autre chose que des briques dans le noir, n'hésitez pas à poser vos questions...
Donc, vous créez ou importez vos propres sprites (en français, on appelle ça un lutin). Pour le premier code, il n'y a qu'un seul tableau qui stocke tout le décor. Je crois qu'il s'appelle Tile(x,y) où vous mettez le n° du sprite et zoup la boucle principale ici présente digère le défilement sans broncher un yota. J'adore les codes souples donc beaucoup de paramètres sont modifiables mais je n'ai pas mis beaucoup de commentaires donc il faut y aller piano pour savoir à quoi correspond chaque variable. Je tiens à préciser que la quasi-totalité des variables sont des entiers donc attention aux réglages. J'ai, depuis fait un code avec flottants, c'est plus souple mais là le code est trop compliqué pour poster la machine à gaz.
Les paramètres principaux que je vous suggère de modifier sont la vitesse de défilement, la taille d'un tile (lutin, morceau carré ou sprite élémentaire dans le décor), la taille du décor lui-même. En ce qui concerne la taille du décor, vous pouvez y aller, ça supporte un bon décor bien immense: ça dépend de votre mémoire vive.
Il y a quatre macros à invoquer pour les quatre directions de défilement (MoveUp, MoveLeft, MoveDown et MoveRight). Elles peuvent être invoquées simultanément pour fusionner des mouvements circulaires ou diagonaux. Regardez juste la boucle principale pour comprendre leur fonctionnement. Pour "téléporter" (=passer d'un endroit du décor à un autre endroit), il doit y avoir une macro qui se charge de mettre à jour les quatre page d'affichage.
Bon, je vous fais l'explication à l'envers (comme d'hab) mais en gros, on ne voit jamais que quatre pages à l'écran qui sont modifiées en permanence en fonctions des mouvements demandés. Ce process permet un défilement toujours régulier qu'il y ait ou non un décor chargé. Pour le parallaxe double plan, il y a huit pages. ça commence alors à prendre pas de mémoire vidéo. Si on veut plus de plans en parallaxe
(3 plans, 4 plans ou plus...), on ne peut plus user de cette méthode: il faut alors afficher directement les tiles du décor à l'écran mais le rendu est moins fluide et régulier.
Pour le parallaxe (le deuxième code plus bas), il y a un second tableau pour stocker le décor: P2Tile(x,y). Exactement le même principe que le premier tableau sans distinction de sprite d'avant-plan et d'arrière plan.
A noter que pour le premier plan en parallaxe, la couleur rgb(0,0,0) (#Black) est transparente.
Bonne bourre!
Code : Tout sélectionner
EnableExplicit
Macro Display()
; Message = ""
; Message + ""
; Message + Str(PageTileW) + " ; "
; ClearScreen(0)
;UseBuffer(#DispMask)
DisplaySprite(Page0, DispX1 + PosX, DispY1 + PosY)
DisplaySprite(Page1, DispX1 + PosX - PageW, DispY1 + PosY)
DisplaySprite(Page2, DispX1 + PosX, DispY1 + PosY - PageH)
DisplaySprite(Page3, DispX1 + PosX - PageW, DispY1 + PosY - PageH)
;UseBuffer(-1)
; DisplayTransparentSprite(#DispMask, DispX1, DispY1)
; StartDrawing(ScreenOutput() )
; DrawText(0, 0, Message)
; StopDrawing()
FlipBuffers()
EndMacro
Macro SpriteDrawing()
For I = 0 To 3
CreateSprite(#Syst + I, 16, 16)
StartDrawing(SpriteOutput(#Syst + I) )
DrawText(0, 0, "P" + Str(I) )
StopDrawing()
Next I
CreateSprite(#Deco, TileSize, TileSize)
StartDrawing(SpriteOutput(#Deco) )
Box(0, 0, TileSize, TileSize, 0)
StopDrawing()
CreateSprite(#Deco + 1, TileSize, TileSize)
StartDrawing(SpriteOutput(#Deco + 1) )
Box(0, 0, TileSize, TileSize, 1)
Box(1, 1, TileSize - 2, TileSize - 2, #Gray)
Line(0, 0, TileSize, TileSize, 1)
Line(TileSize - 1, 0, - TileSize, TileSize, 1)
StopDrawing()
CreateSprite(#DispMask, DispW, DispH)
StartDrawing(SpriteOutput(#DispMask) )
Box(0, 0, DispW, DispH, #White)
Box(1, 1, DispW - 2, DispH - 2, #Black)
StopDrawing()
For I = 0 To 3
CreateSprite(I, PageW, PageH)
UseBuffer(I)
For Y = 0 To PageH - 1
For X = 0 To PageW - 1
DisplaySprite(#Deco + 1, X, Y)
X + TileSize ; Remplace le step
X - 1 ; Idem
Next X
Y + TileSize ; Remplace le Step
Y - 1 ; Idem
Next Y
X = PageW - SpriteWidth(#Syst + I)
Y = PageH - SpriteHeight(#Syst + I)
DisplaySprite(#Syst + I, 0, 0)
DisplaySprite(#Syst + I, X, 0)
DisplaySprite(#Syst + I, 0, Y)
DisplaySprite(#Syst + I, X, Y)
UseBuffer(#PB_Default)
Next I
EndMacro
Macro LevelLoading()
For Y = 0 To LevelTileMaxY
For X = 0 To LevelTileMaxX
Tile(X, Y) = #Deco
Next X
Next Y
For Y = 0 To LevelTileMaxY
Tile(0, Y) = #Deco + 1
Tile(LevelTileMaxX, Y) = #Deco + 1
For X = 0 To LevelTileMaxX
Tile(X, 0) = #Deco + 1
Tile(X, LevelTileMaxY) = #Deco + 1
If Random(9) = 0
Tile(X, Y) = #Deco + 1
EndIf
Next X
Next Y
EndMacro
Macro GetPageNo(X, Y) ; Calcul de la page concernée
((X / PageW) & 1) + (((Y / PageH) & 1) << 1)
EndMacro
Macro GetXValue(X) ; Calcul de X dans la page
((X % PageW) - (X % TileSize) )
EndMacro
Macro GetYValue(Y) ; Calcul de Y dans la page
((Y % PageH) - (Y % TileSize) )
EndMacro
Macro GetTile(XX, YY)
Tile = -1
TempX = XX / TileSize
If (TempX => 0)
If (TempX <= LevelTileMaxX)
TempY = YY / TileSize
If (TempY => 0)
If (TempY <= LevelTileMaxY)
Tile = Tile(TempX, TempY)
EndIf
EndIf
EndIf
EndIf
EndMacro
Macro UpdateTile(XX, YY)
GetTile(XX, YY) ; Retourne le global Tile.I
If Tile <> -1
P = GetPageNo(XX, YY)
UseBuffer(P)
DisplaySprite(Tile, GetXValue(XX), GetYValue(YY) )
UseBuffer(-1)
EndIf
EndMacro
Macro UpdateTileLeftBorder()
For Y = (LevelY - TileSize) To (LevelY + PageH + TileSize) ; Rajouté +TileSize
UpdateTile((LevelX - TileSize), Y)
Y + TileSize
Y - 1
Next Y
EndMacro
Macro UpdateTileRightBorder()
For Y = (LevelY - TileSize) To (LevelY + PageH) ; Rajouté -TileSize
UpdateTile((LevelX + PageW), Y)
Y + TileSize
Y - 1
Next Y
EndMacro
Macro UpdateTileUpBorder()
For X = (LevelX - TileSize) To (LevelX + PageW + TileSize) ; Rajouté +TileSize
UpdateTile(X, (LevelY - TileSize) )
X + TileSize
X - 1
Next X
EndMacro
Macro UpdateTileDownBorder()
For X = (LevelX - TileSize) To (LevelX + PageW) ;Rajouté -TileSize
UpdateTile(X, (LevelY + PageH) )
X + TileSize
X - 1
Next X
EndMacro
Macro DrawVisibleTiles()
For Y = LevelY To LevelY + PageH
For X = LevelX To LevelX + PageW
UpdateTile(X, Y)
X + TileSize
X - 1
Next X
Y + TileSize
Y - 1
Next Y
EndMacro
Macro MoveLeft()
If LevelX > 0
If LevelX - VitX < 0 ; "Sort" du niveau?
VitX = LevelX
EndIf
PosX + VitX
If PosX => PageW
ShiftX + PageW
PosX - PageW
Page0 ! 1
Page1 ! 1
Page2 ! 1
Page3 ! 1
EndIf
LevelX = 0 - (ShiftX + PosX)
OldLevelTileX = LevelTileX
LevelTileX = LevelX / TileSize
If LevelTileX <> OldLevelTileX
UpdateTileLeftBorder()
EndIf
DisplayFlag = 1
EndIf
EndMacro
Macro MoveRight()
If LevelX < (LevelW - DispW)
If LevelX + VitX > (LevelW - DispW) ; "Sort" du niveau?
VitX = (LevelW - DispW) - LevelX
EndIf
PosX - VitX
If PosX < 0
ShiftX - PageW
PosX + PageW
Page0 ! 1
Page1 ! 1
Page2 ! 1
Page3 ! 1
EndIf
LevelX = 0 - (ShiftX + PosX)
OldLevelTileX = LevelTileX
LevelTileX = LevelX / TileSize
If LevelTileX <> OldLevelTileX
UpdateTileRightBorder()
EndIf
DisplayFlag = 1
EndIf
EndMacro
Macro MoveUp()
If LevelY > 0
If LevelY - VitY < 0 ; "Sort" du niveau?
VitY = LevelY
EndIf
PosY + VitY
If PosY => PageH
ShiftY + PageH
PosY - PageH
Page0 ! 2
Page1 ! 2
Page2 ! 2
Page3 ! 2
EndIf
LevelY = 0 - (ShiftY + PosY)
OldLevelTileY = LevelTileY
LevelTileY = LevelY / TileSize
If LevelTileY <> OldLevelTileY
UpdateTileUpBorder()
EndIf
DisplayFlag = 1
EndIf
EndMacro
Macro MoveDown()
If LevelY < (LevelH - DispH)
If LevelY + VitY > (LevelH - DispH) ; "Sort" du niveau?
VitY = (LevelH - DispH) - LevelY
EndIf
PosY - VitY
If PosY < 0
ShiftY - PageH
PosY + PageH
Page0 ! 2
Page1 ! 2
Page2 ! 2
Page3 ! 2
EndIf
LevelY = 0 - (ShiftY + PosY)
OldLevelTileY = LevelTileY
LevelTileY = LevelY / TileSize
If LevelTileY <> OldLevelTileY
UpdateTileDownBorder()
EndIf
DisplayFlag = 1
EndIf
EndMacro
#Syst = 4096
#DispMask = 16
#Deco = 256
;-______________
;- Globals...
;-¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Global TileSize.I ; Taille d'un Tile en pixels
Global ScrW.I ; Largeur de l'écran en pixels
Global ScrH.I ; Hauteur de l'écran en pixels
Global ScrD.I ; Profondeur de l'écran en bits par pixels
Global DispX1.I ; Coordonnée de la zone d'affichage
Global DispY1.I ; en pixels
Global DispX2.I ;
Global DispY2.I ;
Global DispW.I ; Dimensions de l'écran d'affichage
Global DispH.I ; en pixels
Global PageW.I ; Dimensions d'une page en pixels
Global PageH.I ;
Global PageTileW.I ; Dimensions d'une page en Tiles
Global PageTileH.I ;
Global I.I
Global P.I
Global X.I
Global Y.I
Global Tile.I
Global TempX.I
Global TempY.I
Global Message.S
Global Page0.I = 0
Global Page1.I = 1
Global Page2.I = 2
Global Page3.I = 3
;-Vitesse
Global Vit.I = 8
Global PosX.I ; Décalage dans une page
Global PosY.I ; en pixels
Global ShiftX.I ; Décalage page par page
Global ShiftY.I ; en pixels
Global LevelX.I ; Décalage total (page + position)
Global LevelY.I ; en pixels
Global LevelTileX.I ; Décalage total (page + position)
Global LevelTileY.I ; en Tiles
Global OldLevelTileX.I ; Dans la détection des mises à jour
Global OldLevelTileY.I ; Ancien décalage total en Tiles
Global LevelTileW.I ; Dimensions du niveau en Tiles
Global LevelTileH.I ;
Global LevelTileMaxX.I ; Limites du niveau en Tiles
Global LevelTileMaxY.I ;
Global LevelW.I ; Dimensions du niveau en pixels
Global LevelH.I ;
Global DisplayFlag.I
Global VitX.I
Global VitY.I
Global VitesseX.I
Global VitesseY.I
Global QuitGame.I
TileSize = 24
LevelTileW = 256
LevelTileH = 256
LevelW = LevelTileW * TileSize
LevelH = LevelTileH * TileSize
LevelTileMaxX = LevelTileW - 1
LevelTileMaxY = LevelTileH - 1
Global Dim Tile.I(LevelTileMaxX, LevelTileMaxY)
Delay(99)
InitSprite()
InitKeyboard()
ExamineDesktops()
ScrW = DesktopWidth(0)
ScrH = DesktopHeight(0)
ScrD = DesktopDepth(0)
DispX1 = 0
DispY1 = 0
DispX2 = ScrW - 1
DispY2 = ScrH - 1
DispW = (DispX2 - DispX1) + 1
DispH = (DispY2 - DispY1) + 1
PageW = DispW
PageH = DispH
PageW - (PageW % TileSize)
If PageW < DispW: PageW + TileSize: EndIf
PageH - (PageH % TileSize)
If PageH < DispH: PageH + TileSize: EndIf
PageTileW = PageW / TileSize
PageTileH = PageH / TileSize
OpenScreen(ScrW, ScrH, ScrD, "")
SpriteDrawing()
LevelLoading()
DrawVisibleTiles()
Display()
;-______________
;- Repeat...
;-¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Repeat
;Delay(99)
Delay(1)
DisplayFlag = 0
VitX = Vit
VitY = Vit
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
If (VitesseX - 2) > (0 - TileSize)
VitesseX - 2
EndIf
EndIf
If KeyboardPushed(#PB_Key_Right)
If (VitesseX + 2) < TileSize
VitesseX + 2
EndIf
EndIf
If KeyboardPushed(#PB_Key_Up)
If (VitesseY - 2) > (0 - TileSize)
VitesseY - 2
EndIf
EndIf
If KeyboardPushed(#PB_Key_Down)
If (VitesseY + 2) < TileSize
VitesseY + 2
EndIf
EndIf
If KeyboardPushed(#PB_Key_Escape)
QuitGame = 1
EndIf
EndIf
If VitesseX < 0
VitX = -VitesseX
MoveLeft()
VitesseX + 1
EndIf
If VitesseX > 0
VitX = VitesseX
MoveRight()
VitesseX - 1
EndIf
If VitesseY < 0
VitY = -VitesseY
MoveUp()
VitesseY + 1
EndIf
If VitesseY > 0
VitY = VitesseY
MoveDown()
VitesseY - 1
EndIf
If DisplayFlag
Display()
EndIf
Until QuitGame
CloseScreen()
End