Défilement 2D (Smooth Scrolling) avec ou sans parallaxe

Partagez votre expérience de PureBasic avec les autres utilisateurs.
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Ollivier a écrit :Ta modif sème le doute chez moi. Je me demande si le problème de gourmandise en ressources de ClearScreen() n'est pas devenu une histoire ancienne sur la version 4.31...
puisque cette commande n'est pas utilisée pour la 3D, autant prendre de bonnes habitudes avec la 2D( même chose avec le delay).

De plus, l'utilisation de sprite3D induit forcément que la machine doit avoir un GPU pas trop naze...
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

Bon, c'est mon tour de faire subir les derniers outrages au code d'Ollivier.:wink:

Sur le principe de base, je n'ai rien changé. J'ai juste modifié un petit truc qui me gênait, à savoir: pour chaque plan de scrolling, il fallait copier/coller toutes les macros; ça marchait bien, c'était super-rapide, mais à lire et à maintenir, je trouvais ça un peu lourd.

=> dans ma version, il y a une seule "instance" des macros, quel que soit le nombre de layers.
Ces derniers sont stockés dans une liste structurée, ce qui permet d'en ajouter facilement avec un addElement. Le premier de la liste (n°0) est opaque et constitue le fond, les suivants sont transparents et sont affichés par ordre de création.
Cela fait probablement perdre un peu de temps à l'exécution, mais pas trop, je pense (PB est rapide sur les listes).

Ah, pis j'ai aussi ajouté la possibilité d'avoir des tiles rectangulaires et de tailles différentes d'un layer sur l'autre.

Dernière chose: il y a une constante #USESPRITE3D au début, pour utiliser ou non les sprites 3D (ça ne concerne que les 4 grands sprites "pages" de chaque layers). Sur mon PC de test, c'est plutôt plus lent, mais c'est un GPU bureautique alors c'est sans doute normal.

Voilà, je vous laisse tester:

Code : Tout sélectionner

EnableExplicit
#USESPRITE3D = #False
#MAXLAYERS = 3        ; modifiez cette valeur si vous voulez avoir plus de layers
#MAXLEVELSIZEX = 255  ; modifiez cette valeur et celle du dessous
#MAXLEVELSIZEY = 255  ; si vous voulez avoir des niveaux plus grands


;- **** Code générique Scrolling ****
; (tout ce code pourrait être sorti dans un include)

; Structure utilisée par les layers (= "plans de scrolling")
Structure layer_struct
  numlayer.i  ; ordre: le layer 0 est le fond (non transparent), les suivants viennent par dessus

  ; Taille des tiles
  tileSizeX.i ; largeur en pixels
  tileSizeY.i ; hauteur en pixels
  
  ; N° des 4 sprites de la taille de l'écran (= pages) nécessaires au scrolling
  page0.i
  page1.i
  page2.i
  page3.i
  firstPage.i ; n° de la première de ces pages (utilisé dans updateTile)
  
  ; Dimensions d'une page
  PageW.i     ; largeur en pixels
  PageH.i     ; hauteur en pixels
  PageTileW.i ; largeur en Tiles
  PageTileH.i ; hauteur en Tiles
  
  ; Dimensions du niveau
  LevelW.i      ; largeur en pixels
  LevelH.i      ; hauteur en pixels 
  LevelTileW.i  ; largeur en Tiles
  LevelTileH.i  ; hauteur en Tiles
  
  LevelTileMaxX.i ; Limites du niveau en Tiles
  LevelTileMaxY.i ;
  
  PosX.i ; Décalage dans une page
  PosY.i ; en pixels
  
  ShiftX.i ; Décalage page par page
  ShiftY.i ; en pixels
  
  LevelX.i     ; Décalage total (page + position)
  LevelY.i     ; en pixels
  LevelTileX.i ; Décalage total (page + position)
  LevelTileY.i ; en Tiles
  
  OldLevelTileX.i ; Dans la détection des mises à jour
  OldLevelTileY.i ; Ancien décalage total en Tiles

  ; Vitesse de déplacement du layer  
  vitRatio.f  ; ratio par rapport au layer du premier-plan (ex: 2 => le layer se déplace 2x moins vite)
  VitX.i      ; vitesse horizontale
  VitY.i      ; vitesse horizontale
  
