Reference resources
- C and C++ Game Fun Programming Kid Crystal
To make use of every bit of time
"Pin in Seam" Game: Press the space bar and send a pin onto the disc. All the pins turn counterclockwise. If a new pin hits an existing pin, the game ends
Draw discs and needles
Draw a circle to represent a disc, a line segment to represent a needle, and the coordinates of the center of the circle and the starting point of the segment are (width/2, height/2)
#include <graphics.h> #include <conio.h> #include <stdio.h> int main() { int width = 800; int height = 600; initgraph(width, height); setbkcolor(RGB(255, 255, 255)); cleardevice(); setlinestyle(PS_SOLID, 3); // Line width 3 setlinecolor(RGB(0, 0, 0)); line(width / 2, height / 2, width / 2 + 160, height / 2); // Draw a needle setlinecolor(HSVtoRGB(0, 0.9, 0.8)); // Set the disc line color to red circle(width / 2, height / 2, 60); _getch(); closegraph(); return 0; }
Rotation of needle
The start coordinate of the needle is the center of the picture (width/2, height/2). Assuming the length of the needle is lineLength and the rotation angle of the needle is angle, the end coordinate of the needle (xEnd, yEnd) can be calculated by the trigonometric function. Then, the rotation effect of the needle can be achieved by increasing the angle of the needle gradually.
#include <graphics.h> #include <conio.h> #include <stdio.h> #include <math.h> int main() { float PI = 3.1415926; int width = 800; int height = 600; initgraph(width, height); setbkcolor(RGB(255, 255, 255)); float lineLength = 160; float xEnd, yEnd; float angle = 0; float rotateSpeed = PI / 360; setlinestyle(PS_SOLID, 3); // Line width 3 while (1) { cleardevice(); angle += rotateSpeed; if (angle > 2 * PI) // Prevent angle data from increasing indefinitely { angle -= 2 * PI; } xEnd = lineLength * cos(-angle) + width / 2; // Calculate the end coordinates of a needle yEnd = lineLength * sin(-angle) + height / 2; setlinecolor(RGB(0, 0, 0)); line(width / 2, height / 2, xEnd, yEnd); // Draw a needle setlinecolor(HSVtoRGB(0, 0.9, 0.8)); // Set the disc line color to red circle(width / 2, height / 2, 60); Sleep(10); } closegraph(); return 0; }
Batch Draw Multiple Needles
Use arrays to record the angle values of each needle. In addition, when more elements are drawn, an apparent picture flicker occurs, and the batch drawing function can be used. BeginBatchDraw() is used to start a batch drawing, and any drawing operation will be temporarily off-screen until FlushBatchDraw() or EndBatchDraw() outputs the previous drawing.
#include <graphics.h> #include <conio.h> #include <stdio.h> #include <math.h> int main() { float PI = 3.1415926; int width = 800; int height = 600; initgraph(width, height); setbkcolor(RGB(255, 255, 255)); setlinestyle(PS_SOLID, 3); // Line width 3 float lineLength = 160; float xEnd, yEnd; float rotateSpeed = PI / 360; int lineNum = 20; float Angles[20]; int i; for (i = 0; i < lineNum; i++) { Angles[i] = i * 2 * PI / lineNum; } BeginBatchDraw(); while (1) { cleardevice(); setlinecolor(RGB(0, 0, 0)); for (i = 0; i < lineNum; i++) { Angles[i] += rotateSpeed; if (Angles[i] > 2 * PI) // Prevent angle data from increasing indefinitely { Angles[i] -= 2 * PI; } xEnd = lineLength * cos(-Angles[i]) + width / 2; // Calculate the end coordinates of a needle yEnd = lineLength * sin(-Angles[i]) + height / 2; line(width / 2, height / 2, xEnd, yEnd); // Draw a needle } setlinecolor(HSVtoRGB(0, 0.9, 0.8)); // Set the disc line color to red circle(width / 2, height / 2, 60); FlushBatchDraw(); Sleep(10); } closegraph(); return 0; }
Needle Launch and Addition
First draw a pin on the left side of the screen to indicate the location to be emitted; when the user presses the space bar, the number of pins is increased by 1, and the initial angle of the newly added pin is PI. The user continuously presses the space bar to generate new pins
#include <graphics.h> #include <conio.h> #include <stdio.h> #include <math.h> int main() { float PI = 3.1415926; int width = 800; int height = 600; initgraph(width, height); setbkcolor(RGB(255, 255, 255)); setlinestyle(PS_SOLID, 3); // Line width 3 float lineLength = 160; float xEnd, yEnd; float rotateSpeed = PI / 360; int lineNum = 0; float Angles[1000]; int i; BeginBatchDraw(); while (1) { cleardevice(); setlinecolor(RGB(0, 0, 0)); line(0, height / 2, lineLength, height / 2); // A pin in the left firing area for (i = 0; i < lineNum; i++) { Angles[i] += rotateSpeed; if (Angles[i] > 2 * PI) // Prevent angle data from increasing indefinitely { Angles[i] -= 2 * PI; } xEnd = lineLength * cos(-Angles[i]) + width / 2; // Calculate the end coordinates of a needle yEnd = lineLength * sin(-Angles[i]) + height / 2; line(width / 2, height / 2, xEnd, yEnd); // Draw a needle } if (_kbhit()) { char input = _getch(); if (input == ' ') // If Spacebar { lineNum++; Angles[lineNum - 1] = PI; xEnd = lineLength * cos(-Angles[lineNum - 1]) + width / 2; yEnd = lineLength * sin(-Angles[lineNum - 1]) + height / 2; line(width / 2, height / 2, xEnd, yEnd); } } setlinecolor(HSVtoRGB(0, 0.9, 0.8)); // Set the disc line color to red circle(width / 2, height / 2, 60); FlushBatchDraw(); Sleep(10); } closegraph(); return 0; }
Game Failure Judgment
When the absolute difference of rotation angle between the two pins is less than PI/60, collision is judged
for (i = 0; i < lineNum - 1; i++) // Compare new needles with all previous ones { if (fabs(Angles[lineNum - 1] - Angles[i]) < PI / 60) { rotateSpeed = 0; // Stop rotating if colliding break; } }
Score and display improvement
When the user presses the space bar and the game does not fail, the score increases by 1:
score += 1;
Finally, convert the score to string output:
TCHAR s[20]; // Define String Array _stprintf(s, _T("%d"), score); settextstyle(50, 0, _T("Times")); settextcolor(RGB(50, 50, 50)); outtextxy(65, 200, s);
Fill the drawing disc, and as the number of pins increases, the disc filling color becomes more vibrant:
setfillcolor(HSVtoRGB(0, lineNum / 60.0, 0.8)); setlinecolor(HSVtoRGB(0, 0.9, 0.8)); fillcircle(width / 2, height / 2);
Set the color of the spinning needle to blue and the newly launched needle to red:
setlinecolor(RGB(0, 0, 255)); if (i == lineNum - 1) { setlinecolor(RGB(255, 0, 0)); }
Complete Code
#include <graphics.h> #include <conio.h> #include <stdio.h> #include <math.h> int main() { float PI = 3.1415926; int width = 800; int height = 600; initgraph(width, height); setbkcolor(RGB(255, 255, 255)); setlinestyle(PS_SOLID, 3); // Line width 3 float lineLength = 160; float xEnd, yEnd; float rotateSpeed = PI / 360; int lineNum = 0; float Angles[1000]; int score = 0; int i; BeginBatchDraw(); while (1) { cleardevice(); setlinecolor(RGB(0, 0, 0)); line(0, height / 2, lineLength, height / 2); // A pin in the left firing area for (i = 0; i < lineNum; i++) { Angles[i] += rotateSpeed; if (Angles[i] > 2 * PI) // Prevent angle data from increasing indefinitely { Angles[i] -= 2 * PI; } xEnd = lineLength * cos(-Angles[i]) + width / 2; // Calculate the end coordinates of a needle yEnd = lineLength * sin(-Angles[i]) + height / 2; setlinecolor(RGB(0, 0, 255)); // Set the color of the pin to blue if (i == lineNum - 1) { setlinecolor(RGB(255, 0, 0)); // The new pin is red } line(width / 2, height / 2, xEnd, yEnd); // Draw a needle } if (_kbhit() && rotateSpeed != 0) { char input = _getch(); if (input == ' ') // If Spacebar { lineNum++; Angles[lineNum - 1] = PI; xEnd = lineLength * cos(-Angles[lineNum - 1]) + width / 2; yEnd = lineLength * sin(-Angles[lineNum - 1]) + height / 2; line(width / 2, height / 2, xEnd, yEnd); for (i = 0; i < lineNum - 1; i++) // Compare new needles with all previous ones { if (fabs(Angles[lineNum - 1] - Angles[i]) < PI / 60) { rotateSpeed = 0; // Stop rotating if colliding break; } } score += 1; } } setfillcolor(HSVtoRGB(0, lineNum / 60.0, 0.8)); // The more needles, the brighter the disc color setlinecolor(HSVtoRGB(0, 0.9, 0.8)); // Disc lines are red fillcircle(width / 2, height / 2, 60); // Draw the middle disc TCHAR s[20]; // Define String Array swprintf_s(s, _T("%d"), score); settextstyle(50, 0, _T("Times")); // Set text size, font settextcolor(RGB(50, 50, 50)); outtextxy(65, 200, s); FlushBatchDraw(); Sleep(10); } closegraph(); return 0; }