#54487 - Ultima2876 - Mon Sep 19, 2005 10:56 pm
Diagonal Scrolling - while loading tiles at the edges. Argh.
I think many of us have been there, and there's even an ancient topic about it.
I've been fiddling with this for a few days now, and can't get it right. Down and left/right scrolling works absolutely fine, but I'm having a strange problem with the diagonal aspect of the scrolling - it updates most of the VRAM map fine, except for a triangular section... and it only does this with maps of a different width to 32 tiles (although that's probably because I'm using a 256x256 VRAM map - which means it has the correct tiles there anyway). So, I have a 128x32 tile map, being read into my 32x32 VRAM map.
There's my code. The bios mods are for making the maps wrap around the map_height and map_width - which can be of any size.
At first I suspected the problem was to do with incorrect implementation of the X offsetting in this line:
And to be honest I still do. However, my brain is hurting quite a lot and i can't figure it out.
Next up, screenshots.
http://img155.imageshack.us/img155/5968/terrag4je.png
That's what it kind of should look like (a mock up, really).
http://img155.imageshack.us/img155/6033/terrag20jw.png
Any help would be very much appreciated.
I think many of us have been there, and there's even an ancient topic about it.
I've been fiddling with this for a few days now, and can't get it right. Down and left/right scrolling works absolutely fine, but I'm having a strange problem with the diagonal aspect of the scrolling - it updates most of the VRAM map fine, except for a triangular section... and it only does this with maps of a different width to 32 tiles (although that's probably because I'm using a 256x256 VRAM map - which means it has the correct tiles there anyway). So, I have a 128x32 tile map, being read into my 32x32 VRAM map.
Code: |
hofs_prev = *hoffset >> 3;
vofs_prev = *voffset >> 3; scroll_speedpart += speed & 0xFF; //deal with the fixed-point speed, and update the speed part (increment speed for the frame if the speed part overflows) speed = speed >> 8; speed += scroll_speedpart >> 8; scroll_speedpart = scroll_speedpart & 0xFF; if(speed > 8) { speed = 8; } if(direction == 0 || direction == 2 || direction == 4) //(right scrolling) { *hoffset += speed; //increase the offset by the speed if(hofs_prev != *hoffset >> 3) //if the last frame's tile-hoffset was different, you need to update the tiles { for(loop = 0; loop < 21; loop++) //update the tiles at the edge of the screen { temp_vofs = bios_mod(((loop + (*voffset >> 3))), map_height); ((u16*)map_vram)[(((loop + (*voffset >> 3)) & 0x1F) << 5) + *map_write_x] = ((u16*)map)[(map_width * temp_vofs) + *map_position_x]; } *map_position_x += 1; *map_write_x += 1; *map_write_x = *map_write_x & 0x1F; if (*map_position_x == map_width) { *map_position_x = 0; } } *BG_HOFS = *hoffset; //update the H scroll register } else if(direction == 1 || direction == 3 || direction == 5) //(left scrolling) { *hoffset -= speed; //decrease the offset by the speed if(hofs_prev != *hoffset >> 3) //if the last frame's tile-hoffset was different, you need to update the tiles { if (*map_position_x < -1) { *map_position_x = map_width - 1; } for(loop = 0; loop < 21; loop++) //update the tiles at the edge of the screen { temp_vofs = bios_mod(((loop + (*voffset >> 3))), map_height); ((u16*)map_vram)[(((loop + (*voffset >> 3)) & 0x1F) << 5) + *map_write_x] = ((u16*)map)[(map_width * temp_vofs) + *map_position_x]; } *map_position_x -= 1; *map_write_x -= 1; *map_write_x = *map_write_x & 0x1F; if (*map_position_x == -1) { *map_position_x = map_width - 1; } } *BG_HOFS = *hoffset; //update the H scroll register } if(direction == 4 || direction == 5 || direction == 7) //(down scrolling) { *voffset += speed; //increase the offset by the speed if(vofs_prev != *voffset >> 3) //if the last frame's tile-hoffset was different, you need to update the tiles { for(loop = 0; loop < 32; loop++) //update the tiles at the edge of the screen { temp_hofs = bios_mod(loop + hofs_prev, map_width); ((u16*)map_vram)[(*map_write_y << 5) + ((loop + hofs_prev) & 0x1F)] = ((u16*)map)[(map_width * *map_position_y) + temp_hofs]; } *map_position_y += 1; *map_write_y += 1; *map_write_y = *map_write_y & 0x1F; if (*map_position_y == map_height) { *map_position_y = 0; } } *BG_VOFS = *voffset + bgv; } |
There's my code. The bios mods are for making the maps wrap around the map_height and map_width - which can be of any size.
At first I suspected the problem was to do with incorrect implementation of the X offsetting in this line:
Code: |
((u16*)map_vram)[(*map_write_y << 5) + ((loop + hofs_prev) & 0x1F)] = ((u16*)map)[(map_width * *map_position_y) + temp_hofs]; |
And to be honest I still do. However, my brain is hurting quite a lot and i can't figure it out.
Next up, screenshots.
http://img155.imageshack.us/img155/5968/terrag4je.png
That's what it kind of should look like (a mock up, really).
http://img155.imageshack.us/img155/6033/terrag20jw.png
Any help would be very much appreciated.