EndStructure

; Variables globales utilisées par les macro de scrolling
Global P.i
Global X.i
Global Y.i
Global Tile.i
Global TempX.i
Global TempY.i
Global DisplayFlag.b


; Liste des layers
Global NewList tileLayer.layer_struct()

; Voici LE truc qui m'embête: ce tableau aurait logiquement dû être dans la structure ci-dessus, 
; et changer de taille pour chaque layer (en fonction des dimensions du layer et des tiles de ce layer).
; Ce serait possible en utilisant juste une zone mémoire plutôt qu'un tableau, mais ça demande un ou deux
; calculs de plus et c'est moins facile à lire...
Global Dim tile.i(#MAXLAYERS-1,#MAXLEVELSIZEX,#MAXLEVELSIZEY)


; Cette procédure ajoute un layer de scrolling à la liste et en initialise les variables
; Note: c'est une procédure plutôt qu'une macro, car ça n'a pas besoin d'être hyper-rapide
Procedure.i createLayer(dispW.i,dispH.i,TileW.i,TileH.i,speedRatio.f,LevelTileW.i,LevelTileH.i)
  Protected numLayer.i
  
  ; Déterminer le n° du nouveau layer
  If ListSize(tileLayer()) > 0
    LastElement(tileLayer())
    numLayer = tileLayer()\numlayer + 1
  EndIf

  ; Ajout d'un layer dans la liste
  AddElement(tileLayer())
  tileLayer()\numlayer = numLayer
  tileLayer()\TileSizeX = TileW
  tileLayer()\TileSizeY = TileH
  tileLayer()\vitRatio = speedRatio
  tileLayer()\LevelTileW = LevelTileW
  tileLayer()\LevelTileH = LevelTileH
  
  
  ; Calculs faits préalablement pour ne pas perdre de temps à les refaire en cours d'exécution
  tileLayer()\LevelW = tileLayer()\LevelTileW * tileLayer()\TileSizeX
  tileLayer()\LevelH = tileLayer()\LevelTileH * tileLayer()\TileSizeY
  tileLayer()\LevelTileMaxX = tileLayer()\LevelTileW - 1
  tileLayer()\LevelTileMaxY = tileLayer()\LevelTileH - 1
  
  tileLayer()\PageW = DispW
  tileLayer()\PageW - (tileLayer()\PageW % tileLayer()\TileSizeX)
  If tileLayer()\PageW < DispW
    tileLayer()\PageW + tileLayer()\TileSizeX
  EndIf
  
  tileLayer()\PageH = DispH
  tileLayer()\PageH - (tileLayer()\PageH % tileLayer()\TileSizeY)
  If tileLayer()\PageH < DispH
    tileLayer()\PageH + tileLayer()\TileSizeY
  EndIf
  
  tileLayer()\PageTileW = tileLayer()\PageW / tileLayer()\TileSizeX
  tileLayer()\PageTileH = tileLayer()\PageH / tileLayer()\TileSizeY
  
  ProcedureReturn tileLayer()\numlayer
EndProcedure


; Cette procédure initialise les 4 pages nécessaires à chaque layer de scroll
; Note: c'est une procédure plutôt qu'une macro, car ça n'a pas besoin d'être hyper-rapide
Procedure initScrollPages()
  Protected i.i,numpage.i = 0
  
  ; Pour chaque layer, créer 4 pages pour le scrolling
  ForEach tilelayer()
    tilelayer()\firstpage = numpage
    tilelayer()\page0 = numpage
    tilelayer()\page1 = numpage+1
    tilelayer()\page2 = numpage+2
    tilelayer()\page3 = numpage+3

    For i = 0 To 3
      CompilerIf #USESPRITE3D = #True      
        CreateSprite(numpage, tilelayer()\PageW, tilelayer()\PageH, #PB_Sprite_Texture)
        CreateSprite3D(numpage, numpage)
      CompilerElse
        CreateSprite(numpage, tilelayer()\PageW, tilelayer()\PageH)
      CompilerEndIf
      
      numpage+1
    Next i
    
  Next tilelayer()
EndProcedure


Macro GetPageNo(X, Y) ; Calcul de la page concernée
  ((X / tileLayer()\PageW) & 1) + (((Y / tileLayer()\PageH) & 1) << 1)
EndMacro

Macro GetXValue(X) ; Calcul de X dans la page
  ((X % tileLayer()\PageW) - (X % tileLayer()\TileSizeX) )
EndMacro

Macro GetYValue(Y) ; Calcul de Y dans la page
  ((Y % tileLayer()\PageH) - (Y % tileLayer()\TileSizeY) )
EndMacro

Macro GetTile(XX, YY)
  Tile = -1
  TempX = XX / tileLayer()\TileSizeX
  If (TempX => 0)
    If (TempX <= tileLayer()\LevelTileMaxX)
      TempY = YY / tileLayer()\TileSizeY
      If (TempY => 0)
        If (TempY <= tileLayer()\LevelTileMaxY)
          Tile = Tile(tileLayer()\numLayer, 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 + tileLayer()\firstPage)
      DisplaySprite(Tile, GetXValue(XX), GetYValue(YY) )
    UseBuffer(-1)
  EndIf
EndMacro

Macro UpdateTileLeftBorder()
  For Y = (tileLayer()\LevelY - tileLayer()\TileSizeY) To (tileLayer()\LevelY + tileLayer()\PageH + tileLayer()\TileSizeY) ; Rajouté +TileSize
    UpdateTile((tileLayer()\LevelX - tileLayer()\TileSizeY), Y)
    Y + tileLayer()\TileSizeY
    Y - 1
  Next Y
EndMacro

Macro UpdateTileRightBorder()
  For Y = (tileLayer()\LevelY - tileLayer()\TileSizeY) To (tileLayer()\LevelY + tileLayer()\PageH) ; Rajouté -TileSize
    UpdateTile((tileLayer()\LevelX + tileLayer()\PageW), Y)
    Y + tileLayer()\TileSizeY
    Y - 1
  Next Y
EndMacro

Macro UpdateTileUpBorder()
  For X = (tileLayer()\LevelX - tileLayer()\TileSizeX) To (tileLayer()\LevelX + tileLayer()\PageW + tileLayer()\TileSizeX) ; Rajouté +TileSize
    UpdateTile(X, (tileLayer()\LevelY - tileLayer()\TileSizeX) )
    X + tileLayer()\TileSizeX
    X - 1
  Next X
EndMacro

Macro UpdateTileDownBorder()
  For X = (tileLayer()\LevelX - tileLayer()\TileSizeX) To (tileLayer()\LevelX + tileLayer()\PageW) ;Rajouté -TileSize
    UpdateTile(X, (tileLayer()\LevelY + tileLayer()\PageH) )
    X + tileLayer()\TileSizeX
    X - 1
  Next X
EndMacro


Macro DrawVisibleTiles()
  For Y = tileLayer()\LevelY To tileLayer()\LevelY + tileLayer()\PageH
    For X = tileLayer()\LevelX To tileLayer()\LevelX + tileLayer()\PageW
      UpdateTile(X, Y)
      X + tileLayer()\TileSizeX
      X - 1
    Next X
    Y + tileLayer()\TileSizeY
    Y - 1
  Next Y
EndMacro


Macro MoveLeft()
  If tileLayer()\LevelX > 0
    If tileLayer()\LevelX - tileLayer()\VitX < 0 ; "Sort" du niveau?
      tileLayer()\VitX = tileLayer()\LevelX
    EndIf               
    tileLayer()\PosX + tileLayer()\VitX
    If tileLayer()\PosX => tileLayer()\PageW
      tileLayer()\ShiftX + tileLayer()\PageW
      tileLayer()\PosX - tileLayer()\PageW
      tileLayer()\Page0 ! 1
      tileLayer()\Page1 ! 1
      tileLayer()\Page2 ! 1
      tileLayer()\Page3 ! 1
    EndIf
    tileLayer()\LevelX = 0 - (tileLayer()\ShiftX + tileLayer()\PosX)
    tileLayer()\OldLevelTileX = tileLayer()\LevelTileX
    tileLayer()\LevelTileX = tileLayer()\LevelX / tileLayer()\TileSizeX
    If tileLayer()\LevelTileX <> tileLayer()\OldLevelTileX
      UpdateTileLeftBorder()
    EndIf
    DisplayFlag = #True
  EndIf   
EndMacro

Macro MoveRight()
  If tileLayer()\LevelX < (tileLayer()\LevelW - tileLayer()\PageW)
    If tileLayer()\LevelX + tileLayer()\VitX > (tileLayer()\LevelW - tileLayer()\PageW) ; "Sort" du niveau?
      tileLayer()\VitX = (tileLayer()\LevelW - tileLayer()\PageW) - tileLayer()\LevelX
    EndIf
    tileLayer()\PosX - tileLayer()\VitX
    If tileLayer()\PosX < 0
      tileLayer()\ShiftX - tileLayer()\PageW
      tileLayer()\PosX + tileLayer()\PageW
      tileLayer()\Page0 ! 1
      tileLayer()\Page1 ! 1
      tileLayer()\Page2 ! 1
      tileLayer()\Page3 ! 1
    EndIf
    tileLayer()\LevelX = 0 - (tileLayer()\ShiftX + tileLayer()\PosX)
    tileLayer()\OldLevelTileX = tileLayer()\LevelTileX
    tileLayer()\LevelTileX = tileLayer()\LevelX / tileLayer()\TileSizeX
    If tileLayer()\LevelTileX <> tileLayer()\OldLevelTileX
      UpdateTileRightBorder()
    EndIf
    DisplayFlag = #True
  EndIf
EndMacro

Macro MoveUp()
  If tileLayer()\LevelY > 0
    If tileLayer()\LevelY - tileLayer()\VitY < 0 ; "Sort" du niveau?
      tileLayer()\VitY = tileLayer()\LevelY
    EndIf
    tileLayer()\PosY + tileLayer()\VitY
    If tileLayer()\PosY => tileLayer()\PageH
      tileLayer()\ShiftY + tileLayer()\PageH
      tileLayer()\PosY - tileLayer()\PageH
      tileLayer()\Page0 ! 2
      tileLayer()\Page1 ! 2
      tileLayer()\Page2 ! 2
      tileLayer()\Page3 ! 2
    EndIf
    tileLayer()\LevelY = 0 - (tileLayer()\ShiftY + tileLayer()\PosY)
    tileLayer()\OldLevelTileY = tileLayer()\LevelTileY
    tileLayer()\LevelTileY = tileLayer()\LevelY / tileLayer()\TileSizeY
    If tileLayer()\LevelTileY <> tileLayer()\OldLevelTileY
      UpdateTileUpBorder()
    EndIf
    DisplayFlag = #True
  EndIf
EndMacro

Macro MoveDown()
  If tileLayer()\LevelY < (tileLayer()\LevelH - tileLayer()\PageH)
    If tileLayer()\LevelY + tileLayer()\VitY > (tileLayer()\LevelH - tileLayer()\PageH) ; "Sort" du niveau?
      tileLayer()\VitY = (tileLayer()\LevelH - tileLayer()\PageH) - tileLayer()\LevelY
    EndIf
    tileLayer()\PosY - tileLayer()\VitY
    If tileLayer()\PosY < 0
      tileLayer()\ShiftY - tileLayer()\PageH
      tileLayer()\PosY + tileLayer()\PageH
      tileLayer()\Page0 ! 2
      tileLayer()\Page1 ! 2
      tileLayer()\Page2 ! 2
      tileLayer()\Page3 ! 2
    EndIf
    tileLayer()\LevelY = 0 - (tileLayer()\ShiftY + tileLayer()\PosY)
    tileLayer()\OldLevelTileY = tileLayer()\LevelTileY
    tileLayer()\LevelTileY = tileLayer()\LevelY / tileLayer()\TileSizeY
    If tileLayer()\LevelTileY <> tileLayer()\OldLevelTileY
      UpdateTileDownBorder()
    EndIf
    DisplayFlag = #True
  EndIf
EndMacro

Macro Move(moveX,moveY)

  ForEach tileLayer()
  
    If moveX < 0
      tileLayer()\VitX = -(moveX) / tileLayer()\vitRatio
      MoveLeft()
    Else
      If moveX > 0
        tileLayer()\VitX = (moveX) / tileLayer()\vitRatio
        MoveRight()
      EndIf
    EndIf
    
    If moveY < 0
      tileLayer()\VitY = -(moveY) / tileLayer()\vitRatio
      MoveUp()
    Else
      If moveY > 0
        tileLayer()\VitY = (moveY) / tileLayer()\vitRatio 
        MoveDown()
      EndIf
    EndIf 
    
  Next tileLayer()

EndMacro


Macro Display()
  
  CompilerIf #USESPRITE3D = #True      
    Start3D() 
      DisplaySprite3D(tileLayer()\Page0, tileLayer()\PosX, tileLayer()\PosY)
      DisplaySprite3D(tileLayer()\Page1, tileLayer()\PosX - tileLayer()\PageW, tileLayer()\PosY)
      DisplaySprite3D(tileLayer()\Page2, tileLayer()\PosX, tileLayer()\PosY - tileLayer()\PageH)
      DisplaySprite3D(tileLayer()\Page3, tileLayer()\PosX - tileLayer()\PageW, tileLayer()\PosY - tileLayer()\PageH)
    Stop3D()
  CompilerElse
    If tileLayer()\numlayer = 0
      DisplaySprite(tileLayer()\Page0, tileLayer()\PosX, tileLayer()\PosY)
      DisplaySprite(tileLayer()\Page1, tileLayer()\PosX - tileLayer()\PageW, tileLayer()\PosY)
      DisplaySprite(tileLayer()\Page2, tileLayer()\PosX, tileLayer()\PosY - tileLayer()\PageH)
      DisplaySprite(tileLayer()\Page3, tileLayer()\PosX - tileLayer()\PageW, tileLayer()\PosY - tileLayer()\PageH)   
    Else
      DisplayTransparentSprite(tileLayer()\Page0, tileLayer()\PosX, tileLayer()\PosY)
      DisplayTransparentSprite(tileLayer()\Page1, tileLayer()\PosX - tileLayer()\PageW, tileLayer()\PosY)
      DisplayTransparentSprite(tileLayer()\Page2, tileLayer()\PosX, tileLayer()\PosY - tileLayer()\PageH)
      DisplayTransparentSprite(tileLayer()\Page3, tileLayer()\PosX - tileLayer()\PageW, tileLayer()\PosY - tileLayer()\PageH)
    EndIf
  CompilerEndIf
  
EndMacro


;- **** Fin du code générique ****
;-

#DECO=1000
; Création de sprites pour l'exemple
Procedure spriteDrawing()

   ; sprites de l'arrière-plan
   FirstElement(tileLayer())
   CreateSprite(#DECO, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(1,1,1))
   StopDrawing()
   CreateSprite(#DECO+1, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+1) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(127,0,0))
   StopDrawing()
   CreateSprite(#DECO+2, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+2) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(0,127,0))
   StopDrawing()
   CreateSprite(#DECO+3, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+3) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(0,0,127))
   StopDrawing()
    
   ; sprites du layer 1
   NextElement(tileLayer())
   CreateSprite(#DECO+10, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+10) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(0,0,0))
   StopDrawing()
   
   CreateSprite(#DECO+11, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+11) )
      Circle(tileLayer()\TileSizeX/2,tileLayer()\TileSizeY/2,tileLayer()\TileSizeX/2,$777777)
      Circle(tileLayer()\TileSizeX/2-1,tileLayer()\TileSizeY/2-1,tileLayer()\TileSizeX/2-2,$AAAAAA)
      Circle(tileLayer()\TileSizeX/2-3,tileLayer()\TileSizeY/2-3,tileLayer()\TileSizeX/2-6,$BBBBBB)
      Circle(tileLayer()\TileSizeX/2-6,tileLayer()\TileSizeY/2-6,tileLayer()\TileSizeX/2-12,$CCCCCC)
   StopDrawing()
    
   ; sprites du premier plan
   NextElement(tileLayer())
   CreateSprite(#DECO+4, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+4) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(0,0,0))
   StopDrawing()
   CreateSprite(#DECO+5, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+5) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(255,0,0))
   StopDrawing()
   CreateSprite(#DECO+6, tileLayer()\TileSizeX, TileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+6) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(0,255,0))
   StopDrawing()
   CreateSprite(#DECO+7, tileLayer()\TileSizeX, tileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+7) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(255,255,0))
   StopDrawing()
   CreateSprite(#DECO+8, tileLayer()\TileSizeX, TileLayer()\TileSizeY)
   StartDrawing( SpriteOutput(#DECO+8) )
      Box(0, 0, tileLayer()\TileSizeX, tileLayer()\TileSizeY, RGB(0,0,255))
   StopDrawing()
   
EndProcedure

; Création d'un niveau "en dur" (sans Data) pour l'exemple
Procedure levelLoading()
  Protected x.i,y.i
  Protected EmptySprite.i, nbSprites.i

  ; Layer d'arrière-plan
  FirstElement(tileLayer())
  EmptySprite = #DECO ; <= sprite "couleur de fond" pour ce layer
  nbSprites = 3       ; <= Nb de sprites (autre que le "vide") pour ce layer
  
  ; Vider le layer
  For Y = 0 To tileLayer()\LevelTileMaxY
    For X = 0 To tileLayer()\LevelTileMaxX
      Tile(tileLayer()\numLayer, X,Y) = EmptySprite
    Next X
  Next Y
  
  ; Pour le test, mettre des briques au hasard à l'intérieur
  For Y = 0 To tileLayer()\LevelTileMaxY
    For X = 0 To tileLayer()\LevelTileMaxX
      If Random(9) = 0
        Tile(tileLayer()\numLayer, X,Y) = EmptySprite+1 + Random(nbSprites-1)
      EndIf
    Next X
  Next Y

  ; Layer suivant
  NextElement(tileLayer())
  For Y = 0 To tileLayer()\LevelTileMaxY
    For X = 0 To tileLayer()\LevelTileMaxX
      Tile(tileLayer()\numLayer, X,Y) = #DECO+10
    Next X
  Next Y  
  For Y = 0 To tileLayer()\LevelTileMaxY
    For X = 0 To tileLayer()\LevelTileMaxX
       If Random(19) = 0
        Tile(tileLayer()\numLayer, X,Y) = #DECO+11
      EndIf
    Next X
  Next Y
  
  ; Layer du premier-plan
  NextElement(tileLayer())
  EmptySprite = #DECO+4 ; <= sprite "couleur de fond" pour ce layer
  nbSprites = 4         ; <= Nb de sprites (autre que le "vide") pour ce layer
  
  ; Vider le layer
  For Y = 0 To tileLayer()\LevelTileMaxY
    For X = 0 To tileLayer()\LevelTileMaxX
      Tile(tileLayer()\numLayer, X,Y) = EmptySprite
    Next X
  Next Y
  
  ; Pour le test, dessiner les bords du niveau et mettre des briques au hasard à l'intérieur
  For Y = 0 To tileLayer()\LevelTileMaxY
    Tile(tileLayer()\numLayer, 0, Y) = EmptySprite+1
    Tile(tileLayer()\numLayer, tileLayer()\LevelTileMaxX, Y) = EmptySprite+1
    For X = 0 To tileLayer()\LevelTileMaxX
      Tile(tileLayer()\numLayer, X, 0) = EmptySprite+1
      Tile(tileLayer()\numLayer, X, tileLayer()\LevelTileMaxY) = EmptySprite+1
      If Random(19) = 0
        Tile(tileLayer()\numLayer, X,Y) = EmptySprite+1 + Random(nbSprites-1)
      EndIf
    Next X
  Next Y

EndProcedure

;-______________
;- Globals...   
;-¯¯¯¯¯¯¯¯¯¯¯¯¯¯

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 maxSpeed.i = 24
Global VitesseX.i
Global VitesseY.i

Global QuitGame.i
Global num_frames.i,fps.i,lst_second.i

Delay(99)

;- Initialisation système
InitSprite()
InitKeyboard()
CompilerIf #USESPRITE3D = #True      
  InitSprite3D()
  Sprite3DQuality(#PB_Sprite3D_NoFiltering) 
CompilerEndIf

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

OpenScreen(ScrW, ScrH, ScrD, "")

;- Initialisation du scrolling, chargement des sprites et des niveaux
; Arrière-plan: gros blocs sombres
createLayer(dispW,dispH,48,32,2,80,128)
; Layer 1: boules
createLayer(dispW,dispH,64,64,1.5,72,72)
; Layer 2: petits carrés
createLayer(dispW,dispH,24,24,1,256,256)

; Création des pages de scroll (4 par layers)
initScrollPages()

; Pour le test, on dessine quelques sprites et niveaux
spriteDrawing()
levelLoading()

; Affichage initial du décor
ForEach tileLayer()
  DrawVisibleTiles()
  Display()  
Next tileLayer()
FlipBuffers()

;-______________
;- Repeat...   
;-¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  Repeat
    Delay(1)
    DisplayFlag = 0
   
    ; Récupérer l'action de l'utilisateur
    If ExamineKeyboard()
    
      If KeyboardPushed(#PB_Key_Left)        
        If (VitesseX - 2) > -maxSpeed
          VitesseX - 2
        EndIf
      EndIf
      If KeyboardPushed(#PB_Key_Right)
        If (VitesseX + 2) < maxSpeed
          VitesseX + 2
        EndIf
      EndIf
      If KeyboardPushed(#PB_Key_Up)
        If (VitesseY - 2) > -maxSpeed
          VitesseY - 2
        EndIf
      EndIf
      If KeyboardPushed(#PB_Key_Down)
        If (VitesseY + 2) < maxSpeed
          VitesseY + 2
        EndIf
      EndIf
      If KeyboardPushed(#PB_Key_Escape)
          QuitGame = 1
      EndIf
    EndIf
    
    ; La vitesse décroît progressivement (comme si on avait de l'élan), sauf si on rencontre le bord du niveau
    LastElement(tileLayer()) ; on teste le layer de premier plan: c'est lui qui conditionne le mouvement des autres
    If VitesseX < 0
      If tileLayer()\LevelX + VitesseX < 0
        VitesseX = -tileLayer()\LevelX
      Else
        VitesseX+1
      EndIf
    EndIf
    If VitesseX > 0
      If tileLayer()\LevelX + VitesseX > (tileLayer()\LevelW - tileLayer()\PageW)
        VitesseX = (tileLayer()\LevelW - tileLayer()\PageW) - tileLayer()\LevelX
      Else
        VitesseX-1
      EndIf
    EndIf
    If VitesseY < 0
      If tileLayer()\LevelY + VitesseY < 0
        VitesseY = -tileLayer()\LevelY
      Else
        VitesseY+1
      EndIf
    EndIf
    If VitesseY > 0
      If tileLayer()\LevelY + VitesseY > (tileLayer()\LevelH - tileLayer()\PageH)
        VitesseY = (tileLayer()\LevelH - tileLayer()\PageH) - tileLayer()\LevelY
      Else
        VitesseY-1
      EndIf
    EndIf
    
    ; Faire bouger le scrolling
    Move(VitesseX,VitesseY)
    
    ; Si un déplacement a eu lieu, on réaffiche les pages
    If DisplayFlag
      ForEach tileLayer()
        Display()
      Next tileLayer()
     
      ; Ce petit bout de code mesure et affiche les FPS
      num_frames+1 
      If ElapsedMilliseconds()-lst_second>=1000 
        fps=num_frames 
        num_frames=0 
        lst_second=ElapsedMilliseconds() 
      EndIf   
      StartDrawing(ScreenOutput())
      DrawText(5,5,Str(fps))
      StopDrawing()      
      
      ; Inverse les buffers
      FlipBuffers(#PB_Screen_NoSynchronization)  ; pas de synchro, sinon les FPS sont au maximum égaux à la fréquence de rafraîchissement du moniteur
    Else
      lst_second=ElapsedMilliseconds() 
      num_frames=0
    EndIf
    
    
  Until QuitGame
  
  CloseScreen()
  End
 
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

Sous Linux avec la 4.40 B1 et B2, ca ne fonctionne plus chez moi, je post le bug dans le fofo :wink:
Répondre