Thread: mental problem

  1. #1
    Slave MadCow257's Avatar
    Join Date
    Jan 2005
    Posts
    735

    mental problem

    for whatever reason I can't figure this out
    I'm using some code from gamedev for 2d pixel perfect collision detection, it looks like this now
    Code:
    bool CollideYou(int index)
    {
    	int left1, left2;
    	int right1, right2;
    	int top1, top2;
    	int bottom1, bottom2;
        left1 = BulletsE[index].x;
        left2 = You.x;
        right1 = BulletsE[index].x + 5;
        right2 = You.x + 99;
        top1 = BulletsE[index].y;
        top2 = You.y;
        bottom1 = BulletsE[index].y + 20;
        bottom2 = You.y + 75;
        if (bottom1 < top2) return false;
        if (top1 > bottom2) return false;
        if (right1 < left2) return false;
        if (left1 > right2) return false;
    
    	int over_bottom, over_top, over_right, over_left;
        
    	if (bottom1 > bottom2) over_bottom = bottom2;
        else over_bottom = bottom1;
        if (top1 < top2) over_top = top2;
        else over_top = top1;
        if (right1 > right2) over_right = right2;
        else over_right = right1;
        if (left1 < left2) over_left = left2;
        else over_left = left1;
    
    	for (int z = over_bottom; z <= over_top; z++)
    	{
    		for (int y = over_left; y <= over_right; y++)
    		{
    		}
    	}
    	return false;
    }
    The problem is I can't figure out how to convert z and y in the for loops into actual x's and y's for the two SDL surfaces I'm colliding (ship and bullet)

    Thanks,
    MC

  2. #2
    Slave MadCow257's Avatar
    Join Date
    Jan 2005
    Posts
    735
    After a break, I started working on this again and all it seems to be doing is checking for a rectangle collision. The per pixel part seems to be always returning false, and I can't figure out why. Here's the updated code...

    Code:
    bool CollideYou(int index)
    {
    	int left1, left2;
    	int right1, right2;
    	int top1, top2;
    	int bottom1, bottom2;
        left1 = BulletsE[index].x;
        left2 = You.x;
        right1 = BulletsE[index].x + 5;
        right2 = You.x + 99;
        top1 = BulletsE[index].y;
        top2 = You.y;
        bottom1 = BulletsE[index].y + 20;
        bottom2 = You.y + 75;
    
    //The basic rectangle collision, seems to be working fine
        if (bottom1 < top2) return false;
        if (top1 > bottom2) return false;
        if (right1 < left2) return false;
        if (left1 > right2) return false;
    
    	int over_bottom, over_top, over_right, over_left;
        
    	if (bottom1 > bottom2) over_bottom = bottom2;
        else over_bottom = bottom1;
        if (top1 < top2) over_top = top2;
        else over_top = top1;
        if (right1 > right2) over_right = right2;
        else over_right = right1;
        if (left1 < left2) over_left = left2;
        else over_left = left1;
    
    //This should be giving me pixel perfect 2D collision detection, but
    //it's not
    
    	int offset1, offset2;
    	offset1 = ((over_top - You.y) * 99) + over_left;
    	offset2 = ((over_top - MasterList[index].y) * 5) + over_left;
    	for (int y = 0; y <= over_bottom-over_top; y++)
    	{
    		for (int x = 0; x <= over_right-over_left; x++)
    		{
    			if ((!IsPink(ship, x+offset1, y)) && (!IsPink(bulletE, x+offset2, y)))
    				return true;
    		}
    	}
    	return false;
    }
    And just incase this has an error
    Code:
    bool IsPink(SDL_Surface *surface, int x, int y)
    {
      Uint32 color = SDL_MapRGB(screen->format, 255, 0, 255);
      switch (screen->format->BytesPerPixel)
      {
        case 1:
            Uint8 *bufp;
            bufp = (Uint8 *)surface->pixels + y*surface->pitch + x;
    		if (*bufp == color)
    			return true;
    		break;
        case 2:
            Uint16 *bufp1;
            bufp1 = (Uint16 *)surface->pixels + y*surface->pitch/2 + x;
    		if (*bufp1 == color)
    			return true;
    		break;
        case 4:
            Uint32 *bufp2;
            bufp2 = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
    		if (*bufp2 == color)
    			return true;
    		break;
      }
      return false;
    }
    Thanks a bunch
    Last edited by MadCow257; 12-19-2005 at 09:39 PM.

  3. #3
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Hey madcow this is from my game with allegro. I am sure it can be conerted to SDL fairly easily.
    Code:
    bool Sprite::operator== (Sprite &hit)
    {
        //Make sure we are working with the latest info
        Update_Collision();
        hit.Update_Collision();
        	
    	int this_x_offset, this_y_offset, hit_x_offset,hit_y_offset;
    	int overlap_width,overlap_height;
    	
        //loop counters
    	int height_count = 0, width_count = 0;
    	
    	//hold integer rep of pixels
    	int this_pixel;
    	int hit_pixel;
    	
    	//Hold bitmask color of each image
    	int this_bitmask  = bitmap_mask_color(image);
    	int hit_bitmask = bitmap_mask_color(hit.image); 
    
    	//check if ships is alive
    	if(isAlive == false || hit.isAlive == false)
    	{
    		return false; //no collision if one dead
        }
        
    	//check bounding box
    	if(left > hit.right) 
    		return false;
    
    	if(right < hit.left)
    		return false;
    	
    	if(bottom < hit.top)
    		return false;
    
    	if(top > hit.bottom)
    		return false;
    	//bounding box test passed there is intersection
    	//check overlap
    	
    	//find x overlap
    	if(xPos < hit.xPos) //this left of hit
    	{
    		this_x_offset = hit.xPos - xPos;
    		hit_x_offset = 0;
    
    		overlap_width = image->w - this_x_offset;	
    
    	}
    	
    	//else offset is xPos - hit.xPos;
    	else //this right of hit
    	{
    		hit_x_offset = xPos - hit.xPos;
    		this_x_offset = 0;
    
    		//get overlap width
    		overlap_width = hit.image->w - hit_x_offset;
    	}
    
    	//find y overlap
    	if(yPos < hit.yPos) //this above is hit
    	{
    		this_y_offset = hit.yPos - yPos;
    		hit_y_offset = 0;
    
    		//get overlap height
    		overlap_height = (image->h - this_y_offset);
    	}
    
    	//else offset is yPos - hit.yPos;
    
    	else //this below hit
    	{
    		this_y_offset = 0;
    		hit_y_offset = yPos - hit.yPos;
    		
    		//get overlap height
    		overlap_height = (hit.image->h - hit_y_offset);
    	}
    
    	//now that overlap box has been calculated we will check each pixel in the box
    	
    	while(height_count < overlap_height) //check a line loop
    	{
    		while(width_count < overlap_width) //check pixel loop
    		{
    			//get pixel data for this
    			this_pixel = getpixel(image,this_x_offset+width_count,height_count+this_y_offset);			
    			
    			//get pixel data for hit
    			hit_pixel = getpixel(hit.image,hit_x_offset+width_count,height_count+hit_y_offset);		
    		
    			//check to see if both are transparent
    			if( (this_pixel  != this_bitmask && this_pixel   != -1) &&
    				(hit_pixel != hit_bitmask && hit_pixel != -1)) //if both opaque return true
    			{
    				return true;
    			}
    			//else
    			width_count++; //incrment pixel
    		}		
    		width_count = 0; //reset pixel counter
    		height_count++; //increment line
    	}
    	return false; //no collision return false
    }
    Last edited by prog-bman; 12-19-2005 at 09:46 PM.
    Woop?

  4. #4
    Slave MadCow257's Avatar
    Join Date
    Jan 2005
    Posts
    735
    Thanks alot prog-bman, that should be easy to convert

  5. #5
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Now I am not sure how fast this is or how efficent the checks are but I do know that it works
    Woop?

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    There is no way either of those are pixel-perfect. Pixel-perfect would be based on time intervals and not coordinates. Coordinates can fly through one another. You must break the interval down into smaller intervals and then integrate over time to find out the exact moment of impact.

    But for 2D, this would prob work well enough. But I do recommend checking out the moving bounding box intersection test.

  7. #7
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Quote Originally Posted by Bubba
    There is no way either of those are pixel-perfect. Pixel-perfect would be based on time intervals and not coordinates. Coordinates can fly through one another. You must break the interval down into smaller intervals and then integrate over time to find out the exact moment of impact.

    But for 2D, this would prob work well enough. But I do recommend checking out the moving bounding box intersection test.
    I am confused Bubba, This does collision detection based on a pixel that is not the mask, so if two pixels in two different objects that are not a mask are overlapping in a set x,y coord(pixel) there is a collision. What does time have to do with any of this?
    Woop?

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    What it has to do is that time in any game flows in discrete steps, usually called frames, due to the nature of computers. This means that there is a point in time A and a point in time B, and in-between there's nothing.

    Now, if an object is fast enough, it might move more than one pixel each interval. For simplicity's sake, let's assume a 1-dimensional display. Object X has an x-coordinate of 100 and a speed of +4px/frame. Object Y has an x-coordinate of 123 and a speed of -3px/frame.
    As can easily be calculated, the coodinates change like thus:
    1 frame: 104 / 120
    2 frames: 108 / 117
    3 frames: 112 / 114
    4 frames: 116 / 111

    Note that
    1) if the objects are small enough, they might pass through each other completely undetected.
    2) Even if they aren't, the collision is inaccurate. Where exactly did they collide? Without looking at your algorithm, it might be anywhere between 111 and 116. And when? If the collision is perfectly elastic (e.g. a pool billard simulator would depend on this), you'd have to note that, given that the two objects are approaching each other at 7px/frame and are only 2px apart after 3 frames, they'd collide after 2 7ths of the 4th frame and would spend the other 5 7ths moving apart again, during which time X would move (assuming X and Y have equal mass) ~2px to the left, while Y moves ~3 px to the right.

    For these reasons, it is necessary that you do more advanced calculations to know exactly where an object should be.
    This accuracy might not be necessary for your game. But your algorithms won't be pixel perfect without it.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Well now I see . Thanks CornedBee.
    Woop?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM