Advertisement
bochkareffsasha

W3 FINAL

Dec 8th, 2022
485
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.51 KB | None | 0 0
  1. #include <iostream>
  2. #include <ctime>
  3. #include <math.h>
  4. #include <grx20.h>
  5. #include <grxkeys.h>
  6.  
  7. const int _minSpeed = 100; // минимальная скорость фигуры
  8. const int _maxSpeed = 500;
  9. const int _maxNumber = 500; // максимальное количество фигур (без учета главной)
  10. const float pi = 3.1415;
  11. const float pi2 = 6.283;
  12.  
  13. int _masterX = GrMaxX()/2; // положение главной фигуры
  14. int _masterY = GrMaxY()/2;
  15. int _number = 0; // текущее количество фигур
  16.  
  17. class myDot {
  18. public:
  19.     myDot(bool master = false);
  20.  
  21.     int getX(); // получить координаты
  22.     int getY();
  23.  
  24.     void move(); // функция для обработки перемещения фигуры
  25.  
  26.     void draw(); // отрисовка текущего положения
  27.     void hide(); // закрашивание текущего положения цветом фона
  28.     void hideOld(); // то же самое , только для предыдущего положения
  29.     void redraw(); // перерисовка фигуры (удаление старой и отрисовка новой позиции)
  30.     void MaD(); // перерисовка фигуры с перемещением
  31.  
  32. protected:
  33.     virtual void privateDraw(int x, int y, int colVal); // функция для отрисовки фигуры
  34.  
  35.     virtual bool borderCollisionCheckX(int x); // проверка колизии фигуры с границей
  36.     virtual bool borderCollisionCheckY(int y);
  37.  
  38.     void update(); // обновление таймера (для сохранения скорости при понижении частоты отрисовка) + обновление направления зависимых фигур
  39.     unsigned int prevTime; // предыдущее время обновления
  40.     float speedMult; // множитель скорости (для калибровки скорости)
  41.  
  42.     void masterPositionUpdate(); // обновление положения главной фигуры
  43.  
  44.     bool slave; // подчиненная фигура или главная
  45.     bool hided; // скрыта или видима
  46.     int distToMaster; // расстояние до главной фигуры
  47.     int masterOffense; // расстояние , на которое отстает зависимая фигура от главной
  48.     float masterAngleOffense; // погрешность направления (для неравномерного распределения зависимых фигур)
  49.     int x;
  50.     int y;
  51.     int xSpeed(); // функции для расчета скорости
  52.     int ySpeed();
  53.     int xOld; // координаты для перерисовки фигуры
  54.     int yOld;
  55.     float velAngle; // направление скорости (в радианах)
  56.     int velocity; // скорость (в пискелях в секунду)
  57.     int color;
  58. };
  59.  
  60. class myBox : public myDot {
  61. public:
  62. myBox(bool main=false);
  63. protected:
  64. void privateDraw(int xVal, int yVal, int colVal);
  65. bool borderCollisionCheckX(int xVal);
  66. bool borderCollisionCheckY(int yVal);
  67. int halfSizeX; //половина размера квадрата (для удобства расчета положения относительно середины фигуры)
  68. int halfSizeY;
  69. };
  70.  
  71. class myCircle : public myDot {
  72. public:
  73. myCircle(bool main=false);
  74. protected:
  75. void privateDraw(int xVal, int yVal, int colVal);
  76. bool borderCollisionCheckX(int xVal);
  77. bool borderCollisionCheckY(int yVal);
  78. int radius;
  79. };
  80.  
  81.  
  82. int main()
  83. {
  84.     srand(time(0));
  85.     GrSetMode(GR_width_height_graphics, 640, 480);
  86.     GrFilledBox(0, 0, GrMaxX(), GrMaxY(), 0); //установка цвета фона
  87.     myDot *mainFigure; // указатель на главную фигуру
  88.     mainFigure = new myCircle(true);
  89.     myDot *(dots[_maxNumber]); // массив подчиненных фигур
  90.     for (int i = 0; i < _maxNumber; i++) // случайный выбор типа фигуры
  91.         switch (rand()%3) {
  92.             case 0: dots[i] = new myDot;
  93.             break;
  94.             case 1: dots[i] = new myCircle;
  95.             break;
  96.             case 2: dots[i] = new myBox;
  97.             break;
  98.         }
  99.     GrKeyType key = GrKey_0;
  100.     while (key != GrKey_Escape) { // отрисовка и расчет фигур до нажатия Esc
  101.         if (GrKeyPressed()) { // получение нажатой клавиши
  102.             key = GrKeyRead();
  103.             switch (key) {
  104.                 case GrKey_F1: if (_number < _maxNumber) _number++; // если нажата F1, то +1 фигура
  105.                 break;
  106.                 case GrKey_F2: if (_number > 0) {dots[_number-1] -> hide(); _number--; }; // если нажата F2, то удаление 1 фигуры
  107.                 break;
  108.             };
  109.         };
  110.         mainFigure -> move(); // перемещение и затирание старой позиции главной фигуры
  111.         //mainFigure -> hideOld();
  112.         for (int i = 0; i < _number; i++) { // то же самое для подчиненных
  113.             dots[i]->move();
  114.             //dots[i]->hideOld();
  115.         };
  116.         GrFilledBox(0, 0, GrMaxX(), GrMaxY(), 0);
  117.         mainFigure -> draw(); // отрисовка главной фигуры и подчиненных
  118.         for (int i = 0; i < _number; i++) dots[i]->draw();
  119.         GrSleep(20); // пропуск нескольких милисекунд для уменьшения количества морганий
  120.     };
  121.     return 0;
  122. }
  123.  
  124.  
  125. myDot::myDot(bool master) { // конструктор точки
  126.     x = (rand() % (GrMaxX() / 2)) + GrMaxX() / 4; //случайное положение от четверти и до 3/4 экрана
  127.     y = (rand() % (GrMaxY() / 2)) + GrMaxY() / 4;
  128.     xOld = x;
  129.     yOld = y;
  130.  
  131.     slave = !master;
  132.     hided = true;
  133.  
  134.     distToMaster = 0;
  135.     masterOffense = (rand() % 40) + 5;
  136.     masterAngleOffense = ((float)(rand() % 40)-20)/180*pi; // выбор погрешности в диапазоне +-20* в радианах
  137.  
  138.     velAngle = !slave ? ((float)(rand() % 360) / 180 * pi) : 0;
  139.     velocity = rand() % (_maxSpeed - _minSpeed) + _minSpeed; // выбор скорости в диапазоне
  140.  
  141.     int tran = rand()%14+1;
  142.     color = slave? (tran > 9 ? tran+1:tran ): 10; // подчиненные разных цветов, главный - зеленого
  143.  
  144.     prevTime = 0;
  145.     speedMult = 0;
  146. };
  147.  
  148. int myDot::getX() { return x; };
  149. int myDot::getY() { return y; };
  150.  
  151. void myDot::move() {
  152.     update();
  153.     int newX = x + xSpeed(); // получение новых значений
  154.     int newY = y + ySpeed();
  155.     if (!slave) { // Если не подчиненный, то обработка колизии и направления
  156.         if (borderCollisionCheckX(newX)) {
  157.              xOld = x;
  158.              x = newX;
  159.         }
  160.         else {
  161.             xOld = x;
  162.             velAngle = (velAngle > pi) ? (pi2 + pi - velAngle) : (pi - velAngle); // при столкновении со стеной меняем угол на противоположный относительно оси синусов
  163.         };
  164.         if (borderCollisionCheckY(newY)) {
  165.             yOld = y;
  166.             y = newY;
  167.         }
  168.         else {
  169.             yOld = y;
  170.             velAngle = pi2 - velAngle; // при столкновении с полом или потолком меняем угол на противоположный относительно оси косинусов
  171.         };
  172.         masterPositionUpdate(); // обновление позиции косинусов
  173.     }
  174.     else { // если подчиненный, то просто перемещаем точку
  175.         xOld = x;
  176.         x = newX;
  177.         yOld = y;
  178.         y = newY;
  179.     }
  180. };
  181.  
  182. int myDot::xSpeed() {
  183.     if (slave) // если подчиненный
  184.         return round(cos(velAngle) * velocity * speedMult * (distToMaster - masterOffense) / 150); // перемножение синуса и скорости (горизонтальная скорость) на временной коэффициент и расстояние до мастера
  185.     else // для главной фигуры то же самое, только без расстояния
  186.         return round(cos(velAngle) * velocity * speedMult);
  187. };
  188. int myDot::ySpeed() { // то же самое, только с синусом
  189.     if (slave)
  190.         return round(sin(velAngle) * velocity * speedMult * (distToMaster - masterOffense) / 150);
  191.     else
  192.         return round(sin(velAngle) * velocity * speedMult);
  193. };
  194.  
  195. void myDot::draw() { privateDraw(x, y, color); }; // оболочки для функций (для удобства)
  196. void myDot::hide() { privateDraw(x, y, 0); hided = true;}; // при скрытии дополнительно поднимается флаг "скрыт"
  197. void myDot::hideOld() { privateDraw(xOld, yOld, 0); };
  198. void myDot::redraw() { hideOld(); draw(); };
  199. void myDot::MaD() { move(); redraw(); };
  200.  
  201. void myDot::privateDraw(int x, int y, int colVal) {
  202.     GrFilledCircle(x, y, 3, colVal);
  203. };
  204.  
  205. bool myDot::borderCollisionCheckX(int x) {
  206.     return (x + 3 < GrMaxX() && x > 3);
  207. };
  208.  
  209. bool myDot::borderCollisionCheckY(int y) {
  210.     return (y + 3 < GrMaxY() && y > 3);
  211. };
  212.  
  213. void myDot::update() {
  214.     //timer update
  215.     unsigned int time = clock();
  216.     if (!hided)
  217.         speedMult = (float)(time - prevTime) / 1000; // временной коэф. - это разница текущего и предыдущего времени вызова функции перемещения в секундах
  218.     else { // если фигура скрыта, то временной коэффициент обнуляется (иначе из-за большого времени простоя фигура вылетает за границы)
  219.         speedMult = 0;
  220.         hided = false;
  221.     };
  222.     prevTime = time;
  223.     // position update
  224.     if (slave) { // если подчиненный, то дополнительно определяется направление до главной фигуры (с погрешностью) с помощью арктангенса
  225.         int offX = _masterX - x;
  226.         int offY = _masterY - y;
  227.         distToMaster = round(sqrt(offX * offX + offY * offY));
  228.         velAngle = atan2((float)offY / distToMaster, (float)offX / distToMaster) + masterAngleOffense;
  229.     }
  230. };
  231.  
  232. void myDot::masterPositionUpdate(){
  233.     _masterX = x;
  234.     _masterY = y;
  235. };
  236.  
  237. myBox::myBox(bool main): myDot(main){ // переопределения функций для прямоугольника
  238.     halfSizeX = rand()%10+10;
  239.     halfSizeY = rand()%10+10;
  240. };
  241.  
  242. void myBox::privateDraw(int x, int y, int colVal) {
  243.     GrFilledBox(x-halfSizeX, y-halfSizeY, x+halfSizeX,y+halfSizeY, colVal);
  244. }
  245.  
  246. bool myBox::borderCollisionCheckX(int x) {
  247.     return (x + halfSizeX < GrMaxX() && x > halfSizeX);
  248. };
  249. bool myBox::borderCollisionCheckY(int y) {
  250.     return (y + halfSizeY < GrMaxY() && y > halfSizeY);
  251. };
  252.  
  253. myCircle::myCircle(bool main): myDot(main) { // для окружности
  254.     radius = rand()%10+10;
  255. };
  256.  
  257. void myCircle::privateDraw(int x, int y, int colVal) {
  258.     GrFilledCircle(x, y, radius, colVal);
  259. }
  260.  
  261. bool myCircle::borderCollisionCheckX(int x) {
  262.     return (x + radius < GrMaxX() && x > radius);
  263. };
  264. bool myCircle::borderCollisionCheckY(int y) {
  265.     return (y +radius < GrMaxY() && y > radius);
  266. };
  267.  
  268.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement