allegro "simple collision" issues

Feb 1, 2011 at 1:28am
I've been having a hard time trying to figure out how to make a correct

response when a collision is detected. The below code works perfectly on my

computer and uses allegro, it is also a simplified version of my total code. I

am wondering what I need to add to this to make my main character stop moving

but be able to back up and jump on top of the other one (just like in 2d games

like mario and super meat boy). So basically i need the 2nd part of

collision. I've been told that i need to know about vectors and dot products

and stuff and sure i can learn those but I would have no idea how to use that

knowledge to put it into my game. If anyone can help it would be much

appreciated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <allegro.h>
#include <stdlib.h>

volatile long speed_counter = 0; //integer to store value of the speed counter
void increment_speed_counter() //function to increment the speed counter
{
     speed_counter++;
     }
END_OF_FUNCTION(increment_speed_counter);

int main(int argc, char *argv[])
{
    allegro_init();
    install_keyboard();
    install_timer();
    
    LOCK_VARIABLE(speed_counter);
    LOCK_FUNCTION(increment_speed_counter);
    install_int_ex(increment_speed_counter, BPS_TO_TIMER(60));
    
    set_color_depth(32);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640,480,0,0);
    
    BITMAP *buffer = create_bitmap(640,480); //create a buffer for smooth animation
    if(buffer == NULL)
    {
              set_gfx_mode(GFX_TEXT,0,0,0,0);
              allegro_message("Could not create buffer!");
              exit(EXIT_FAILURE);
              }
BITMAP *image1 = load_bitmap("C:\\Users\\RARMAN\\Desktop\\pics\\muffin_man_FRONT.bmp", NULL);
if(image1 == NULL)
{
          set_gfx_mode(GFX_TEXT,0,0,0,0); //sets screen mode for allegro messages
          allegro_message("Could not load image1.bmp");
          exit(EXIT_FAILURE);
          }
BITMAP *image2 = load_bitmap ("C:\\Users\\RARMAN\\Desktop\\Chosen_One\\Lesson8\\image2.bmp", NULL);
if(image2 == NULL)
{
          set_gfx_mode(GFX_TEXT,0,0,0,0);
          allegro_message("Could not load image2.bmp");
          exit(EXIT_FAILURE);
          }
int image1_x_position = 0;
int image1_y_position = 0;

int image2_x_position = 100;
int image2_y_position = 100;

int image1_bb_left = image1_x_position;
int image1_bb_top = image1_y_position;
int image1_bb_right = (image1_bb_left + image1->w);
int image1_bb_bottom = (image1_bb_top + image1->h);

int image2_bb_left = image2_x_position;
int image2_bb_top = image2_y_position;
int image2_bb_right = (image2_bb_left + image2->w);
int image2_bb_bottom = (image2_bb_top + image2->h);

int show_bbox = FALSE;
int collision = FALSE;

while(!key[KEY_ESC])
{
                    while(speed_counter > 0)
                    {
                    if(key[KEY_LEFT])
                    image1_x_position --;
                    if(key[KEY_RIGHT])
                    image1_x_position ++;
                    if(key[KEY_DOWN])
                    image1_y_position ++;
                    if(key[KEY_UP])
                    image1_y_position --;
                    
                    if(key[KEY_A])
                    image2_x_position --;
                    if(key[KEY_D])
                    image2_x_position ++;
                    if(key[KEY_S])
                    image2_y_position --;
                    if(key[KEY_W])
                    image2_y_position ++;
                    
                    if(key[KEY_SPACE])
                    show_bbox = TRUE;
                    else if(!key[KEY_SPACE])
                    show_bbox = FALSE;
                    
                    image1_bb_left = image1_x_position;
                    image1_bb_top = image1_y_position;
                    image1_bb_right = (image1_bb_left + image1->w);
                    image1_bb_bottom = (image1_bb_top + image1->h);
                    
                    image2_bb_left = image1_x_position;
                    image2_bb_top = image1_y_position;
                    image2_bb_right = (image2_bb_left + image2->w);
                    image2_bb_bottom = (image2_bb_top + image2->h);
                    
                    collision = TRUE; //assume there is a collision
                    if(image1_bb_bottom < image2_bb_top)
                    {
                                        collision = FALSE;
                                        }
                    if(image1_bb_top > image2_bb_bottom)
                    {
                                     collision = FALSE;
                                     }
                    if(image1_bb_right < image2_bb_left)
                    {
                                       collision = FALSE;
                                       }
                    if(image1_bb_left < image2_bb_right)
                    {
                                      collision = FALSE;
                                      }
                    speed_counter --;
                    }

draw_sprite(buffer, image1, image1_x_position, image1_y_position);
draw_sprite(buffer, image2, image2_x_position, image2_y_position);

if(show_bbox == TRUE)
{
line(buffer, image1_bb_left, image1_bb_top, image1_bb_right, image1_bb_top, makecol(255,0,0));
line(buffer, image1_bb_left, image1_bb_bottom, image1_bb_right, image1_bb_bottom, makecol(255,0,0));
line(buffer, image1_bb_left, image1_bb_top, image1_bb_left, image1_bb_bottom, makecol(255,0,0));
line(buffer, image1_bb_right, image1_bb_top, image1_bb_right, image1_bb_bottom, makecol(255,0,0));

line(buffer, image2_bb_left, image2_bb_top, image2_bb_right, image2_bb_top, makecol(255,0,0));
line(buffer, image2_bb_left, image2_bb_bottom, image2_bb_right, image2_bb_bottom, makecol(255,0,0));
line(buffer, image2_bb_left, image2_bb_top, image2_bb_left, image2_bb_bottom, makecol(255,0,0));
line(buffer, image2_bb_right, image2_bb_top, image2_bb_right, image2_bb_bottom, makecol(255,0,0));
}

if(collision == TRUE)
{
             textprintf_ex(buffer, font, 0,0, makecol(255,255,255), -1, "Collision!");
             }

blit(buffer, screen, 0,0,0,0,640,480); //blit the buffer
clear(buffer); //clear the buffer
}


