Basic geometric drawing steps:
- Create brush: default color BLACK
CreatePen(...)
- Create brush: the default brush color is NULL
CreateSolidBrush(...)
CreateHatchBrush(...) Shadow brush
CreatePatternBrush(...) Not commonly used
- Pick up the brush: SelectObject(...)
- Draw lines:
- LineTo(...) The parameter has only the end point. The current point is (0, 0) by default. After drawing, the end point becomes the current point
- MoveToEx(...) Moves the current point of the brush
- Draw a Rectangle(...)
- Delete brush: DeleteObject(...)
Game random number system
Generally, computers can only generate pseudo-random numbers: the process of generating random numbers by computers is a series of numbers calculated by a recursive formula based on a number. However, when the series of numbers are large, they conform to the normal distribution, which is equivalent to generating random numbers
- srand((unsigned)time(NULL)) initializes random seeds with system time
- rand(...) Generate random number
Simple algorithms for several random numbers
See it when you need it
Algorithm + drawing
Design:
Effect: each time you run, you will get different brushes and brushes
Definition of global variables based on GDI
HPEN g_hPen[7]={0}; HBRUSH g_hBrush[7]={0}; int g_iPenStyle[7] = {PS_SOLID,PS_DASH,PS_DOT,PS_DASHDOT,PS_DASHDOTDOT,PS_NULL,PS_INSIDEFRAME}; int g_iBrushStyle[6] = {HS_VERTICAL,HS_HORIZONTAL,HS_CROSS,HS_DIAGCROSS,HS_FDIAGONAL,HS_BDIAGONAL};
PlaySound(L"AIR - Xia Ying.wav", NULL, SND_FILENAME | SND_ASYNC|SND_LOOP); //Loop background music
Randomly generate the colors of brushes and brushes
BOOL Game_Init( HWND hwnd ) { g_hdc = GetDC(hwnd); srand((unsigned)time(NULL)); for(int i=0;i<=6;i++) { g_hPen[i] = CreatePen(g_iPenStyle[i],1,RGB(rand()%256,rand()%256,rand()%256)); if(i==6) g_hBrush[i] = CreateSolidBrush(RGB(rand()%256,rand()%256,rand()%256)); else g_hBrush[i] = CreateHatchBrush(g_iBrushStyle[i],RGB(rand()%256,rand()%256,rand()%256)); } Game_Paint(hwnd); ReleaseDC(hwnd,g_hdc); return TRUE; }
Drawing logic
VOID Game_Paint( HWND hwnd ) { //Define a y coordinate value int y=0; //A for loop that draws lines with seven different brushes for(int i=0;i<=6;i++) { y = (i+1) * 70; SelectObject(g_hdc,g_hPen[i]);//Select the corresponding brush MoveToEx(g_hdc,30,y,NULL); //The cursor moves to the corresponding (30, y) coordinate LineTo(g_hdc,100,y); //Draw a line segment from (30, y) to (100, y) } /*Note that y=420 after drawing above, which is also useful when drawing rectangle below*/ //Define two x coordinate values int x1 = 120; int x2 = 190; //Fill the rectangle with 7 different brushes for(int i=0;i<=6;i++) { SelectObject(g_hdc,g_hBrush[i]); //Choose brush Rectangle(g_hdc,x1,70,x2,y); //Draw a closed rectangle. The coordinates of the upper left corner of the rectangle are (x1,50) and the coordinates of the lower right corner are (x2, y) x1 += 90; x2 += 90; } }
Release handle
BOOL Game_CleanUp( HWND hwnd ) { //A for loop that releases all brush and brush handles for (int i=0;i<=6;i++) { DeleteObject(g_hPen[i]); DeleteObject(g_hBrush[i]); } return TRUE; }
Drawing with QT frame
Graphics/View framework: store, display and process interactive commands that operate on graphic elements
QGraphicsView: it is responsible for displaying some or all graphic elements in a scene. It has its own coordinate system and is closely related to specific display devices
QGraphicsItem: graphic elements displayed
QGraphicsScene: a scene that includes all graphic elements
Maintain a list: record which graphic elements are selected
Data structure: record which graphic element or elements get focus
Collision of graphic elements
Detection principle:
The virtual function shape() in QGraphicsItem is responsible for returning its own contour,
colidingItems() in QGraphicsScene is responsible for querying the outline of each graphic element in the scene and judging which elements collide with a specified element
Colliding mice
int main(int argc, char **argv) { QApplication app(argc, argv); qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));//Initializing random seeds with system time QGraphicsScene scene;//Scene object scene.setSceneRect(-300, -300, 600, 600); scene.setItemIndexMethod(QGraphicsScene::NoIndex); for (int i = 0; i < MouseCount; ++i) { //6 mice Mouse *mouse = new Mouse;//Mouse object mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, ::cos((i * 6.28) / MouseCount) * 200);//Set position scene.addItem(mouse);//Add to scene } QGraphicsView view(&scene);//Responsible for displaying some or all elements in a scene view.setRenderHint(QPainter::Antialiasing); view.setBackgroundBrush(QPixmap(":/images/cheese.jpg"));//Sweetheart picture view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setDragMode(QGraphicsView::ScrollHandDrag); view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); view.resize(400, 300); view.show(); QTimer timer; //Timer Objects QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance())); //Signal slot (timer signal advance) timer.start(1000 / 30); //Timer (advance () of graphic elements at a frequency of 3s) return app.exec(); }
#include <QGraphicsItem> class Mouse : public QGraphicsItem { public: Mouse(); //Returns the smallest rectangle surrounding a mouse figure QRectF boundingRect() const override; //Returns the exact shape of the mouse QPainterPath shape() const override; //This function is called when a graphic element needs to be drawn void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; protected: //Update the position of the mouse and the color of the eyes void advance(int step) override; private: qreal angle; qreal speed; qreal mouseEyeDirection; QColor color; };
Function: returns the smallest rectangle surrounding a mouse figure
Implementation idea:
static qreal normalizeAngle(qreal angle) { while (angle < 0) angle += TwoPi; while (angle > TwoPi) angle -= TwoPi; return angle; }
Function: initialize the variable value and set the angle direction of the mouse
Mouse::Mouse() : angle(0), speed(0), mouseEyeDirection(0), color(qrand() % 256, qrand() % 256, qrand() % 256) { setRotation(qrand() % 360 ); }
Function: returns the smallest rectangle surrounding a mouse figure
QRectF Mouse::boundingRect() const { qreal adjust = 0.5; return QRectF(-18 - adjust, -22 - adjust, 36 + adjust, 60 + adjust); }
Function: returns the exact shape of the mouse
QPainterPath Mouse::shape() const { QPainterPath path; path.addRect(-10, -20, 20, 40); return path; }
Function: when you need to draw a graphic element, this function will be called
Realization idea: splice each organ of the mouse by drawing ellipses and coordinate positions
void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { // Body painter->setBrush(color); painter->drawEllipse(-10, -20, 20, 40); // Eyes painter->setBrush(Qt::white); painter->drawEllipse(-10, -17, 8, 8); painter->drawEllipse(2, -17, 8, 8); // Nose painter->setBrush(Qt::black); painter->drawEllipse(QRectF(-2, -22, 4, 4)); //Eyeball painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); // Ears painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red);//collision detection painter->drawEllipse(-17, -12, 16, 16); painter->drawEllipse(1, -12, 16, 16); // Tail QPainterPath path(QPointF(0, 20)); path.cubicTo(-5, 22, -5, 22, 0, 25); path.cubicTo(5, 27, 5, 32, 0, 30); path.cubicTo(-5, 32, -5, 42, 0, 35); painter->setBrush(Qt::NoBrush); painter->drawPath(path); }
Function: update the position of the mouse and the color of the eyes
Realization idea: to be studied
void Mouse::advance(int step) { if (!step) return; // Don't move too far away QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); if (lineToCenter.length() > 150) { qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); if (lineToCenter.dy() < 0) angleToCenter = TwoPi - angleToCenter; angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); if (angleToCenter < Pi && angleToCenter > Pi / 4) { // Rotate left angle += (angle < -Pi / 2) ? 0.25 : -0.25; } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { // Rotate right angle += (angle < Pi / 2) ? 0.25 : -0.25; } } else if (::sin(angle) < 0) { angle += 0.25; } else if (::sin(angle) > 0) { angle -= 0.25; } // Try not to crash with any other mice QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF() << mapToScene(0, 0) << mapToScene(-30, -50) << mapToScene(30, -50)); foreach (QGraphicsItem *item, dangerMice) { if (item == this) continue; QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); if (lineToMouse.dy() < 0) angleToMouse = TwoPi - angleToMouse; angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); if (angleToMouse >= 0 && angleToMouse < Pi / 2) { // Rotate right angle += 0.5; } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { // Rotate left angle -= 0.5; } } // Add some random movement if (dangerMice.size() > 1 && (qrand() % 10) == 0) { if (qrand() % 1) angle += (qrand() % 100) / 500.0; else angle -= (qrand() % 100) / 500.0; } speed += (-50 + qrand() % 100) / 100.0; qreal dx = ::sin(angle) * 10; mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; setRotation(rotation() + dx); setPos(mapToParent(0, -(3 + sin(speed) * 3))); }
a design chart
Renderings
Oh, my God, I'm so tired. Give yourself a compliment!