Thread: Collision Detection

  1. #1
    C++ Newbie
    Join Date
    Aug 2005
    Posts
    55

    Question Collision Detection

    The final hurdle in my little snake game: collision detection. I read a tutorial on Allegro collision detection, and used their method. I have the snake, and I have the little fruit that you have to get to score. For both of the images, I have a bounding box with 4 variables, one for each side. But for some reason, it always thinks that the snake has collided with the fruit, even if it hasn't. I don't know if anyone wants to take the time to check over all the collision detection code, but it would be greatly appreciated. I've looked over it and can't find anything wrong. I basically just copied it from the tutorial, so it should work.

    Code:
    //Includes
    #include <allegro.h>
    #include<iostream>
    #include<string>
    #include <stdlib.h>
    #include <stdlib.h> 
    #include <cstdlib>
    #include <time.h>
    #include <vector>
    #include <complex>
    #include <math.h>
    #include <cmath>
    #include <time.h>
    
    using namespace std;
    
    //Graphics
    BITMAP *snakeimg = NULL;
    BITMAP *buffer = NULL;
    BITMAP *fruit = NULL;
    
    //Sounds
    
    //Variables
    float x,y;
    float dir = 45;
    float dx = sin(dir);
    float dy = cos(dir);
    #define PI 3.14159265
    int maxsize = 3;
    int timer = 0;
    int fx,fy;
    int snakeright,snakeleft;
    int snaketop,snakebottom;
    int fruitright,fruitleft;
    int fruittop,fruitbottom;
    bool collision = false;
    
    //Structs
    struct snake {
    	int x;
    	int y;
    };
    
    //Vectors
    vector<snake> snakes(0);
    
    //Functions
    void UpdateSnake();
    void TestKeys();
    void TestCollisions();
    
    int main(int argc, char argv[1])
    {
    	srand( (unsigned)time( NULL ) );
    	fx = (rand() % 400) + 0;
    	fy = (rand() % 400) + 0;
    	allegro_init();
    	install_keyboard();
    	set_color_depth(24);
    	set_gfx_mode(GFX_AUTODETECT_WINDOWED,400,400,0,0);
    
    	//BITMAPS
    	snakeimg = load_bitmap("Snake.bmp",NULL);
    	buffer = create_bitmap(400,400);
    	fruit = load_bitmap("Fruit.bmp",NULL);
    
    	while(!key[KEY_ESC])
    	{
    	clear_bitmap(buffer);
    	TestKeys();
    	UpdateSnake();
    	TestCollisions();
    	draw_sprite(buffer,fruit,fx,fy);
    	draw_sprite(screen,buffer,0,0);
    	}
    
    	allegro_exit();
    	return 0;
    
    	//Cleanup
    	for(int i = 0;i < snakes.size(); i++);
    	{
    		snakes.erase(snakes.begin()+i);
    	}
    	destroy_bitmap(snakeimg);
    	destroy_bitmap(buffer);
    	destroy_bitmap(fruit);
    }
    
    	
    END_OF_MAIN();
    
    void UpdateSnake()
    {
    	snakeleft = x;
    	snaketop = y;
    	snakeright = snakeleft + snakeimg->w;
    	snakebottom = snaketop + snakeimg->h;
    
    	fruitleft = fx;
    	fruittop = fy;
    	fruitright = fruitleft + fruit->w;
    	fruitbottom = fruittop + fruit->h;
    
    	dx = sin(dir*PI/180);
    	dy = cos(dir*PI/180);
    	x = x + dx/5;
    	y = y + dy/5;
    
    	timer++;
    
    if(timer >50)
    {
    	snake w;
    	w.x = x;
    	w.y = y;
    	snakes.push_back(w);
    	timer = 0;
    }
    	if(snakes.size() > maxsize)
    	{
    		snakes.erase(snakes.begin()+0);
    	}
    
    	for(int i = 0; i < snakes.size(); i++)
    	{
    		draw_sprite(buffer,snakeimg,snakes[i].x,snakes[i].y);
    	}
    }
    END_OF_FUNCTION(UpdateSnake);
    
    void TestKeys()
    {
    	if(key[KEY_LEFT])
    	{
    		dir = dir + .4; 
    	}
    	else if(key[KEY_RIGHT])
    	{
    		dir = dir - .4;
    	}
    }
    END_OF_FUNCTION(TestKeys);
    
    void TestCollisions()
    {
    	collision = false;
    	 // Test the top left corncer of the first box to the second
    // (Is the corner in or on the second box?)
    if(
       (snakeleft >= fruitleft) && (snaketop >= fruittop) &&
       (snakeleft <= fruitright) && (snaketop <= fruitbottom)
    )
    {
       collision = true;
    }
    
    // Test the top right corner of the first box to the second
    // (Is the corner in or on the second box?)
    else if(
       (snakeright <= fruitright) && (snakeright >= fruitleft) &&
       (snaketop >= fruittop) && (snaketop <= fruitbottom)
    )
    {
       collision = true;
    }
    // Test the bottom left corner of the first box to the second
    // (Is the corner in or on the second box?)
    else if(
       (snakeleft >= fruitleft) && (snakeleft <= fruitright) &&
       (snakebottom <= fruitbottom) && (snakebottom >= fruittop)
    )
    {
       collision = true;
    }
    // Test the borrom right corner of the first box to the second
    // (Is the corner in or on the second box?)
    else if(
       (snakeright <= fruitright) && (snakeright >= fruitleft) &&
       (snakebottom <= fruitbottom) && (snakebottom >= fruittop)
    )
    {
       collision = true;
    }
    
    // Test the top left corner of the second box to the first box
    // (Is the corner in or on the first box?)
    if(
       (fruitleft >= snakeleft) && (fruittop >= snaketop) &&
       (fruitleft <= snakeright) && (fruittop <= snakebottom)
    )
    {
       collision = true;
    }
    
    // Text the top right corner of the second box to the first box
    // (Is the corner in or on the second box?)
    else if(
       (fruitleft <= snakeright) && (fruitright >= snakeleft) &&
       (fruittop >= snaketop) && (fruittop <= snakebottom)
    )
    {
       collision = true;
    }
    
    // Test the bottom left corner of the second box to the first box
    // (Is the corner in or on the second box?)
    else if(
       (fruitright <= snakeright) && (fruitright >= snakeleft) &&
       (fruitbottom <= snakebottom) && (fruitbottom >= snaketop)
    )
    {
       collision = true;
    }
    
    // Test the bottom right corner of the second box to the first box
    // (Is the corner in or on the second box?)
    else if(
       (fruitright <= snakeright) && (fruitright >= snakeleft) &&
       (fruitbottom <= snakebottom) && (fruitbottom >= snaketop)
    )
    {
       collision = true;
    }
    
    // Check box 1 for a horizontal cross on box 2
    // (This covers a vertical cross for box 2 on box 1)
    if(
        (snaketop > fruittop) && (snakebottom < fruitbottom) &&
        (fruitleft > snakeleft) && (fruitright < snakeright)
    )
    {
        collision = true;
    }
    
    // Check box 2 for a horizontal cross on box 1
    // (This covers veritcal cross for box 1 on box 2)
    if(
        (fruittop > snaketop) && (fruitbottom < snakebottom) &&
        (snakeleft > fruitleft) && (snakeright < fruitright)
    )
    {
        collision = true;
    }
    
    if(collision = true)
    {
    	fx = (rand() % 400) + 0;
    	fy = (rand() % 400) + 0;
    }
    }
    END_OF_FUNCTION(TestCollisions);

  2. #2
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    That is way to much work for simple bounding box collision detection collision. Here is a good algo for that.
    Code:
    struct Box
    {
        int left, right;
        int top, bottom;
    };
    
    bool detectCollision(const Box &b1, const Box &b2)
    {
        return !(b1.right < b2.left &&
                 b2.right < b1.left &&
                 b1.bottom < b2.top &&
                 b2.bottom < b1.top);
    }
    Then you can make a box of your fruit and snakes coordinates and then pass it to this function to see if the are colliding. Fell free to pm me with anymore questions since I love allegro .
    Woop?

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > if(collision = true)
    This can't be good.

    If you're using gcc for your compiler, add
    -W -Wall
    to the command line arguments.

    In addition, fix the indentation of your code. In particular, make sure all tabs have been replaced with an appropriate number of spaces before posting on the board.

    Finally, don't use so many global variables - make use of function parameters.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    C++ Newbie
    Join Date
    Aug 2005
    Posts
    55
    Quote Originally Posted by Salem
    > if(collision = true)
    This can't be good.

    If you're using gcc for your compiler, add
    -W -Wall
    to the command line arguments.

    In addition, fix the indentation of your code. In particular, make sure all tabs have been replaced with an appropriate number of spaces before posting on the board.

    Finally, don't use so many global variables - make use of function parameters.
    Oh oops. Was it supposed to be if(collision == true)?

    It still thinks that it's always colliding...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems with AABB Collision Detection.
    By Shamino in forum Game Programming
    Replies: 10
    Last Post: 03-30-2009, 07:00 PM
  2. Collision Detection Problems
    By Dark_Phoenix in forum Game Programming
    Replies: 1
    Last Post: 12-17-2006, 03:25 PM
  3. bounding box collision detection
    By DavidP in forum Game Programming
    Replies: 7
    Last Post: 07-07-2002, 11:43 PM
  4. collision detection
    By DavidP in forum Game Programming
    Replies: 2
    Last Post: 05-11-2002, 01:31 PM
  5. Replies: 4
    Last Post: 05-03-2002, 09:40 PM