What type of tilemapper are you going for? Smooth-scrolling tilemappers add an extra degree of pain-in-the-ass, and it is not always as simple as writing an aligned mapper first then converting it so it scrolls smoothly, as you will probably find that your finished tilemapper is too slow to be of any use. That's not to say that writing an aligned mapper isn't worth it, it's a relatively simple exercise that will get you used to using and manipulating tilemaps, and as an added bonus you'll be able to see how your maps turned out/look on the calculator.
For smoothscrolling, there are a lot of different ideas and routines floating around: with/without a buffer, rotating the entire screen, rotating the individual tiles, shifting in pixels, fastcopy mixed into the sprite routine, etc. You may spend a lot of time coming up with ideas, implementing them halfway, finding that it won't work or is too complicated, and starting over, or you may find something that works for you right away. Keep in mind that some tilemaps are easier to implement other things, such as animated tiles and multipixel scrolling.
A (very brief) general overview of tilemaps:
A basic tilemap:
Code: mapData:
.db 11,11
.db 1,1,1,1,1,1,1,1,1,1,1
.db 1,0,0,0,0,0,0,0,0,0,1
.db 1,0,2,0,0,0,0,0,0,0,1
.db 1,0,0,0,0,0,0,0,0,0,1
.db 1,0,0,0,0,0,0,0,0,0,1
.db 1,0,0,0,2,0,0,0,0,0,1
.db 1,0,0,0,0,0,0,0,0,0,1
.db 1,0,0,0,0,0,2,0,0,0,1
.db 1,0,0,0,0,0,0,0,0,0,1
.db 1,0,0,0,0,0,0,0,0,0,1
.db 1,1,1,1,1,1,1,1,1,1,1
tileData:
;tile 0
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
.db %00000000,%00000000
;tile 1
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
.db %01010101,%01010101
;tile 2
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
.db $FF,$FF
Reading from a tilemap, you have the start of the map data supplied to a register combo (hl, ix, de, bc, or maybe one of the shadow registers) where you find the offset (mapStart + mapWidth*y + x). You can save a bit of time using SMC (self-modifying code) in setting up the map offset and all of that, but the speed you would gain is pretty much negligible here. What you will find is that certain parts of your routine are repeated MANY MANY times (ie, over 700 bytes on the LCD must be updated. Your routine to update the screen will be run through that many times! 8x8 tiles have 8x12=96 tiles on screen, and 96 repetitions). If you aren't satisfied with the speed, look at the routines which are looped through many times and try to optimize them further. Cutting 4 cycles off a piece of your routine that is run 764 times will give you something to smile about :)
To actually pull the tile ID and get the tile's address:
Code: ;hl points to first onscreen tile
ld e,(hl)
ld d,0
ld hl,tileData
ex de,hl;de=tileData hl=tileID
add hl,hl;x2
add hl,hl;x4
add hl,hl;x8
add hl,hl;x16
add hl,hl;x32
add hl,de;hl=tileData + tileID*32
To read the first byte of data in the sprite (also note that the example i am using uses 16x16 sprites) load the value of (hl) somewhere to manipulate it. There's really no saying what to do from here, as it all depends on how you structure your tilemapper.
Things to think about with smoothscrolling mappers:
-in a tilemap with 8x8 tiles, when the tilemap is aligned there will be 8 rows and 12 columns of the tilemap data displayed on the screen. If the tilemap is unaligned for x values, there will be 13 columns of data displayed, and the first and last columns will be clipped. Same idea for unaligned y values.
-figuring out how you want to handle unaligned x values will require a lot of thinking! If the x offset is 3 (3 bytes offscreen to the left) every sprite has to be shifted left three pixels. As the LCD is arranged so that 1 byte holds 8 pixels, every sprite will straddle two bytes. Yikes!
-a simple solution to drawing a map with an unaligned y offset is to simply start drawing the sprite at the yth row of the sprite. To clip a sprite with 3 pixels off the top edge, draw rows 4 through (# rows in sprite - 3).
i had some other things in my head, but it is late now (the sun is about to come up and i haven't yet slept) and i can't remember them. I had planned for this to be more thorough, but i guess just ask questions if you have them. I am glad you're still thinking about this project But i'm off to bed! |