How Do You Code BG Collision?

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.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

How Do You Code BG Collision?

Post by Drew Sebastino »

I decided that I wouldn't get myself stuck like last time messing with object animation and vram slots and whatnot, so I've decided that I want to try something with BGs. The thing is, how does it work? Isn't it like you load the object's x position, divide it by the width of each block to find the starting block, and also divide the hitbox width by the width of each block to find how many tiles over you look for? You'd also do this vertically. Then, based on your new offsets (you'd record the stuff you found), you'd look over every one of the blocks and see how it effects the object and then do that, like if it's a wall, it will push the object out of it. I kind of wonder how collision maps are generally stored. I'd probably do a byte per block. This way, when you're dividing the object's position and width/height, you can store that number into x or y and not do anything else and you'll be able to offset the collision table exactly where you want to.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How Do You Code BG Collision?

Post by tokumaru »

Espozo wrote:Isn't it like you load the object's x position, divide it by the width of each block to find the starting block, and also divide the hitbox width by the width of each block to find how many tiles over you look for?
To avoid getting touching the subject of how hitboxes are defined (some people like them at the top left corner, others in the center, etc.), it might be better to say that you check all blocks from one corner of the hitbox to another. For example, to look for collisions against the ground when falling, you'd check all blocks between (left, bottom) and (right, bottom). And yes, coordinates must be divided by the dimensions of the blocks that define the collision map.

If the game is only made of blocks, this is all it takes to do proper collision detection: move horizontally, check for solid blocks in the direction of the movement, eject if solid blocks are found; move vertically, check for solid blocks in the direction of the movement, eject if solid blocks are found.

If you have slopes though, things can get quite a bit more complicated, and there are hundreds of ways to implement those depending on the kind of levels you want to make. Generally, slopes affect the speed of objects (speeding them up or down depending on the angle and the direction of the movement), and after being moved horizontally, they "snap" to the ground. The exact way in which an object snaps to the ground is what varies the most from game to game... One of the most common solutions is to sample only a single point directly below the center of the object, and the other is to sample both sides and go with the highest. Both of these methods have advantages and disadvantages, and should be tweaked to be able to handle all kinds of structures you plan on drawing in your levels.
I kind of wonder how collision maps are generally stored. I'd probably do a byte per block. This way, when you're dividing the object's position and width/height, you can store that number into x or y and not do anything else and you'll be able to offset the collision table exactly where you want to.
Personally, I'm against having a collision map separate from the level map, for reasons explained in this post, unless the game is going out of its way to hide the grid where the map is defined, like tepples pointed out.
UnDisbeliever
Posts: 123
Joined: Mon Mar 02, 2015 1:11 am
Location: Australia (PAL)
Contact:

Re: How Do You Code BG Collision?

Post by UnDisbeliever »

I found this document helpful in describing the various sections of a map: http://higherorderfun.com/blog/2012/05/ ... atformers/
Espozo wrote:Isn't it like you load the object's x position, divide it by the width of each block to find the starting block, and also divide the hitbox width by the width of each block to find how many tiles over you look for?
That's the method I first tried with Castle Platformer and it would occasionally cause the player to fall through a wall if the player's width is not a multiple of the tile width. After a few days of tinkering I found that the formula {number to tiles to check = ((entity->left & 0x000F) + entity->width - 1) / 16 + 1} worked for a 16px tile map.
Espozo wrote: I kind of wonder how collision maps are generally stored.
In my research I found most games use a MetaTile format, with a simple index lookup to read the collision parameters of the selected metaTile.

For my engine, the map data is a grid of word indexes that point to the tile parameter tables (Structure of Arrays: tilemapdata, collision table, physics table, function table).

Currently my collision table is just 2 bits (solid and platform), I'll be adding more things like slopes to it later.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How Do You Code BG Collision?

Post by Drew Sebastino »

