How Do You Code BG Collision?
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
How Do You Code BG Collision?
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.
Re: How Do You Code BG Collision?
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.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?
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.
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.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.
-
- Posts: 123
- Joined: Mon Mar 02, 2015 1:11 am
- Location: Australia (PAL)
- Contact:
Re: How Do You Code BG Collision?
I found this document helpful in describing the various sections of a map: http://higherorderfun.com/blog/2012/05/ ... atformers/
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.
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: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?
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.Espozo wrote: I kind of wonder how collision maps are generally stored.
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.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: How Do You Code BG Collision?
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.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
Re: How Do You Code BG Collision?
You can simply do:
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.
Code: Select all
BlockLeft = ObjectLeft / BlockWidth;
BlockRight = ObjectRight / BlockWidth;
BlockBottom = ObjectBottom / BlockHeight;
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: How Do You Code BG Collision?
Shouldn't there be another one for checking against the ceiling?
Re: How Do You Code BG Collision?
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.
-
- Posts: 3140
- Joined: Wed May 19, 2010 6:12 pm
Re: How Do You Code BG Collision?
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.
Re: How Do You Code BG Collision?
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.
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.
Re: How Do You Code BG Collision?
Getting "creative" may involve slightly shearing the sprite as a substitute for rotation.
Re: How Do You Code BG Collision?
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.tepples wrote:Getting "creative" may involve slightly shearing the sprite as a substitute for rotation.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: How Do You Code BG Collision?
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.
Re: How Do You Code BG Collision?
psychopathicteen has written one or two examples of realtime rotation for the SNES, but I don't remember where to find them.
Re: How Do You Code BG Collision?
And tepples has done it on the NES, IIRC. Or was it just scaling? Can't remember.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: How Do You Code BG Collision?
I think tepples only did scaling.