destroy_bitmap(buffer);
destroy_bitmap(image1);
destroy_bitmap(image2);

return 0;
}
END_OF_MAIN()
Feb 1, 2011 at 5:39am
Ahh collision handling... my old nemesis...

You don't have to know all of the math behind everything, you can program completely without it. However with a little bit of knowledge you would be able to figure out where to plug it into your code (if you can't you shouldn't be programming =) probably

With your specific code, I'm hoping that your less simplified code is using a little bit of the oop paradigm? I personally would encapsulate a lot of this in functions and classes (though it looks like you're using c)

I would (I know you don't want to hear this) actually just beat the code to death, or beat google to death for an answer. I've learned more about programming just by grinding out code myself then any other method, but if you need help, please be more specific.
Feb 1, 2011 at 7:18am
this code was in a tutorial i think, and the code that i have now started as this, now i'm using structs and/or classes to keep all the information for the characters together (and soon other things like bullets or projectiles).

Ya...about beating the code to death and google... i've done that.

This is my first time working with graphics in C++ (previously the biggest thing i've made in c++ was a tic tac toe program that would have two AIs battle each other for an amount of games), I used java with graphics a bit but really didnt like it compared to C++.

So i guess what my question should be is how do I change the main character's coordinates after the program determines that it has collided with another character?

Right now if a collision happens the velocity of my character stops being applied and i cant get it so it can back up from being stuck (I've tried a lot of random stuff and this is just my latest attempt)

This code is from my current program instead of the simplified one (the program above)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

			for(int current_object = 1; current_object < 2; ++current_object)
			{//this loop checks each world object which includes enemies (only one enemy right now)
				if(!collision_check(current_object, collision, &hero_player, game_objects))
				{

					hero_player.image_x_position += velx;	//hero can now move on the x axis
					hero_player.image_y_position += vely;	//same but for y axis

					//if you do the response this way the player cant move when colliding
				}
				
				//else
				//{
					//not sure what to put in here 
				//}
				

			}



collision check returns true or false depending on if collision happened, velx and vely are changed when a player pushes left right up or down.

So to be even more specific about my question, what would i put in the else statement? unless this is just completely the wrong way to go about the collision response (i don't know lol).

Thanks for your reply(ies)!
Last edited on Feb 1, 2011 at 7:38am
Feb 1, 2011 at 8:28am
Well what you are looking at is collision resolution, one of the most common methods is separating the axis and checking each one individually. That's the method that I ended up using and it seems to work pretty well: see http://sourceforge.net/projects/ultiscroll/files/SideScroller_11.zip/download

Now the problem with your current method is you have a single function to check all collisions, it would be tough (not impossible by any means) to have a single function to handle them all. You could look into creating a manager class that will manage the collision handling and collision detection system. You could send messages to the manager to check for collision, the manager could check for proximity (to make sure it's necessary to check for collisions) then resolve any collisions based on the properties of the entities in question;

One thing you may want to look into is the separation of the screen into different subsections, and when you update your position, update all current quadrants your object is in, that way you could just do collision detection by quadrant and speed up the process a little.

Really the best way in my opinion is to have a collision prevention system, but that's a little tougher, and I believe slower. Your call, but there is quite a bit of reference material available.
Last edited on Feb 1, 2011 at 8:30am
Topic archived. No new replies allowed.