目錄
球球大作戰
一、開發環境
二、流程圖預覽
三、代碼邏輯
1、初始化時間
2、設置開始界面大小
3、設置開始界面
4、讓玩家選擇速度
5、設置玩家小球、人機小球、食物的屬性
6、一次性把圖繪制到界面里
7、進入死循環
8、移動玩家小球
9、移動人機
10、食物刷新
11、畫出邊界、食物、人機、玩家、小地圖,添加擊殺數、半徑(質量)、玩家名字
12、將內存中的繪圖操作批量地繪制到屏幕上,從而提高繪圖效率
四、代碼預覽+運行結果
球球大作戰
一、開發環境
VisualStudio專業版:
所需依賴庫:EasyX庫
二、流程圖預覽
由于上面的比較模糊,下面分開截取流程圖圖片
三、代碼邏輯
1、初始化時間
starttime();
2、設置開始界面大小
initgraph(WIDTH, HEIGHT);
3、設置開始界面
void start() {setbkcolor(WHITE); // 白色背景cleardevice(); // 初始化背景settextcolor(BLACK); // 改字體setbkmode(TRANSPARENT); //設置背景是透明的//加載背景圖片IMAGE image;loadimage(&image, _T("D:\\桌面\\file2\\球球大作戰\\source\\Ball Ball\\x64\\img\\10.jpg"), WIDTH, HEIGHT);//在當前設備上繪制指定圖像putimage(0, 0, &image);//加入提示信息settextcolor(WHITE);settextstyle(22, 0, _T("黑體"));outtextxy(50, 480, _T("請選擇關卡:"));outtextxy(50, 550, _T("1.小試牛刀"));outtextxy(200, 550, _T("2.爐火純青"));outtextxy(350, 550, _T("3.登峰造極"));settextstyle(15, 0, _T("宋體"));outtextxy(600, 550, _T("注:按序號選擇,默認選擇關卡1;游戲中按空格鍵可以暫停。"));settextcolor(BLACK);settextstyle(22, 0, _T("黑體"));TCHAR s[5];//_stprintf(s, _T("%d"), readCount());_stprintf_s(s, _countof(s), _T("%d"), readCount());outtextxy(810, 200, _T("歡迎進入游戲!"));outtextxy(810, 240, _T("游戲次數:"));outtextxy(910, 240, s);
}
4、讓玩家選擇速度
void ChooseSpeed() {switch (_getch()) {case 1:speed = 4;case 2:speed = 3;case 3:speed = 2;default:speed = 4;}
}
5、設置玩家小球、人機小球、食物的屬性
void setall() {srand((unsigned)time(NULL)); // 隨機數mover.color = RGB(rand() % 256, rand() % 256, rand() % 256); // 隨機顏色mover.life = 1; // 賦初值1//把玩家的球一直放在屏幕中央mover.x = int(WIDTH * 0.5);mover.y = int(HEIGHT * 0.5);//設置半徑mover.r = 20;
?for (int i = 0; i < AINUM; i++) { // AI 的屬性ai[i].life = 1;ai[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);//ai[i].r = float(rand() % 10 + 10);ai[i].r = 20;ai[i].x = rand() % (MAPW - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);ai[i].y = rand() % (MAPH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);}
?for (int i = 0; i < FNUM; i++) { // 食物的屬性food[i].eat = 1;food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);food[i].x = rand() % MAPW;food[i].y = rand() % MAPH;food[i].type = rand() % 10 + 1;}
?pBuffer = GetImageBuffer(NULL); // 獲取顯存指針setbkcolor(WHITE); // 白色背景cleardevice(); // 初始化背景settextcolor(LIGHTRED); // 改字體//設置背景是透明的setbkmode(TRANSPARENT);settextstyle(16, 0, _T("宋體"));
?
}
6、一次性把圖繪制到界面里
BeginBatchDraw();
7、進入死循環
8、移動玩家小球
void move(BALL* ball) {if (ball->r <= 0)ball->life = false;if (ball->life == false) { // 判定游戲是否接束HWND hwnd = GetHWnd();MessageBox(hwnd, _T("你被吃了"), _T("游戲結束"), MB_ICONEXCLAMATION);endtime();
?}
?if (eaten + ai_eaten == AINUM) // 是否吃掉所有 AI{HWND hwnd = GetHWnd();MessageBox(hwnd, _T("恭喜過關"), _T("游戲結束"), MB_OK | MB_ICONEXCLAMATION); // 結束endtime();}
?for (int i = 0; i < AINUM; i++) { // 玩家吃 AI 判定if (ball->r >= ai[i].r) {if (ai[i].life == 0) continue;if (DISTANCE(ball->x, ball->y, ai[i].x, ai[i].y) < (4 / 5.0 * (ball->r + ai[i].r))) {ai[i].life = 0; //AI被吃ball->r = sqrt(ai[i].r * ai[i].r + ball->r * ball->r);eaten++;}}}
?for (int n = 0; n < FNUM; n++) { // 玩家吃食物if (food[n].eat == 0) continue;if (DISTANCE(ball->x, ball->y, food[n].x, food[n].y) < ball->r) {ball->r += 4 / ball->r; // 增加面積food[n].eat = 0; // 食物被吃}}
?static int mx = 0, my = 0; // 記錄偏移量
?//判斷怎么移動if (GetAsyncKeyState(VK_UP) && (ball->y - ball->r > 0 && ball->y <= (MAPH - ball->r + 10))) {ball->y -= speed;my += speed;}if (GetAsyncKeyState(VK_DOWN) && (ball->y - ball->r >= -10 && ball->y < (MAPH - ball->r))) {ball->y += speed;my -= speed;}if (GetAsyncKeyState(VK_LEFT) && ball->x - ball->r > 0 && (ball->x <= (MAPW - ball->r + 10))) {ball->x -= speed;mx += speed;}if (GetAsyncKeyState(VK_RIGHT) && ball->x - ball->r >= -10 && (ball->x < (MAPW - ball->r))) {ball->x += speed;mx -= speed;}
?//判斷是否輸入其他用于退出、暫停、繼續的按鍵if (GetAsyncKeyState(VK_SPACE)) {settextcolor(WHITE);settextstyle(32, 0, _T("宋體"));outtextxy(384 - mx, 350 - my, _T("游戲已暫停!"));outtextxy(20 - mx, 500 - my, _T("(ESC)退出"));outtextxy(780 - mx, 500 - my, _T("(回車鍵)繼續"));FlushBatchDraw();_getch();if (GetAsyncKeyState(VK_ESCAPE))exit(0);else_getch();}
?setorigin(mx, my); //坐標修正
}
9、移動人機
void AI() {for (int i = 0; i < AINUM; i++) { // AI 吃玩家if (ai[i].r > mover.r) {if (DISTANCE(mover.x, mover.y, ai[i].x, ai[i].y) < (ai[i].r + mover.r)) {ai[i].r = sqrt(ai[i].r * ai[i].r + mover.r * mover.r);mover.life = 0;mover.r = 0;}}for (int j = 0; j < AINUM; j++) { // AI 吃 AIif (ai[i].r > ai[j].r) {if (ai[j].life == 0) continue;if (DISTANCE(ai[i].x, ai[i].y, ai[j].x, ai[j].y) < (ai[i].r + ai[j].r)) {ai[i].r = sqrt(ai[i].r * ai[i].r + ai[j].r * ai[j].r);ai[j].life = 0;ai[j].r = 0;ai_eaten++;}}}
?double min_DISTANCE = 100000;int min = -1;for (int k = 0; k < AINUM; k++) { // AI 靠近 AIif (ai[i].r > ai[k].r && ai[k].life != 0) {if (DISTANCE(ai[i].x, ai[i].y, ai[k].x, ai[k].y) < min_DISTANCE) {min_DISTANCE = DISTANCE(ai[i].x, ai[i].y, ai[k].x, ai[k].y);min = k;}}}if ((min != -1) && (rand() % 2 == 1) && (ai[i].y - ai[i].r > 0 && ai[i].y <= (MAPH - ai[i].r + 10))) {if (rand() % 2) {if (ai[i].x < ai[min].x)ai[i].x += speed ;elseai[i].x -= speed ;}else {if (ai[i].y < ai[min].y)ai[i].y += speed ;elseai[i].y += speed ;}}for (int n = 0; n < FNUM; n++) { // AI 吃食物if (food[n].eat == 0) continue;if (DISTANCE(ai[i].x, ai[i].y, food[n].x, food[n].y) < ai[i].r) {ai[i].r += 4 / ai[i].r;food[n].eat = 0;}}}
}
10、食物刷新
void Food() {for (int i = 0; i < FNUM; i++) { // 食物刷新if (food[i].eat == 0) {food[i].eat = 1;food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);food[i].x = rand() % MAPW;food[i].y = rand() % MAPH;food[i].type = rand() % 10 + 1;}}
}
11、畫出邊界、食物、人機、玩家、小地圖,添加擊殺數、半徑(質量)、玩家名字
void draw() {float asp = 1;//清空裁剪區,超出區域的繪圖操作將被裁剪掉clearcliprgn();IMAGE image;loadimage(&image, _T(""), WIDTH * 4, HEIGHT * 4);putimage(0, 0, &image);//繪畫出一個矩形框setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 20); // 改變筆的顏色、狀態setlinecolor(RGB(0, 100, 0));line(-20, MAPH + 20, -20, -20); // 左豎line(-20, MAPH + 20, MAPW + 20, MAPH + 20); // 上橫line(-20, -20, MAPW + 20, -20); // 下橫line(MAPW + 20, -20, MAPW + 20, MAPH + 20); // 右豎setfillcolor(GREEN);//當球接近邊界時,會在邊界外側繪制一個綠色的填充矩形,// 是用來表示碰撞或者邊界的視覺效果if (mover.x - 0.5 * WIDTH / asp < -20)floodfill(-20 - 11, mover.y, RGB(0, 100, 0));if (mover.x + 0.5 * WIDTH / asp > MAPW + 20)floodfill(MAPW + 20 + 11, mover.y, RGB(0, 100, 0));if (mover.y - 0.5 * HEIGHT / asp < -20)floodfill(mover.x, -20 - 11, RGB(0, 100, 0));if (mover.y + 0.5 * HEIGHT / asp > MAPH + 20)floodfill(mover.x, MAPH + 20 + 11, RGB(0, 100, 0));setlinecolor(WHITE);setlinestyle(PS_NULL);for (int i = 0; i < FNUM; i++) { // 畫出食物if (food[i].eat == 0) continue;setfillcolor(food[i].color);switch (food[i].type) { // 形狀case 1: solidellipse(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;case 2: solidellipse(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;case 3: solidrectangle(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;case 4: solidrectangle(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;case 5: solidroundrect(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4, 2, 2); break;case 6: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 2); break;case 7: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 4, 2); break;case 8: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 4); break;case 9: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 1, 1); break;case 10: fillcircle(food[i].x, food[i].y, 4); break;}}for (int i = 0; i < AINUM; i++) { // 畫 AIif (ai[i].life == 0) continue;setfillcolor(ai[i].color);//繪圓fillcircle(ai[i].x, ai[i].y, int(ai[i].r + 0.5));}setfillcolor(mover.color); // 畫玩家fillcircle(mover.x, mover.y, int(mover.r + 0.5));IMAGE map(150, 100); // 小地圖SetWorkingImage(&map);setbkcolor(RGB(120, 165, 209)); // 淺灰色背景cleardevice();for (int i = 0; i < AINUM; i++) // 畫 AI(小地圖){if (ai[i].life == 0) continue;setfillcolor(ai[i].color);fillcircle(ai[i].x * 150 / WIDTH / 4, ai[i].y * 100 / HEIGHT / 4, int(ai[i].r / 28 + 1.5));}setfillcolor(mover.color); // 畫玩家(小地圖)fillcircle(mover.x * 150 / WIDTH / 4, mover.y * 100 / HEIGHT / 4, int(mover.r / 28 + 3.5));setlinecolor(RGB(0, 100, 0));SetWorkingImage(); // 恢復繪圖背景putimage(mover.x + int(0.5 * WIDTH) - 150, mover.y - int(0.5 * HEIGHT), 150, 100, &map, 0, 0); // 畫出小地圖setlinecolor(LIGHTBLUE);setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 4);line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT), mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99); // 地圖邊框線line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99, mover.x + int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT) + 99); // 地圖邊框線setlinestyle(PS_NULL); // 恢復筆TCHAR str[32];swprintf_s(str, _T("質量:%.1fg 擊殺:%d"), mover.r, eaten);settextcolor(WHITE); // 改字體outtextxy(mover.x - int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT), str);settextcolor(WHITE);outtextxy(mover.x - 20, mover.y, _T("itlsl"));
}
12、將內存中的繪圖操作批量地繪制到屏幕上,從而提高繪圖效率
FlushBatchDraw();
四、代碼預覽+運行結果
源代碼+流程圖+README資源:https://download.csdn.net/download/2403_82436914/90623088?spm=1001.2014.3001.5503