Cooljerk, on 11 May 2018 - 06:57 AM, said:
None, because the only one provided by the VDP sucks:
Cooljerk, on 11 May 2018 - 06:57 AM, said:
This bit checks if any hardware sprite has overlapped with any other hardware sprite in their non-transparent pixels. So in Sonic 2, for example, it is set whenever Tails is on-screen because some pixels of his tails overlap with some pixels of his body.
The sprite collision bit is only ever cleared when you read the VDP status register, so you have to keep constantly reading it during active display: if you don't, all you will only know that in some point on the screen, two sprites overlapped in their non-transparent pixels. You will also have to constantly read the H/V register, so you can get an approximate position on when the collision happened. And you will have to log all of those collisions to somewhere in RAM so you can process them later: if you try to process them as they happen, you will miss others.
All of that will combine to keep the 68k occupied during the entirety of active display (or you will miss collisions), consuming a lot of CPU time. It also means you are continually poking the VDP when it is busiest, which is not good. And the further processing you will need to do after active display to figure out which correspond to different objects which should collide will eat up a lot more time, especially because a lot of the collisions will be spurious.
And to make matters worse, the position you read from the H/V register will be very coarse in X position, meaning you are likely to be wrong about the collision anyway.
Yeah, it sucks, and is totally not worth it.
Cooljerk, on 11 May 2018 - 06:57 AM, said:
Entirely software.
Cooljerk, on 11 May 2018 - 09:17 AM, said:
alternatively, what sort of patterns does the software use to speed up these kinds of checks? A buckets approach to limit number of checks or what?
There are several completely different groups of collision detection routines used in these games, and they change along the games (being similar, though). They also use different strategies for optimization which were progressively added, as well as different goals of optimization. Since they are generally better commented and labelled, I will give the names of the Git S2 disassembly.
- object/terrain collision: This is a superset of what I described in the above posts; I focused on characters, and other objects tend to do it a bit differently: generally, they don't care about terrain at all, and those that do only cast one or two sensor rays at most. Except for S1 and SCD, all other games have a lookup table in the function that locates the required tile for speeding up the collision checks. Relevant functions:
- Find_Tile: lower level function which locates the tile at the input position. No object calls this directly.
- FindFloor, Ring_FindFloor, FindWall: calls Find_Tile, potentially finds another tile further away, inspects collision from the tiles, and returns distance until/inside terrain. No objects call these directly.
- Any other functions that call the above functions: these are directly called by objects, and they generally just use the distance returned.
- Find_Tile: lower level function which locates the tile at the input position. No object calls this directly.
- object/object collision: These are platform and solid objects: objects you can stand on, push on (or be pushed by), or bump into them from below. Basically, objects where it matters which side you collided with, and which eject you out of their collision box. I am writing something this group of collisions, but I am still tabulating the information from the several games, and I am still thinking on how to make it digestible. SCD optimizes for size, and combines all object/object collision into one single function which checks the type of collision in the routine. The others tend to optimize for speed, and split off into different routines for different types of collision.
Relevant functions: SolidObject, SolidObject_Always, SlopedSolid, SolidObject45, PlatformObject, SlopedPlatform, PlatformObject2, PlatformObjectD5, etc. - object/object touch: This is a different kind of collision, which uses a different collision box, the hitbox. In a nutshell, any object which does not care the direction from which you collide with it, and which neither ejects you out of its collision box, nor carries you on top. Examples include badniks, rings in S1/SCD, all bumpers in S1/SCD, some bumpers in S2/S3/S&K/S3&K, attracted rings in S3/S&k/S3&K, etc. S3/S&K/S3&K have a subscription-based model: touchable objects add themselves to a list, and the characters check collision only with objects on the list. In S1/S2/SCD, on the other hand, check against every other object loaded. In all games, the check stops as soon as something is touched. Relevant function: TouchResponse.
- object/ring touch: In S1/SCD, rings are objects, and just use object/object touch. In S2/S3/S&K/S3&K, rings have their own separate per-level data for their positions, and the games check collision of each character with all rings in a certain range. Relevant function: Touch_Rings.
- object/special collision: S2/S3/S&K/S3&K also have routines for collision with special bumpers; I think some rocks in Lava Reef in S&K/S3&K are also not normal objects, but Neo/Tiddles probably know more. Relevant function: Check_CNZ_bumpers.
I won't get into collision in the various special or bonus stages.