Collision Help Please...

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Post Reply
AnthonyPython
Interested
Posts: 10
Joined: Wed Oct 26, 2016 1:27 am

Collision Help Please...

Post by AnthonyPython » Fri Nov 04, 2016 12:18 am

Hi, I'm pretty new when it comes to programming the collision's for the Sega genesis, all I want to do is make a platformer, with a few specific sprites/ platform tiles, that when you overlap them or collide with x will happen, like an enemy killing you or walking in front of a door sprite and press say B to open doors, etc. can anyone help me understand it better? perhaps code snippet examples. and I already seen kaneda's, It just seem's I can't get it to work in sgdk, there truly needs to be more tutorial's/better ones, since I haven't got 68k asm to compile yet. well I'd rather use C anyways.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Collision Help Please...

Post by Miquel » Fri Nov 04, 2016 5:54 am

First of all collision means detecting if two sprites/objects/entities are overlapping, since you question is that general perhaps you are adding other issues.

Usually in 16bits you have two types of collisions:
A) one sprite with another sprite
B) one sprite with the ground (tiles)

To solve A you just need to check if two rectangles (bounding boxes) are intersecting. Search for intersecting rectangles on internet for code, it's just 4 compares.

To work out B you set a few strategic points surrounding the sprite and check if they are inside a solid or hollow tile. An algorithm for this last one depends very much on how you structured your levels, it could be as easy as:

bool solid = level[ player.x / 8 ][ player.y / 8 ];

About collision response:

To interact with you level, open doors and things like this, usually with your tiles indexes, or even groups of tiles indexes, are accompanied with collision information so when you collide with a tile you known what to do next. So you can extend the information described previously as Solid and Hollow, into Water, Stairs, Button, Door, etcetera.

On the other hand sprites are classified into types, like player, power up, foe, shoot, etcetera so you can write a common way of working with them. A matrix, managing every possible intersection could do the work.
HELP. Spanish TVs are brain washing people to be hostile to me.

AnthonyPython
Interested
Posts: 10
Joined: Wed Oct 26, 2016 1:27 am

Re: Collision Help Please...

Post by AnthonyPython » Fri Nov 04, 2016 6:40 pm

Miquel wrote:First of all collision means detecting if two sprites/objects/entities are overlapping, since you question is that general perhaps you are adding other issues.

Usually in 16bits you have two types of collisions:
A) one sprite with another sprite
B) one sprite with the ground (tiles)

To solve A you just need to check if two rectangles (bounding boxes) are intersecting. Search for intersecting rectangles on internet for code, it's just 4 compares.

so the collision's of other sprites I can do

Code: Select all

// Returns true if two rectangles overlap
static void doOverlap(Sprite* rect_a,Sprite* rect_b)
{
    // If one rectangle is on left side of other
    if (rect_a->x > rect_b->x || rect_b->x > rect_a->x)
        Overlap = false;

    // If one rectangle is above other
    if (rect_a->y < rect_b->y || rect_b->y < rect_a->y)
        Overlap = false;
    else
    	Overlap = true;
}
and then use say do

Code: Select all

doOverlap(sprites[0],sprites[1]);
        doOverlap(sprites[0],sprites[2]);
and just check if Overlap is true right?

it doesn't seem to work for me though.

btw I'm using it with the sonic example.

Grind
Very interested
Posts: 69
Joined: Fri Jun 13, 2014 1:26 pm
Location: US
Contact:

Re: Collision Help Please...

Post by Grind » Fri Nov 04, 2016 11:55 pm

Here is the usual algorithm for detecting if 2 rectangles overlap:

Code: Select all

if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
    RectA.Y1 < RectB.Y2 && RectA.Y2 > RectB.Y1) 
Your code is not taking the size of the rectangles into consideration, so the function will only set "Overlap" to true if the 2 sprites are perfectly aligned.

Actually, since your first if statement is completely disregarded, it'll set "Overlap" to true whenever they are aligned on the x axis. I'm puzzled by this and why a global variable is being used instead of a return value.

Code: Select all

// Returns true if two rectangles overlap
static u8 doOverlap(Sprite* rect_a,Sprite* rect_b)
{
	return rect_a->x < rect_b->x + rect_b->width &&
			rect_a->x + rect_a->width > rect_b->x  &&
			rect_a->y < rect_b->y + rect_b->height &&
			rect_a->y + rect_a->height > rect_b->y;
}
Now there is another problem. Sprite has no width or height. Looking in SGDK source the individual frames store a width and height in pixels. So this may work instead of rect_a->width and rect_a->height:

rect_a->frame[0]->w
rect_a->frame[0]->h

Then plugging it in

Code: Select all

if(doOverlap(sprite[0], sprite[1]) {
	// Collided
}
if(doOverlap(sprite[0], sprite[2]) {
	// Collided
}
or:

Code: Select all

#define NUM_SPRITES	3
for(u16 i = 1; i < NUM_SPRITES; i++) {
	if(doOverlap(sprite[0], sprite[i])) {
		// Collided
	}
}
Consider creating an object struct that contains the sprite, speed values and a collision rectangle which can be reused for players, objects and enemies. Collision in games gets much more complicated, especially platformers, and often you may want an object's "hit box" to be smaller than the actual sprite.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Collision Help Please...

Post by Miquel » Sat Nov 05, 2016 1:51 am

AnthonyPython wrote: and just check if Overlap is true right?

it doesn't seem to work for me though.

btw I'm using it with the sonic example.
This is how I do it:

Code: Select all

	bool bColision = false;
	if( ! ( (pActor->boundingBox.left.integer > pActor2Test->boundingBox.right.integer) ||
		(pActor->boundingBox.right.integer < pActor2Test->boundingBox.left.integer) ||
		(pActor->boundingBox.top.integer > pActor2Test->boundingBox.bottom.integer) ||
		(pActor->boundingBox.bottom.integer < pActor2Test->boundingBox.top.integer) ) )
	{
		bColision = true;
	}
Well, not exactly like this because 16bit cpu's have no enough power to handle collisions from everyone to everyone when you have plenty of sprites on screen (at 60/50 fps).

pActor is a pointer to a Sprite struct currently being actualized.
pActor2Test is the other sprite currently being compared with.
boundingBox is a struct with 4 values (fixed points): left, right, top, bottom.
a fixed point has a integer and a decimal, last one not used in this code.
Last edited by Miquel on Sun Nov 06, 2016 5:00 am, edited 1 time in total.
HELP. Spanish TVs are brain washing people to be hostile to me.

AnthonyPython
Interested
Posts: 10
Joined: Wed Oct 26, 2016 1:27 am

Re: Collision Help Please...

Post by AnthonyPython » Sat Nov 05, 2016 10:36 am

Thanks a bunch guys, got sprite collision working, now I just need Tile collision.

I'll get back with you guys when I get some real tiles made and put in the game, and not use that bitmap of a sonic level.

Glad to finally make some progress, I was pulling my hair out over this for days.

I'll be sure to add this valuable info into the new MegaDrive Wiki I made on my website, since it seems there was two others, but I'll try my very best to keep this one up, I doubt there will be many spammers on this one guys. Since you have to have an account and to confirm your email to edit/make pages.

http://mdwiki.virtualpython.com

AnthonyPython
Interested
Posts: 10
Joined: Wed Oct 26, 2016 1:27 am

Re: Collision Help Please...

Post by AnthonyPython » Tue Nov 08, 2016 7:57 am

Miquel wrote: To work out B you set a few strategic points surrounding the sprite and check if they are inside a solid or hollow tile. An algorithm for this last one depends very much on how you structured your levels, it could be as easy as:

bool solid = level[ player.x / 8 ][ player.y / 8 ];

About collision response:

To interact with you level, open doors and things like this, usually with your tiles indexes, or even groups of tiles indexes, are accompanied with collision information so when you collide with a tile you known what to do next. So you can extend the information described previously as Solid and Hollow, into Water, Stairs, Button, Door, etcetera.

On the other hand sprites are classified into types, like player, power up, foe, shoot, etcetera so you can write a common way of working with them. A matrix, managing every possible intersection could do the work.
uh? I don't quite understand that piece of code snippet, I haven't had anything a bool being set to something other than false or true work right as of it.

and exactly how would one retrieve this tile index info after you collide/ overlap with it/ extra collision info? I was looking around the sgdk source code, but it's getting pretty late right now, and I'm pretty tired from being up all day. so I'm going to go on and get some rest talk later. thanks for all the help so far guys, I appreciate you all helping a noob when it comes to doing this sort of stuff.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Collision Help Please...

Post by Miquel » Tue Nov 08, 2016 3:58 pm

AnthonyPython wrote: uh? I don't quite understand that piece of code snippet, I haven't had anything a bool being set to something other than false or true work right as of it.

and exactly how would one retrieve this tile index info after you collide/ overlap with it/ extra collision info? I was looking around the sgdk source code, but it's getting pretty late right now, and I'm pretty tired from being up all day. so I'm going to go on and get some rest talk later. thanks for all the help so far guys, I appreciate you all helping a noob when it comes to doing this sort of stuff.
In a few hours I'm going to fully answering you, now I'm going to sleep, but meanwhile if you can answer those it will help:
¿What kind of platformer are you designing?
¿Do you plan to do a level editor?
¿Have you thought a structure for you levels?
¿What kind of information do you need to perform like you designed it?
HELP. Spanish TVs are brain washing people to be hostile to me.

AnthonyPython
Interested
Posts: 10
Joined: Wed Oct 26, 2016 1:27 am

Re: Collision Help Please...

Post by AnthonyPython » Tue Nov 08, 2016 7:14 pm

Miquel wrote:
In a few hours I'm going to fully answering you, now I'm going to sleep, but meanwhile if you can answer those it will help:
¿What kind of platformer are you designing?
¿Do you plan to do a level editor?
¿Have you thought a structure for you levels?
¿What kind of information do you need to perform like you designed it?
1.(for theme it is a 1960's looking facilities , failed human experiments of an unknown cell type), it is a mixture of shooting, and puzzle's(sort of like megaman 7), with two character's you play as at different points in the game(with switching between two different realities), one character at a time.
2. yes, I do, I use the Game Boy Map editor/ tile designer at the moment, if you have something else better to recommend say so.
3.Not quite yet, working on it
4. Enemies, doors, ladder's, lever's, button's(wall or floor), some pallet switching for the different realities/different sprite for the enemies, projectiles, health of course, weapon changes upon player absorbs the weapon(firstplayer) The second character will be able to pull in enemies/projectiles/powerups with a sort of whip like device(invisible multiple hands), but can't be seen by normal people(only herself can see them, and the player playing)

That's about it I think, I don't think I'll be using slops at the time.

oh btw I'm prototyping in unity at the time(for pc, linux, mac, and ps vita), but my group of friends ultimate goal is a 16bit-retro game, that can play on
the sega genesis/megadrive, we are all passionate with older games. (me-programming mostly but I pitch in to help with the overall desgin/gameplay, my friend the concept helper/gameplay designer , My musician friend he has been loving deflemask, My other friend is a audio mixer, mostly but can help create music as well, but is good at programming too) we don't have a pixel artist really, as I can draw on paper well, but anything computer wise I suck. We all are going to see this through though.
We all appreciate you, and anyone helping us in our endeavors greatly.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Collision Help Please...

Post by Miquel » Thu Nov 10, 2016 12:51 pm

AnthonyPython wrote: uh? I don't quite understand that piece of code snippet, I haven't had anything a bool being set to something other than false or true work right as of it.
In the most basic scheme you only need to know if this tile is solid or not (bool).

Code: Select all

bool g_Level[ 128 ][ 128 ];

void MoveCharacterFunction( Sprite* pSprite, int speedX, int speedY )
{
	while( speedX || speedY )
	{
		if( speedX > speedY )
		{
			const int sX = speedX % 8;
			if( g_Level[ (pSprite->x + sX) / 8 ][ pSprite->y / 8 ] )
			{
				return;
			}
			speedX -= sX;
			pSprite->x += sX;
		}
		else
		{
			const int sY = speedY % 8;
			if( g_Level[ pSprite->x / 8 ][ (pSprite->y + sY) / 8 ] )
			{
				return;
			}
			speedY -= sY;
			pSprite->y += sY;
		}
	}
}
I assume that tiles are 8x8. Instead of "return", it needs to be adjusted to pixel. It's the most simple case but it works.
AnthonyPython wrote: and exactly how would one retrieve this tile index info after you collide/ overlap with it/ extra collision info? I was looking around the sgdk source code, but it's getting pretty late right now, and I'm pretty tired from being up all day. so I'm going to go on and get some rest talk later. thanks for all the help so far guys, I appreciate you all helping a noob when it comes to doing this sort of stuff.
Every time you need more info just expand you data structures:

Code: Select all

typedef struct _Cell
{
	bool bSolid;
	uint /*u16 in MD*/ tileIndex;
} Cell;

Cell g_Level[ 128 ][ 128 ];

void MoveCharacterFunction( Sprite* pSprite, int speedX, int speedY )
{
	while( speedX || speedY )
	{
		if( speedX > speedY )
		{
			const int sX = speedX % 8;
			if( g_Level[ (pSprite->x + sX) / 8 ][ pSprite->y / 8 ].bSolid )
			{
				return;
			}
			speedX -= sX;
			pSprite->x += sX;
		}
		else
		{
			const int sY = speedY % 8;
			if( g_Level[ pSprite->x / 8 ][ (pSprite->y + sY) / 8 ].bSolid )
			{
				return;
			}
			speedY -= sY;
			pSprite->y += sY;
		}
	}
}
I recomend you to work with something like this:

Code: Select all

typedef enum _Terrain
{
	Air,
	Water,
	Door,
	Button
} Terrain;

typedef struct _Cell
{
	Terrain terrain[ 2 ][ 2 ];
	uint tileIndex[ 2 ][ 2 ];
} Cell;
Where instead of managing every tile, you work in blocks of 4 tiles (2x2). Most 8bit and 16bit games work this way for broad range of reasons (Ask if you are not sure).
But only if this meets your requirements, of course. Once you realize you are out of memory, talk to me again.

Edit: I forgot, in MD tiles indexes are like:

Code: Select all

typedef union _PlaneCell
{
	struct
	{
		u16 priority : 1;		// -> z order in relation to other planes and sprites
		u16 palete : 2;
		u16 flipHoritzontal : 1;
		u16 flipVertical : 1;
		u16 title : 11;			// -> 2048 max titles
	};
	u16	fullValue;
} PlaneCell;
So, Cell would be like:

Code: Select all

typedef struct _Cell
{
	Terrain terrain[ 2 ][ 2 ];
	PlaneCell planeCell[ 2 ][ 2 ];
} Cell;
I don't use MD-SDK so adjust data structures to it, if needed.
HELP. Spanish TVs are brain washing people to be hostile to me.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Collision Help Please...

Post by Miquel » Fri Nov 11, 2016 6:25 am

Continuing,

in 16bits I know 2 adequate ways to represent levels, let's call them the Sonic way and the Nintendo way. Both have the 2x2 tiles structure as their base.

I don't know so much about the Sonic way, since I never used it, but it works by grouping every time more tiles in every time bigger map of tiles. For example first level is 2x2 tiles, second level is 16x16 tiles (but references to the previous structure, not tiles themselves), third level is 128x128 tiles (again it points to second level), and then the final map level using previous structure. It works well for very large, repetitive (Sonic is fast enough so you don't notice) and unmodifiable levels. Most people in this forum like Sonic so they have learn very well this way.

On the other hand, in the Nintendo way we have an array of 2x2 tile structures and a map/matrix in RAM with indexes to those structures. Is that simple. The complex part is how to build the map on loading time. It works well for modifiable short levels (with 32KB of RAM using this precise method you can do 2048x2048 pixel levels).

¿There are other ways of doing it? yes ¿Are they as good as those two? probably not.
AnthonyPython wrote: 1.(for theme it is a 1960's looking facilities , failed human experiments of an unknown cell type), it is a mixture of shooting, and puzzle's(sort of like megaman 7), with two character's you play as at different points in the game(with switching between two different realities), one character at a time.
2. yes, I do, I use the Game Boy Map editor/ tile designer at the moment, if you have something else better to recommend say so.
3.Not quite yet, working on it
4. Enemies, doors, ladder's, lever's, button's(wall or floor), some pallet switching for the different realities/different sprite for the enemies, projectiles, health of course, weapon changes upon player absorbs the weapon(firstplayer) The second character will be able to pull in enemies/projectiles/powerups with a sort of whip like device(invisible multiple hands), but can't be seen by normal people(only herself can see them, and the player playing)
About those buttons and puzzle's: to my understanding the big question is if you want to modify your levels at action time or not. If you want to, you can't use static maps. Pallets are sprites, so don't count.

About the level editor: my recommendation is to build your own, with the characteristics you need, and spend about 50% of development time in it. And above all don't use tile based editors, they are fine to build you first level, but when you realize that there are 499 to complete your game, you are going to go crazy. And then some one changed some tiles, or even the size (in pixels) of some object, then you have to modify ALL your levels, it's just the fast first results, but never ending way.
HELP. Spanish TVs are brain washing people to be hostile to me.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Collision Help Please...

Post by Miquel » Wed Nov 23, 2016 3:05 pm

Finally I left you with an example of what I said, using the "Nintendo way" (By that I mean a way of working with levels developed in 8 and 16 bits mainly in Nintendo devices). It was a competitive test for my level engine I did months ago.

There are two strong points:
- You can modify the level at any given point
- The level input is given at the object level: you say: "build a house here, with that width and height" (instead of editing tile by tile).

Tiles taken from Zelda (SNES).
Music isn't mine.
Is work in progress (awful palette).
Attachments
RoomTest.zip
(183.99 KiB) Downloaded 280 times
RoomTest.jpg
RoomTest.jpg (86.34 KiB) Viewed 9327 times
HELP. Spanish TVs are brain washing people to be hostile to me.

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: Collision Help Please...

Post by GeoffLedak » Sat Jan 07, 2017 11:23 pm

Here's a good tutorial on basic physics and floor collection detection using 68k assembly on the Genesis:
https://www.youtube.com/watch?v=Kalmryn9_sE

Post Reply