Collisions maps in Rpgs

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
dangu
Posts: 11
Joined: Wed Apr 08, 2020 3:20 am

Collisions maps in Rpgs

Post by dangu »

hi. First post here
I jumped into snes programming about a year ago, and have done a bit of experimentation with various modes, windows, colour math, sprite movements etc..
Now I've rougly implemented a simple sprite character that moves around a map 64x64 and the camera follows him in a 8 way direction fascion. I was planning to implement a collision map to interact with the background, and was wondering what could be the best approac.
At first, I though to load an array of 8x64 byte (for that 64x64map) where each 8 byte rappresent a row of 8x8pixel tiles, and each bit of every byte rappresents every single tile of the map. If bit is 0, the tile is walkable, if 1 it is not.
Because it's the first time i'm doing this I ask if there's a better way of doing this. Obviously now i'm not counting interation with other sprites and I don't care right now

Here the rom file
thanks
Attachments
main.smc
(256 KiB) Downloaded 112 times
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Collisions maps in Rpgs

Post by tokumaru »

I think that using a single bit (walkable vs. not walkable) is extremely restrictive, regardless of the kind of game. There's usually much more information that you have to extract from the map: certain tiles may be walkable only in specific directions, there might be different types of ground (e.g. dirt, grass, ice) that interact differently with the game characters, certain tiles may serve as triggers to transport the player into buildings or to other maps, and so on.

For this reason, I usually advocate against having a separate map dedicated exclusively to collisions, even if you use more than a single bit per tile/block. If you have tiles/metatiles with the appearance of grass, it makes sense to associate the behavior of grass to those tiles. If you have tiles with the appearance of a brick wall, it makes sense to associate the solidity of a brick wall directly to those tiles. That way you can be as specific or as generic with the attributes/behavior of each tile/metatile that you use to build your maps, and you can extract the collision information direct from the visual map, no need to build 2 separate maps and risk desynchronizing the visual map from the collision map.
dangu
Posts: 11
Joined: Wed Apr 08, 2020 3:20 am

Re: Collisions maps in Rpgs

Post by dangu »

U give me something new to scatch my head :o

So, If I understand correctly..
I upload my tileset in VRAM, then upload my Background maps too..
After, in the main cicle if I detect a movement, i load the destination from the tilemap and use it as an index that points to a propriety table associated with the tileset, and then test the tile propriety if I can walk over or not.
Is it correct???
If it is, this changes completly the approach I was thinking with other interactions too
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Collisions maps in Rpgs

Post by tokumaru »

dangu wrote: Mon Apr 13, 2020 10:38 amAfter, in the main cicle if I detect a movement, i load the destination from the tilemap and use it as an index that points to a propriety table associated with the tileset, and then test the tile propriety if I can walk over or not.
It's kinda like that, but instead of giving attributes to raw 8x8 tiles (which would result in you having to waste VRAM with duplicate graphics if 2 tiles happen to look the same but behave differently, among other problems) you create a new kind of block, and use these as the basic building blocks of your game maps.

Most people call these blocks "metatiles", and they're usually 16x16 pixels (although many other size combinations are possible), and their attributes include everything you need to know about them in your specific game engine. In addition to the 4 8x8 tiles that represent how each block looks (along with palette and flipping bits), you'd include collision information, basic type identification (terrain, hazard, water, adornment, etc.) and whatever else you need in order to implement rich interactions between your game characters and world maps.

Going with this approach also means you won't be including raw (or naively compressed) VRAM tilemaps in your ROM. Drawing a new map will involve scanning/decompressing maps built from metatiles, extracting the tile information from each metatile and then writing that to VRAM. And you won't be reading VRAM for collisions purposes either - background interactions will be based on the metatile map, which you can access in ROM (if uncompressed) or in RAM (if cached).
dangu
Posts: 11
Joined: Wed Apr 08, 2020 3:20 am

Re: Collisions maps in Rpgs

Post by dangu »

So, if I a metatile can be build from multiple tiles, I can compress the multiple common proprieties of the tiles (like palette, priority and most significative bits of tileset) in lesser space, and add other proprieties to it like collisions, sound effects and other intreactions.
This should spare on overall space the map would take in the rom? Especialy on bigger maps I think.
I've done this rougly with the sprite in the rom I posted earlyer, but didn't crossed my mind it could be done with the maps too.
Thanks

