oblivioncth

mouse.cpp

Apr 19th, 2016
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "mouse.h"
  2.  
  3. #include <QGraphicsScene>
  4. #include <QPainter>
  5. #include <QStyleOption>
  6.  
  7. #include <math.h>
  8.  
  9. //CONSTANTS
  10. //---------
  11. static const double Pi = 3.14159265358979323846264338327950288419717;
  12. static double TwoPi = 2.0 * Pi;
  13.  
  14. //MICE SPECIFIC
  15. //-------------
  16. static qreal normalizeAngle(qreal angle)
  17. {
  18.     while (angle < 0)
  19.         angle += TwoPi;
  20.     while (angle > TwoPi)
  21.         angle -= TwoPi;
  22.     return angle;
  23. }
  24.  
  25. Mouse::Mouse()
  26.     : angle(0), speed(0), mouseEyeDirection(0),
  27.       color(qrand() % 256, qrand() % 256, qrand() % 256)
  28. {
  29.     setRotation(qrand() % (360 * 16));
  30. }
  31.  
  32. QRectF Mouse::boundingRect() const
  33. {
  34.     qreal adjust = 0.5;
  35.     return QRectF(-18 - adjust, -22 - adjust,
  36.                   36 + adjust, 60 + adjust);
  37. }
  38.  
  39. QPainterPath Mouse::shape() const
  40. {
  41.     QPainterPath path;
  42.     path.addRect(-10, -20, 20, 40);
  43.     return path;
  44. }
  45.  
  46. void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
  47. {
  48.     // Body
  49.     painter->setBrush(color);
  50.     painter->drawRect(-10, -20, 20, 40);
  51.  
  52.     // Eyes
  53.     painter->setBrush(Qt::yellow);
  54.     painter->drawEllipse(-10, -17, 8, 8);
  55.     painter->drawEllipse(2, -17, 8, 8);
  56.  
  57.     // Nose
  58.     painter->setBrush(Qt::black);
  59.     painter->drawEllipse(QRectF(-2, -22, 4, 4));
  60.  
  61.     // Pupils
  62.     painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4));
  63.     painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4));
  64.  
  65.     // Ears
  66.     painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::black : Qt::red);
  67.     painter->drawRect(-16, -12, 6, 12);
  68.     painter->drawRect(10, -12, 6, 12);
  69.     painter->drawRect(-16, 10, 6, 12);
  70.     painter->drawRect(10, 10, 6, 12);
  71.  
  72.  
  73.     // Tail
  74.     QPainterPath path(QPointF(0, 20));
  75.     path.cubicTo(-5, 22, -5, 22, 0, 25);
  76.     path.cubicTo(5, 27, 5, 32, 0, 30);
  77.     path.cubicTo(-5, 32, -5, 42, 0, 35);
  78.     painter->setBrush(Qt::NoBrush);
  79.     painter->drawPath(path);
  80. }
  81.  
  82. void Mouse::advance(int step)
  83. {
  84.     if (!step)
  85.         return;
  86.     // Don't move too far away
  87.     QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
  88.     if (lineToCenter.length() > 150) {
  89.         qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
  90.         if (lineToCenter.dy() < 0)
  91.             angleToCenter = TwoPi - angleToCenter;
  92.         angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
  93.  
  94.         if (angleToCenter < Pi && angleToCenter > Pi / 4) {
  95.             // Rotate left
  96.             angle += (angle < -Pi / 2) ? 0.25 : -0.25;
  97.         } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) {
  98.             // Rotate right
  99.             angle += (angle < Pi / 2) ? 0.25 : -0.25;
  100.         }
  101.     } else if (::sin(angle) < 0) {
  102.         angle += 0.25;
  103.     } else if (::sin(angle) > 0) {
  104.         angle -= 0.25;
  105.     }
  106.  
  107.     // Try not to crash with any other mice
  108.     QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()
  109.                                                        << mapToScene(0, 0)
  110.                                                        << mapToScene(-30, -50)
  111.                                                        << mapToScene(30, -50));
  112.     foreach (QGraphicsItem *item, dangerMice) {
  113.         if (item == this)
  114.             continue;
  115.  
  116.         QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
  117.         qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
  118.         if (lineToMouse.dy() < 0)
  119.             angleToMouse = TwoPi - angleToMouse;
  120.         angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
  121.  
  122.         if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
  123.             // Rotate right
  124.             angle += 0.5;
  125.         } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) {
  126.             // Rotate left
  127.             angle -= 0.5;
  128.         }
  129.     }
  130.  
  131.     // Add some random movement
  132.     if (dangerMice.size() > 1 && (qrand() % 10) == 0) {
  133.         if (qrand() % 1)
  134.             angle += (qrand() % 100) / 500.0;
  135.         else
  136.             angle -= (qrand() % 100) / 500.0;
  137.     }
  138.  
  139.     speed += (-50 + qrand() % 100) / 100.0;
  140.  
  141.     qreal dx = ::sin(angle) * 10;
  142.     mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;
  143.  
  144.     setRotation(rotation() + dx);
  145.     setPos(mapToParent(0, -(3 + sin(speed) * 3)));
  146. }
Advertisement
Add Comment
Please, Sign In to add comment