space invaders barriers implementation

Started by
18 comments, last by BeerNutts 9 years, 1 month ago

Hi All

I'm trying to clone a space invader

I'm currently doing the bullets that hit the green barriers. Currently I can get the pixels of the green image, and I also found the intersect rectangle between both the bullet when it hits the green barrier.

But right now I stopped and I don't know how to proceed further with the algorithm ?

Advertisement

Nice exercise in a time of MMO wannabe! biggrin.png

I will try to turn to black the color of some of the green pixels nearby the point of impact.

In this case, you might want to do a per-pixel intersection test, since your blocks are going to not be rectangle after they have been hit a few times.

What that means is, do a typical rectangle intersection test between the bullet and the block. once you've confirmed it's within the rectangle, then do a pixel-by-pixel comparison of where the bullet will be next frame, and the color of the block at that location. If it's black, then it's not hit. if it's green, then you can just put a small black circle (or some other algorithm) near the spot of impact as the crater the bullet's explosion creates.

Just a thought. Good luck and have fun.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

where the bullet will be next frame, and the color of the block at that location.

How to do that in pseudocode?

where the bullet will be next frame, and the color of the block at that location.

How to do that in pseudocode?

It depends on how you are storing your "blocks." Are they bitmaps rendered to a surface that can be manipulated, or are you just drawing rectangles? Assuming it's a bitmap that was originally rendered to a surface, then it'd be something like this:


// Create a rectangle where the bullet is moving to this frame
TRect NewBulletRect = Bullet.Rect + Bullet.Velocity;
 
// check if the bullet and block will be intersecting
if (RectIntersect(NewBulletRect , Block.Rect)) {
  // find the offset within the block's rect the bullet is to check the color within the block's surface
  Vector2D BulletLocationInBlock = Bullet.Rect - Block.Rect;
 
  // now check the color of the Block at the leading location of the Bullet
  // we need to know the pixel depth, which is probably 32-bits, and possibly the pitch, which should be bitmap width * pixel depth
  TColor BlockLocationColor = Block.Surface.Memory + (Block.Surface.Pitch * BulletLocationInBlock.Y) + (BulletLocationInBlock.X * Block.Surface.BitsPerPixel);
 
  // Check if it's black (which means the RGB value is 0, but you have to know the layout of the pixels; is Alpha the 1st byte or the last?  I'll assume 1st)
  if ((BlockLocationColor & 0xFFFFFF) != 0) {
    // it's not black, so it hit the block
    // Draw a circle on the Block's Surface to indicate crater, and so the next bullet will continue this this location
    ...
  }

It's obvious pseudo-code, but it should make sense. If you don't know how the data is stored in the surfaces, you may need to experiment some, or do a little research on how graphics bitmap data is stored on surfaces.

Good luck.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Thanks but I didn't get this:

// find the offset within the block's rect the bullet is to check the color within the block's surface
Vector2D BulletLocationInBlock = Bullet.Rect - Block.Rect;

is that ? in equations it should be Abs(X1-X2), Abs(Y1-Y2) ?
I tried to visualize it, but still didn't clear it up

Thanks but I didn't get this:

// find the offset within the block's rect the bullet is to check the color within the block's surface
Vector2D BulletLocationInBlock = Bullet.Rect - Block.Rect;

is that ? in equations it should be Abs(X1-X2), Abs(Y1-Y2) ?
I tried to visualize it, but still didn't clear it up

Just imagine the bullet falling into the block. Now, you need to determine, where in reference to the block (where 0, 0 is the Block's upper left) the end of the bullet is. So, it'd be The Bullet's BottomY minus the Block's TopY. that would give you how deep the bullet penetrated. Same with X, take the Bullet's Middle-X minus the Block's Left-X, and you'll have the bullet's offset within the block.

hope that makes sense.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

I have tried your algorithm, but pixels of the original image never get overwritten, I have a logical problem there but can't get it

so first

1. is colliding

2. get the intersected rect

3. modify pixels <-- not working probably


cRect Intersection(const cRect& boundsA, const cRect& boundsB)
{
	int x1 = Maximum(boundsA.x, boundsB.x);
	int y1 = Maximum(boundsA.y, boundsB.y);
	int x2 = Minimum(boundsA.x + boundsA.w, boundsB.x + boundsB.w);
	int y2 = Minimum(boundsA.y + boundsA.h, boundsB.y + boundsB.h);

	int width = x2 - x1;
	int height = y2 - y1;

	if (width > 0 && height > 0)
	{
		cRect intersect;
		intersect.x = x1;
		intersect.y = y1;
		intersect.w = width;
		intersect.h = height;
		return intersect;
	}
	else
	{
		cRect intersect;
		intersect.x = 0;
		intersect.y = 0;
		intersect.w = 0;
		intersect.h = 0;
		return intersect;
	}
}


// check collision function() 
bool CheckCollisionNewBarriers(Ship *ship, vector<Barrier*> *barriers, CIwTexture *tex, uint8*pixels, uint32 pitch)
{
for (vector<Barrier*>::iterator itBarrier = barriers->begin(); itBarrier != barriers->end();)
	{
		for (list<Bullet*>::iterator it = ship->Bullets->begin(); it != ship->Bullets->end();)
		{
			if (IntersectsWith((*it)->BoundingRect, (*itBarrier)->BoundingRect))
			{

				cRect bounding = Intersection((*it)->BoundingRect, (*itBarrier)->BoundingRect);
				Iw2DDrawRect(CIwFVec2(bounding.x, bounding.y),CIwFVec2(20,20));
			
				int bpp = 4;
				uint8 pixelOffset = bounding.x*bpp + bounding.y*pitch;
				pixels[pixelOffset] = 0xff000000;
 				 
				tex->ChangeTexels(pixels);
				tex->Upload();
                              } 
                            }
 

I have tried your algorithm, but pixels of the original image never get overwritten, I have a logical problem there but can't get it

so first

1. is colliding

2. get the intersected rect

3. modify pixels <-- not working probably


cRect Intersection(const cRect& boundsA, const cRect& boundsB)
{
	int x1 = Maximum(boundsA.x, boundsB.x);
	int y1 = Maximum(boundsA.y, boundsB.y);
	int x2 = Minimum(boundsA.x + boundsA.w, boundsB.x + boundsB.w);
	int y2 = Minimum(boundsA.y + boundsA.h, boundsB.y + boundsB.h);

	int width = x2 - x1;
	int height = y2 - y1;

	if (width > 0 && height > 0)
	{
		cRect intersect;
		intersect.x = x1;
		intersect.y = y1;
		intersect.w = width;
		intersect.h = height;
		return intersect;
	}
	else
	{
		cRect intersect;
		intersect.x = 0;
		intersect.y = 0;
		intersect.w = 0;
		intersect.h = 0;
		return intersect;
	}
}


// check collision function() 
bool CheckCollisionNewBarriers(Ship *ship, vector<Barrier*> *barriers, CIwTexture *tex, uint8*pixels, uint32 pitch)
{
for (vector<Barrier*>::iterator itBarrier = barriers->begin(); itBarrier != barriers->end();)
	{
		for (list<Bullet*>::iterator it = ship->Bullets->begin(); it != ship->Bullets->end();)
		{
			if (IntersectsWith((*it)->BoundingRect, (*itBarrier)->BoundingRect))
			{

				cRect bounding = Intersection((*it)->BoundingRect, (*itBarrier)->BoundingRect);
				Iw2DDrawRect(CIwFVec2(bounding.x, bounding.y),CIwFVec2(20,20));
			
				int bpp = 4;
				uint8 pixelOffset = bounding.x*bpp + bounding.y*pitch;
				pixels[pixelOffset] = 0xff000000;
 				 
				tex->ChangeTexels(pixels);
				tex->Upload();
                              } 
                            }
 

Crap, it lost my changes. Well, let me re-write...

What are you trying to do with this?

Iw2DDrawRect(CIwFVec2(bounding.x, bounding.y),CIwFVec2(20,20));
You don't need to draw a rectangle on the current surface. That should be handled by setting the pixels on the block texture.
Which leads me to...

int bpp = 4;
uint8 pixelOffset = bounding.x*bpp + bounding.y*pitch;
pixels[pixelOffset] = 0xff000000;
  
tex->ChangeTexels(pixels);
tex->Upload();
Youre on the right path, but you're only setting a single pixel. You need to set an area of pixels arond the interseciton point to be able to see the block's explosion. You may also want to use GetFormat() to determine bpp and the format of the pixels (ARGB or BGRA).
Finally, remember, once the bullet is in the block's bounding box, you'll want to test the pixels to see if it's not black, and then cause a collision.
I think you'r eon the right track, keep working at it.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

The drawing rect is just for debugging.

Right now I the pixels get blasted but they drawn on the top of the image not bottom :S and they don't fill a space... looks like the rect calculations is wrong.


int normX = (*it)->BoundingRect.x - (*itBarrier)->BoundingRect.x;
				//int normY = (*it)->BoundingRect.y - (*itBarrier)->BoundingRect.y;
				int y = 34 - 1;
			 	for (int i = 0; i < 34; i++) {

					//the x calculation (0 - 53)
					if (normX >= 53) {
						normX = 53 - 1;
					}

					uint8 pixelOffset = normX * 4 + y*pitch;
					if (pixels[pixelOffset] != 0xff000000)
					{
						uint32* ptr = (uint32*)pixels;

						for (int i = normX - 16; i <= normX + 16; i++)
						{
							for (int j = y - 16; j <= y + 16; j++)
							if (i >= 0 && i < 51 && j > 0 && j < 35)
							{
								uint8 pixelOffset = i * 4 + j*pitch;
								ptr += pixelOffset;
								*ptr = 0xff0000ff;
							}
						}
						break;

					}

					y--;
				}

This topic is closed to new replies.

Advertisement