UnDisbeliever wrote:That's the method I first tried with Castle Platformer and it would occasionally cause the player to fall through a wall if the player's width is not a multiple of the tile width
Oh yeah... If the collision isn't even at least the width of the tile, it won't count as anything... I guess it's like divide by the width of the tile, (ror) and if there's a remainder, (since the bits wrap around, check to see if the value is at least a certain side and then discard the bits) add one. This definitely seems a lot easier than the shenanigans I was trying to pull of with vram.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How Do You Code BG Collision?

Post by tokumaru »

You can simply do:

Code: Select all

BlockLeft = ObjectLeft / BlockWidth;
BlockRight = ObjectRight / BlockWidth;
BlockBottom = ObjectBottom / BlockHeight;
And then check all blocks between (BlockLeft, BlockBottom) and (BlockRight, BlockBottom). It might be only 1 block, if the hitbox is narrower than a block's width, but it will never be less than 1 block.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How Do You Code BG Collision?

Post by Drew Sebastino »

Shouldn't there be another one for checking against the ceiling?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How Do You Code BG Collision?

Post by tokumaru »

Well, it's either the floor or the ceiling, because objects can only go up OR down, not both. The same goes for left and right. Unless the level geometry can change around the objects, or there's another layer with a moving map that objects can collide with.
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: How Do You Code BG Collision?

Post by psycopathicteen »

I nice trick I found for handling slopes is to use "underslope" tiles. Each slope tile requires a certain type of tile underneath to "catch" a sprite from falling through a slope.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How Do You Code BG Collision?

Post by tokumaru »

In my engine, slope blocks are identified as such, and if you want to know whether a certain point in them is solid, you have to look at their height maps, which are arrays containing the height of each column of a block.

Having objects stand on slopes is the easy part, really. The complex things about slopes is dealing with ledges, peaks, and concave constructions. At the same time you want to minimize the amount of points to sample when looking for collisions for performance reasons, you know you need to gather a lot of information about the terrain so you don't make bad decisions.

Another thing that complicates slopes, in my experience, are rotations that result from running up walls and ceilings. If old consoles could smoothly rotate sprites and hitboxes, this would be easy, but since they can't, you have to be a little creative to prevent rotations from looking jerky.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How Do You Code BG Collision?

Post by tepples »

Getting "creative" may involve slightly shearing the sprite as a substitute for rotation.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How Do You Code BG Collision?

Post by tokumaru »

tepples wrote:Getting "creative" may involve slightly shearing the sprite as a substitute for rotation.
Indeed! Unfortunately, this technique doesn't work for all kinds of sprite arrangements... it's great for grids of 8x8 sprites, but not so much for unaligned 8x16 sprites, so this is not an option for me. Fortunately, you can still make the movement look smooth even if the sprite animation is jerky, by using the center of the object as an anchor, instead of the feet, and, as a consequence, skipping small sections of ground/wall/ceiling when the orientation changes.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How Do You Code BG Collision?

Post by Drew Sebastino »

It definitely won't work well if the minimum sprite size you're using is 16x16. However, since most SNES games were way bigger, they could store more predrawn angles for the objects. Really though, unless you're Bragalad, memory isn't even really a problem anymore. (Granted, it's not good to waste it, but I wouldn't purposely go out and limit myself because of it.) Is there any demo of someone doing real time sprite rotation on the SNES, or even the NES? It's probably frighteningly slow.
Revenant
Posts: 462
Joined: Sat Apr 25, 2015 1:47 pm
Location: FL

Re: How Do You Code BG Collision?

Post by Revenant »

psychopathicteen has written one or two examples of realtime rotation for the SNES, but I don't remember where to find them.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How Do You Code BG Collision?

Post by tokumaru »

And tepples has done it on the NES, IIRC. Or was it just scaling? Can't remember.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How Do You Code BG Collision?

Post by Drew Sebastino »

I think tepples only did scaling.
Post Reply