EDIT: I was doing right now a few calcs on the compression of that approach.
Assuming a map of 128x128 tiles of 8x8pixel in mode 1 using all 3 Backgrounds.
Normaly the tilemap would be $8000bytes for each BG, so it would take 3 whole banks in a LoRom
So, using metatiles of 16x16, 4 rawtiles each, I think the data stored in it would take about 5 or 6 bytes of space.
I don't think I'm going to use more than 256 metatiles fora each MetaMap, so I'll assume 1byte per Metatile is enough.
Knowing this, the new Metamap will be (128*128)/4*1byte for every BG. For 3 BGs total il $3000 byte..
Summing up the array of created metatiles, in the worst case with all 256 filled up with 6 byte each, I would end up with $3600 bytes of ROM space used for the full map
I sturctured the metatile like this:
4 bytes that contain the flip bits + 6 less significative tile number bits of each tile
1 byte, the common values for all, that contains palette number, priority bit and the 4 most significative bits of the tile number
1 byte (or more?) that will contain proprieties of the metatile, collisions etc...

This is surely better than not using metas at all, but could this be done better?? Any exemples??
I think i can compress the meta a bit more, but there's not so much gain
It would be interesting to compress more the map without sacrificing to much time in the decompressing function
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Collisions maps in Rpgs

Post by Oziphantom »

you have a SNES, it draws 16x16 tiles natively. which drops the tile, pallete, flip, priority etc to 2 bytes for all 4 'chars'. without the need for you to do anything.

depending on your zoom level, and art style.. maybe going to 4x4 is better ( or 2x2 at 16x16 tiles). On the C64 4x4 was the typical sweet spot. but anything goes, 2x2, 2x8 etc

What you can do it pull the collision and "meta tiles" apart.

Say you have 256 tiles.
0-128 are solid, 129-192 are pass through, 192-255 are special functions that you call custom code on.
Then your 'block' ( for some reason NES developers use Meta Tile, but I find Blocks to a better name, as in you build your map out of "building blocks" ) are designed to make the most sense for you level. You don't even need to stick to a single size, you can make large 32x32, then draw some 16x16 over the top in places. You have 128K of RAM so building parts of the map ready to be sent to VRAM is not a problem. Then your collision code look at the tiles in this "upload to VRAM" buffer and reacts to them based upon their number.
To which you use the grouping to work out their function.
i.e < 128 then its a solid tile.
The numbers will change per each map, so you need to store them in a variable.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Collisions maps in Rpgs

Post by tokumaru »

Oziphantom wrote: Wed Apr 15, 2020 11:12 pmyou have a SNES, it draws 16x16 tiles natively. which drops the tile, pallete, flip, priority etc to 2 bytes for all 4 'chars'. without the need for you to do anything.
If you don't plan on reusing many 8x8 tiles in different metatiles, this is perfectly fine. Otherwise you'll have a lot of repeated data in VRAM, in which case it might be better to explicitly index each 8x8 tile.
Say you have 256 tiles.
0-128 are solid, 129-192 are pass through, 192-255 are special functions that you call custom code on.
Again, classifying things implicitly may result in some data redundancy and/or wasted space. Depending on how much freedom you want when allocating your resources, you may prefer to explicitly index things instead.
You have 128K of RAM
This is one of the reasons why I don't see much sense in relying on implicit classification on the SNES. I think it's okay for games like SMB1 on the NES to do this kind of thing, since the space required to explicitly stitch things together could take a significant toll on the 32KB of ROM and 2KB of RAM, but on the SNES? I prefer the versatility of distributing my resources with as much fine control as possible, rather than being restricted by artificial hardcoded ranges. Some maps/levels may just need different amounts of each type of block, and I don't want to have to settle for the least common denominator just because I don't have the freedom to move things around.

This is the freaking SNES... If later NES games can afford to use lots of tables to classify and connect stuff together, surely the SNES can handle it as well.
dangu
Posts: 11
Joined: Wed Apr 08, 2020 3:20 am

Re: Collisions maps in Rpgs

Post by dangu »

I didn't plan anything yet, so I'm gonna grab some tileset from few games and start doing some practice. I think I'll compress as much as I can the maps to spare on rom space and work with collision&other funtions on cached maps in Ram space
Post Reply