Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

191 Neutral

About Soundstone

  • Rank
  1. Soundstone

    Linear collision question

    I figured I would post the full solution in case anyone ever needs to use this again. Here is how I was able to solve the collision checks for both the ceiling and the floor - both of which are generated randomly with array of Vector3.   In the game loop I calculate if the player is close enough to the ceiling to be worthy of checking and the same goes for the floor. If the player is close enough I use a for loop to cycle through the vector3 positions of the ceiling / floor points. It continues over the points that are too far from the player. Once it finds a pair of contiguous points it sends a call out to check the ceiling or floor for collision based on these two points. Here is the cycle in game loop: for (int i = 0; i < NUM_POINTS; i++) { if (ship.shipPos.x > topPoints[i + 1].x) continue; if (ship.shipPos.x < topPoints[i].x) continue; collide = CheckCollisionsTop(ship, topPoints[i], topPoints[i + 1]); }  Below you'll see the collision check for my ceiling. It takes a reference to a SpaceShip because eventually it will alter the ship's position based on collision. It also takes 2 Vector3 positions.  The line segment is just a new vector that contains the distance between pointTwo and pointOne. The shipWidthPosition alters the ship position to test based on which side of the ship we want to test. This matters for the direction of the line in question. If the line is upwards - pointTwo.y is higher than pointOne.y then we will use normal ship position since the (X,Y,Z) of shipPos is the upper left corner of the ship. For a downward line (pointOne.y is higher than pointTwo.y) then we use the other side by adding the width to the ships coords.  bool CheckCollisionsTop(SpaceShip &ship, Vector3 pointOne, Vector3 pointTwo) { Vector3 lineSegment = GetVectorDistance(pointOne, pointTwo); Vector3 shipWidthPosition(ship.shipPos.x + ship.GetWidth(), ship.shipPos.y, ship.shipPos.z); if (pointTwo.y < pointOne.y) //upwards line { Vector3 lineNormal(lineSegment.y, -lineSegment.x, 0); double u = GetVectorDistance(ship.shipPos, pointTwo) * lineNormal; if (u > 0) return false; else if (u < 0) return true; } else if (pointTwo.y > pointOne.y) //downwards line { Vector3 lineNormal(lineSegment.y, -lineSegment.x, 0); double u = GetVectorDistance(shipWidthPosition, pointOne) * lineNormal; if (u > 0) return false; else if (u < 0) return true; } } And here is the collision check for the floor - differs slightly in ship testing coordinates, the sign of "u" and the normal of the line is different. bool CheckCollisionsBottom(SpaceShip &ship, Vector3 pointOne, Vector3 pointTwo) { Vector3 lineSegment = GetVectorDistance(pointOne, pointTwo); Vector3 shipHeightPosition(ship.shipPos.x, ship.shipPos.y + ship.GetHeight(), ship.shipPos.z); Vector3 shipWidthHeightPosition(ship.shipPos.x + ship.GetWidth(), ship.shipPos.y + ship.GetHeight(), ship.shipPos.z); if (pointTwo.y < pointOne.y) //upwards line { Vector3 lineNormal(-lineSegment.y, lineSegment.x, 0); double u = GetVectorDistance(shipWidthHeightPosition, pointTwo) * lineNormal; if (u > 0) return false; else if (u < 0) return true; } else if (pointTwo.y > pointOne.y) //downwards line { Vector3 lineNormal(-lineSegment.y, lineSegment.x, 0); double u = GetVectorDistance(shipHeightPosition, pointTwo) * lineNormal; if (u > 0) return false; else if (u < 0) return true; } } If you have needed linear collision, then I hope this has been some help to you. 
  2. Soundstone

    Linear collision question

    Thanks Haegarr,   I finally got the algorithm working for the ceiling. It kind of works for the floor at this moment, but I'm sure I'm pretty close to it. Once again thanks for the help.    Regards
  3. Soundstone

    Allegro bitmaps at runtime?

    Hi Fastcall,    Thanks for the reply! The information was a relief to hear. Would you recommend printing the entire thing to one bitmap and then drawing a region of that bitmap with al_draw_bitmap_region() or just keep a bitmap the size of my screen and keep clearing / drawing the new sets of points to it before blitting to the display? Thanks again.
  4. Hello everyone,   I have recently run into a problem that I'm not sure Allegro 5 can handle. I was curious if anyone knew whether or not the following functionality existed for the Allegro graphics library.   I am aware that to get a scrolling background one can provide an image and load it in as a ALLEGRO_BITMAP *background. I have done this just fine. However, for the particular game I am trying to code I generate the level at random.   Basically I generate two arrays of points, one for my ceiling and one for my floor. These arrays are size top[333] and bottom[333]. The distance between each point is between 36 - 48 pixels, thus my final point in both arrays is someone just over 12,050 as the X coord.   My question is this, does Allegro have a way to create an image at runtime based on the plot placement of these randomly generated points? I've tried looking at the Allegro5 manual and it doesn't really provide any information on bitmap creation at runtime. Does anyone have experience with this sort of thing, or am I doomed to choose a new graphics library or create static images instead of random?   Thanks for taking the time to read and any advice that may be offered.    
  5. Soundstone

    Linear collision question

    Hi Haegarr, thanks for the continued input. I feel like I'm really close to getting this, but there is part of it that eludes me visually. To better explain where I am getting lost, I'd like to provide an example and work the steps out here for it. As you know I am not necessarily trying to draw a perpendicular line, rather instead use the math behind the perpendicular line to decide whether or not my square has collided with a line.   I have an array of points P[0] through P[4000]. Each of these points in the array are end points for a line. They are all spaced 36 units away from each other along the X axis.   lets say P[42] = (105, 50) and P[43] = (141, 82)   The distance vector is represented by Dn = (Dx , Dy) where as in this example Dx = (141 - 105) = 36 and Dy = (82 - 50) = 32;   Thus Dn = (36, 32)   From DnI can gather that the magnitude (length) of the line L = (P[42], P[43]) is equal to sqrt(36^2 + 32^2) = 48.17   If I'm understanding everything correctly so far then Vn = either (-32, 36) or (32, -36) depending on the direction I want my perpendicular vector to go. One is good for my ceiling and the other is good for my floor.   In this example, I'm worried about the ceiling so I'll choose Vn = (32, -36).   This is where my mind loses its grasp.    I believe I normalize this new vector Vn by  (32 / -36) / sqrt(32^2 + (-36)^2) giving me -.019.   If I plot similarly scaled coords on graph paper, I can see that my perpendicular line is correct based on the point Dn but it is way off based on the coords of P[42]  and P[43].   I am not grasping how to determine the "start" point of this perpendicular line. By this I mean the perpendicular line will run infinitely parallel to itself across the line P[42], P[43] (for all the points on the line segment), How does this apply to getting the relative point on the original line?   Once I grasp this step (above), I think that all I have to do is generate the distance between the point of interest (my square) and the line, and as long as its above 0 I'll be below the line.   I apologize if this is convoluted but this is the best way I could pose a question to you to further understand it. As always thanks for your time.   Regards
  6. Soundstone

    Linear collision question

    Thanks for the continued information Haegarr.   I've had some internet problems with a snow storm over the weekend so I haven't been able to get on to respond. I've made some progress but I don't believe that I've done it correctly.  I am having a little difficulty trying to determine what your variables in the formulas stand for.   I get the Pn is the a point for the line. I assume that dn is the distance between the two points. At this point, I kind of get lost. What is Dx and Dy? Are these the individual distances from x and y? Is Vn just a new point of (Distance of y, -Distance of x) for the start of the perpendicular to the point of interest? From here you have the equation    pn + t * dn + u * vn = c.   Again I understand Pn to be one of the original points (does it matter which?)  t I'm not sure about. dnI once again assume is distance calculated from point 1 to point 2 of initial line. U I'm not sure about. Same with Vn. All of this adds (add multiplies) to the point of interest c?   I apologize for sounding completely ignorant in this matter, and I thank you for the time you have already taken on this. Could you please explain the variables a little better.   Also here is a new screenshot of what I've accomplished thus far using this forum thread.   The blue lines are simply drawn from points 1 and 2 of line to point of interest. The yellow line was my initial attempt (ended up being parallel in regards to square's placement against line) and the red line is calculated as half the x and half the y difference between the two points, then drawn to the point of interest.   New Picture   Thanks again for your help thus far.
  7. Soundstone

    Linear collision question

    Thanks for the response Trienco.   I see what your saying using the floats. It makes sense now as to why it's not working given your example. Given what you have said and what Haegarr said before you, would you suggest finding the perpendicular off of the wall line to the point of interest. Then use the two line equations to find the point of intersection on the first line. Then use that point of intersection along with the initial point of interest to calculate distance between the two. Finally testing this distance to be within a range of say 0 and 1? Does that make sense?   I also just realized that the link containing the photo image of this scenario isn't able to be used in this thread for some reason. Is it easy enough to understand the action I'm looking for without the visual? If not, I can try and figure out another way to get the image posted on here.   Thanks again.
  8. Soundstone

    Linear collision question

    Thanks for the response Haegarr.   I follow that having two separate float values equaling the same is a low probability, but doesn't it at some point (despite how brief) have to equal a point on the line, say just before it crosses over the line. Does this mean that the update loop itself is too slow to catch the point as is?   I've taken a look at your proposal of using the perpendicular dot product of the line segment, but fear I don't fully comprehend it in this situation. To walk myself through it I'd like to mock up a scenario really quick.    Lets say that a line consisting of these two points A (108, 157) and B (144, 132) exists and that we are trying to find if another point collides with said line. If I'm understanding this correctly, I would want to create a perpendicular vector from this initial line to the point of interest, calculate the magnitude of this vector, if positive its on side A and if negative its on side B - resulting in collision. Is this correct? If this is not correct (albeit - perhaps even far off) would / could you provide me with a trivial example to demonstrate how the perpDot would be used correctly in this situation?   I must admit that I've been trying to re-teach myself math as it's been over a decade since my last formal math class. Its tough to re-learn after so long, hard to find a good book or resource that walks one through it much like they did in High School / College.    Once again, thank you so much for taking time to look into this. I greatly appreciate it.    Regards
  9. Hello all,   I have this concept that I am currently working on that creates a procedurally generated tunnel. This is done simply by starting with a start point and generating random points being offset by a variable distance over iteration. The results produce a tunnel of set length (rather long) looking something like this small portion.      (apparently I can't put the photo here - please follow link to see if you would like to see a screen shot of the tunnel to better help you understand)   Each of these lines is drawn based on the new point added through the random generation.and the lines are drawn via the Allegro5 library. The issue I'm having is collision based on these random lines and a players avatar - currently a square. What I had mapped out was testing collision based on a set of points on the avatar. So I get these 8 points.    1. (square.x, square.y) - Top Left Corner 2. (square.x + square.width / 2, square.y) Top Middle 3. (square.x + square.width, square.y ) Top Right Corner 4. (square.x, square.y + square.height /2) Left Middle 5. (square.x + square.width, square.y + square.height /2) Right Middle 6. (square.x, square.y + square.height) Bottom Left Corner 7. (square.x + square.width / 2, square.y + square.height) Bottom Middle 8. (square.x + square.width, square.y + square.height) Bottom Right Corner   as my test points for collision. To test the collision that requires finding out if any of these points lie on each of the lines. Since the lines are generated randomly at the it seems like it would be wrong to test each frame for all lines and these points. So I started with a simple test to see if checking collision is even needed this update. This was done via this code. for (int i = 0; i < NUM_POINTS; i++) { if(points[i + 1].y < points[i].y) { //preliminary check for collision, is ship within checking range? if( (ship.pos.x > points[i].x) && (ship.pos.x < points[i + 1].x) && (ship.pos.y > points[i + 1].y) && (ship.pos.y < points[i].y)) NUM_POINTS is the array that holds all randomly generated points. Lets say it currently stores 1000 points. This brings us to 999 lines in the level. There is also a BOT_NUM_POINTS set exactly the same way to make up the bottom of the tunnel.  The initial check of: if(points[i + 1].y < points[i]. y) is testing to see if the lines first point would be higher on the screen then the second. This determines if the line is sloped left or right. The next check of: if( (ship.pos.x > points[i].x) && (ship.pos.x < points[i + 1].x) && (ship.pos.y > points[i + 1].y) && (ship.pos.y < points[i].y)) is the preliminary check to see if collision is worth looking into. These works by checking to see if the ships upper left corner is within the x's of the line and if so if its between the height of the two as well. If this succeeds it continues on to perform collision checking for the line in question. float slope = GetLineSlope(points[i], points[i + 1]); float intercept = GetYIntercept(points[i], slope); //if( IsOnLine(ship.pos.x, ship.pos.y, slope, intercept) ) if(IsOnLine(ship.pos.x, ship.pos.y, points[i], points[i + 1])) { //Collide al_draw_textf(font, al_map_rgb(255,0,0), 100, 10, 0, "Line points (%5d, %5d)", points[i].x, points[i].y); al_draw_textf(font, al_map_rgb(255,0,0), 100, 35, 0, "Line points (%5d, %5d)", points[i + 1].x, points[i + 1].y); al_draw_textf(font, al_map_rgb(255,0,0), WIDTH / 2, HEIGHT / 2, 0, "COLLISION AT %5d, %5d", ship.pos.x, ship.pos.y); return true; } //else if ( IsOnLine((ship.pos.x + ship.boundx) / 2, ship.pos.y, slope, intercept) ) else if( IsOnLine( (ship.pos.x + ship.boundx) / 2, ship.pos.y, points[i], points[i + 1]) ) { //Collide al_draw_textf(font, al_map_rgb(255,0,0), 100, 10, 0, "Line points (%5d, %5d)", points[i].x, points[i].y); al_draw_textf(font, al_map_rgb(255,0,0), 100, 35, 0, "Line points (%5d, %5d)", points[i + 1].x, points[i + 1].y); al_draw_textf(font, al_map_rgb(255,0,0), WIDTH / 2, HEIGHT / 2, 0, "COLLISION AT %5d, %5d", ship.pos.x + ship.boundx, ship.pos.y); return true; } //else if ( IsOnLine(ship.pos.x + ship.boundx, ship.pos.y, slope, intercept) ) else if( IsOnLine(ship.pos.x + ship.boundx, ship.pos.y, points[i], points[i + 1]) ) { //Collide al_draw_textf(font, al_map_rgb(255,0,0), 100, 10, 0, "Line points (%5d, %5d)", points[i].x, points[i].y); al_draw_textf(font, al_map_rgb(255,0,0), 100, 35, 0, "Line points (%5d, %5d)", points[i + 1].x, points[i + 1].y); al_draw_textf(font, al_map_rgb(255,0,0), WIDTH / 2, HEIGHT / 2, 0, "COLLISION AT %5d, %5d", (ship.pos.x + ship.boundx) / 2, ship.pos.y); return true; } } } else if(points[i + 1].y > points[i].y) { //preliminary check for collision. Is ship within checking range? if( (ship.pos.x > points[i].x) && (ship.pos.x < points[i + 1].x) && (ship.pos.y < points[i + 1].y) && (ship.pos.y > points[i].y)) { //TODO: need to place another if statement here checking the slope of the line and if the point lies on the line. //collide al_draw_textf(font, al_map_rgb(255,0,0), 100, 10, 0, "Line points (%5d, %5d)", points[i].x, points[i].y); al_draw_textf(font, al_map_rgb(255,0,0), 100, 35, 0, "Line points (%5d, %5d)", points[i + 1].x, points[i + 1].y); return true; } } } return false; } As you can see the first thing I try to do is to figure out the slope of the current line. This is done by checking (y2- y1) / (x2-x1). The slope is then used in the lines formula and the points of the avatar are inserted into the formula to see if they lay on the line. The code to check to see if point is on the line is as follows. bool IsOnLine(int boxX, int boxY, Point p1, Point p2) { Point temp; temp.x = boxX; temp.y = boxY; return ( (p1.y - temp.y) == GetLineSlope(p1, p2) * (p1.x - temp.x) ); } where as GetLineSlope is: float GetLineSlope(Point p1, Point p2) { return ( (p2.y - p1.y) / (p2.x - p1.x) ); } The issue I'm having is that it hardly recognizes collision. It does recognize it from time to time but a majority of the time the debug display that should be printed doesn't indicating a collision is not taking place. I also realize that the above code doesn't test all of the test points discussed earlier. I figured if I could get it working right for an easy point like its Top Left corner (x,y) then I could theoretically get it working correctly for the rest of the points.    My question is this. Am I over-thinking this or under-thinking it for that matter. Is there a better way to go about doing this? If not, does anyone recognize why this may not be working as intended. I understand that sounds like someone please do work for me, but I don't expect that from anyone. I am merely wondering if anyone has tried linear collision before and what method was taken to get it to work. Thank you in advance for your time and any assistance you may provide. 
  10. Hi Trienco, Thanks for the help and the advice, what you present seems to be a good solution to go off of. I think my originial intention with the map container over the array was that I wanted to have a string key that I could easily reference the items by. The items in the container are similar and inherit from an abstract base item class. The end game was to use this as part of an inventory system for a game. Not necessarily what the player is carrying but what they are storing into an external container in game. This container has actions that it takes much like an AI player. I was really tied to the idea of item lookup through string key. Thank you all for your comments and help. I'll be thinking through this much more in depth.
  11. Thanks for advice guys, Ill try and make it more clear what I am trying to accomplish.   In visualization terms think of a box, this box can hold exactly 9 objects in it,each of the 9 spots is a numbered index 0-8, but only objects of either type A or type B. I would like a associative container that can keep track of which everything in the box, including which type is located at which box index. I tried doing this through inheritance and downcasting but I feel like there should be a better way. I have data members in A and B that extend a baseclass. The classes look similar to this: Class BaseClass { public: BaseClass(string, int, string, int, int, int); ~BaseClass(); void SetName(string value) {name = value;} void SetType(int value) {type = value;} void SetFlavor(string value) {flavor = value;} void SetNum1(int value) {num1 = value;} void SetNum2(int value) {num2 = value;} void SetNum3(int value) {num3 = value;} const string GetName() {return name;} const int GetType() {return type;} const string GetFlavor() {return flavor;} Const int GetNum1() {return num1;} const int GetNum2() {return num2;} const int GetNum3() {return num3;} protected: string name; //name of object int type; //flagged 0 for type a and 1 for type B string flavor; //flavor text about object int num1; int num2; int num3; } Class A : public BaseClass { public: A(string name, int type, string flavor, int num1, int num2, int num3, int num4 int num5, float speed) :BaseClass(name, type, flavor, num1, num2, num3); ~A(); //getters and setters for speed, num4 and num5... private: float speed; int num4; int num5; } Class B : public BaseClass { public: B(string name, int type, string flavor, int num1, int num2, int num3 int bInt) :BaseClass(name, type, flavor, num1, num2, num3); ~B(); void SetBInt(int value) {bInt = value;} const int GetBInt() {return bInt;} private: int bInt; } so that when in class box it would look like this:   //Box.h #include "A.h" #include "B.h" #include "BaseClass.h" Class Box { public: Box(); ~Box(); void AddObjectTypeA(A* objectA); void AddObjectTypeB(B* objectB); private: map<int, BaseClass*> myBoxMap; } //Box.cpp void Box::AddObjectTypeA(A* objectA) { bool full = false; for(int i = 0; i < myBoxMap.size(); i++) { if(i == myBoxMap.size()) { //map is full - only want 9 objects inside no more full = true; break; } if(mFoundOffensiveMap->GetOffCellName() != "") //preloaded during box construction with 9 objects inside of type Basecell name = "" { //bad choice cell full already continue; } else if(mFoundOffensiveMap->GetOffCellName() == "") { //good cell choice - it's empty currently myBoxMap->SetName(cell->GetName()); myBoxMap->SetType(cell->GetType()); myBoxMap->Setnum1(cell->Getnum1()); myBoxMap->Setnum2(cell->Getnum2()); myBoxMap->Setnum3(cell->Getnum3()); myBoxMap->Setnum4(cell->GetNum4()); myBoxMap->setSpeed(cell->GetSpeed()); myBoxMap->setnum5(cell->Getnum5()); break; } } return full; } finally in main.cpp       //main.cpp int main() { A* myObjA = new A("Steve", 0, "is a man", 4, 6, 7, 17, 8, 3.4f); Box* myBox; myBox->AddObjectA(myObjA); /* during the above call I would like to set myObjA into the Box at the first available index without another object. It tests this in the function by checking if name = "". */ } I hope that better explains it. As it currently stand I'm getting access violation errors when in the function to add. Those errors are keeping me from knowing if this set up will actually work for what I want. Thank you again, for reading into this. I truly appreciate the quick responses you have offered.   Regards, Soundstone
  12. Hi everyone,    not sure if this is the proper thread to post this question to, if not I apologize and will gladly post it where it needs to be. I am having an issue with understanding how to use multiple data types in one map container. For example my code looks like this:     struct A {     string mName;     int    mNumber; };   struct B {     string mName;     float  mFloater;     bool   mFlag; };     class C {      C();      ~C();   //basically I want this map to hold a list by reference int for the entire collection of both objects from A and B. map<int, A/B> myMultiMap;   }   so that in main..   int main() {      C* myC;      A* myA;      B* myB;       myC->myMultiMap[0] = myA;     myC->myMultiMap[1] = myB; }   is there any easy way to do this. I haven't had much luck with getting the boost libraries to load correctly, I've only been at this about a year, and don't completely know how to do some of the things. I appreciate any help that is offered, even ifs its just a link or something. Thanks for reading.    Regards, Soundstone
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!