Allegro.cc Forums » Programming Questions » Line Collision / Shot Detection System

 Line Collision / Shot Detection System
 EricsonWillians Member #15,027 April 2013 Greetings!I'm developing a Top-View 2D Multiplayer Shooter in C and I'm having serious problems with the Shot Detection System.I would really enjoy a major help concerning the whole problem that I've posted in the stackoverflow website:http://stackoverflow.com/questions/15722996/c-and-allegro-how-to-detect-shots-in-a-top-view-2d-shooterThe answer they gave to me involving atan2() from the C standard math library is mysterious to me and I'm looking forward to expand my knowledge in Geometry and Mathematics to fully understand it.Nevertheless, I can draw a line between the two players in this way:#SelectExpand 1al_draw_line(defaultPlayer1.pos[0], defaultPlayer1.pos[1], defaultPlayer2.pos[0], defaultPlayer2.pos[1], al_map_rgb(0, 255, 0), 2); It would be rather easy if I could detect when the first button of the mouse is pressed OVER the line (When the weapon is above the line between the two players). In this way I could detect the shot. But the problem with this idea is: al_draw_line() does not return anything, I can't find a way to test if something interacts with the line drawn. Anyway, you all are experts in the Allegro library and I am just a programmer beginning to deal with game concepts and the Allegro library. It would be really really helpful if you could point me an example of a solution to this top-view problem.Thank you very much!
 Arthur Kalliokoski Second in Command February 2005 I guess you mean that the image rotates as you move your mouse sideways? You've already passed the angle in radians to al_draw_rotated_bitmap(), so you get the difference between player2 y and player1 y (to make a vector) to pass as the first argument to atan2(), then do the differences in x to get the second argument. If the returned value (an angle in radians) is "close enough" to the angle you drew the sprite at, it collides. The "close enough" part is to account for the size of the enemy (after all, he's not an infinitely small point).The distance between the players can be gotten by the good old Pythagorian theorom to see if it's within range or not. If you want to get fancy, you could associate this distance with the "good enough" value by various ways so the closer the enemy was, it'd be easier to hit him, just like you'd expect.I wish I was articulate. The guy who answered you on stackoverflow is Matthew, the guy who runs this site. “Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”― Robert A. Heinlein
 EricsonWillians Member #15,027 April 2013 First of all, I thank you two for the excellent replies. I haven't completely understand it yet, but now I have stronger clues. Yes, I have the angle when the left mouse button is pressed; as you've said, I draw the rotated bitmap already. I do so here:#SelectExpand 1al_draw_rotated_bitmap(playerTux, defaultPlayer1.size / 2, defaultPlayer1.size / 2, 2defaultPlayer1.pos[0], defaultPlayer1.pos[1], mousePos / mouseSensitivity, 0); For you to understand it more clearly, the angle in this case is a division of mousePos with a constant called mouseSensitivity (Giving the fact that it is a shooter game, I found a way to give to the user the option of choosing between 4 sensitivities.)The rotation of the bitmap involves a curious solution that I've found:#SelectExpand 1if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) { 2 3// This says that the variable mousePos equals to the movement of the mouse 4// in the x axis, which is something necessary to change the angle of the image. 5 6 mousePos = ev.mouse.x; 7 8 9// I had several problems with the image stoping to rotate when the mouse 10// goes off the screen area. So this basically warps the mouse cursor to the 11// beginning of the screen when it goes off it, and vice-versa. To examine 12// how this works, put a comment in the "al_hide_mouse_cursor()" up there. 13 14 if (mousePos >= screenWidth - 1) { // If the mouse cursor goes off the screen (right), 15 al_set_mouse_xy(display, 1, 0); } // warp it to the beginning of the screen. 16 if (mousePos < 1) { // If the mouse cursor goes off the screen (left), 17 al_set_mouse_xy(display, screenWidth - 1, 0); } } // warp it to the end of the screen. This "mouse cursor teleportation" solved perfectly an old problem of mine (Maybe there's a clever way to solve this, but if it is, I don't know it yet).The "mouseSensitivity" is declared together with the mousePos in this way:#SelectExpand 1float mousePos = 0.0; 2float mouseSensitivity = LOW_MOUSE_SENSITIVITY; LOW_MOUSE_SENSITIVITY is a constant, defined together with these ones:#SelectExpand 1#define PLAYER_ROTATION_FACTOR 81.2 2#define VERY_LOW_MOUSE_SENSITIVITY PLAYER_ROTATION_FACTOR * 2 3#define LOW_MOUSE_SENSITIVITY PLAYER_ROTATION_FACTOR 4#define MEDIUM_MOUSE_SENSITIVITY PLAYER_ROTATION_FACTOR / 2 5#define HIGH_MOUSE_SENSITIVITY PLAYER_ROTATION_FACTOR / 2 / 2 This "rotation factor" is a solution to a terrible problem. When I've put the mouse.x as an angle argument to draw the rotated bitmap; even with the pivot placed properly, the bitmap didn't rotate completely (360), and then, by testing endlessly, I found that when I divided the mousePos with this value (81.2), the turn was complete (And therefore, mathematically speaking, I could double it's value to get a slower turn, but a still complete turn). I don't know if this all is clear enough, but it's working perfectly.The thing is, thanks to this odd division, the angle does not go from 0 to 360; instead, it goes from 0.000000 to 6.299999. If I print this angle multiplied by something closer to 28 I can get the 360, but it's irrelevant. Now I've come to my actual problem, and I'm trying to apply this atan2() like this:#SelectExpand 1 double playerPosArray1X[2] = {defaultPlayer1.pos[0], defaultPlayer2.pos[0]}; 2 double playerPosArray1Y[2] = {defaultPlayer1.pos[1], defaultPlayer2.pos[1]}; 3 double angleCalculation = atan2(playerPosArray1Y, playerPosArray1X); And then, inside the loop:#SelectExpand 1printf("Angle Calculation: %f\n", angleCalculation); But I receive the following error in terminal:main.c: In function ‘main’: main.c:84:2: error: incompatible type for argument 1 of ‘atan2’ In file included from /usr/include/math.h:71:0, from main.c:22: /usr/include/x86_64-linux-gnu/bits/mathcalls.h:61:1: note: expected ‘double’ but argument is of type ‘double *’ main.c:84:2: error: incompatible type for argument 2 of ‘atan2’ In file included from /usr/include/math.h:71:0, from main.c:22: /usr/include/x86_64-linux-gnu/bits/mathcalls.h:61:1: note: expected ‘double’ but argument is of type ‘double *’ make: *** [main] Error 1 So, I can't pass an array as an argument of atan2(), and I'm still quite lost. But I'll keep studying... After all, that's what game development is all about, right? Solving terrible problems in the most efficient way .Thank you very much again!
 Arthur Kalliokoski Second in Command February 2005 EricsonWillians said: The thing is, thanks to this odd division, the angle does not go from 0 to 360; instead, it goes from 0.000000 to 6.299999. If I print this angle multiplied by something closer to 28 I can get the 360It's giving you the angle in radians, not degrees. If you multiply that by 180.0/M_PI (which is close to 28) then you get degrees. As I said before, you're passing radians to al_draw_bitmap(), but I guess you didn't know it.Quote: expected ‘double’ but argument is of type ‘double *’So put an asterisk in front, to dereference the pointers. double angleCalculation = atan2(*playerPosArray1Y, *playerPosArray1X);  “Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”― Robert A. Heinlein