Advertisement
bochkareffsasha

jopa

Dec 8th, 2022
593
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.67 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.     /*switch (rand()%1) { // случайный выбор типа фигуры
  89.         case 0: mainFigure = new myCircle(true);
  90.         break;
  91.     }
  92.     */
  93.     mainFigure = new myCircle(true);
  94.     myDot *(dots[_maxNumber]); // массив подчиненных фигур
  95.     for (int i = 0; i < _maxNumber; i++) // случайный выбор типа фигуры
  96.         switch (rand()%3) {
  97.             case 0: dots[i] = new myDot;
  98.             break;
  99.             case 1: dots[i] = new myCircle;
  100.             break;
  101.             case 2: dots[i] = new myBox;
  102.             break;
  103.         }
  104.     GrKeyType key = GrKey_0;
  105.     while (key != GrKey_Escape) { // отрисовка и расчет фигур до нажатия Esc
  106.         if (GrKeyPressed()) { // получение нажатой клавиши
  107.             key = GrKeyRead();
  108.             switch (key) {
  109.                 case GrKey_F1: if (_number < _maxNumber) _number++; // если нажата F1, то +1 фигура
  110.                 break;
  111.                 case GrKey_F2: if (_number > 0) {dots[_number-1] -> hide(); _number--; }; // если нажата F2, то удаление 1 фигуры
  112.                 break;
  113.             };
  114.         };
  115.         mainFigure -> move(); // перемещение и затирание старой позиции главной фигуры
  116.         //mainFigure -> hideOld();
  117.         for (int i = 0; i < _number; i++) { // то же самое для подчиненных
  118.             dots[i]->move();
  119.             //dots[i]->hideOld();
  120.         };
  121.         GrFilledBox(0, 0, GrMaxX(), GrMaxY(), 0);
  122.         mainFigure -> draw(); // отрисовка главной фигуры и подчиненных
  123.         for (int i = 0; i < _number; i++) dots[i]->draw();
  124.         GrSleep(20); // пропуск нескольких милисекунд для уменьшения количества морганий
  125.     };
  126.     return 0;
  127. }
  128.  
  129.  
  130. myDot::myDot(bool master) { // конструктор точки
  131.     x = (rand() % (GrMaxX() / 2)) + GrMaxX() / 4; //случайное положение от четверти и до 3/4 экрана
  132.     y = (rand() % (GrMaxY() / 2)) + GrMaxY() / 4;
  133.     xOld = x;
  134.     yOld = y;
  135.  
  136.     slave = !master;
  137.     hided = true;
  138.  
  139.     distToMaster = 0;
  140.     masterOffense = (rand() % 40) + 5;
  141.     masterAngleOffense = ((float)(rand() % 40)-20)/180*pi; // выбор погрешности в диапазоне +-20* в радианах
  142.  
  143.     velAngle = !slave ? ((float)(rand() % 360) / 180 * pi) : 0;
  144.     velocity = rand() % (_maxSpeed - _minSpeed) + _minSpeed; // выбор скорости в диапазоне
  145.  
  146.     int tran = rand()%14+1;
  147.     color = slave? (tran > 9 ? tran+1:tran ): 10; // подчиненные разных цветов, главный - белого
  148.  
  149.     prevTime = 0;
  150.     speedMult = 0;
  151. };
  152.  
  153. int myDot::getX() { return x; };
  154. int myDot::getY() { return y; };
  155.  
  156. void myDot::move() {
  157.     update();
  158.     int newX = x + xSpeed(); // получение новых значений
  159.     int newY = y + ySpeed();
  160.     if (!slave) { // Если не подчиненный, то обработка колизии и направления
  161.         if (borderCollisionCheckX(newX)) {
  162.              xOld = x;
  163.              x = newX;
  164.         }
  165.         else {
  166.             xOld = x;
  167.             velAngle = (velAngle > pi) ? (pi2 + pi - velAngle) : (pi - velAngle); // при столкновении со стеной меняем угол на противоположный относительно оси синусов
  168.         };
  169.         if (borderCollisionCheckY(newY)) {
  170.             yOld = y;
  171.             y = newY;
  172.         }
  173.         else {
  174.             yOld = y;
  175.             velAngle = pi2 - velAngle; // при столкновении с полом или потолком меняем угол на противоположный относительно оси косинусов
  176.         };
  177.         masterPositionUpdate(); // обновление позиции косинусов
  178.     }
  179.     else { // если подчиненный, то просто перемещаем точку
  180.         xOld = x;
  181.         x = newX;
  182.         yOld = y;
  183.         y = newY;
  184.     }
  185. };
  186.  
  187. int myDot::xSpeed() {
  188.     if (slave) // если подчиненный
  189.         return round(cos(velAngle) * velocity * speedMult * (distToMaster - masterOffense) / 150); // перемножение синуса и скорости (горизонтальная скорость) на временной коэффициент и расстояние до мастера
  190.     else // для главной фигуры то же самое, только без расстояния
  191.         return round(cos(velAngle) * velocity * speedMult);
  192. };
  193. int myDot::ySpeed() { // то же самое, только с синусом
  194.     if (slave)
  195.         return round(sin(velAngle) * velocity * speedMult * (distToMaster - masterOffense) / 150);
  196.     else
  197.         return round(sin(velAngle) * velocity * speedMult);
  198. };
  199.  
  200. void myDot::draw() { privateDraw(x, y, color); }; // оболочки для функций (для удобства)
  201. void myDot::hide() { privateDraw(x, y, 0); hided = true;}; // при скрытии дополнительно поднимается флаг "скрыт"
  202. void myDot::hideOld() { privateDraw(xOld, yOld, 0); };
  203. void myDot::redraw() { hideOld(); draw(); };
  204. void myDot::MaD() { move(); redraw(); };
  205.  
  206. void myDot::privateDraw(int x, int y, int colVal) {
  207.     GrFilledCircle(x, y, 3, colVal);
  208. };
  209.  
  210. bool myDot::borderCollisionCheckX(int x) {
  211.     return (x + 3 < GrMaxX() && x > 3);
  212. };
  213.  
  214. bool myDot::borderCollisionCheckY(int y) {
  215.     return (y + 3 < GrMaxY() && y > 3);
  216. };
  217.  
  218. void myDot::update() {
  219.     //timer update
  220.     unsigned int time = clock();
  221.     if (!hided)
  222.         speedMult = (float)(time - prevTime) / 1000; // временной коэф. - это разница текущего и предыдущего времени вызова функции перемещения в секундах
  223.     else { // если фигура скрыта, то временной коэффициент обнуляется (иначе из-за большого времени простоя фигура вылетает за границы)
  224.         speedMult = 0;
  225.         hided = false;
  226.     };
  227.     prevTime = time;
  228.     // position update
  229.     if (slave) { // если подчиненный, то дополнительно определяется направление до главной фигуры (с погрешностью) с помощью арктангенса
  230.         int offX = _masterX - x;
  231.         int offY = _masterY - y;
  232.         distToMaster = round(sqrt(offX * offX + offY * offY));
  233.         velAngle = atan2((float)offY / distToMaster, (float)offX / distToMaster) + masterAngleOffense;
  234.     }
  235. };
  236.  
  237. void myDot::masterPositionUpdate(){
  238.     _masterX = x;
  239.     _masterY = y;
  240. };
  241.  
  242. myBox::myBox(bool main): myDot(main){ // переопределения функций для прямоугольника
  243.     halfSizeX = rand()%10+10;
  244.     halfSizeY = rand()%10+10;
  245. };
  246.  
  247. void myBox::privateDraw(int x, int y, int colVal) {
  248.     GrFilledBox(x-halfSizeX, y-halfSizeY, x+halfSizeX,y+halfSizeY, colVal);
  249. }
  250.  
  251. bool myBox::borderCollisionCheckX(int x) {
  252.     return (x + halfSizeX < GrMaxX() && x > halfSizeX);
  253. };
  254. bool myBox::borderCollisionCheckY(int y) {
  255.     return (y + halfSizeY < GrMaxY() && y > halfSizeY);
  256. };
  257.  
  258. myCircle::myCircle(bool main): myDot(main) { // для окружности
  259.     radius = rand()%10+10;
  260. };
  261.  
  262. void myCircle::privateDraw(int x, int y, int colVal) {
  263.     GrFilledCircle(x, y, radius, colVal);
  264. }
  265.  
  266. bool myCircle::borderCollisionCheckX(int x) {
  267.     return (x + radius < GrMaxX() && x > radius);
  268. };
  269. bool myCircle::borderCollisionCheckY(int y) {
  270.     return (y +radius < GrMaxY() && y > radius);
  271. };
  272.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement