; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* #file scrollengine.pbi #;************************************************************************ #; Scroll Engine for PureBasic v1.0 #; Code from Ollivier (july 2009) #; Modified for use with TileStudio by Kelebrindae (August 2009) #;************************************************************************ EnableExplicit #;- Constants ##USESPRITE3D = #False #; Bound structure (if Bit 7 = 0): #; Bit 0: Upper bound #; Bit 1: Left bound #; Bit 2: Lower bound #; Bit 3: Right bound ##BOUNDBIT_UP = 1 ##BOUNDBIT_LEFT = 2 ##BOUNDBIT_DOWN = 4 ##BOUNDBIT_RIGHT = 8 #;- Structure des séquences ( = tiles animées) Structure SCROLL_sequence_struct numLayer.i ; layer auquel appartient la séquence numSequence.i ; n° identifiant la séquence nbFrames.i ; longueur totale currentFrame.l ; n° frame actuel *ptrFrames.l ; Zone mémoire pour stocker la liste des frames *ptrCurrentFrame.l ; adresse de la frame courante *ptrLastFrame.l ; adresse de la dernière frame (après celle-ci, on revient au début de la séquence) EndStructure #;- Structure utilisée par les layers Structure SCROLL_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 ; ; Position dans le niveau PosX.i ; Décalage dans une page PosY.i ; en pixels PosXreal.f ; idem en float pour gérer les vitesses à virgule PosYreal.f ; ex: plan 1 se déplace à 1, arrière-plan se déplace à 0.75 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 SequenceShiftX.i ; Décalage des Tiles par rapport SequenceShiftY.i ; coords 0,0 de l'écran , en pixels (pour afficher les tiles animées) ; Vitesse de déplacement du layer vitRatioX.f ; ratios par rapport au layer du premier-plan (ex: 2 => le layer se déplace 2x moins vite) vitRatioY.f VitX.f ; vitesse horizontale VitY.f ; vitesse horizontale ; N° du premier et dernier sprite du layer (pour pouvoir les libérer) numFirstSprite.i numLastSprite.i ; Liste des pointeurs vers les séquences du niveau (256 maximum) *ptrListSequences.SCROLL_sequence_struct[256] ; Stockage des données du niveau *ptrLevelMap.w ; zone mémoire contenant un tableau(x,y) des tiles du layer levelLineSizeByte.i ; pour accélerer un peu les calculs. = largeur niveau en tiles * taille d'un .w en octets (càd 2) *ptrLevelBounds.b ; zone mémoire contenant un tableau(x,y) des "bords" des tiles *ptrLevelSequences.b ; zone mémoire contenant un tableau(x,y) des séquences du layer ( = tiles animées) EndStructure #;- Variables globales du Scrolling Global SCROLL_P.i Global SCROLL_Tile.i Global SCROLL_X.i, SCROLL_Y.i Global SCROLL_TempX.i,SCROLL_TempY.i Global SCROLL_seqX.i,SCROLL_seqY.i,SCROLL_seqTile.b Global SCROLL_DisplayFlag.b #; Liste des layers Global NewList SCROLL_layer.SCROLL_layer_struct() #; Liste des séquences Global NewList SCROLL_sequence.SCROLL_sequence_struct() #; 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 SCROLL_createLayer(numLayer.i,dispW.i,dispH.i,TileW.i,TileH.i,speedRatioX.f,speedRatioY.f,LevelTileW.i,LevelTileH.i) ; Ajout d'un layer dans la liste AddElement(SCROLL_layer()) SCROLL_layer()\\numlayer = numLayer SCROLL_layer()\\TileSizeX = TileW SCROLL_layer()\\TileSizeY = TileH SCROLL_layer()\\vitRatioX = speedRatioX SCROLL_layer()\\vitRatioY = speedRatioY SCROLL_layer()\\LevelTileW = LevelTileW SCROLL_layer()\\LevelTileH = LevelTileH ; Calculs faits préalablement pour ne pas perdre de temps à les refaire en cours d'exécution SCROLL_layer()\\LevelW = SCROLL_layer()\\LevelTileW * SCROLL_layer()\\TileSizeX SCROLL_layer()\\LevelH = SCROLL_layer()\\LevelTileH * SCROLL_layer()\\TileSizeY SCROLL_layer()\\LevelTileMaxX = SCROLL_layer()\\LevelTileW - 1 SCROLL_layer()\\LevelTileMaxY = SCROLL_layer()\\LevelTileH - 1 SCROLL_layer()\\PageW = DispW SCROLL_layer()\\PageW - (SCROLL_layer()\\PageW % SCROLL_layer()\\TileSizeX) If SCROLL_layer()\\PageW \< DispW SCROLL_layer()\\PageW + SCROLL_layer()\\TileSizeX EndIf SCROLL_layer()\\PageH = DispH SCROLL_layer()\\PageH - (SCROLL_layer()\\PageH % SCROLL_layer()\\TileSizeY) If SCROLL_layer()\\PageH \< DispH SCROLL_layer()\\PageH + SCROLL_layer()\\TileSizeY EndIf SCROLL_layer()\\PageTileW = SCROLL_layer()\\PageW / SCROLL_layer()\\TileSizeX SCROLL_layer()\\PageTileH = SCROLL_layer()\\PageH / SCROLL_layer()\\TileSizeY ; allocation d'un espace mémoire pour stocker le plan du niveau SCROLL_layer()\\levelLineSizeByte = SCROLL_layer()\\LevelTileW * 2 ; taille d'une ligne du niveau composé de .w SCROLL_layer()\\ptrLevelMap = AllocateMemory(SCROLL_layer()\\LevelTileH * SCROLL_layer()\\levelLineSizeByte) ; Allocation d'un espace mémoire pour stocker les "bords" du niveau SCROLL_layer()\\ptrLevelBounds = AllocateMemory(SCROLL_layer()\\LevelTileH * SCROLL_layer()\\LevelTileW) ; Allocation d'un espace mémoire pour stocker les séquences du niveau SCROLL_layer()\\ptrLevelSequences = AllocateMemory(SCROLL_layer()\\LevelTileH * SCROLL_layer()\\LevelTileW) ProcedureReturn SCROLL_layer()\\numlayer EndProcedure #; Libère les ressources liées à un layer Procedure SCROLL_freeLayer(numLayer.i = -1) Protected NewList seqToDelete() Protected *ptrCurrentLayer.SCROLL_layer_struct Protected i.i Protected found.b ; If called without parameter, this procedure frees the current layer ; Else, find the layer If numLayer \<> -1 *ptrCurrentLayer = @SCROLL_layer() ForEach SCROLL_layer() If SCROLL_layer()\\numlayer = numLayer found = #True Break EndIf Next SCROLL_layer() If found = #False ProcedureReturn 0 EndIf EndIf ; Free memory FreeMemory(SCROLL_layer()\\ptrLevelMap) FreeMemory(SCROLL_layer()\\ptrLevelBounds) FreeMemory(SCROLL_layer()\\ptrLevelSequences) ; Free sprites For i=SCROLL_layer()\\numFirstSprite To SCROLL_layer()\\numLastSprite If IsSprite(i) FreeSprite(i) EndIf Next i ; Free pages FreeSprite(SCROLL_layer()\\page0) FreeSprite(SCROLL_layer()\\page1) FreeSprite(SCROLL_layer()\\page2) FreeSprite(SCROLL_layer()\\page3) ; Free sequences ForEach SCROLL_sequence() If SCROLL_sequence()\\numLayer = SCROLL_layer()\\numLayer FreeMemory(SCROLL_sequence()\\ptrFrames) AddElement(seqToDelete()) seqToDelete() = @SCROLL_sequence() EndIf Next SCROLL_sequence() ForEach seqToDelete() ChangeCurrentElement(SCROLL_sequence(),seqToDelete()) DeleteElement(SCROLL_sequence()) Next seqToDelete() ClearList(seqToDelete()) ; Reposition layer list If numLayer \<> -1 And *ptrCurrentLayer \<> 0 ChangeCurrentElement(SCROLL_layer(),*ptrCurrentLayer) EndIf 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 SCROLL_initPages() Protected i.i,numpage.i = 0 ; Pour chaque layer, créer 4 pages pour le scrolling ForEach SCROLL_layer() SCROLL_layer()\\firstpage = numpage SCROLL_layer()\\page0 = numpage SCROLL_layer()\\page1 = numpage+1 SCROLL_layer()\\page2 = numpage+2 SCROLL_layer()\\page3 = numpage+3 For i = 0 To 3 CompilerIf #USESPRITE3D = #True CreateSprite(numpage, SCROLL_layer()\\PageW, SCROLL_layer()\\PageH, #PB_Sprite_Texture) CreateSprite3D(numpage, numpage) CompilerElse CreateSprite(numpage, SCROLL_layer()\\PageW, SCROLL_layer()\\PageH) CompilerEndIf numpage+1 Next i Next SCROLL_layer() EndProcedure #; give >0 when there's a bound in the given X,Y coords (see BOUNDBIT_[direction]) Macro SCROLL_getBounds(X,Y) PeekB(SCROLL_layer()\\ptrLevelBounds + (X) + (Y)*SCROLL_layer()\\LevelTileW) EndMacro #; Syntax for the 4 following macros: #; If SCROLL_isBlockedUp(X,Y) #; [what to do if there's a wall above] #; ... Macro SCROLL_isBlockedUp(X,Y) PeekB(SCROLL_layer()\\ptrLevelBounds + (X) + (Y)*SCROLL_layer()\\LevelTileW) & #BOUNDBIT_DOWN > 0 EndMacro Macro SCROLL_isBlockedLeft(X,Y) PeekB(SCROLL_layer()\\ptrLevelBounds + (X) + (Y)*SCROLL_layer()\\LevelTileW) & #BOUNDBIT_RIGHT > 0 EndMacro Macro SCROLL_isBlockedDown(X,Y) PeekB(SCROLL_layer()\\ptrLevelBounds + (X) + (Y)*SCROLL_layer()\\LevelTileW) & #BOUNDBIT_UP > 0 EndMacro Macro SCROLL_isBlockedRight(X,Y) PeekB(SCROLL_layer()\\ptrLevelBounds + (X) + (Y)*SCROLL_layer()\\LevelTileW) & #BOUNDBIT_LEFT > 0 EndMacro #; Calcul de la page concernée Macro SCROLL_GetPageNo(X, Y) ((X / SCROLL_layer()\\PageW) & 1) + (((Y / SCROLL_layer()\\PageH) & 1) \<\< 1) EndMacro #; Calcul de X dans la page Macro SCROLL_GetXvalue(X) ((X % SCROLL_layer()\\PageW) - (X % SCROLL_layer()\\TileSizeX) ) EndMacro #; Calcul de Y dans la page Macro SCROLL_GetYvalue(Y) ((Y % SCROLL_layer()\\PageH) - (Y % SCROLL_layer()\\TileSizeY) ) EndMacro #; Get tile number for the given XX,YY coords Macro SCROLL_GetTile(XX, YY) SCROLL_Tile = -1 SCROLL_TempX = XX / SCROLL_layer()\\TileSizeX If (SCROLL_TempX => 0) If (SCROLL_TempX \<= SCROLL_layer()\\LevelTileMaxX) SCROLL_TempY = YY / SCROLL_layer()\\TileSizeY If (SCROLL_TempY => 0) If (SCROLL_TempY \<= SCROLL_layer()\\LevelTileMaxY) SCROLL_Tile = PeekW(SCROLL_layer()\\ptrLevelMap + SCROLL_TempX*2 + SCROLL_TempY*SCROLL_layer()\\levelLineSizeByte) EndIf EndIf EndIf EndIf EndMacro #; Draw the tile at then XX,YY coords Macro SCROLL_updateTile(XX, YY) SCROLL_GetTile(XX, YY) ; Retourne le global SCROLL_Tile.i If SCROLL_Tile \<> -1 SCROLL_P = SCROLL_GetPageNo(XX, YY) UseBuffer(SCROLL_P + SCROLL_layer()\\firstPage) DisplaySprite(SCROLL_Tile, SCROLL_GetXvalue(XX), SCROLL_GetYvalue(YY) ) UseBuffer(-1) EndIf EndMacro #; Update the borders of the page Macro SCROLL_updateTileLeftBorder() For SCROLL_Y = (SCROLL_layer()\\LevelY - SCROLL_layer()\\TileSizeY) To (SCROLL_layer()\\LevelY + SCROLL_layer()\\PageH + SCROLL_layer()\\TileSizeY) ; Rajouté +TileSize SCROLL_updateTile((SCROLL_layer()\\LevelX - SCROLL_layer()\\TileSizeY), SCROLL_Y) SCROLL_Y + SCROLL_layer()\\TileSizeY SCROLL_Y - 1 Next SCROLL_Y EndMacro Macro SCROLL_updateTileRightBorder() For SCROLL_Y = (SCROLL_layer()\\LevelY - SCROLL_layer()\\TileSizeY) To (SCROLL_layer()\\LevelY + SCROLL_layer()\\PageH) ; Rajouté -TileSize SCROLL_updateTile((SCROLL_layer()\\LevelX + SCROLL_layer()\\PageW), SCROLL_Y) SCROLL_Y + SCROLL_layer()\\TileSizeY SCROLL_Y - 1 Next SCROLL_Y EndMacro Macro SCROLL_updateTileUpBorder() For SCROLL_X = (SCROLL_layer()\\LevelX - SCROLL_layer()\\TileSizeX) To (SCROLL_layer()\\LevelX + SCROLL_layer()\\PageW + SCROLL_layer()\\TileSizeX) ; Rajouté +TileSize SCROLL_updateTile(SCROLL_X, (SCROLL_layer()\\LevelY - SCROLL_layer()\\TileSizeX) ) SCROLL_X + SCROLL_layer()\\TileSizeX SCROLL_X - 1 Next SCROLL_X EndMacro Macro SCROLL_updateTileDownBorder() For SCROLL_X = (SCROLL_layer()\\LevelX - SCROLL_layer()\\TileSizeX) To (SCROLL_layer()\\LevelX + SCROLL_layer()\\PageW) ;Rajouté -TileSize SCROLL_updateTile(SCROLL_X, (SCROLL_layer()\\LevelY + SCROLL_layer()\\PageH) ) SCROLL_X + SCROLL_layer()\\TileSizeX SCROLL_X - 1 Next SCROLL_X EndMacro ; Draw all the visible tiles Macro SCROLL_drawVisibleTiles() For SCROLL_Y = SCROLL_layer()\\LevelY To SCROLL_layer()\\LevelY + SCROLL_layer()\\PageH For SCROLL_X = SCROLL_layer()\\LevelX To SCROLL_layer()\\LevelX + SCROLL_layer()\\PageW SCROLL_updateTile(SCROLL_X, SCROLL_Y) SCROLL_X + SCROLL_layer()\\TileSizeX SCROLL_X - 1 Next SCROLL_X SCROLL_Y + SCROLL_layer()\\TileSizeY SCROLL_Y - 1 Next SCROLL_Y EndMacro #; Move the scrolling Macro SCROLL_moveLeft() If SCROLL_layer()\\LevelX > 0 If SCROLL_layer()\\LevelX - SCROLL_layer()\\VitX \< 0 ; "Sort" du niveau? SCROLL_layer()\\VitX = SCROLL_layer()\\LevelX EndIf SCROLL_layer()\\PosXReal + SCROLL_layer()\\VitX SCROLL_layer()\\PosX = SCROLL_layer()\\PosXReal If SCROLL_layer()\\PosX => SCROLL_layer()\\PageW SCROLL_layer()\\ShiftX + SCROLL_layer()\\PageW SCROLL_layer()\\PosX - SCROLL_layer()\\PageW SCROLL_layer()\\PosXReal = SCROLL_layer()\\PosX SCROLL_layer()\\Page0 ! 1 SCROLL_layer()\\Page1 ! 1 SCROLL_layer()\\Page2 ! 1 SCROLL_layer()\\Page3 ! 1 EndIf SCROLL_layer()\\LevelX = 0 - (SCROLL_layer()\\ShiftX + SCROLL_layer()\\PosX) SCROLL_layer()\\OldLevelTileX = SCROLL_layer()\\LevelTileX SCROLL_layer()\\LevelTileX = SCROLL_layer()\\LevelX / SCROLL_layer()\\TileSizeX If SCROLL_layer()\\LevelTileX \<> SCROLL_layer()\\OldLevelTileX SCROLL_updateTileLeftBorder() EndIf SCROLL_layer()\\SequenceShiftX = -(SCROLL_layer()\\LevelX % SCROLL_layer()\\tileSizeX) SCROLL_DisplayFlag = #True EndIf EndMacro Macro SCROLL_moveRight() If SCROLL_layer()\\LevelX \< (SCROLL_layer()\\LevelW - SCROLL_layer()\\PageW) If SCROLL_layer()\\LevelX + SCROLL_layer()\\VitX > (SCROLL_layer()\\LevelW - SCROLL_layer()\\PageW) ; "Sort" du niveau? SCROLL_layer()\\VitX = (SCROLL_layer()\\LevelW - SCROLL_layer()\\PageW) - SCROLL_layer()\\LevelX EndIf SCROLL_layer()\\PosXReal - SCROLL_layer()\\VitX SCROLL_layer()\\PosX = SCROLL_layer()\\PosXReal If SCROLL_layer()\\PosX \< 0 SCROLL_layer()\\ShiftX - SCROLL_layer()\\PageW SCROLL_layer()\\PosX + SCROLL_layer()\\PageW SCROLL_layer()\\PosXReal = SCROLL_layer()\\PosX SCROLL_layer()\\Page0 ! 1 SCROLL_layer()\\Page1 ! 1 SCROLL_layer()\\Page2 ! 1 SCROLL_layer()\\Page3 ! 1 EndIf SCROLL_layer()\\LevelX = 0 - (SCROLL_layer()\\ShiftX + SCROLL_layer()\\PosX) SCROLL_layer()\\OldLevelTileX = SCROLL_layer()\\LevelTileX SCROLL_layer()\\LevelTileX = SCROLL_layer()\\LevelX / SCROLL_layer()\\TileSizeX If SCROLL_layer()\\LevelTileX \<> SCROLL_layer()\\OldLevelTileX SCROLL_updateTileRightBorder() EndIf SCROLL_layer()\\SequenceShiftX = -(SCROLL_layer()\\LevelX % SCROLL_layer()\\tileSizeX) SCROLL_DisplayFlag = #True EndIf EndMacro Macro SCROLL_moveUp() If SCROLL_layer()\\LevelY > 0 If SCROLL_layer()\\LevelY - SCROLL_layer()\\VitY \< 0 ; "Sort" du niveau? SCROLL_layer()\\VitY = SCROLL_layer()\\LevelY EndIf SCROLL_layer()\\PosYReal + SCROLL_layer()\\VitY SCROLL_layer()\\PosY = SCROLL_layer()\\PosYReal If SCROLL_layer()\\PosY => SCROLL_layer()\\PageH SCROLL_layer()\\ShiftY + SCROLL_layer()\\PageH SCROLL_layer()\\PosY - SCROLL_layer()\\PageH SCROLL_layer()\\PosYReal = SCROLL_layer()\\PosY SCROLL_layer()\\Page0 ! 2 SCROLL_layer()\\Page1 ! 2 SCROLL_layer()\\Page2 ! 2 SCROLL_layer()\\Page3 ! 2 EndIf SCROLL_layer()\\LevelY = 0 - (SCROLL_layer()\\ShiftY + SCROLL_layer()\\PosY) SCROLL_layer()\\OldLevelTileY = SCROLL_layer()\\LevelTileY SCROLL_layer()\\LevelTileY = SCROLL_layer()\\LevelY / SCROLL_layer()\\TileSizeY If SCROLL_layer()\\LevelTileY \<> SCROLL_layer()\\OldLevelTileY SCROLL_updateTileUpBorder() EndIf SCROLL_layer()\\SequenceShiftY = -(SCROLL_layer()\\LevelY % SCROLL_layer()\\tileSizeY) SCROLL_DisplayFlag = #True EndIf EndMacro Macro SCROLL_moveDown() If SCROLL_layer()\\LevelY \< (SCROLL_layer()\\LevelH - SCROLL_layer()\\PageH) If SCROLL_layer()\\LevelY + SCROLL_layer()\\VitY > (SCROLL_layer()\\LevelH - SCROLL_layer()\\PageH) ; "Sort" du niveau? SCROLL_layer()\\VitY = (SCROLL_layer()\\LevelH - SCROLL_layer()\\PageH) - SCROLL_layer()\\LevelY EndIf SCROLL_layer()\\PosYReal - SCROLL_layer()\\VitY SCROLL_layer()\\PosY = SCROLL_layer()\\PosYReal If SCROLL_layer()\\PosY \< 0 SCROLL_layer()\\ShiftY - SCROLL_layer()\\PageH SCROLL_layer()\\PosY + SCROLL_layer()\\PageH SCROLL_layer()\\PosYReal = SCROLL_layer()\\PosY SCROLL_layer()\\Page0 ! 2 SCROLL_layer()\\Page1 ! 2 SCROLL_layer()\\Page2 ! 2 SCROLL_layer()\\Page3 ! 2 EndIf SCROLL_layer()\\LevelY = 0 - (SCROLL_layer()\\ShiftY + SCROLL_layer()\\PosY) SCROLL_layer()\\OldLevelTileY = SCROLL_layer()\\LevelTileY SCROLL_layer()\\LevelTileY = SCROLL_layer()\\LevelY / SCROLL_layer()\\TileSizeY If SCROLL_layer()\\LevelTileY \<> SCROLL_layer()\\OldLevelTileY SCROLL_updateTileDownBorder() EndIf SCROLL_layer()\\SequenceShiftY = -(SCROLL_layer()\\LevelY % SCROLL_layer()\\tileSizeY) SCROLL_DisplayFlag = #True EndIf EndMacro #; Generic "move" macro, which calls the others Macro SCROLL_move(moveX,moveY) ForEach SCROLL_layer() If moveX \< 0 SCROLL_layer()\\VitX = -(moveX) / SCROLL_layer()\\vitRatioX SCROLL_moveLeft() Else If moveX > 0 SCROLL_layer()\\VitX = (moveX) / SCROLL_layer()\\vitRatioX SCROLL_moveRight() EndIf EndIf If moveY \< 0 SCROLL_layer()\\VitY = -(moveY) / SCROLL_layer()\\vitRatioY SCROLL_moveUp() Else If moveY > 0 SCROLL_layer()\\VitY = (moveY) / SCROLL_layer()\\vitRatioY SCROLL_moveDown() EndIf EndIf Next SCROLL_layer() EndMacro #; Display the animated tiles in the current layer Macro SCROLL_displaySequences() SCROLL_TempX = SCROLL_layer()\\LevelTileX + SCROLL_layer()\\PageTileW If SCROLL_TempX > SCROLL_layer()\\LevelTileMaxX SCROLL_TempX-1 EndIf SCROLL_TempY = SCROLL_layer()\\LevelTileY + SCROLL_layer()\\PageTileH If SCROLL_TempY > SCROLL_layer()\\LevelTileMaxY SCROLL_TempY-1 EndIf SCROLL_seqX = SCROLL_layer()\\SequenceShiftX SCROLL_seqY = SCROLL_layer()\\SequenceShiftY For SCROLL_Y = SCROLL_layer()\\LevelTileY To SCROLL_TempY For SCROLL_X = SCROLL_layer()\\LevelTileX To SCROLL_TempX SCROLL_seqTile = PeekB(SCROLL_layer()\\ptrLevelSequences + SCROLL_X + SCROLL_Y*SCROLL_layer()\\LevelTileW) If SCROLL_seqTile > 0 DisplayTransparentSprite(SCROLL_layer()\\ptrListSequences[SCROLL_seqTile]\\currentFrame, SCROLL_seqX, SCROLL_seqY) EndIf SCROLL_seqX+SCROLL_layer()\\tileSizeX Next SCROLL_X SCROLL_seqX = SCROLL_layer()\\SequenceShiftX SCROLL_seqY+SCROLL_layer()\\tileSizeY Next SCROLL_Y EndMacro #; Display the current layer Macro SCROLL_display() CompilerIf #USESPRITE3D = #True Start3D() DisplaySprite3D(SCROLL_layer()\\Page0, SCROLL_layer()\\PosX, SCROLL_layer()\\PosY) DisplaySprite3D(SCROLL_layer()\\Page1, SCROLL_layer()\\PosX - SCROLL_layer()\\PageW, SCROLL_layer()\\PosY) DisplaySprite3D(SCROLL_layer()\\Page2, SCROLL_layer()\\PosX, SCROLL_layer()\\PosY - SCROLL_layer()\\PageH) DisplaySprite3D(SCROLL_layer()\\Page3, SCROLL_layer()\\PosX - SCROLL_layer()\\PageW, SCROLL_layer()\\PosY - SCROLL_layer()\\PageH) Stop3D() CompilerElse If SCROLL_layer()\\numlayer = 0 DisplaySprite(SCROLL_layer()\\Page0, SCROLL_layer()\\PosX, SCROLL_layer()\\PosY) DisplaySprite(SCROLL_layer()\\Page1, SCROLL_layer()\\PosX - SCROLL_layer()\\PageW, SCROLL_layer()\\PosY) DisplaySprite(SCROLL_layer()\\Page2, SCROLL_layer()\\PosX, SCROLL_layer()\\PosY - SCROLL_layer()\\PageH) DisplaySprite(SCROLL_layer()\\Page3, SCROLL_layer()\\PosX - SCROLL_layer()\\PageW, SCROLL_layer()\\PosY - SCROLL_layer()\\PageH) Else DisplayTransparentSprite(SCROLL_layer()\\Page0, SCROLL_layer()\\PosX, SCROLL_layer()\\PosY) DisplayTransparentSprite(SCROLL_layer()\\Page1, SCROLL_layer()\\PosX - SCROLL_layer()\\PageW, SCROLL_layer()\\PosY) DisplayTransparentSprite(SCROLL_layer()\\Page2, SCROLL_layer()\\PosX, SCROLL_layer()\\PosY - SCROLL_layer()\\PageH) DisplayTransparentSprite(SCROLL_layer()\\Page3, SCROLL_layer()\\PosX - SCROLL_layer()\\PageW, SCROLL_layer()\\PosY - SCROLL_layer()\\PageH) EndIf CompilerEndIf SCROLL_displaySequences() EndMacro disableExplicit ; IDE Options = PureBasic v4.31 (Windows - x86) ; Folding = -- #end file ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* ; --- bitmap file ---------------------------------------- #tileset #tilebitmap tileset\\TS_.png 512 #end tilebitmap #end tileset ; -------------------------------------------------------- ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* #file TSinclude_.pbi #; ---------- Generated by Tile Studio ---------- #; #; --- Version 1.0 --- #; #tileset ##SPRITESHEET = <(TileSetNumber + 1) * 256> #end tileset #;****************************************************************** #; Load the tile sets from the bitmaps #;****************************************************************** Procedure loadTileSets() Protected numImage.i, imageNbTileW.i,imageNbTileH.i Protected numSprite.i Protected i.i, x.i, y.i TransparentSpriteColor(#PB_Default,RGB(,,)) #tileset numimage = LoadSprite(#PB_any, "tileset\\TS_.png") x=0:y=0 createSprite(#SPRITESHEET,,) StartDrawing(SpriteOutput(#SPRITESHEET)) Box(0,0,,,RGB(,,)) StopDrawing() for i=1 to ClipSprite(numimage,x,y,,) createSprite(#SPRITESHEET + i,,) StartDrawing(SpriteOutput(#SPRITESHEET + i)) Box(0,0,,,RGB(,,)) StopDrawing() useBuffer(#SPRITESHEET + i) DisplayTransparentSprite(numimage,0,0) UseBuffer(#PB_Default) x+ if x >= x=0 y+ endif next i freeSprite(numimage) #end tileset endprocedure #;****************************************************************** #; Load the level infos: #; - Map #; - Bounds #; and create each layers #;****************************************************************** Procedure LoadLevel(scrWidth.i,scrHeight.i) Protected x.i,y.i Protected xSpeed.f, ySpeed.f Protected numTile.w Protected bounds.b #tileset #map ; Création du Layer x = 1:y=1 xSpeed = 1 / () ySpeed = 1 / () SCROLL_createLayer(,scrWidth,scrHeight,,,xSpeed,ySpeed,,) SCROLL_layer()\\numFirstSprite = #SPRITESHEET SCROLL_layer()\\numLastSprite = #SPRITESHEET + 255 ; Lecture du plan du layer "" Restore _MapData For y = 0 To For x = 0 To Read.w numTile If numtile >= 0 PokeW(SCROLL_layer()\\ptrLevelMap + x*2 + y*SCROLL_layer()\\levelLineSizeByte,numTile + #SPRITESHEET) PokeB(SCROLL_layer()\\ptrLevelSequences + x + y*SCROLL_layer()\\levelTileW,0) Else PokeW(SCROLL_layer()\\ptrLevelMap + x*2 + y*SCROLL_layer()\\levelLineSizeByte,#SPRITESHEET) PokeB(SCROLL_layer()\\ptrLevelSequences + x + y*SCROLL_layer()\\levelTileW,-numTile) EndIf Next x Next y ; Lecture des bords du layer "" Restore _BoundData For y = 0 To For x = 0 To Read.b bounds PokeB(SCROLL_layer()\\ptrLevelBounds + x + y*SCROLL_layer()\\levelTileW,bounds) Next x Next y #end map #end tileset SortStructuredList(SCROLL_layer(),#PB_Sort_Ascending,OffsetOf(SCROLL_layer_struct\\numLayer),#PB_Sort_Long) endProcedure #;****************************************************************** #; Load the animated tiles infos and store them #; in the "SCROLL_sequence" list #;****************************************************************** Procedure loadSequences() Protected i.i,j.i,k.i Protected numLayer.i,numSequence.i,nbImages.i,nbFrames.i, totalNbFrames.i Protected *ptrFrame.w Protected Dim frame.w(1) Protected Dim frameCount.i(1) #tileset ; Lecture des Datas des séquences pour le tileset Restore _SequenceData For i=1 To ; Ajout dans la liste des séquences AddElement(SCROLL_sequence()) Read.i SCROLL_sequence()\\numLayer Read.i SCROLL_sequence()\\numSequence Read.i nbImages ReDim frame(nbImages) ReDim frameCount(nbImages) ; Estimer la taille de la mémoire nécessaire totalNbFrames = 0 For j=1 To nbImages Read.i frame(j) Read.i frameCount(j) totalNbFrames + frameCount(j) Next j ; Allouer la mémoire SCROLL_sequence()\\ptrFrames = AllocateMemory(totalNbFrames * 4) ; Remplir la mémoire *ptrFrame = SCROLL_sequence()\\ptrFrames For j=1 To nbImages For k=1 To frameCount(j) PokeL(*ptrFrame,frame(j)+#SPRITESHEET) *ptrFrame+4 Next k Next j ; Renseigner les adresses de la frame en cours et de la dernière frame SCROLL_sequence()\\ptrCurrentFrame = SCROLL_sequence()\\ptrFrames SCROLL_sequence()\\ptrLastFrame = *ptrFrame-4 SCROLL_sequence()\\currentFrame = PeekL(SCROLL_sequence()\\ptrCurrentFrame) Next i #end tileset ; Renseigner la liste des ptr sur séquences dans les layers ForEach SCROLL_layer() nbSequences = 0 ForEach SCROLL_sequence() If SCROLL_sequence()\\numLayer = SCROLL_layer()\\numLayer SCROLL_layer()\\ptrListSequences[SCROLL_sequence()\\numSequence] = @SCROLL_sequence() EndIf Next SCROLL_sequence() Next SCROLL_layer() EndProcedure #;- Datas for sequences, maps, and bounds DataSection #tileset _SequenceData: #sequence Data.i ,, #sequencedata "\nData.i " ", " , #end sequencedata #end sequence #end tileset #tileset #map _MapData: #mapdata "\nData.w " "," "\nData.w " "\nData.w " "" #end mapdata _BoundData: #mapdata "\nData.b " "," "\nData.b " "\nData.b " "" $ #end mapdata #end map #end tileset endDataSection ; IDE Options = PureBasic v4.31 (Windows - x86) ; Folding = -- #; ---------- end of generated file ---------- #end file ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* ; ********************************************************************************************************************************************* #;****************************************************************** #; Un petit programme pour tester / visualiser le niveau #; construit sous TileStudio #;****************************************************************** #file test.pb #; These 2 files must be included xincludeFile "scrollEngine.pbi" includeFile "TSinclude_.pbi" enableExplicit #;- 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 = 20 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 UsePNGImageDecoder() loadTileSets() loadLevel(ScrW,ScrH) loadSequences() #; Création des pages de scroll (4 par layers) SCROLL_initPages() #; Affichage initial du décor ForEach SCROLL_layer() SCROLL_drawVisibleTiles() SCROLL_display() Next SCROLL_layer() FlipBuffers() lst_second=ElapsedMilliseconds() #; une petite balle, pour tester les collisions CreateSprite(999,16,16) StartDrawing(SpriteOutput(999)) Box(0,0,16,16,$FF00FF) Circle(7,7,8,$FF0066) StopDrawing() Global xballtile.i=0,yballtile.i=0,oldxballtile.i=0,oldyballtile.i=0 Global xball.i = 320,yball.i = 240 Global xdball.i = 3 ,ydball.i = -2 Global trace.b EnableExplicit #;-______________ #;- Repeat... #;-¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Repeat Delay(1) SCROLL_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(SCROLL_layer()) ; on teste le layer de premier plan: c'est lui qui conditionne le mouvement des autres If VitesseX \< 0 If SCROLL_layer()\\LevelX + VitesseX \< 0 VitesseX = -SCROLL_layer()\\LevelX Else VitesseX+1 EndIf EndIf If VitesseX > 0 If SCROLL_layer()\\LevelX + VitesseX > (SCROLL_layer()\\LevelW - SCROLL_layer()\\PageW) VitesseX = (SCROLL_layer()\\LevelW - SCROLL_layer()\\PageW) - SCROLL_layer()\\LevelX Else VitesseX-1 EndIf EndIf If VitesseY \< 0 If SCROLL_layer()\\LevelY + VitesseY \< 0 VitesseY = -SCROLL_layer()\\LevelY Else VitesseY+1 EndIf EndIf If VitesseY > 0 If SCROLL_layer()\\LevelY + VitesseY > (SCROLL_layer()\\LevelH - SCROLL_layer()\\PageH) VitesseY = (SCROLL_layer()\\LevelH - SCROLL_layer()\\PageH) - SCROLL_layer()\\LevelY Else VitesseY-1 EndIf EndIf ; Faire bouger le scrolling SCROLL_move(VitesseX,VitesseY) ; Faire bouger la balle oldxballTile=xball/32:oldyballTile=yball/32 xball+xdball:yball+ydball xballTile=xball/32:yballTile=yball/32 If xballTile \<> oldxballTile If xdball \< 0 If SCROLL_isBlockedLeft(xballTile,oldyballTile) Or SCROLL_isBlockedLeft(xballTile,yballTile) xball-xdball xdball = Random(1)+2 EndIf Else If SCROLL_isBlockedRight(xballTile,oldyballTile) Or SCROLL_isBlockedRight(xballTile,yballTile) xball-xdball xdball = -(Random(1)+2) EndIf EndIf EndIf If yballTile \<> oldyballTile If ydball \< 0 If SCROLL_isBlockedUp(oldxballTile,yballTile) Or SCROLL_isBlockedUp(xballTile,yballTile) yball-ydball ydball = Random(1)+2 EndIf Else If SCROLL_isBlockedDown(oldxballTile,yballTile) Or SCROLL_isBlockedDown(xballTile,yballTile) yball-ydball ydball = -(Random(1)+2) EndIf EndIf EndIf ; Si la balle est sur l'écran, rafraîchir l'affichage If xball-SCROLL_layer()\\LevelX > -16 And xball-SCROLL_layer()\\LevelX \< scrW And yball-SCROLL_layer()\\LevelY > -16 And yball-SCROLL_layer()\\LevelY \< scrH SCROLL_DisplayFlag = #True EndIf ; Si un déplacement a eu lieu, on réaffiche les pages If SCROLL_DisplayFlag ; Animation des séquences ForEach SCROLL_sequence() SCROLL_sequence()\\ptrCurrentFrame+4 If SCROLL_sequence()\\ptrCurrentFrame > SCROLL_sequence()\\ptrLastFrame SCROLL_sequence()\\ptrCurrentFrame = SCROLL_sequence()\\ptrFrames EndIf SCROLL_sequence()\\currentFrame = PeekL(SCROLL_sequence()\\ptrCurrentFrame) Next SCROLL_sequence() ; Affichage des layers ForEach SCROLL_layer() SCROLL_display() Next SCROLL_layer() ; Affichage de la balle DisplayTransparentSprite(999,xball-8-SCROLL_layer()\\LevelX,yball-8-SCROLL_layer()\\LevelY) ; 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 ; Libérer les ressources liées aux layers de scrolling ForEach SCROLL_layer() SCROLL_freeLayer() Next SCROLL_layer() ClearList(SCROLL_layer()) ; Adios ! CloseScreen() End #end file