Advertisement
SilverTES

2D Collisions MugenEngine : Brute , QuadTree , Grid

Jan 25th, 2017
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 20.76 KB | None | 0 0
  1. #include <cstdio>
  2. #include <functional>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <list>
  6. #include <deque>
  7. #include <map>
  8. #include <ctime>
  9. #include <memory>
  10.  
  11. #include <allegro5/allegro.h>
  12. #include <allegro5/allegro_font.h>
  13. #include <allegro5/allegro_primitives.h>
  14.  
  15. #pragma region Globals Vars
  16.  
  17.     bool _quit = false;
  18.     ALLEGRO_KEYBOARD_STATE keyState;
  19.     ALLEGRO_MOUSE_STATE mouseState;
  20.  
  21.     bool keyPause = false;
  22.  
  23.     bool bruteMethod = false;
  24.     bool quadMethod = false;
  25.     bool gridMethod = false;
  26.  
  27.     int fps = 60;
  28.     int xMouse;
  29.     int yMouse;
  30.  
  31.     int screenW = 640;
  32.     int screenH = 480;
  33.     int scaleWin = 2;
  34.  
  35.     ALLEGRO_EVENT_SOURCE eventSource;
  36.     ALLEGRO_EVENT_QUEUE *eventQueue;
  37.     ALLEGRO_EVENT event;
  38.     ALLEGRO_EVENT userEvent;
  39.  
  40.     ALLEGRO_TIMER *timer = nullptr;
  41.     ALLEGRO_DISPLAY* display = nullptr;
  42.     ALLEGRO_BITMAP* buffer = nullptr;
  43.     ALLEGRO_FONT* font = nullptr;
  44.  
  45. #pragma endregion
  46.  
  47. template <class M = const char*, class E = int>
  48. E log(M msg, E error = 0)
  49. {
  50.     printf(msg);
  51.     return error;
  52. }
  53.  
  54. enum
  55. {
  56.     NW = 0,
  57.     NE,
  58.     SW,
  59.     SE
  60.  
  61. };
  62.  
  63. struct Circle
  64. {
  65.     int _x;
  66.     int _y;
  67.     int _r;
  68. };
  69.  
  70. struct Rect
  71. {
  72.     int _x;
  73.     int _y;
  74.     int _w;
  75.     int _h;
  76. };
  77.  
  78. enum EventType
  79. {
  80.     EV_QUIT      = 1,
  81.     EV_COLLISION = 2
  82. };
  83.  
  84. int random(int mini, int maxi)
  85. {
  86.     return (rand() % (maxi-mini)) + mini;
  87. }
  88.  
  89. bool collisionCC(Circle &c1, Circle &c2)
  90. {
  91.     int d2 = (c1._x - c2._x)*(c1._x - c2._x) + (c1._y - c2._y)*(c1._y - c2._y);
  92.  
  93.     if (d2 > (c1._r + c2._r)*(c1._r + c2._r))
  94.         return false;
  95.     else
  96.         return true;
  97. }
  98. bool collisionRR(Rect &r1, Rect &r2)
  99. {
  100.     if ((r2._x >= r1._x + r1._w)    // trop à droite
  101.         || (r2._x + r2._w <= r1._x) // trop à gauche
  102.         || (r2._y >= r1._y + r1._h) // trop en bas
  103.         || (r2._y + r2._h <= r1._y))  // trop en haut
  104.         return false;
  105.     else
  106.         return true;
  107. }
  108.  
  109. struct Ball
  110. {
  111.     int _x;
  112.     int _y;
  113.     int _r;
  114.     int _vx;
  115.     int _vy;
  116.  
  117.     Rect _rect;
  118.  
  119.     int _screenW;
  120.     int _screenH;
  121.  
  122.     bool _isCollide = false;
  123.  
  124.     Ball(int x, int y, int r, int screenW, int screenH) :
  125.         _x(x),
  126.         _y(y),
  127.         _r(r),
  128.         _screenW(screenW),
  129.         _screenH(screenH)
  130.     {
  131.         _vx = (random(1, 3));
  132.         _vy = (random(1, 3));
  133.         _rect._x = _x - _r;
  134.         _rect._y = _y - _r;
  135.         _rect._w = _r * 2;
  136.         _rect._h = _r * 2;
  137.  
  138.     }
  139.  
  140.     virtual ~Ball()
  141.     {
  142.  
  143.     }
  144.  
  145.     void update()
  146.     {
  147.         _x += _vx;
  148.         _y += _vy;
  149.  
  150.         _rect._x = _x - _r;
  151.         _rect._y = _y - _r;
  152.         _rect._w = _r * 2;
  153.         _rect._h = _r * 2;
  154.  
  155.         if (_x < 0)
  156.             _vx = (random(1,3));
  157.         if (_x > _screenW)
  158.             _vx = -(random(1,3));
  159.         if (_y < 0)
  160.             _vy = (random(1, 3));
  161.         if (_y > _screenH)
  162.             _vy = -(random(1, 3));
  163.  
  164.  
  165.     }
  166.  
  167.     void render()
  168.     {
  169.         if (_isCollide)
  170.         {
  171.             //al_draw_filled_circle(_x, _y, _r, al_map_rgba(255,125,100,50));
  172.             al_draw_filled_rectangle(
  173.                 _rect._x + .5, _rect._y + .5,
  174.                 _rect._x - .5 + _rect._w, _rect._y - .5 + _rect._h,
  175.                 al_map_rgb(255, 155, 100));
  176.         }
  177.         //else
  178.         //{
  179.             //al_draw_circle(_x, _y, _r, al_map_rgb(255,255,0),0);
  180.             al_draw_rectangle(
  181.                 _rect._x+.5, _rect._y+.5,
  182.                 _rect._x-.5 + _rect._w, _rect._y-.5 + _rect._h,
  183.                 al_map_rgb(255,55,0),0);
  184.  
  185.         //}
  186.  
  187.  
  188.     }
  189. };
  190.  
  191. std::vector<Ball*> _vecBall;
  192.  
  193. struct BallManager
  194. {
  195.  
  196.     BallManager()
  197.     {
  198.  
  199.     }
  200.     virtual ~BallManager()
  201.     {
  202.         if (!_vecBall.empty())
  203.             for (auto & it : _vecBall)
  204.                 if (it != nullptr)
  205.                 {
  206.                     delete it;
  207.                     it = nullptr;
  208.                 }
  209.         _vecBall.clear();
  210.     }
  211.  
  212.     void add(Ball *ball)
  213.     {
  214.         if (ball != nullptr)
  215.             _vecBall.push_back(ball);
  216.     }
  217.  
  218.     void add(int x, int y, int r, int screenW, int screenH)
  219.     {
  220.         this->add(new Ball(x, y, r, screenW, screenH));
  221.     }
  222.  
  223.     void update()
  224.     {
  225.         if (!_vecBall.empty())
  226.             for (auto & it : _vecBall)
  227.                 if (it != nullptr)
  228.                 {
  229.                     it->_isCollide = false;
  230.                     it->update();
  231.                 }
  232.     }
  233.     void render()
  234.     {
  235.         if (!_vecBall.empty())
  236.         {
  237.             unsigned index = 0;
  238.             for (auto & it : _vecBall)
  239.             {
  240.                 if (it != nullptr)
  241.                 {
  242.                     it->render();
  243.                     //al_draw_textf(font, al_map_rgb(255, 25, 255),
  244.                     //           it->_rect._x, it->_rect._y - 12, 0,
  245.                     //            "%i", index
  246.                     //);
  247.                 }
  248.                 ++index;
  249.             }
  250.         }
  251.     }
  252.  
  253.     void testCollide()
  254.     {
  255.         if (!_vecBall.empty())
  256.         {
  257.        
  258.             for (unsigned i = 0; i < _vecBall.size(); ++i)
  259.             {
  260.                
  261.                 for (unsigned j = i+1; j < _vecBall.size(); ++j)
  262.                 {
  263.                     //Circle c1 = {_vecBall[i]->_x, _vecBall[i]->_y, _vecBall[i]->_r};
  264.                     //Circle c2 = {_vecBall[j]->_x, _vecBall[j]->_y, _vecBall[j]->_r};
  265.  
  266.  
  267.                     if (collisionRR(_vecBall[i]->_rect, _vecBall[j]->_rect))
  268.                     {
  269.                         _vecBall[i]->_isCollide = true;
  270.                         _vecBall[j]->_isCollide = true;
  271.                         //log("collide !");
  272.  
  273.  
  274.                         //userEvent.user.data1 = EV_COLLISION;
  275.                         //Collision collision(i,j);
  276.                         //userEvent.user.data2 = (intptr_t)&collision;
  277.                         //al_emit_user_event(&eventSource, &userEvent, 0);
  278.                     }
  279.                 }
  280.             }
  281.         }
  282.  
  283.     }
  284. };
  285.  
  286. struct Entity
  287. {
  288.     unsigned _index;
  289.     Rect _rect;
  290. };
  291.  
  292. struct QuadTree
  293. {
  294.     unsigned _currentLevel = 0;
  295.     unsigned _maxObject;
  296.     unsigned _maxLevel;
  297.     Rect _rect;
  298.     QuadTree *_parent;
  299.     QuadTree *_node[4] = {nullptr};
  300.     std::vector<Entity*> _vecIndex; // Contain all index of entity in the Quad
  301.  
  302.     QuadTree(Rect rect, QuadTree *parent = nullptr, int maxObject = 8, int maxLevel = 5) :
  303.         _rect(rect),
  304.         _parent(parent),
  305.         _maxObject(maxObject),
  306.         _maxLevel(maxLevel)
  307.     {
  308.         if (_parent == nullptr)
  309.             _currentLevel = 0;
  310.         else
  311.         {
  312.             _currentLevel = _parent->_currentLevel + 1;
  313.             _maxObject = _parent->_maxObject;
  314.             _maxLevel = _parent->_maxLevel;
  315.         }
  316.     }
  317.     ~QuadTree()
  318.     {
  319.         clearNode();
  320.     }
  321.     bool haveChild()
  322.     {
  323.         return (_node[0] != nullptr);
  324.     }
  325.     bool isLastBranch()
  326.     {
  327.         bool isLastBranch = true;
  328.         for (int i = 0; i < 4; ++i)
  329.         {
  330.             if (_node[i] != nullptr)
  331.             {
  332.                 if (_node[i]->haveChild())
  333.                     isLastBranch = false;
  334.             }
  335.         }
  336.         if (isLastBranch)
  337.             log("- is Last Branch -");
  338.         return isLastBranch;
  339.     }
  340.     void split()
  341.     {
  342.         if (_currentLevel < _maxLevel)
  343.         {
  344.             int x = _rect._x;
  345.             int y = _rect._y;
  346.             int w = _rect._w;
  347.             int h = _rect._h;
  348.             int cW = w / 2;
  349.             int cH = h / 2;
  350.        
  351.             _node[NW] = new QuadTree(Rect{x,y,cW,cH}, this);
  352.             _node[NE] = new QuadTree(Rect{x+cW,y,cW,cH}, this);
  353.             _node[SW] = new QuadTree(Rect{x,y+cH,cW,cH}, this);
  354.             _node[SE] = new QuadTree(Rect{x+cW,y+cH,cW,cH}, this);
  355.         }
  356.     }
  357.     void unSplit()
  358.     {
  359.         clearNode();
  360.     }
  361.     void clearNode()
  362.     {
  363.         if (!_vecIndex.empty())
  364.         {
  365.             for (auto & it : _vecIndex)
  366.             {
  367.                 if (it != nullptr)
  368.                 {
  369.                     delete it;
  370.                     it = nullptr;
  371.  
  372.                 }
  373.             }
  374.             _vecIndex.clear();
  375.             //log("- vecIndex cleared -");
  376.         }
  377.  
  378.         //log("- Begin Clear Node -");
  379.         if (haveChild())
  380.         {
  381.             //log("- Node have child -");
  382.             for (int i = 0; i < 4; ++i)
  383.             {
  384.                 //if (_node[i] != nullptr)
  385.                 //{
  386.  
  387.                     if (_node[i]->haveChild())
  388.                         _node[i]->clearNode();
  389.                    
  390.                     delete _node[i];
  391.                     _node[i] = nullptr;
  392.  
  393.                     //printf("Delete Node %i \n", i);
  394.                 //}
  395.             }
  396.         }
  397.  
  398.  
  399.  
  400.     }
  401.     // Return wich node the object belongs to , -1 = Object belong Parent node
  402.     int getQuadIndex(Rect &rect)
  403.     {
  404.         int index = -1;
  405.         int cX = _rect._x + _rect._w / 2;
  406.         int cY = _rect._y + _rect._h / 2;
  407.    
  408.         bool inN = (rect._y + rect._h < cY);
  409.         bool inS = (rect._y > cY);
  410.         bool inW = (rect._x + rect._w < cX);
  411.         bool inE = (rect._x > cX);
  412.    
  413.         if (inN && inW) index = NW;
  414.         if (inN && inE) index = NE;
  415.         if (inS && inW) index = SW;
  416.         if (inS && inE) index = SE;
  417.    
  418.         return index;
  419.     }
  420.     void insert(unsigned index, Rect rect)
  421.     {
  422.         if (haveChild()) // If have child transmit to child
  423.         {
  424.             int quadIndex = getQuadIndex(rect);
  425.             if (quadIndex != -1)
  426.                 _node[quadIndex]->insert(index, rect);
  427.  
  428.             return;
  429.         }
  430.        
  431.         _vecIndex.push_back(new Entity{ index, rect });
  432.  
  433.         if (_vecIndex.size() > _maxObject && _currentLevel < _maxLevel)
  434.         {
  435.             //log("- need split -\n");
  436.             if (!haveChild())
  437.                 split();
  438.  
  439.             unsigned i = 0;
  440.             while (i < _vecIndex.size())
  441.             {
  442.                 int quadIndex = getQuadIndex(_vecIndex[i]->_rect);
  443.                 if (quadIndex != -1)
  444.                 {
  445.                     _node[quadIndex]->insert(_vecIndex[i]->_index, _vecIndex[i]->_rect);
  446.                     delete _vecIndex[i]; // don't forget to delete Entity pointer !
  447.                     _vecIndex.erase(_vecIndex.begin() + i);
  448.                 }
  449.                 else
  450.                 {
  451.                     ++i;
  452.                 }
  453.             }
  454.         }
  455.     }
  456.     void findNear(std::vector<Entity*> &vecEntity, Rect &rect)
  457.     {
  458.         if (haveChild())
  459.         {
  460.             int quadIndex = getQuadIndex(rect);
  461.  
  462.             if (quadIndex != -1)
  463.             {
  464.                 _node[quadIndex]->findNear(vecEntity, rect);
  465.             }
  466.             else
  467.             {
  468.                 for (unsigned i = 0; i < 4; ++i)
  469.                 {
  470.                     _node[i]->findNear(vecEntity, rect);
  471.                 }
  472.             }
  473.         }
  474.  
  475.         for (auto & it: _vecIndex)
  476.             vecEntity.push_back(it);
  477.     }
  478.  
  479.  
  480.     void update(int mouseX, int mouseY, int mouseB)
  481.     {
  482.         //if ((mouseB & 1) && !haveChild())
  483.         //{
  484.         //  if (mouseX > _rect._x && mouseX < _rect._x + _rect._w &&
  485.         //      mouseY > _rect._y && mouseY < _rect._y + _rect._h)
  486.         //  {
  487.         //      split();
  488.         //  }
  489.         //  mouseB = 0;
  490.         //}
  491.  
  492.         //if ((mouseB & 2) && haveChild())
  493.         //{
  494.         //  if (mouseX > _rect._x && mouseX < _rect._x + _rect._w &&
  495.         //      mouseY > _rect._y && mouseY < _rect._y + _rect._h)
  496.         //  {
  497.         //      bool nodeHaveChild = false;
  498.         //      for (int i = 0; i < 4; ++i)
  499.         //      {
  500.         //          if (_node[i] != nullptr)
  501.         //          {
  502.         //              if (_node[i]->haveChild())
  503.         //                  nodeHaveChild = true;
  504.         //                 
  505.         //          }
  506.         //      }
  507.  
  508.         //      if (!nodeHaveChild)
  509.         //          unSplit();
  510.         //  }      
  511.         //}
  512.  
  513.         //if (haveChild())
  514.         //{
  515.         //  for (int i = 0; i < 4; ++i)
  516.         //  {
  517.         //      if (_node[i] != nullptr)
  518.         //      {
  519.         //          _node[i]->update(mouseX, mouseY, mouseB);
  520.         //      }
  521.         //  }
  522.         //}
  523.  
  524.     }
  525.  
  526.     void render(int mouseX, int mouseY, int mouseB)
  527.     {
  528.  
  529.         if (mouseX > _rect._x && mouseX < _rect._x + _rect._w &&
  530.             mouseY > _rect._y && mouseY < _rect._y + _rect._h &&
  531.             !haveChild())
  532.         {
  533.             al_draw_filled_rectangle(
  534.                 .5 + _rect._x, .5 + _rect._y,
  535.                 .5 + _rect._x + _rect._w + 1, .5 + _rect._y + _rect._h + 1,
  536.                 al_map_rgba(0, 155, 100, 50));
  537.  
  538.  
  539.             //for (unsigned i = 0; i < _vecIndex.size(); ++i)
  540.             //{
  541.             //  al_draw_textf(font, al_map_rgb(25, 205, 255),
  542.             //                mouseX, mouseY + (i * 12), 0,
  543.             //                "vec[%i]=%i", i, _vecIndex[i]->_index
  544.             //                );
  545.             //}
  546.  
  547.         }
  548.  
  549.         if (haveChild())
  550.         {
  551.             al_draw_line(
  552.                 .5 + _rect._x + _rect._w / 2, .5 + _rect._y,
  553.                 .5 + _rect._x + _rect._w / 2, .5 + _rect._y + _rect._h,
  554.                 al_map_rgb(0, 155, 100), 0);
  555.            
  556.             al_draw_line(
  557.                 .5 + _rect._x , .5 + _rect._y + _rect._h / 2 ,
  558.                 .5 + _rect._x + _rect._w, .5 + _rect._y + _rect._h / 2,
  559.                 al_map_rgb(0, 155, 100), 0);
  560.  
  561.             //for (unsigned i = 0; i < _vecIndex.size(); ++i)
  562.             //{
  563.             //  al_draw_textf(font, al_map_rgb(25, 205, 255),
  564.             //                _rect._x + 2, _rect._y + 12 + (i * 12)  , 0,
  565.             //                "vec[%i]=%i", i, _vecIndex[i]->_index
  566.             //  );
  567.             //}
  568.         }
  569.  
  570.         if (haveChild())
  571.             for (int i = 0; i < 4; ++i)
  572.             {
  573.                 if (_node[i] != nullptr)
  574.                 {
  575.                     _node[i]->render(mouseX, mouseY, mouseB);
  576.                 }
  577.             }
  578.  
  579.         if (!haveChild())
  580.         {
  581.             al_draw_filled_circle(
  582.                 .5 + _rect._x + _rect._w/2, .5 + _rect._y + _rect._h/2, 1,
  583.                 al_map_rgba(0, 155, 100, 255));
  584.  
  585.             //al_draw_textf(font, al_map_rgb(255, 200, 200),
  586.             //            _rect._x + 2, _rect._y + 2, 0,
  587.             //            //_rect._x + _rect._w / 2, _rect._y - 1 + _rect._h / 2, 1,
  588.             //            "%i:%i", _currentLevel, _vecIndex.size());
  589.         }
  590.  
  591.     }
  592. };
  593.  
  594.  
  595. struct Cell
  596. {
  597.     std::vector<Entity*> _vecIndex; // Contain all index of entity in the Cell
  598. };
  599.  
  600. struct GridSpatialPart
  601. {
  602.     int _originX;
  603.     int _originY;
  604.  
  605.     int _gridW;
  606.     int _gridH;
  607.     int _cellSize;
  608.            
  609.     std::vector<std::vector<Cell*>> _vec2dCell;
  610.  
  611.     GridSpatialPart(int gridW, int gridH, int cellSize)
  612.     {
  613.         _cellSize = cellSize;
  614.  
  615.         _gridW = gridW;
  616.         _gridH = gridH;
  617.  
  618.         _vec2dCell.resize(_gridW);
  619.         for (int x = 0; x < _gridW; ++x)
  620.         {
  621.             _vec2dCell[x].resize(_gridH);
  622.             for (int y = 0; y < _gridH; ++y)
  623.             {
  624.                 _vec2dCell[x][y] = new Cell();
  625.             }
  626.         }
  627.     }
  628.  
  629.     Cell *cell(unsigned x, unsigned y)
  630.     {
  631.         return _vec2dCell[x][y];
  632.     }
  633.        
  634.     void clear()
  635.     {
  636.         for (int x = 0; x < _gridW; ++x)
  637.         {
  638.             for (int y = 0; y < _gridH; ++y)
  639.             {
  640.                 if (cell(x,y) != nullptr)
  641.                 {
  642.                     if (!cell(x, y)->_vecIndex.empty())
  643.                     {
  644.                         for (auto & it: cell(x, y)->_vecIndex)
  645.                             if (it != nullptr)
  646.                             {
  647.                                 delete it;
  648.                                 it = nullptr;
  649.                             }
  650.                        
  651.                         cell(x, y)->_vecIndex.clear();
  652.  
  653.                     }
  654.                 }
  655.             }
  656.         }
  657.     }
  658.  
  659.     void insert(unsigned index, Rect rect)
  660.     {
  661.         int left = std::max(0, rect._x / _cellSize);
  662.         int top = std::max(0,rect._y / _cellSize);
  663.         int right = std::min(_gridW-1,(rect._x + rect._w - 1) / _cellSize);
  664.         int bottom = std::min(_gridH-1,(rect._y + rect._h - 1) / _cellSize);
  665.  
  666.         for (int x = left; x <= right; ++x)
  667.         {
  668.             for (int y = top; y <= bottom; ++y)
  669.             {
  670.                 cell(x, y)->_vecIndex.push_back(new Entity{ index, rect });
  671.             }
  672.         }
  673.  
  674.     }
  675.  
  676.     void findNear(std::vector<Entity*> &_vecIndexTemp, Rect rect)
  677.     {
  678.         int left = std::max(0, rect._x / _cellSize);
  679.         int top = std::max(0, rect._y / _cellSize);
  680.         int right = std::min(_gridW - 1, (rect._x + rect._w - 1) / _cellSize);
  681.         int bottom = std::min(_gridH - 1, (rect._y + rect._h - 1) / _cellSize);
  682.  
  683.         for (int x = left; x <= right; ++x)
  684.         {
  685.             for (int y = top; y <= bottom; ++y)
  686.             {
  687.                 for (unsigned i = 0; i < cell(x, y)->_vecIndex.size(); ++i)
  688.                 {
  689.                     Entity *entity = cell(x, y)->_vecIndex[i];
  690.  
  691.                     //if (entity->_index != index)
  692.                         _vecIndexTemp.push_back(entity);
  693.                 }
  694.                
  695.             }
  696.         }
  697.     }
  698.  
  699.     Entity* getNearest()
  700.     {
  701.  
  702.     }
  703.  
  704.  
  705.     void update()
  706.     {
  707.  
  708.     }
  709.  
  710.     void render()
  711.     {
  712.         for (int x = 0; x < _gridW; ++x)
  713.         {
  714.             for (int y = 0; y < _gridH; ++y)
  715.             {
  716.                
  717.                 int px = x*_cellSize;
  718.                 int py = y*_cellSize;
  719.  
  720.  
  721.                 al_draw_rectangle(
  722.                     px, py,
  723.                     px + _cellSize, py + _cellSize,
  724.                     al_map_rgb(255, 205, 120), 0
  725.                 );
  726.  
  727.                 //al_draw_textf(
  728.                 //  font,
  729.                 //  al_map_rgb(250,250,0),
  730.                 //  px + 2, py + 2, 0,
  731.                 //  "%i,%i = %i",
  732.                 //  x, y, cell(x, y)->_vecIndex.size()
  733.                 //);
  734.  
  735.                 if (!(cell(x, y)->_vecIndex.empty()))
  736.                 {
  737.                     //log("not empty !\n");
  738.  
  739.                     //for (unsigned i = 0; i < cell(x, y)->_vecIndex.size(); ++i)
  740.                     //{
  741.                     //  al_draw_textf(font, al_map_rgb(25, 205, 255),
  742.                     //                px + 2, py+12 + (i * 12)  , 0,
  743.                     //                "vec[%i]=%i", i, cell(x, y)->_vecIndex[i]->_index
  744.                     //  );
  745.                     //}
  746.                 }
  747.  
  748.  
  749.             }
  750.         }
  751.  
  752.     }
  753.  
  754. };
  755.  
  756. int init()
  757. {
  758.     srand(time(0));
  759.  
  760.     al_init();
  761.  
  762.     al_init_font_addon();
  763.     al_init_primitives_addon();
  764.    
  765.     al_install_keyboard();
  766.     al_install_mouse();
  767.    
  768.     al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST);
  769.  
  770.  
  771.     display = al_create_display(screenW*scaleWin, screenH*scaleWin);
  772.     buffer = al_create_bitmap(screenW, screenH);
  773.     font = al_create_builtin_font();
  774.    
  775.  
  776.     al_init_user_event_source(&eventSource);
  777.  
  778.     eventQueue = al_create_event_queue();
  779.     al_register_event_source(eventQueue, &eventSource);
  780.  
  781.     //userEvent.user.data1 = 42;
  782.     //al_emit_user_event(&eventSource, &userEvent, 0);
  783.  
  784.     timer = al_create_timer(1.0 / fps);
  785.     al_register_event_source(eventQueue, al_get_timer_event_source(timer));
  786.     al_start_timer(timer);
  787.  
  788.     return log("Init OK !\n");
  789. }
  790.  
  791. int main()
  792. {
  793.  
  794.     if (init())
  795.         _quit = true;
  796.  
  797.     std::shared_ptr<BallManager> _manBall;
  798.  
  799.     QuadTree *_quad = new QuadTree(Rect{ 0,0,screenW,screenH }, nullptr, 8);
  800.  
  801.     int cellSize = 64;
  802.     int gridW = screenW / cellSize;
  803.     int gridH = screenH / cellSize;
  804.    
  805.     GridSpatialPart *_grid = new GridSpatialPart(gridW, gridH, cellSize);
  806.  
  807.     int rangeX = _grid->_gridW* _grid->_cellSize;
  808.     int rangeY = _grid->_gridH* _grid->_cellSize;
  809.  
  810.     for (int i = 0; i < 3200; ++i)
  811.     {
  812.         int x = random(0, rangeX);
  813.         int y = random(0, rangeY);
  814.         int r = random(4, 8);
  815.  
  816.         //_manBall->add(new Ball(x, y, r, screenW, screenH));
  817.         //_manBall->add(x, y, r, screenW, screenH);
  818.         _manBall->add(x, y, r, rangeX, rangeY);
  819.  
  820.     }
  821.    
  822.     //auto _quad = std::make_shared<QuadTree<Ball>>(0, Rect{0, 0, screenW, screenH});
  823.    
  824.  
  825.  
  826.     bool mouseDown = false;
  827.     int mouseB = 0;
  828.  
  829.     bool pause = false;
  830.  
  831.  
  832.     std::vector<Entity*> vecEntity;
  833.  
  834.     while (!_quit)
  835.     {
  836.        
  837.         // update
  838.         al_wait_for_event(eventQueue, &event);
  839.  
  840.         if ((int)event.user.data1 == EV_QUIT)
  841.         {
  842.             printf("Wee quiiit !!! \n");
  843.             _quit = true;
  844.         }
  845.  
  846.  
  847.         al_get_keyboard_state(&keyState);
  848.         al_get_mouse_state(&mouseState);
  849.  
  850.         if (!al_key_down(&keyState, ALLEGRO_KEY_SPACE)) keyPause = false;
  851.  
  852.         if (al_key_down(&keyState, ALLEGRO_KEY_SPACE) && !keyPause)
  853.         {
  854.             keyPause = true;
  855.  
  856.             pause = !pause;;
  857.         }
  858.  
  859.         if (al_key_down(&keyState, ALLEGRO_KEY_ESCAPE))
  860.             _quit = true;
  861.  
  862.         //if (al_key_down(&keyState, ALLEGRO_KEY_Q))
  863.         //{
  864.         //  userEvent.user.data1 = EV_QUIT;
  865.         //  al_emit_user_event(&eventSource, &userEvent, 0);
  866.         //}
  867.        
  868.         if (al_key_down(&keyState, ALLEGRO_KEY_BACKSPACE))
  869.         {
  870.             bruteMethod = false;
  871.             quadMethod = false;
  872.             gridMethod = false;
  873.         }
  874.  
  875.         if (al_key_down(&keyState, ALLEGRO_KEY_A))
  876.         {
  877.             bruteMethod = true;
  878.             quadMethod = false;
  879.             gridMethod = false;
  880.         }
  881.         if (al_key_down(&keyState, ALLEGRO_KEY_Q))
  882.         {
  883.             bruteMethod = false;
  884.             quadMethod = true;
  885.             gridMethod = false;
  886.         }
  887.         if (al_key_down(&keyState, ALLEGRO_KEY_G))
  888.         {
  889.             bruteMethod = false;
  890.             quadMethod = false;
  891.             gridMethod = true;
  892.         }
  893.  
  894.  
  895.  
  896.         xMouse = mouseState.x / scaleWin;
  897.         yMouse = mouseState.y / scaleWin;
  898.  
  899.         mouseB = 0;
  900.  
  901.         if (!mouseState.buttons) mouseDown = false;
  902.  
  903.         if (mouseState.buttons && !mouseDown)
  904.         {
  905.             //log(" <clicked> ");
  906.             mouseDown = true;
  907.             mouseB = mouseState.buttons;
  908.         }
  909.  
  910.  
  911.         if (mouseB & 1)
  912.         {
  913.             _manBall->add(xMouse, yMouse, 4, screenW, screenH);
  914.         }
  915.  
  916.         if (!pause)
  917.         {
  918.             _manBall->update();
  919.         }
  920.        
  921.         if (bruteMethod)
  922.             _manBall->testCollide();
  923.        
  924.  
  925.         if (gridMethod)
  926.         {
  927.  
  928.             _grid->clear();
  929.  
  930.             for (unsigned i = 0 ; i < _vecBall.size(); ++i)
  931.             {
  932.                 _grid->insert(i, _vecBall[i]->_rect);
  933.             }
  934.  
  935.        
  936.             for (unsigned i = 0; i < _vecBall.size(); ++i)
  937.             {
  938.                 vecEntity.clear();
  939.            
  940.                 _grid->findNear(vecEntity, _vecBall[i]->_rect);
  941.  
  942.                 if (!vecEntity.empty())
  943.                 {
  944.                     for (unsigned x = 0; x < vecEntity.size(); ++x)
  945.                     {
  946.                         unsigned j = vecEntity[x]->_index;
  947.                         if (i != j)
  948.                         {
  949.                             if (j >= 0 && j < _vecBall.size())
  950.                             {
  951.                                 if (collisionRR(_vecBall[i]->_rect, _vecBall[j]->_rect))
  952.                                 {
  953.                                     _vecBall[i]->_isCollide = true;
  954.                                     _vecBall[j]->_isCollide = true;
  955.                                 }
  956.  
  957.                             }
  958.                         }
  959.                     }
  960.                 }
  961.  
  962.             }
  963.         }
  964.  
  965.         if (quadMethod)
  966.         {
  967.             _quad->clearNode();
  968.             for (unsigned i = 0; i < _vecBall.size(); ++i)
  969.             {
  970.                 _quad->insert(i, _vecBall[i]->_rect);
  971.             }
  972.  
  973.             std::vector<Entity*> vecEntity;
  974.  
  975.             for (unsigned i = 0; i < _vecBall.size(); ++i)
  976.             {
  977.                 vecEntity.clear();
  978.                 _quad->findNear(vecEntity, _vecBall[i]->_rect);
  979.            
  980.                 for (unsigned x = 0; x < vecEntity.size(); ++x)
  981.                 {
  982.                     unsigned j = vecEntity[x]->_index;
  983.                     if (i != j)
  984.                     {
  985.                         //Circle c1 = { _vecBall[i]->_x, _vecBall[i]->_y, _vecBall[i]->_r };
  986.                         //Circle c2 = { _vecBall[j]->_x, _vecBall[j]->_y, _vecBall[j]->_r };
  987.  
  988.                         if (collisionRR(_vecBall[i]->_rect, _vecBall[j]->_rect))
  989.                         {
  990.                             _vecBall[i]->_isCollide = true;
  991.                             _vecBall[j]->_isCollide = true;
  992.                         }
  993.                     }
  994.  
  995.                 }
  996.                
  997.             }
  998.             _quad->update(xMouse, yMouse, mouseB);
  999.         }
  1000.  
  1001.  
  1002.         // render
  1003.         al_set_target_bitmap(buffer);
  1004.         al_clear_to_color(al_map_rgb(0, 0, 0));
  1005.         //al_draw_text(font, al_map_rgb(255, 255, 255), screenW/2, 2, ALLEGRO_ALIGN_CENTER, "MugenEgine : Event and Collision System");
  1006.        
  1007.         _manBall->render();
  1008.  
  1009.         if (gridMethod)
  1010.             _grid->render();
  1011.  
  1012.  
  1013.         if (quadMethod)
  1014.         {
  1015.             _quad->render(xMouse, yMouse, mouseB);
  1016.  
  1017.             for (unsigned i = 0; i < _quad->_vecIndex.size(); ++i)
  1018.             {
  1019.                 al_draw_textf(font, al_map_rgb(25, 205, 255),
  1020.                               2, 2 + (i * 12), 0,
  1021.                               "vec[%i]=%i", i, _quad->_vecIndex[i]->_index
  1022.                 );
  1023.             }
  1024.         }
  1025.  
  1026.  
  1027.        
  1028.  
  1029.  
  1030.  
  1031.         //al_draw_line(0, yMouse + .5,
  1032.         //           screenW, yMouse + .5,
  1033.         //           al_map_rgba(55, 125, 100, 25), 0);
  1034.  
  1035.         //al_draw_line(xMouse + .5, 0,
  1036.         //           xMouse + .5, screenH,
  1037.         //           al_map_rgba(55, 125, 100, 25), 0);
  1038.  
  1039.        
  1040.         al_set_target_backbuffer(display);
  1041.         al_draw_scaled_bitmap(buffer,
  1042.                               0, 0,
  1043.                               screenW, screenH,
  1044.                               0, 0,
  1045.                               screenW*scaleWin, screenH*scaleWin,
  1046.                               0);
  1047.  
  1048.         const char *method = "No Collisions Test !";
  1049.         if (bruteMethod) method = "Brute Force !";
  1050.         if (quadMethod) method = "QuadTree !";
  1051.         if (gridMethod) method = "Grid Spatial Partition !";
  1052.  
  1053.         al_draw_textf(font, al_map_rgb(25, 205, 255),
  1054.                       (screenW*scaleWin) /2, (screenH*scaleWin)-12, -1,
  1055.                       "NB ENTITY = %i  :(A)BruteForce (Q)QuadTree (G)Grid : Method = %s", _vecBall.size(), method);
  1056.  
  1057.         al_flip_display();
  1058.     }
  1059.  
  1060.     if (!_grid)
  1061.         delete _grid;
  1062.  
  1063.     if (!_quad)
  1064.         delete _quad;
  1065.  
  1066.     _manBall.reset();
  1067.    
  1068.     al_destroy_timer(timer);
  1069.     al_destroy_event_queue(eventQueue);
  1070.     al_destroy_bitmap(buffer);
  1071.     al_destroy_display(display);
  1072.     al_destroy_font(font);
  1073.  
  1074.     system("Pause");
  1075.     return 0;
  1076. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement