《球球大作戰》雖然在玩法上類似于大球吃小球的模式看起來很單薄。但是在游戲過程中會出現無數種意外情況,這就需要玩家運用一系列策略來達到不被吃和吃掉別人球的目的,大大增加了游戲的耐玩性。
一個人的話想要實現復刻球球太困難了,所以這是仿照成熟版球球大作戰寫的簡易版小游戲,有食物、敵人,甚至像和平精英一樣加了一層外面的毒圈。
游戲操作起來很簡單,用 A S D W 四個鍵控制球的移動方向。
地圖大小是屏幕的16倍,吃完所有敵人就勝利。記住不要被敵人吃掉哦!
效果圖展示:
完整的游戲源代碼如下:
#include#include #include #include #include #define WIDTH 1024 // 屏幕寬 #define HEIGHT 576 // 屏幕高 #define MAPW (WIDTH * 4) // 地圖寬 #define MAPH (HEIGHT * 4) // 地圖高 #define AINUM 100 // AI 數量 #define FNUM 2000 // FOOD 數量 #define PTIME 180 // 毒圈刷新時間 #define DISTANCE(x1, y1, x2, y2) (sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))) struct FOOD { bool eat; COLORREF color; // 顏色 int x, y; // 坐標 char type; }; struct BALL // 定義小球結構 { bool life; // 生命 COLORREF color; // 顏色 int x, y; // 坐標 float r; // 半徑 }; FOOD food[FNUM]; // 食物 BALL mover = { 1, RGB(0, 0, 0), 0, 0, 0 }; // 玩家 BALL ai[AINUM] = { 1, RGB(0, 0, 0), 0, 0, 0 }; // 機器大軍 void move(BALL* ball); // 玩家移動 void draw(); // 繪圖 void start(); // 游戲開始 void setall(); // 初始化數據 void AI(); // AI void Food(); // 食物 void delay(DWORD ms); // 絕對延時 DWORD* pBuffer; // 顯示緩沖區指針 int eaten = 0; // 吃 AI 的數量 int ai_eaten = 0; // AI 吃 AI的數量 int lx = -20, ly = MAPH + 20, rx = MAPW + 20, ry = -20; // 毒的位置 int relx = -20, rely = MAPH + 20, rerx = MAPW + 20, rery = -20; // 毒的位置 float asp = 1; // 縮放因子 float Time = 0; // 時間 int main() { initgraph(WIDTH, HEIGHT); start(); setall(); // 游戲初始化 BeginBatchDraw(); while (true) { move(&mover); // 玩家移動 AI(); Food(); draw(); // 繪圖 FlushBatchDraw(); // 顯示緩存的繪制內容 delay(20); // 絕對延遲 } } void move(BALL* ball) { if (ball->r <= 0) ball->life = false; if (ball->life == false) // 判定游戲是否接束 { HWND hwnd = GetHWnd(); MessageBox(hwnd, _T("你被吃了"), _T("游戲結束"), MB_OK | MB_ICONEXCLAMATION); // 結束 closegraph(); exit(0); } if (eaten + ai_eaten == AINUM) // 是否吃掉所以 AI { HWND hwnd = GetHWnd(); MessageBox(hwnd, _T("恭喜過關"), _T("游戲結束"), MB_OK | MB_ICONEXCLAMATION); // 結束 closegraph(); exit(0); } if (ball->x > (MAPW - ball->r) || ball->x - ball->r < 0 || ball->y - ball->r < 0 || ball->y >(MAPH - ball->r)) ball->r -= 0.1f; 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; // 吃掉 ball->r += (ai[i].r * ai[i].r / 2) / ball->r; // 推理過程: pai * ball->r*ball->r += pai*ai[i].r*ai[i].r; πr*r=πr*r+πai[i].r*ai[i].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(65) & 0x8000) { ball->x -= 2; mx += 2; } //左邊 if (GetAsyncKeyState(87) & 0x8000) { ball->y -= 2; my += 2; } //上面 if (GetAsyncKeyState(83) & 0x8000) { ball->y += 2; my -= 2; } //下面 if (GetAsyncKeyState(68) & 0x8000) { ball->x += 2; mx -= 2; } //右邊 setorigin(mx, my); // 坐標修正 } void AI() { for (int i = 0; i < AINUM; i++) { if (ai[i].r > mover.r) // AI 吃玩家 { if (DISTANCE(mover.x, mover.y, ai[i].x, ai[i].y) < 2 / 3.0 * ai[i].r + mover.r) { ai[i].r += (mover.r * mover.r) / ai[i].r; mover.life = 0; mover.r = 0; } } for (int j = 0; j < AINUM; j++) // AI 吃 AI { if (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) < 4 / 5.0 * ai[i].r + ai[j].r) { ai[i].r += (ai[j].r * ai[j].r) / ai[i].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 靠近 AI { if (ai[i].r > ai[k].r && ai[k].life == 1) { if (DISTANCE(ai[i].x, ai[k].x, ai[i].y, ai[k].y) < min_DISTANCE) { min_DISTANCE = DISTANCE(ai[i].x, ai[k].x, ai[i].y, ai[k].y); min = k; } } } if ((min != -1) && (rand() % 2 == 1)) { if (rand() % 2) { if (ai[i].x < ai[min].x) ai[i].x++; else ai[i].x--; } else { if (ai[i].y < ai[min].y) ai[i].y++; else ai[i].y--; } } 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; } } } } 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; } } } void draw() { clearcliprgn(); setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 20); // 改筆的顏色、狀態 setlinecolor(RGB(0, 100, 0)); line(relx, rely, relx, rery); // 左豎 line(relx, rely, rerx, rely); // 上橫 line(relx, rery, rerx, rery); // 下橫 line(rerx, rery, rerx, rely); // 右豎 setfillcolor(GREEN); if (mover.x - 0.5 * WIDTH / asp < relx) floodfill(relx - 11, mover.y, RGB(0, 100, 0)); if (mover.x + 0.5 * WIDTH / asp > rerx) floodfill(rerx + 11, mover.y, RGB(0, 100, 0)); if (mover.y - 0.5 * HEIGHT / asp < rery) floodfill(mover.x, rery - 11, RGB(0, 100, 0)); if (mover.y + 0.5 * HEIGHT / asp > rely) floodfill(mover.x, rely + 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++) // 畫 AI { if (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 + 0.5)); } setfillcolor(mover.color); // 畫玩家 fillcircle(mover.x * 150 / WIDTH / 4, mover.y * 100 / HEIGHT / 4, int(mover.r / 28 + 0.5)); setlinecolor(RGB(0, 100, 0)); if (lx != rx && ly != rx) { line(lx * 150 / WIDTH, ly * 100 / HEIGHT, lx * 150 / WIDTH, ry * 100 / HEIGHT); // 左豎 line(lx * 150 / WIDTH, ly * 100 / HEIGHT, rx * 150 / WIDTH, ly * 100 / HEIGHT); // 上橫 line(lx * 150 / WIDTH, ry * 100 / HEIGHT, rx * 150 / WIDTH, ry * 100 / HEIGHT); // 下橫 line(rx * 150 / WIDTH, ry * 100 / HEIGHT, rx * 150 / WIDTH, ly * 100 / HEIGHT); // 右豎 } setfillcolor(GREEN); floodfill(lx - 11, ly - 11, 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); // 恢復筆 wchar_t str[32]; swprintf_s(str, L"質量:%.1f 擊殺:%d", mover.r, eaten); settextcolor(BLUE); // 改字體 outtextxy(mover.x - int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT), str); settextcolor(BLUE); // 改字體 outtextxy(mover.x - 36, mover.y - 8, _T("作者:無言")); } void setall() { srand((unsigned)time(NULL)); // 隨機數 mover.color = RGB(rand() % 256, rand() % 256, rand() % 256); // 隨機顏色 mover.life = 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].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("宋體")); } void delay(DWORD ms) // 絕對延時 { static DWORD oldtime = GetTickCount(); while (GetTickCount() - oldtime < ms) Sleep(1); oldtime = GetTickCount(); } void start() { setbkcolor(WHITE); // 白色背景 cleardevice(); // 初始化背景 settextcolor(RED); // 改字體 setbkmode(TRANSPARENT); settextstyle(128, 0, _T("宋體")); outtextxy(40, 20, _T("仿制球球大作戰")); settextstyle(32, 0, _T("宋體")); outtextxy(740, 135, _T("Ver 1.6")); settextcolor(BLUE); // 改字體 outtextxy(304, 240, _T("W上移 S下移 A左移 D右移")); outtextxy(112, 340, _T("躲避大球 追補小球 貪吃食物 增強實力")); settextcolor(BLACK); //改字體 settextstyle(32, 0, _T("宋體")); outtextxy(384, 500, _T("按任意鍵開始游戲")); settextstyle(20, 0, _T("宋體")); outtextxy(810, 10, _T("作者粉絲群: 734106058")); _getch(); }
大家趕緊去動手試試吧!
審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
游戲
+關注
關注
2文章
722瀏覽量
26212 -
C語言
+關注
關注
180文章
7576瀏覽量
133994 -
源碼
+關注
關注
8文章
625瀏覽量
28964 -
C++
+關注
關注
21文章
2084瀏覽量
73298 -
源代碼
+關注
關注
96文章
2942瀏覽量
66440
原文標題:C/C++實現球球大作戰(高仿版),全源碼分享帶你輕松完成!
文章出處:【微信號:cyuyanxuexi,微信公眾號:C語言編程學習基地】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
開學大作戰!元氣加滿不做盧瑟??!
自己要改的缺點向好友公開,總不會厚臉皮不行動吧!只需要登錄人人網找到“惠普電腦”即可啦!努力了才會成為下一個喬布斯!才能成為下一個蓋茨巴菲特!才會成為下一個林書豪!更何況,這樣才會有姑娘喜歡!想要在新學期脫卝光的,想要在考卝試時輕卝松過的,想要在年輕時不做盧瑟的!新學期大作戰,趕緊走起來!
發表于 02-24 16:12
怎樣用C語言(及少量C++)實現火柴人打羽毛球
分享20級同學大一上學期用C語言(及少量C++)實現的火柴人打羽毛球。由于同學們剛學了三個月的編程,實現還不夠完善,工程代碼、圖片音樂素材可
發表于 07-20 07:54
從0開始,181頁知識帶你輕松搞定C++語言
擅長面向對象程序設計的同時,還可以進行基于過程的程序設計,因而C++就適應的問題規模而論,大小由之。 C++不僅擁有計算機高效運行的實用性特征,同時還致力于提高大規模程序的編程質量與程序設計語言的問題描述能力。 這個資料帶你從最
發表于 07-24 13:10
如何使用C語言實現動態擴容的string
眾所周知,C++ 中的string使用比較方便,關于C++ 中的string源碼實現可以看我的這篇文章:源碼分析
如何用C語言實現球球大作戰項目
? 這篇文章主要為大家詳細介紹了 C語言實現——《球球大作戰項目》 ,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參
C++之父新作帶你勾勒現代C++地圖
為了幫助大家解決這些痛點問題,讓大家領略現代C++之美,掌握其中的精髓,更好地使用C++,C++之父Bjarne Stroustrup坐不住了,他親自操刀寫就了這本《C++之旅》!
評論