21 February 2019, 15:53 | #1 |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Horisontal Scrolling Demo (updated: 2019-03-12)
I started experimenting with tilemap scrolling techniques and will upload working examples here as I finish them. I'm basing this on the scrolling tricks C demos from Aminet: http://aminet.net/package/dev/src/ScrollingTrick
First off is a horisontal only corkscrew scroll, full screen 320x256 display. At a scrolling speed of 1px/frame, only ONE tile needs to be drawn per frame when scrolling left or right. If direction changes, then TWO tiles need to be drawn in that single frame. Bitmap size needed is only 352x256 (+some marginal height depending on total map width) The zip file contains the code, tiles, the map as binary file and for Tiled (.tmx) Next up I will see if I can figure out vertical scrolling from earoks Kiwi's Tale dev-notes... Code:
; **************************************************** ; ; Interleaved single buffer horisontal corkscrew scrolling demo ; by MickGyver @ English Amiga Board 2019 ; Based on http://aminet.net/package/dev/src/ScrollingTrick ; ; MIT License, read license.txt ; ; For a scrolling speed of 1px/frame, only one tile ; per frame needs to be drawn. Tiles needed to be ; drawn per frame equals scrolling speed. ; ; In order to use the Bitmap newtype, include the resident file ; Blitzlibs:Bb2objtypes.res in the residents list in the compiler options. ; ; Notes about the tilemap: ; The leftmost and rightmost columns of the tilemap will never be visible, ; so you need to add one padding row to the left and right. ; ; **************************************************** ; Include other source files INCLUDE "system.bb2" ; Enable running from Workbench WBStartup ; Set default type to word DEFTYPE .w Constants: ; ----------------------------------------------------------- #ScreenMainWidth=320 ; Width of visible screen #ScreenMainHeight=256 ; Height of visible screen #ScreenMainDepth=5 ; The depth of the screen #ScreenMainColors=32 ; The number of colours for the main screen #TileDepth=5 ; Tile bit depth #TileWidth=16 ; Width of tiles #TileHeight=16 ; Height of tiles #TileXShift=4 ; Set according to #TileWidth (16->4, 32->5) #TileYShift=4 ; Set according to #TileHeight (16->4, 32->5) #MapWidth=82 ; Tilemap width (number of tiles wide) #MapHeight=16 ; Tilemap height (number of tiles high) ; Calculated constants (from constants above) #ScreenXCount=10 ; Total number of screens horisontally in tilemap #TileHeight1P=#TileHeight*#TileDepth ; Used to get pointer to bitmap buffer #TOffsB=#TileHeight1P-#ScreenMainDepth ; Tile bottom offset for the interleaved bitmap #BufferWidth=#ScreenMainWidth+#TileWidth*2 ; Buffer bitmap width (screen width + padding) #BufferHeight=#ScreenMainHeight ; Buffer bitmap height (screen height) #BufferTilesX=#BufferWidth/#TileWidth ; Number of tiles that fits horisontally on the buffer bitmap #BufferTilesY=#BufferHeight/#TileHeight ; Number of tiles that fits vertically on the buffer bitmap #MapXMax=#MapWidth*#TileWidth-#ScreenMainWidth-#TileWidth*2 ; Max X position on map ; Keyboard etc. constants #KeyUp=$4C #KeyDown=$4D #KeyLeft=$4F #KeyRight=$4E #KeyEscape=$45 #DirNone=0 #DirUp=1 #DirDown=2 #DirLeft=3 #DirRight=4 #BitmapBuffer1=1 #BitmapBuffer2=2 #BitmapTiles=3 #BitmapVTiles=4 #BitmapVBuffer1=5 #BitmapVBuffer2=6 #BobTemp=0 #PaletteMain=0 #CopListMain=0 ; Tiles bitmap #TileCountX=229 ; The number of tiles horisontally in the tiles bitmap #TileCountY=1 ; The number of tiles vertically in the tiles bitmap Macros: ; --------------------------------------------------------------- ; Get a tile from the tilemap array ; The bitwise AND 255 is for reading the byte value as unsigned Macro GetTile (map(`1, `2) & 255) End Macro ; Draw a tile ;!DrawTile{tileX,tileY,x,y} Macro DrawTile BlockScroll (map(`1, `2) & 255) LSL #TileXShift, 0, #TileWidth, #TileHeight1P, `3, `4, #BitmapVTiles End Macro Macro DrawTileTop BlockScroll (map(`1, `2) & 255) LSL #TileXShift,0,#TileWidth,#TileDepth,`3,`4,#BitmapVTiles End Macro ; #TOffsB=#TileHeight1P-#ScreenMainDepth = 16*5-5 = 75 Macro DrawTileBottom BlockScroll (map(`1, `2) & 255) LSL #TileXShift,#TOffsB,#TileWidth,#TileDepth,`3,`4+#TOffsB,#BitmapVTiles End Macro ; Round down value to nearest tile height ; -16 is the same as ~(#TileHeight-1) Macro RoundToBlockWidth (`1 & -#TileWidth) End Macro ; This is a faster way of doing MOD #TileWidth Macro ModNumSteps (`1 & (#TileWidth-1)) End Macro Variables: ; --------------------------------------------------------------- db.b=1 ; Keeps track of double buffer bitmap used (not in use currently) x=0 y=0 tile_x=0 tile_y=0 map_w=0 map_h=0 map_x=0 scroll_dir_prev.b=#DirNone ScreenSetup: ; --------------------------------------------------------------- ; Create one bitmap for a single buffered display BitMap #BitmapBuffer1,#BufferWidth,#BufferHeight+#ScreenXCount,#ScreenMainDepth ; Convert the bitmap to be interleaved ConvertBMToIL{#BitmapBuffer1,#BufferWidth,#BufferHeight+#ScreenXCount,#ScreenMainDepth} ; Get a pointer to the background bitmap *db1.bitmap = Addr Bitmap(#BitmapBuffer1) ; Set clipping limit to max to enable blitting ourside of bitmap *db1\_xclip = $7FFF ; Create a "virtual" one plane bitmap for blitting to. We will still use the ; "normal" bitmap with the display command CludgeBitMap #BitmapVBuffer1,#BufferWidth,(#BufferHeight+#ScreenXCount)*#ScreenMainDepth,1,*db1\_data[0] ; Get a pointer to the virtual bitmap *dbv.bitmap = Addr Bitmap(#BitmapVBuffer1) ; Set clipping limit to max to enable blitting ourside of bitmap *dbv\_xclip = $7FFF *dbv\_yclip = $7FFF ; Create a bitmap for the tiles BitMap #BitmapTiles,#TileCountX*#TileWidth,#TileCountY*#TileHeight,#ScreenMainDepth *bmt.bitmap = Addr Bitmap(#BitmapTiles) ; Load the tiles LoadBitMap #BitmapTiles,"tilesrow32.iff" ; Load the palette from the same image LoadPalette #PaletteMain,"tilesrow32.iff" ; Convert the tiles bitmap to be interleaved ConvertBMToIL{#BitmapTiles, #TileCountX LSL #TileXShift, #TileCountY LSL #TileYShift, #ScreenMainDepth} ; Create a virtual 1-plane bitmap from the tiles bitmap CludgeBitMap #BitmapVTiles, #TileCountX LSL #TileXShift, #TileHeight1P, 1, *bmt\_data[0] ; Read the tile map If ReadFile(0,"world.map") ; First two words are width and height of tilemap ReadMem 0,&map_w,2 ReadMem 0,&map_h,2 ; Create a two dimensional array for the tilemap Dim map.b(map_w-1, map_h-1) ; Read the entire tilemap into the array ReadMem 0,&map(0,0),map_w*map_h ; Close the tilemap file CloseFile 0 EndIf ; Wait for disk activity to finish before going into Blitz mode VWait 100 ; Go into blitz mode and enable blitzkeys BLITZ BlitzKeys On ; Create copperlists for the display (y=44, lores, smoothscroll, 5 bitplanes, 8 sprites, 32 colors) InitCopList #CopListMain,44,#ScreenMainHeight,$10+#ScreenMainDepth,8,#ScreenMainColors,0 ; Create a display using copperlist CreateDisplay #CopListMain ; Set up palette DisplayPalette #CopListMain,#PaletteMain ; Use the virtual one plane bitmap Use BitMap #BitmapVBuffer1 ; Draw tiles to fill the whole bitmap For y = 0 To #BufferTilesY-1 For x = 0 To #BufferTilesX-1 !DrawTile{x, y, x LSL #TileXShift, y * #TileHeight1P} Next Next MainLoop: ; ----------------------------------------------------------- Repeat ; Wait for vertical blank VWait 1 ; Show bitmap on main copperlist DisplayBitMap #CopListMain,#BitmapBuffer1,map_x+#TileWidth,0 ; Scrolling right? If RawStatus(#KeyRight) AND map_x < #MapXMax JSR ScrollRight : JSR ScrollRight Else ; Scrolling left? If RawStatus(#KeyLeft) AND map_x > 0 JSR ScrollLeft : JSR ScrollLeft EndIf EndIf Until RawStatus(#KeyEscape)=-1 ; Quit game End ; ------------------------------------------------ ; Scroll Left ; ------------------------------------------------ ScrollLeft: ; Decrease position first map_x-1 ; Get blit position x = !RoundToBlockWidth{map_x} tile_y = !ModNumSteps{map_x} y = tile_y * #TileHeight1P ; Blit tile If tile_y < #BufferTilesY tile_x = map_x LSR #TileXShift !DrawTile{tile_x, tile_y, x, y} ; Repair broken tile if needed If scroll_dir_prev = #DirRight If tile_y+1 < #BufferTilesY !DrawTileTop{tile_x, tile_y+1, x, y+#TileHeight1P} EndIf EndIf EndIf scroll_dir_prev=#DirLeft RTS ; ------------------------------------------------ ; Scroll Right ; ------------------------------------------------ ScrollRight: ; Get blit position x = #BufferWidth + !RoundToBlockWidth{map_x} tile_y = !ModNumSteps{map_x} y = tile_y * #TileHeight1P ; Blit tile If tile_y < #BufferTilesY tile_x = map_x LSR #TileXShift + #BufferTilesX !DrawTile{tile_x, tile_y, x, y} ; Repair broken tile if needed If scroll_dir_prev = #DirLeft If tile_y-1 >= 0 !DrawTileBottom{tile_x,tile_y-1,x,y-#TileHeight1P} EndIf EndIf EndIf ; Increase position last map_x+1 ; Set right as previous scroll direction scroll_dir_prev=#DirRight RTS 2019-03-12 - Added MIT license.txt 2019-03-11 - Changed to use interleaved bitmaps - Optimisations and cleanup 2019-02-23 - Small optimisations 2019-02-21 - First version Last edited by MickGyver; 12 March 2019 at 11:44. Reason: Updated the source (including the zip) |
21 February 2019, 16:23 | #2 |
Registered User
Join Date: Feb 2018
Location: London / UK
Posts: 112
|
If you don't need much vertical scrolling necessarily you can still use the corkscrew method if you make the buffer just slightly taller than the screen.
I'm working on a game at the moment which uses a 384 pixels tall buffer so there's 160 pixels to scroll up/down with a 320 x 224 viewport which is kind of decent, way nicer than horizontal only. I'm then updating 1 or 2 tiles per pixel scrolled. I might do a proper raster split tile engine "next time" but for now it was much easier to get started with the corkscrew stuff. |
22 February 2019, 09:25 | #3 |
Registered User
Join Date: Dec 2016
Location: Warsaw area
Posts: 152
|
@MickGyver
Thanks man. I will check that later today but judging the code quickly it's similar to what I did. I wonder how you implement the vertical scroll. I'm stuck here. I mean I understand the principles (some helped me in other thread) but it's still buggy. Wait for your solution. and then finally 8 way? I'm really curious. |
22 February 2019, 09:32 | #4 | ||
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Quote:
Quote:
By the way you said somebody helped you in another thread, which thread is that? EDIT: It's this one I guess: http://eab.abime.net/showthread.php?t=81634&page=3 Last edited by MickGyver; 22 February 2019 at 09:42. |
||
22 February 2019, 19:42 | #5 |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Vertical Scrolling Demo (updated: 2019-03-11)
I have managed to get vertical tilemap scrolling working (using a coppersplit) thanks to earoks Kiwi's Tale dev notes. There is a small glitch when bitmap wraps around for some reason, can't figure it out at the moment. splitline becomes negative for a tile height, I can't get everything to sync, probably something simple with bitmap heights etc. Maybe Erik the Genius or somebody else can see what's wrong?
EDIT1: I edited the code a little, I found a hack/solution to the problem I explained above, the offset y position can for sure be handled in a prettier way than it is now however. EDIT2: I figured it out and have edited the code, it should now be good to go. 8-way scrolling next. Only two tiles needs drawing every frame, or it's like 10 frames with two tiles drawn, 6 frames with no tiles drawn. Visible area is 320x208. Bitmap size needed is only 320x240. If using a width of 256 (16 tiles) instead of 320 (20 tiles) then only one tile needs to be drawn per step when scrolling. (The code uses the same tilemap etc. as in the ScrollX example above.) Code:
; **************************************************** ; ; Interleaved single buffer vertical scrolling demo (coppersplit) ; by MickGyver @ English Amiga Board 2019 ; Based on http://aminet.net/package/dev/src/ScrollingTrick ; and earoks (English Amiga Board) dev notes for Kiwi's Tale ; ; MIT License, read license.txt ; ; In order to use the Bitmap newtype, include the resident file ; Blitzlibs:Bb2objtypes.res in the residents list in the compiler options. ; ; Notes about the tilemap: ; The topmost and bottommost rows of the tilemap will never be visible, ; so you need to add one padding row to the top and bottom. ; ; **************************************************** ; Include other source files INCLUDE "system.bb2" ; Enable running from Workbench WBStartup ; Set default type to word DEFTYPE .w Constants: ; --------------------------------------------------------------- #ScreenMainWidth=320 ; Width of visible screen #ScreenMainHeight=208 ; Height of visible screen #ScreenMainDepth=5 ; The bit depth of the main screen #ScreenMainColors=32 ; The number of colors for the main screen #HudHeight=40 ; Height of HUD #HudDepth=5 ; The bit depth of the HUD #HudColors=32 ; The number of colors for the HUD #TileWidth=16 ; Width of tiles #TileHeight=16 ; Height of tiles #TileDepth=5 ; The bit depth of the tiles (other bit depths than 5 is untested) #TileXShift=4 ; Set according to #TileWidth (16->4, 32->5) #TileYShift=4 ; Set according to #TileHeight (16->4, 32->5) #MapWidth=20 ; Tilemap width (number of tiles wide) #MapHeight=52 ; Tilemap height (number of tiles high) #ScrollSpeed=1 ; Scroll speed, this equals the number of tiles that needs to be drawn every frame ; Calculated constants (from constants above) #TileXAndNot=0-#TileWidth ; Used for inverted bitshift AND to get nearest multiple of #TileWidth #TileYAndNot=0-#TileHeight ; Used for inverted bitshift AND to get nearest multiple of TileHeight #TileHeight1P=#TileHeight*#TileDepth ; The tileheight for an interleaved bitmap #BufferDepth=#ScreenMainDepth ; The buffer bit depth, same as main screen depth #BufferWidth=#ScreenMainWidth ; Buffer bitmap width (screen width) #BufferHeight=#ScreenMainHeight+#TileHeight*2 ; Buffer bitmap height (screen height + padding) #BufferTilesX=#BufferWidth/#TileWidth ; Number of tiles that fits horisontally on the buffer bitmap #BufferTilesY=#BufferHeight/#TileHeight ; Number of tiles that fits vertically on the buffer bitmap #MapXMax=#MapWidth*#TileWidth-#ScreenMainWidth-#TileWidth*2 ; Camera max x position #MapYMax=#MapHeight*#TileHeight-#ScreenMainHeight-#TileHeight*2 ; Camera max y position ; Keyboard etc. constants #KeyUp=$4C #KeyDown=$4D #KeyLeft=$4F #KeyRight=$4E #KeyEscape=$45 #DirNone=0 #DirUp=1 #DirDown=2 #DirLeft=3 #DirRight=4 #BitmapTemp=0 #BitmapBuffer1=1 #BitmapBuffer2=2 #BitmapHud=3 #BitmapTiles=4 #BitmapVTiles=5 #BitmapVBuffer1=6 #BitmapVBuffer2=7 #PaletteMain=0 #PaletteHud=0 #CopListMain=0 #CopListHud=1 ; Tiles bitmap #TileCountX=229 ; The number of tiles horisontally in the tiles bitmap #TileCountY=1 ; The number of tiles vertically in the tiles bitmap Macros: ; --------------------------------------------------------------- ; Get a tile from the tilemap array ; The bitwise AND 255 is for reading the byte value as unsigned Macro GetTile (map(`1, `2) & 255) End Macro ; Draw a tile ;!DrawTile{TileX,TileY,X,Y} Macro DrawTile BlockScroll (map(`1, `2) & 255) LSL #TileXShift, 0, #TileWidth, #TileHeight1P, `3, `4, #BitmapVTiles End Macro ; Round down value to nearest tile height ; -16 is the same as ~(#TileHeight-1) Macro RoundToBlockHeight (`1 & -#TileHeight) End Macro ; This is a faster way of doing MOD #TileHeight Macro ModNumSteps (`1 & (#TileHeight-1)) End Macro Variables: ; --------------------------------------------------------------- db.b=0 ; Keeps track of double buffer bitmap used (not in use currently) x=0 y=0 tile_x=0 tile_y=0 map_w=0 map_h=0 map_x=0 map_y=0 scroll_dir_prev.b=#DirNone bp.l=0 videopos_y=0 show_y=0 ScreenSetup: ; --------------------------------------------------------- ; Create two bitmaps for double buffered display BitMap #BitmapBuffer1,#BufferWidth,#BufferHeight,#BufferDepth BitMap #BitmapHud,#ScreenMainWidth,#HudHeight,#HudDepth ; Convert the buffer bitmap to be interleaved ConvertBMToIL{#BitmapBuffer1,#BufferWidth,#BufferHeight,#BufferDepth} ; Get a pointer to the background bitmap *db1.bitmap = Addr Bitmap(#BitmapBuffer1) ; Set clipping limit to max to enable blitting ourside of bitmap *db1\_xclip = $7FFF ; Create a "virtual" one plane bitmap for blitting to. We will still use the ; "normal" bitmap with the display command CludgeBitMap #BitmapVBuffer1,#BufferWidth,#BufferHeight*#BufferDepth,1,*db1\_data[0] ; Get a pointer to the virtual bitmap *dbv.bitmap = Addr Bitmap(#BitmapVBuffer1) ; Set clipping limit to max to enable blitting ourside of bitmap *dbv\_xclip = $7FFF *dbv\_yclip = $7FFF ; Create a bitmap for the tiles BitMap #BitmapTiles,#TileCountX*#TileWidth,#TileCountY*#TileHeight,#TileDepth *bmt.bitmap = Addr Bitmap(#BitmapTiles) ; Load the tiles to bitmap 2 LoadBitMap #BitmapTiles,"tilesrow32.iff" ; Load the palette from the same image LoadPalette #PaletteMain,"tilesrow32.iff" ; Convert the tiles bitmap to be interleaved ConvertBMToIL{#BitmapTiles, #TileCountX LSL #TileXShift, #TileCountY LSL #TileYShift, #TileDepth} ; Create a virtual 1-plane bitmap from the tiles bitmap CludgeBitMap #BitmapVTiles, #TileCountX LSL #TileXShift, #TileHeight1P, 1, *bmt\_data[0] ; Read the tile map If ReadFile(0,"world.map") ; First two words are width and height of tilemap ReadMem 0,&map_w,2 ReadMem 0,&map_h,2 ; Create a two dimensional array for the tilemap Dim map.b(map_w-1, map_h-1) ; Read the entire tilemap into the array ReadMem 0,&map(0,0),map_w*map_h ; Close the tilemap file CloseFile 0 EndIf ; Wait for disk activity to finish before going into Blitz mode VWait 100 ; Go into blitz mode and enable blitzkeys BLITZ BlitzKeys On ; Create copperlists for the display ; y=44, lores, smoothscroll, 5 bitplanes, 8 sprites, 32 colours, 12 copper commands InitCopList #CopListMain,44,#ScreenMainHeight,$10+#ScreenMainDepth,8,#ScreenMainColors,12 ; y=44, lores, smoothscroll, 5 bitplanes, 8 sprites, 32 colours, 12 copper commands InitCopList #CopListHud,46+#ScreenMainHeight,#HudHeight,$10+#HudDepth,8,#HudColors,12 ; Create a display using the copperlists CreateDisplay #CopListMain,#CopListHud ; Set up palettes DisplayPalette #CopListMain,#PaletteMain DisplayPalette #CopListHud,#PaletteHud ; Output text to HUD bitmap BitMapOutput #BitmapHud Colour 18,4 Use BitMap #BitmapHud Cls 4 ; Use virtual buffer bitmap Use BitMap #BitmapVBuffer1 ; Draw tiles to fill the whole bitmap For y = 0 To #BufferTilesY-1 For x = 0 To #BufferTilesX-1 !DrawTile{x, y, x LSL #TileXShift, y * #TileHeight1P} Next Next ; Display HUD bitmap on HUD copperlist DisplayBitMap #CopListHud,#BitmapHud,0,0 MainLoop: ; --------------------------------------------------------- Repeat ; Wait for vertical blank VWait 1 ; Set screen position show_y = (videopos_y+#TileHeight) MOD #BufferHeight splitline = #BufferHeight-show_y ; Show bitmap on copperlist DisplayBitMap 0,#BitmapBuffer1,0,show_y ; Reset the main copper list CopperReset 0, 0 ; Are we displaying over the bottom edge If splitline < #ScreenMainHeight ; Wait until the bottom edge CopperWait 0, splitline + 44 ; Reset the display to the top of the bitmap bp.l = *db1\_data[0] CopperMove $0e0, bp lsr 16 CopperMove $0e2, bp & $ffff bp.l = *db1\_data[1] CopperMove $0e4, bp lsr 16 CopperMove $0e6, bp & $ffff bp.l = *db1\_data[2] CopperMove $0e8, bp lsr 16 CopperMove $0ea, bp & $ffff bp.l = *db1\_data[3] CopperMove $0ec, bp lsr 16 CopperMove $0ee, bp & $ffff bp.l = *db1\_data[4] CopperMove $0f0, bp lsr 16 CopperMove $0f2, bp & $ffff Else ; If we're not displaying over the bottom edge, just wipe out our copper commands CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 EndIf ; Scrolling up? If RawStatus(#KeyUp) JSR ScrollUp : JSR ScrollUp EndIf ; Scrolling down? If RawStatus(#KeyDown) JSR ScrollDown : JSR ScrollDown EndIf ;Locate 0,0 : Print "Y:",map_y," " Until RawStatus(#KeyEscape)=-1 ; Exit game End ; ------------------------------------------------ ; Scroll Up ; ------------------------------------------------ ScrollUp: If map_y > 0 ; Decrease position first map_y-1 videopos_y-1 If videopos_y < 0 Then videopos_y+#BufferHeight ; Tile position tile_x = !ModNumSteps{map_y} LSL 1 If tile_x < #BufferTilesX tile_y = map_y LSR #TileYShift x = tile_x LSL #TileXShift y = !RoundToBlockHeight{videopos_y} * #BufferDepth !DrawTile{tile_x, tile_y, x, y} If tile_x+1 < #BufferTilesX !DrawTile{tile_x+1, tile_y, x+#TileWidth, y} EndIf EndIf EndIf RTS ; ------------------------------------------------ ; Scroll Down ; ------------------------------------------------ ScrollDown: If map_y < #MapYMax tile_x = !ModNumSteps{map_y} LSL 1 If tile_x < #BufferTilesX tile_y = #BufferTilesY + map_y LSR #TileYShift x = tile_x LSL #TileXShift y = !RoundToBlockHeight{videopos_y} * #BufferDepth !DrawTile{tile_x, tile_y, x, y} If tile_x+1 < #BufferTilesX !DrawTile{tile_x+1, tile_y, x+#TileWidth, y} EndIf EndIf ; Increase position last map_y+1 videopos_y+1 If videopos_y >= #BufferHeight Then videopos_y-#BufferHeight EndIf RTS 2019-03-12 - Added MIT license.txt 2019-03-11 - Changed to use interleaved bitmaps - Optimisations and cleanup 2019-02-23 - Copper bug fixed (thanks to earok) - Working HUD 2019-02-22 - First version Last edited by MickGyver; 12 March 2019 at 11:45. Reason: Updated the demo source |
23 February 2019, 09:14 | #6 | ||
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,542
|
I think I might have worked out the Copper bug (why you've needed to use CopperEnd there).
In the documentation of the CopperFX library Quote:
Quote:
I think it's safe to be a bit generous and give yourself more copper space than you think you need. |
||
23 February 2019, 12:31 | #7 | |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Quote:
|
|
24 February 2019, 00:44 | #8 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,542
|
Excellent!
There was one more thing I wanted to bring up. You might have noticed that the screen height the example isn't exactly fullscreen, that's indeed due to complications around having the vertical wrap past line 255. However, it's perfectly possible to do so, but it's a little more tricky. You do indeed need to use CopperEnd in that case (and ONLY when the wrap is beyond line 255). On top of that, you need to make sure you run at least two wait commands to get to the correct line (since the wait command uses bytes for Y position, you can't specify a line higher than 255 - you need to do two wait commands). ALSO, it makes it even more complicated if you have a second copper display (say, a UI bar at the bottom). It may be a bit easier if you're exercising total control over the copper, but if you're using Blitz's copperlist commands it may be far more complicated to manage. For that reason, with the Kiwi's Tale I opted to make the top display end just short of the 255 line, and use all of the space underneath that for UI. |
26 February 2019, 21:52 | #9 | |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
8-Way Scrolling Beta
Quote:
I have now almost managed to get 8-way tilemap scrolling to work using coppersplit+corkscrew by looking at http://aminet.net/package/dev/src/ScrollingTrick and the devnotes for Kiwi's Tale. I would be super grateful if somebody else could have a look at what's wrong. The variable names are the same as in the ScrollingTrick examples and this demo is based on "Scroller_XYLimited". There are sources and html explanations in ScrollingTrick.lha. The problem: When scrolling down-right there can be graphical errors of tile-wide lines. This is caused by corkscrew scrolling but for some reason I can't repair it. The repairing when switching from left-right or vice-versa is working. Code:
; **************************************************** ; ; Single buffer 8-way tilemap scrolling demo (corkscrew+coppersplit) ; by MickGyver @ English Amiga Board 2019 ; Based on http://aminet.net/package/dev/src/ScrollingTrick ; and earoks dev notes for Kiwi's Tale ; ; TODO: Fix graphic glitch when scrolling down-right (tile needs repairing) ; TODO: Implement double buffering ; ; In order to use the Bitmap newtype, include the resident file ; Blitzlibs:Bb2objtypes.res in the residents list in the compiler options. ; ; **************************************************** ;INCLUDE "helper_functions.bb2" ; Enable running from Workbench WBStartup ; Set default type to word DEFTYPE .w ; Set up interrupt 5 so we can cap to 25fps etc. vb=0 SetInt 5 vb+1 End SetInt ; Macros ; Get a tile from the tilemap array ; The bitwise AND 255 is for reading the byte value as unsigned Macro GetTile (map(`1, `2) & 255)-1 End Macro ; Round down value to nearest tile width ; -16 is the same as ~(#TILE_W-1) Macro RoundToBlockWidth `1 & -16 End Macro ; Round down value to nearest tile width Macro RoundToBlockHeight `1 & -16 End Macro ; Frame (for debugging) Macro Frame Box `1+1,`2+1,`1+14,`2+14,`3 End Macro ; Constants #SCR_W=320 ; Width of visible screen #SCR_H=208 ; Height of visible screen #HUD_H=40 ; Height of HUD #TILE_W=16 ; Width of tiles #TILE_H=16 ; Height of tiles #TILE_XSHIFT=4 ; Set according to #TILE_W (16->4, 32->5) #TILE_YSHIFT=4 ; Set according to #TILE_H (16->4, 32->5) #MAP_W=82 ; Tilemap width (number of tiles wide) #MAP_H=51 ; Tilemap height (number of tiles high) #SCROLL_SPEED=1 ; Scroll speed, this equals the number of tiles that needs to be drawn every frame ; Calculated constants (from constants above) #SCR_XCOUNT=10 ; Total number of screens horisontally in tilemap #TILE_XPAD=#TILE_W ; The horisontal tile padding, for each side #TILE_YPAD=#TILE_H ; The vertical tile padding #TILE_XANDNOT=0-#TILE_W ; Used for inverted bitshift AND to get nearest multiple of TILE_W #TILE_YANDNOT=0-#TILE_H ; Used for inverted bitshift AND to get nearest multiple of TILE_H #BM_W=#SCR_W+#TILE_XPAD*2 ; Buffer bitmap width (screen width + padding) #BM_H=#SCR_H+#TILE_YPAD*2 ; Buffer bitmap height (screen height + padding) #BUFFER_H=#BM_H ; #BM_TILES_X=#BM_W/#TILE_W ; Number of tiles that fits horisontally on the buffer bitmap #BM_TILES_Y=#BM_H/#TILE_H ; Number of tiles that fits vertically on the buffer bitmap #MAP_XMAX=#MAP_W*#TILE_W-#SCR_W-#TILE_W*2 #MAP_YMAX=#MAP_H*#TILE_H-#SCR_H-#TILE_H*2 #TWOBLOCKS=#BM_TILES_X-#TILE_H #TWOBLOCKSTEP=#TWOBLOCKS ; Keyboard etc. constants #KEY_UP=$4C #KEY_DOWN=$4D #KEY_LEFT=$4F #KEY_RIGHT=$4E #KEY_ESCAPE=$45 #KEY_BACKSPACE=$41 #DIR_NONE=0 #DIR_UP=1 #DIR_DOWN=2 #DIR_LEFT=3 #DIR_RIGHT=4 ; Tiles bitmap #TILECOUNT_X=19 ; The number of tiles horisontally in the tiles bitmap #TILECOUNT_Y=12 ; The number of tiles vertically in the tiles bitmap #TILE_BLUE=205 #TILE_YELLOW=207 #TILE_ORANGE=208 #WHITE=18 #YELLOW=19 #TURQOISE=20 #ORANGE=21 #PINK=22 ; Global variables db.b=0 ; Keeps track of double buffer bitmap used (not in use currently) x=0 y=0 x2=0 y2=0 ymax=0 i=0 mapx=0 mapy=0 tile=0 map_w=0 map_h=0 mapposx=0 ; Map X position, increments infinitely mapposy=0 blit_yoffset.b=0 ; Y offset for blitting due to corkscrew scroll scroll_dir_prev.b=#DIR_NONE bp.l=0 videoposx=0 videoposy=0 show_y=0 splitline=0 splitoffset=0 ; Create two bitmaps for double buffered display BitMap 0,#BM_W,#BUFFER_H+20,5 BitMap 1,#BM_W,#BUFFER_H+20,5 BitMap 2,#SCR_W,#HUD_H,5 ; Create a bitmap for the tiles BitMap 3,#TILECOUNT_X*#TILE_W,#TILECOUNT_Y*#TILE_H,5 ; Load the tiles to bitmap 2 LoadBitMap 3,"tiles.iff" ; Load the palette from the same image LoadPalette 0,"tiles.iff" ; Create shapes for all the tiles (increase the max number of shapes in compiler options to 255) i = 0 For y=0 To #TILECOUNT_Y-1 For x=0 To #TILECOUNT_X-1 GetaShape i, x LSL #TILE_XSHIFT, y LSL #TILE_YSHIFT, #TILE_W, #TILE_H i+1 Next Next ; Helper tiles for debugging ;LoadBitMap 3,"tiles_helpers.iff" ;helpers_start=i ;For i=helpers_start To helpers_start+5 ; GetaShape i, i LSL #TILE_XSHIFT, 0, #TILE_W, #TILE_H ;Next ; Free the bitmap used to load the tiles Free BitMap 3 ; Read the tile map If ReadFile(0,"world.map") ; First two words are width and height of tilemap ReadMem 0,&map_w,2 ReadMem 0,&map_h,2 ; Create a two dimensional array for the tilemap Dim map.b(map_w-1, map_h-1) ; Read the entire tilemap into the array ReadMem 0,&map(0,0),map_w*map_h ; Close the tilemap file CloseFile 0 EndIf ; Wait for disk activity to finish before going into Blitz mode VWait 100 ; Go into blitz mode and enable blitzkeys BLITZ BlitzKeys On ; Create copperlists for the display InitCopList 0,44,#SCR_H,$15,8,32,12 ; y=44, lores, smoothscroll, 5 bitplanes, 8 sprites, 32 colours, 12 copper commands InitCopList 1,46+#SCR_H,#HUD_H,$15,8,32,12 ; y=44, lores, smoothscroll, 5 bitplanes, 8 sprites, 32 colours, 12 copper commands ; Create a display using copperlist 0 and 1 CreateDisplay 0,1 ; Use palette 0 (second parameter) for copperlist 0 (first parameter) DisplayPalette 0,0 DisplayPalette 1,0 ; Output text to bitmap 2 (HUD) BitMapOutput 2 Colour 18,4 Use BitMap 2 Cls 4 ; Use first bitmap Use BitMap db ; Draw tiles to fill the whole bitmap For y = 0 To #BM_TILES_Y-1 For x = 0 To #BM_TILES_X-1 ; Map is exported from Tiled, so the value 0 means no tile, because of that the tile value is reduced by one Block !GetTile{x,y}, x LSL #TILE_XSHIFT, y LSL #TILE_YSHIFT Next Next ; Copy bitmap 0 to bitmap 1 so both double buffer bitmaps are identical CopyBitMap 0,1 ; Display HUD bitmap on second copperlist DisplayBitMap 1,2,0,0 ; Get the pointer to the front buffer bitmap *b.bitmap = Addr Bitmap(db) *b\_xclip = $7FFF block_videoposy=0 stepx=0 stepy=0 mapblocky=0 mapblockx=0 time_taken=0 time_max=0 timeq.q=0.0 time_dir_pressed=0 ; The main loop MainLoop: Repeat ; Wait for vertical blank VWait 1 vb=0 ; Set screen position show_y = (videoposy+#TILE_H) MOD #BM_H splitline = #BM_H-show_y ; Show bitmap 0 on copperlist 0 at offset DisplayBitMap 0,db,mapposx+#TILE_XPAD,show_y ; Switch to other double buffer bitmap ; db = 1-db ; Use BitMap db ;StartTimer{} ; Reset the copper, this is needed for the library to work CopperReset 0, 0 ; Update the copperlist ; Are we displaying over the bottom edge? If splitline < #SCR_H ; Scroll to the correct position splitoffset = (mapposx+#TILE_XPAD) / 8 ; Wait until the bottom edge CopperWait 0, splitline + 44 ; Reset the display to the top of the bitmap bp.l = *b\_data[0] + splitoffset CopperMove $0e0, bp lsr 16 CopperMove $0e2, bp & $ffff bp.l = *b\_data[1] + splitoffset CopperMove $0e4, bp lsr 16 CopperMove $0e6, bp & $ffff bp.l = *b\_data[2] + splitoffset CopperMove $0e8, bp lsr 16 CopperMove $0ea, bp & $ffff bp.l = *b\_data[3] + splitoffset CopperMove $0ec, bp lsr 16 CopperMove $0ee, bp & $ffff bp.l = *b\_data[4] + splitoffset CopperMove $0f0, bp lsr 16 CopperMove $0f2, bp & $ffff Else ; If we're not displaying over the bottom edge, just wipe out our copper commands CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 CopperMove $1fe, 0 : CopperMove $1fe, 0 : CopperMove $1fe, 0 EndIf ; Reset the max value for the timer? If RawStatus(#KEY_BACKSPACE) time_max=0 EndIf ; Scrolling up? If RawStatus(#KEY_UP) BSR ScrollUp : BSR ScrollUp : BSR ScrollUp Else ; Scrolling down? If RawStatus(#KEY_DOWN) BSR ScrollDown : BSR ScrollDown : BSR ScrollDown EndIf EndIf ; Scrolling left? If RawStatus(#KEY_LEFT) BSR ScrollLeft : BSR ScrollLeft : BSR ScrollLeft Else ; Scrolling right? If RawStatus(#KEY_RIGHT) BSR ScrollRight : BSR ScrollRight : BSR ScrollRight EndIf EndIf ; Stop timer ;time_taken=EndTimer{} ; Check the result of the timer before printing If time_taken>time_max time_max=time_taken timeq=time_max*time_constant EndIf ; Print stuff to HUD Locate 0,0 : Print "mapposx:",mapposx,",mapposy:",mapposy," " Locate 0,1 : Print "mapblockx:",mapblockx,"mapblocky:",mapblocky," " Locate 0,2 : Print "stepx:",stepx,",block_videoposy:",block_videoposy," " Locate 0,3 : Print "timer:",0,",timer_max:",timeq,"us " Until RawStatus(#KEY_ESCAPE)=-1 ; Quit game End ScrollUp: If mapposy > 0 ; Increase position first mapposy-1 mapblocky=mapposy LSR #TILE_YSHIFT stepy=mapposy & (#TILE_H-1) videoposy-1 If videoposy<0 videoposy+#BM_H EndIf If stepy = (#TILE_H-1) block_videoposy-#TILE_H If block_videoposy<0 block_videoposy+#BM_H EndIf If stepx > 0 ; step 1: blit the 1st block in the fillup mapx=mapblockx+#BM_TILES_X mapy=mapblocky+1 x=!RoundToBlockWidth{videoposx} y=(block_videoposy+#TILE_H) MOD #BM_H Block !GetTile{mapx,mapy}, x+#BM_W, y ; step 2: remove the (former) bottommost fill up block ; we blit a 'left' block If stepx+1 < #BM_TILES_Y mapy=stepx+1 ;Else ; mapy=#BM_TILES_Y-1 ;EndIf y = (block_videoposy+(mapy LSL #TILE_YSHIFT)) MOD #BM_H mapx-#BM_TILES_X mapy+mapblocky Block !GetTile{mapx,mapy}, x, y ; Repair broken tile if needed If scroll_dir_prev=#DIR_RIGHT ; OK!!! If stepx+2 < #BM_TILES_Y y2=y+#TILE_H If y2>=#BM_H Then y2-#BM_H Block !GetTile{mapx,mapy+1}, x, y2 EndIf EndIf ; Set previous direction as left scroll_dir_prev=#DIR_LEFT EndIf EndIf EndIf mapx=stepy mapy=mapblocky y=block_videoposy If mapx >= #TWOBLOCKSTEP ; blit only one block mapx+#TWOBLOCKSTEP x=mapx LSL #TILE_XSHIFT + !RoundToBlockWidth{videoposx} mapx+mapblockx Block !GetTile{mapx,mapy}, x, y Else ; Draw two tiles mapx=mapx LSL 1 x=mapx LSL #TILE_XSHIFT + !RoundToBlockWidth{videoposx} mapx+mapblockx Block !GetTile{mapx,mapy}, x, y Block !GetTile{mapx+1,mapy}, x+#TILE_W, y EndIf EndIf RTS ScrollDown: If mapposy < #MAP_YMAX ; Get positions mapx = stepy mapy = mapblocky + #BM_TILES_Y y = block_videoposy If mapx >= #TWOBLOCKSTEP ; blit only one block mapx+#TWOBLOCKSTEP x=mapx LSL #TILE_XSHIFT + !RoundToBlockWidth{videoposx} mapx+mapblockx Block !GetTile{mapx,mapy}, x, y Else ; Blit two blocks mapx = mapx LSL 1 x = mapx LSL #TILE_XSHIFT + !RoundToBlockWidth{videoposx} mapx+mapblockx ; Get tiles and draw them Block !GetTile{mapx,mapy}, x, y Block !GetTile{mapx+1,mapy}, x+#TILE_W, y EndIf ; Increase position mapposy+1 mapblocky=mapposy LSR #TILE_YSHIFT stepy=mapposy & (#TILE_H-1) videoposy+1 If videoposy>=#BM_H videoposy-#BM_H EndIf ; If stepy=0 then we need to fix the horisontal fillup row If stepy=0 block_videoposy+#TILE_H If block_videoposy>=#BM_H block_videoposy-#BM_H EndIf If stepx > 0 ; step 1: blit the 1st block in the fillup row (y) mapx=mapblockx mapy=mapblocky x=!RoundToBlockWidth{videoposx} y=block_videoposy ; should be this value already Block !GetTile{mapx,mapy}, x, y ; step 2: blit the (new) bottommost fill up block ; we blit a 'right-block' If stepx < #BM_TILES_Y mapy=stepx Else mapy=#BM_TILES_Y-1 EndIf x+#BM_W y=(block_videoposy+(mapy LSL #TILE_YSHIFT)) MOD #BM_H y2=(block_videoposy+((mapy+1) LSL #TILE_YSHIFT)) MOD #BM_H mapx+#BM_TILES_X mapy+mapblocky ; Can get out of range, does map need to be one tile higher? ; Repair broken tile if needed ; There's something wrong with down-right scrolling! ; If scroll_dir_prev=#DIR_LEFT ;If stepx < #BM_TILES_Y-1 ; y2=y-#TILE_H ; If y2<0 Then y2+#BM_H ;Block !GetTile{mapx,mapy+1}, x, y2 ;!Frame{x,y,#YELLOW} ;EndIf ; EndIf Block !GetTile{mapx,mapy}, x, y ;!Frame{x,y,#WHITE} ; Set previous direction as right scroll_dir_prev=#DIR_RIGHT End If EndIf EndIf RTS ScrollLeft: If mapposx > 0 ; Decrease position mapposx-1 mapblockx=mapposx LSR #TILE_XSHIFT stepx=mapposx & (#TILE_W-1) videoposx-1 If stepx = (#TILE_W-1) ; step 1: blit the block which came in at the left side, ; which might or might not be a fill up block mapx=mapblockx mapy=mapblocky If stepy > 0 ; there is a fill up block mapy+#BM_TILES_Y EndIf x=!RoundToBlockWidth{videoposx} y=block_videoposy ; Mostly ok Block !GetTile{mapx,mapy}, x, y ; step 2: remove the (former) rightmost fillup-block mapx=stepy If mapx > 0 ; there is a fill up block If mapx >= #TWOBLOCKSTEP mapx+#TWOBLOCKSTEP Else mapx=mapx LSL 1 ; mapx=mapx*2 EndIf x=!RoundToBlockWidth{videoposx}+(mapx LSL #TILE_XSHIFT) ; mapx*#TILE_W y=block_videoposy mapx+mapblockx mapy-#BM_TILES_Y ; Mostly ok Block !GetTile{mapx,mapy}, x, y EndIf EndIf mapx=mapblockx mapy=stepx+1 x=!RoundToBlockWidth{videoposx} y=(block_videoposy+(mapy LSL #TILE_YSHIFT)) MOD #BM_H mapy+mapblocky ; Repair broken tile if needed If scroll_dir_prev=#DIR_RIGHT ; OK!!!! If stepx+2 < #BM_TILES_Y y2=y+#TILE_H If y2>=#BM_H Then y2-#BM_H Block !GetTile{mapx,mapy+1}, x, y2 EndIf EndIf If stepx+1 < #BM_TILES_Y ; Don't draw tiles every step, it's not needed/wanted Block !GetTile{mapx,mapy}, x, y EndIf If stepx > 0 scroll_dir_prev=#DIR_LEFT Else scroll_dir_prev=#DIR_NONE EndIf EndIf RTS ScrollRight: If mapposx < #MAP_XMAX mapx=mapblockx + #BM_TILES_X mapy=stepx+1 x=!RoundToBlockWidth{videoposx} y=(block_videoposy+(mapy LSL #TILE_YSHIFT)) MOD #BM_H ;y2=(block_videoposy+((mapy-1) LSL #TILE_YSHIFT)) MOD #BM_H mapy+mapblocky ; Repair broken tile if needed If scroll_dir_prev=#DIR_LEFT If stepx > 0 AND stepx < #BM_TILES_Y-1 y2=y-#TILE_H If y2<0 Then y2+#BM_H Block !GetTile{mapx,mapy-1}, x+#BM_W, y2 EndIf EndIf ; Blit one block If stepx+1 < #BM_TILES_Y ; Don't draw tiles every step, it's not needed/wanted Block !GetTile{mapx,mapy}, x+#BM_W, y EndIf ; Increase position mapposx+1 mapblockx=mapposx LSR #TILE_XSHIFT stepx=mapposx & (#TILE_W-1) videoposx+1 If stepx = 0 ; step 1: blit the block which came in at the right side, ; which is never a fill up block mapx=mapblockx+#BM_TILES_X-1 mapy=mapblocky x=!RoundToBlockWidth{videoposx}+(#BM_TILES_X-1) LSL #TILE_XSHIFT y=block_videoposy ; Seems ok Block !GetTile{mapx,mapy}, x, y ; step 2: blit the (new) rightmost fillup-block mapx=stepy If mapx > 0 ; there is a fill up block If mapx >= #TWOBLOCKSTEP mapx = mapx + (#TWOBLOCKSTEP-1) Else mapx = mapx LSL 1 - 1 EndIf x=!RoundToBlockWidth{videoposx} + (mapx LSL #TILE_XSHIFT) y=block_videoposy mapx+mapblockx ; Seems ok Block !GetTile{mapx,mapy+#BM_TILES_Y}, x, y EndIf EndIf If stepx > 0 scroll_dir_prev=#DIR_RIGHT Else scroll_dir_prev=#DIR_NONE EndIf EndIf RTS Last edited by MickGyver; 11 March 2019 at 10:38. Reason: Removed the attachment due to updated version |
|
27 February 2019, 00:27 | #10 |
Phone Homer
Join Date: Jun 2006
Location: 5150
Posts: 5,775
|
If im correct the C Demo Scrolling trick uses the method were you draw behind and in front creating an identical image like this http://eab.abime.net/showthread.php?t=80646or for horizontal and vertical -
and no corkscrew is used ive only ever done 8 way scrolling like this and yes scrolling down right is the ultimate test - if you view the entire Bitmap save it as iff not just what is displayed on screen ie something like 640 *480 you will see it split into something like 4 identical pictures - when full scroll down right. There must be a fairly simple formula for this something like screen width, height = number of tiles that must be drawn and height and width bimtmap must be to complete perfect down right scroll. I never figured it out the formula and no one has ever published it to my knowledge I just guessed and worked on overkill to make sure I drew enough tiles etc. and as you know Blitz has problems InitCopList corkscrew past 8191 Last edited by Retro1234; 27 February 2019 at 00:46. |
27 February 2019, 07:20 | #11 | |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Quote:
There are several scrolling methods explained in the ScrollingTrick archive. I'm trying to implement (almost there) the most efficient 8-way scrolling using a copper split for vertical scrolling and corkscrew for horisontal scrolling. The bitmap size needed is only a little more than screen size and incoming tiles are only drawn once. |
|
27 February 2019, 14:46 | #12 |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
This shows what's happening when scrolling down, then slightly right. It happens at certain x-positions only, sooo annoying, I'm so close to having this working.
The actual bitmap (thanks for the tip Retro1234) |
27 February 2019, 15:02 | #13 | |
Registered User
Join Date: Nov 2015
Location: Italy
Posts: 191
|
Quote:
The demo programs in ScrollingTrick archive can be started with "HOW" parameter. Then the scrolling is disabled and you see on screen how the horizontal/vertical fillup columns are filled and readjusted while moving around. Try something similiar with your code and compare. |
|
27 February 2019, 15:22 | #14 |
Registered User
Join Date: Nov 2015
Location: Italy
Posts: 191
|
Hmm ... in theory the left side should be in false/different colors because of the plane shifting (if the bitmap is looked at the from fixed 0,0 position then the more to the right that you have scrolled, the more the new blocks have shifted into different planes. see scrollintrick demos with HOW param and keep scrolling to the right). |
27 February 2019, 18:14 | #15 |
Registered User
Join Date: Nov 2015
Location: Italy
Posts: 191
|
|
27 February 2019, 18:48 | #16 |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Thanks for helping! That is a non-interleaved bitmap yes. My implementation seems to work fine except for that one small down-right graphic glitch. The tilemap I'm testing with is 80x50 tiles or 1280x800px big. I'm going to look into interleaved mode now.
|
27 February 2019, 19:02 | #17 |
Phone Homer
Join Date: Jun 2006
Location: 5150
Posts: 5,775
|
cools pics, love stuff like that
Wheres the error? those 6 green lines? looks like the tiles are just slightly wrong Y position? |
27 February 2019, 19:14 | #18 |
Registered User
Join Date: Oct 2008
Location: Finland
Posts: 643
|
Those six green lines yes, they appear when scrolling down and then right, but only when scrolling down at certain x-values. My screen is only 208px high, the ScrollingTrick demos assume a 256px high screen so I have had to modify some things that could have created this bug. I'm going to try to convert this example to use interleaved shapes and bitmaps (if I can) to see if works any better. I somehow suspect that I shouldn't have to use interleaved bitmaps since the demo is otherwise working fine but you'll never know.
|
27 February 2019, 19:46 | #19 | |
Registered User
Join Date: Nov 2015
Location: Italy
Posts: 191
|
Quote:
If your code isn't using the "saveword" optimization as in demo sources (only save/restore 2 bytes which are ~"trashed" when left/right scrolling, instead of a whole tile/block) then that can be so. But there are some differences for algorithm between interleaved and non interleaved bitmaps. For interleaved bitmap to be able to scroll 16 pixels to the right, the bitmap needs to only have additional 2 extra bytes (32 pixels -> 4 bytes -> 320 pixels -> 40 bytes). For a non interleaved bitmap that would be 2*numplanes extra bytes (32 pixels -> 4 * numplanes bytes, 320 pixels -> 40 * numplanes bytes). Example: interleaved bitmap at start x pixel position 0 goes from 0x10000 to 0x20000. At start x pixel position 16 it goes from 0x10002 to 0x20002. That's the whole bitmap with all planes. Because interleaved bitmap is basically a bit like a vertical strecthed single plane bitmap. For a non interleaved 2 plane bitmap at start x pixel position 0: plane 1 0x10000 to 0x11000. plane 2 0x12000 to 0x13000. At pixel position 16: plane 1 0x10002 to 0x11002. plane 2 0x12002 to 0x130002. Each plane needs an additional 2 bytes. So in total 4 extra bytes. |
|
27 February 2019, 19:51 | #20 |
Phone Homer
Join Date: Jun 2006
Location: 5150
Posts: 5,775
|
Yeah guess is all that's happening is corkscrew is out of sync and not on correct Y position, 1 pixel out.
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Tilemap Designer for Blitz Basic | Havie | Coders. Blitz Basic | 5 | 16 June 2014 00:19 |
tilemap.library | Samurai_Crow | Coders. System | 4 | 02 November 2011 21:08 |
smooth scrolling.is it possible? | kirk | support.WinUAE | 30 | 01 October 2007 13:57 |
Tilemap + Scrolling routines source code | Ultron | Coders. General | 0 | 02 April 2007 01:00 |
0.8.21 R2: Scrolling issues | andreas | support.WinUAE | 0 | 12 March 2002 08:14 |
|
|