|
Collision detection and keyboard input question.. |
Gnamra
Member #12,503
January 2011
|
This is my first attempt at collision detection and I'm going to use bounding box / rectangle collision detection, do I need to check with all the objects on the map? If I have 100 different platforms, boxes and other stuff do I need to check with all of them if they collide with the player? This seems really tedious and inefficient.. I also have a problem with the keyboard input / events in my game, when I press left / right arrow key then press the up arrow key to jump while holding left / right it stops moving to the left / right. What I thought would happen, if this is the event queue: right, right, right, up, right, right, right, etc etc. What actually happens: Right, right, right, up then it stops. Sorry if my explaining is a bit confusing. Here's some code. Player.cpp Move function. 1void Player::Move(ALLEGRO_EVENT* events)
2{
3
4 if(events->type = ALLEGRO_EVENT_KEY_DOWN)
5 {
6 switch(events->keyboard.keycode)
7 {
8 case ALLEGRO_KEY_DOWN:
9 break;
10 case ALLEGRO_KEY_UP:
11 Player::Jump();
12 break;
13 case ALLEGRO_KEY_RIGHT:
14 if(Player::vel_X <=10)Player::vel_X += 1;
15 break;
16 case ALLEGRO_KEY_LEFT:
17 if(Player::vel_X >=-10)Player::vel_X -= 1;
18 break;
19 };
20 }
21}
The jumping function only sets the vel_Y to -20 and sets jumping = true My game loop. 1while(!done)
2{
3 al_clear_to_color(al_map_rgb(0,0,0));
4 ALLEGRO_EVENT events;
5 if(al_wait_for_event_timed(event_queue, &events, 0.0001)) player.Move(&events);
6 game.update(&player);
7 game.draw(&player);
8 al_rest(0.030);
9}
my Game.update 1 void Game::update(Player *p)
2{
3 p->setX(p->getfX() + p->getfVel_X());
4 p->setY(p->getfY() + p->getfVel_Y());
5 if(p->getfVel_X() > 0.1 && !p->jumping) p->setVel_X(p->getfVel_X() - 0.5);
6 if(p->getfVel_X() < -0.1 && !p->jumping) p->setVel_X(p->getfVel_X() + 0.5);
7 if(p->getfY() < 400) p->setVel_Y(p->getfVel_Y() + 5);
8 if(p->getfY() == 400.0)
9 {
10 p->setVel_Y(0);
11 p->jumping = false;
12 }
13 if(p->getfY() > 400)
14 {
15 p->setY(400);
16 p->jumping = false;
17 }
18
19};
Right now it's only a "P" being drawn on a black background, I'm trying to perfect character movement before I add platforms, images, sound etc oh and, whats the difference between Player::vel_X and just typing vel_X in player.cpp?
|
Stas B.
Member #9,615
March 2008
|
Gnamra said: This is my first attempt at collision detection and I'm going to use bounding box / rectangle collision detection, do I need to check with all the objects on the map? If I have 100 different platforms, boxes and other stuff do I need to check with all of them if they collide with the player? This seems really tedious and inefficient.. If this is your first attempt at collision detection, I'd say you have a long way to go before you get to the point where optimizing bounding box checks becomes a real concern. Concentrate on getting something that feels like a game done, then optimize, if needed. It's easy to get carried away trying to figure out how to speed things up with space partitioning. Well, since I've already mentioned it, the general idea is to divide the space into simple, non-intersecting regions, figure a fast algorithm to find out which region an object is inside, then check for collisions only between objects that are in the same region. The most common method for a 2D game is probably a simple grid of squares. You can try quad trees if you want to get fancy, but it's almost always overkill. |
Gnamra
Member #12,503
January 2011
|
Stas B. said: Well, since I've already mentioned it, the general idea is to divide the space into simple, non-intersecting regions, figure a fast algorithm to find out which region an object is inside, then check for collisions only between objects that are in the same region. The most common method for a 2D game is probably a simple grid of squares. You can try quad trees if you want to get fancy, but it's almost always overkill. I see, so checking for collision with all the objects in a level isn't something that will slow down the game? Even if there are hundreds or perhaps thousands of objects? Thanks Only need to workout the keyboard problem now.
|
Cassio Renan
Member #14,189
April 2012
|
A fast and easy way to improve collision detection(if it's slow) is to check for bounding circles first, and then for bounding boxes. That way your algorithm will only check for boxes if the sprites are close enough to do so. in pseudo-code(actually, I guess this works fine in C): 1bool check_collision(sprite a,sprite b)
2{
3 // a's centre x
4 a.cx = a.x + a.w/2
5 // a's centre y
6 a.cy = a.y + a.h/2
7
8 // a's radium. you should get it at creation of the sprite,
9 // not at collision time, since you only need to get it once.
10 // it's simply the distance from the centre to the up-left
11 // vertice of the sprite.
12 a.r = distance(a.x, a.y, a.cx, a.cy)
13
14 // Same for "b"
15 b.cx = b.x + b.w/2 // b's centre x
16 b.cy = b.y + b.h/2 // b's centre y
17 b.r = distance(b.x, b.y, b.cx, b.cy) // b's radium
18
19 // forget the sqrt, it's slow. The squared distance will already work.
20 distance = pow(a.cx - b.cx, 2) + pow(a.cy - b.cy, 2)
21
22 if(distance <= pow(a.r + b.r))
23 return check_bounding_boxes(a, b)
24 else
25 return false;
26}
Could anyone confirm this is a good practice? I sometimes do it this way and it works most time.(guess I turned my answer to a question, ) |
David Sopala
Member #5,056
September 2004
|
You might be better off doing something like: I think an angled line could cut corners if you have oddly shaped sprites. max(sprite->w,sprite->h); <img src="http://imgur.com/bfHvGkj.jpg" /> |
Stas B.
Member #9,615
March 2008
|
Gnamra said: I see, so checking for collision with all the objects in a level isn't something that will slow down the game? Even if there are hundreds or perhaps thousands of objects? Hundreds? Nope. Thousands? Probably not enough to slow down a modern PC, but if you manage to get into that range, it will probably become worthwhile to free up some CPU cycles for the other tasks needed to handle thousands of objects. Note that when you say thousands of objects, I assume that each one of them may collide with any other. That's not usually the case. Either way, my point is that you shouldn't worry about this yet, whether it will become a problem in the future or not. Focus on the fun part of making an actual game. Optimizations are a huge time sink and it's quite demotivating when you realize you've spent two weeks trying to implement quad trees but don't have anything that even remotely resembles a game yet. Cassio Renan said: A fast and easy way to improve collision detection(if it's slow) is to check for bounding circles first, and then for bounding boxes. That way your algorithm will only check for boxes if the sprites are close enough to do so. Depends on the type of bounding boxes. If they're axis-aligned, it's a waste of time, since a method to check wether they intersect should look roughly like this: if(min.x > other.max.x || min.y > other.max.y || other.min.x > max.x || other.min.y > max.y) return false; else return true; If they're allowed to rotate, well, that's another story, but I think the OP doesn't really care for rotating bounding boxes yet. |
Gnamra
Member #12,503
January 2011
|
Thanks for all the help, I think rotating bounding boxes and quad trees are beyond me right now, so I'll save that for later! Uhm.. about the problem I have with key events. Do all keyboards stop repeating the keystroke when another key was pressed? I'm currently trying to figure out how to keep sending keystrokes of the last button pressed excluding the jump button. If someone has a fix for my problem then please post
|
Cassio Renan
Member #14,189
April 2012
|
well, 8if(p->getfY() == 400.0)
9 {
10 p->setVel_Y(0);
11 p->jumping = false;
12 }
13 if(p->getfY() > 400)
14 {
15 p->setY(400);
16 p->jumping = false;
17 }
and not 8if(p->getfY() >= 400.0 &&p->jumping)
9 {
10 p->setVel_Y(0);
11 p->setY(400);
12 p->jumping = false;
13 }
? EDIT: Added "p->jumping" into the condition, so it only happens during jump. |
Gnamra
Member #12,503
January 2011
|
Because I'm stupid sometimes edited the code to match yours. I have a bad habit of creating more if statements than needed, at that point I was trying to figure out why the velocity would sometimes continue to increase even though it hit 400. Then I realized it was because it never actually hit 400 but went past it so I made another if statement for when that happens. Also, I found a workaround for the keyboard / key event problem I had. For anyone who stumbles into the same problem, here's how I fixed it player.cpp 1 void Player::Move(ALLEGRO_EVENT* events)
2{
3 if(keyDown == true){
4 switch(lastEvent.keyboard.keycode)
5 {
6 case ALLEGRO_KEY_RIGHT:
7 keyDown = true;
8 lastEvent.keyboard.keycode = ALLEGRO_KEY_RIGHT;
9 if(Player::vel_X <= 10)Player::vel_X += 1;
10 break;
11
12 case ALLEGRO_KEY_LEFT:
13 keyDown = true;
14 lastEvent.keyboard.keycode = ALLEGRO_KEY_LEFT;
15 if(Player::vel_X >= -10)Player::vel_X -= 1;
16 break;
17 };
18 }
19
20 if(events->type == ALLEGRO_EVENT_KEY_DOWN && events->keyboard.keycode != ALLEGRO_KEY_UP || keyDown == true)
21 {
22 switch(events->keyboard.keycode)
23 {
24 case ALLEGRO_KEY_RIGHT:
25 keyDown = true;
26 lastEvent.keyboard.keycode = ALLEGRO_KEY_RIGHT;
27 if(Player::vel_X <= 10)Player::vel_X += 1;
28 break;
29
30 case ALLEGRO_KEY_LEFT:
31 keyDown = true;
32 lastEvent.keyboard.keycode = ALLEGRO_KEY_LEFT;
33 if(Player::vel_X >= -10)Player::vel_X -= 1;
34 break;
35 };
36 }
37 if(events->type == ALLEGRO_EVENT_KEY_UP && events->keyboard.keycode != ALLEGRO_KEY_UP) keyDown = false;
38 if(events->type == ALLEGRO_EVENT_KEY_DOWN && events->keyboard.keycode == ALLEGRO_KEY_UP) Player::Jump();
39}
What I did was I added And stored the last keyboard keycode in lastEvent. There is most likely a better way to do it
|
|