Page 1 of 2

level sizes

Posted: Wed Aug 18, 2010 3:22 pm
by psycopathicteen
I'm making a new game engine, and it currently handles levels that are 32x4 screens or 512x64 blocks long. If I make my engine support other level sizes, do I need a different tile collision algorithm for every level size, or is there a way to make your tile collsion algorithm adjust to different sized levels?

Posted: Wed Aug 18, 2010 3:40 pm
by Memblers
I don't think it would matter, unless you're wanting to account for off-screen collisions (heheh). I haven't implemented this stuff properly yet, but I would hope to have the collision code indexing the level based on the scroll position. So then it would go as far as your level data goes.

Posted: Wed Aug 18, 2010 3:50 pm
by tokumaru
In a well programmed game level sizes shouldn't have anything to do with collision detection. You just need a solid way to read collision information from the map based on world coordinates, and that should work for levels of all sizes.

Posted: Wed Aug 18, 2010 4:24 pm
by psycopathicteen
How can it not have to do with the size of the level? If I have 512 x 64 tiles, I have to multiply the y-tile by 512 and add it to the x-tile. If I have 256 x 128 tiles, I have to multiply the y-tile by 256 and add it to the x-tile.

Posted: Wed Aug 18, 2010 4:31 pm
by tokumaru
psycopathicteen wrote:How should I store the level then?
Depends on how much ROM you have to waste! =)

Since you're working on the SNES, which has much more RAM than the NES, it makes sense to have your whole map decompressed from whatever format you compressed it with to RAM. Once in RAM it should be nothing more than a 2D array, that you access with the good old formula Y * width + X.

Posted: Wed Aug 18, 2010 4:33 pm
by tokumaru
psycopathicteen wrote:How can it not have to do with the size of the level? If I have 512 x 64 tiles, I have to multiply the y-tile by 512 and add it to the x-tile. If I have 256 x 128 tiles, I have to multiply the y-tile by 256 and add it to the x-tile.
Just don't hardcode the width. I'm sure the SNES can handle a dynamic multiplication. If you think it will be too slow, you can set aside some RAM and pre-calculate pointers to each row, like I do with my NES game.

Posted: Wed Aug 18, 2010 6:22 pm
by psycopathicteen
Too bad the Snes only has an 8 bit multiply.

Posted: Wed Aug 18, 2010 6:35 pm
by tokumaru
Well, the NES doesn't have any built-in multiplication and it can handle arbitrarily sized levels just fine, I'm sure the SNES can do it as well.

In my NES game, the level map is composed of screens (256x256 pixel blocks), like Sonic 1 on the MD or Mega Man X on the SNES, and levels can be up to 64 screens tall. Since the width of the maps varies and I don't want to do a multiplication every time I want to access them, Before the level starts I pre-calculate the address of every row of screens and store in a table, so that the Y coordinate will indicate which address I must use and the X coordinate is used as an index from that address on.

Posted: Wed Aug 18, 2010 6:35 pm
by ReaperSMS
So write a multiply function. The SNES one is 8x8=16 IIRC, and you can build whatever size you need out of that, and even do it with straight normal arithmetic if you so chose.

Posted: Wed Aug 18, 2010 6:37 pm
by tepples
You could arrange your decompressed level as a set of 256x256 pixel areas, as tokumaru edited into his post while I was writing mine. Animal Crossing series does this, wherein the 16x16-metatile areas are called "acres". Under such a scheme, you could even have screens with nothing in them be a null pointer; AC uses this for the solid wall or water acres outside the area where the player character can walk. Sonic 2 for Genesis likewise uses supermetatiles, each 128x128 pixels or 8x8 metatiles. Levels have a fixed size, but an individual supermetatile (such as those representing emptiness) is reused several times in a level. The one thing that becomes more complicated with supermetatile reuse is destructible terrain; you have to reserve some parts of RAM for copy-on-write, which is why Sonic tends to use sprites for anything destructible (such as rings).

Posted: Wed Aug 18, 2010 7:25 pm
by psycopathicteen
If I'm doing it by level, I'll use logarithmic multiplication.

If I'm doing it by room, I'll use the hardware multiplication.

Which method is the better method?


Just so you know, I'm doing v-ram loading a little bit different than conventional ways. I'm using the PPU's 16x16 pixel tile mode as opposed to metatiles, and I'm updating the screen as a whole as opposed to the conventional collumn and row method. I'm blanking out the top and bottom 16 scanlines to have more dma time. It might sound a little redundant, but it will make swapping out tiles so much easier.

Posted: Wed Aug 18, 2010 7:28 pm
by tokumaru
Aren't rooms essentially small levels? I don't see much difference.

Posted: Wed Aug 18, 2010 8:03 pm
by tepples
Perhaps "rooms" use screen-aligned scrolling as seen in The Legend of Zelda or Smash TV or The Legend of Zelda: Link's Awakening.

Posted: Wed Aug 18, 2010 8:41 pm
by blargg
psycopathicteen wrote:Too bad the Snes only has an 8 bit multiply.
It has signed 16x8 as well. See M7A, M7B, MPYL, MPYM, and MPYH.

Posted: Wed Aug 18, 2010 10:24 pm
by TmEE
On MD I have a so called "sector" setup, where there's always 4 active sectors that are decompressed into RAM and from within the objects are checked etc. Each sector is 16x16 metatiles in size, each metatile being 16x16 pixels. I only need 2Kbyte decomrpession buffer and all colission data etc. are derived from stage data in the zones. There's no MUL or DIV happening since there's no need, just old fashioned shifts ^^

Gotta love powers of two ^^ (and VDP address auto increment, I can toss out nearly all VRAM location calculations with the help of it :D )

One linitation is that going from one end of the stage to another will require decompressing inbetween sectors... that could be remedied if you use seek tables...