C/C++編程筆記:C語言開發球球大作戰(源碼分享),你想試試嗎?

来源:https://www.cnblogs.com/yxy6/archive/2020/07/10/13281834.html
-Advertisement-
Play Games

游戲背景 《球球大作戰》是Superpop一款自主研du發的免費手機網路游戲。 以玩家間的實時互動PK產生游戲樂趣為設計宗旨,通過簡單的規則將玩家操作直接轉化為游戲策略,體驗智謀碰撞的戰鬥樂趣。 游戲的基本操作包括鍵盤按下(上下左右四個方向,還有作弊測試按鍵空格鍵和A鍵),玩家可以在地圖上隨意移動, ...


游戲背景

《球球大作戰》是Superpop一款自主研du發的免費手機網路游戲。 以玩家間的實時互動PK產生游戲樂趣為設計宗旨,通過簡單的規則將玩家操作直接轉化為游戲策略,體驗智謀碰撞的戰鬥樂趣。   

游戲的基本操作包括鍵盤按下(上下左右四個方向,還有作弊測試按鍵空格鍵和A鍵),玩家可以在地圖上隨意移動,不過不能超出邊界。不管是玩家還是AI都可以吃比自己小的球,反之也可以被吃,吃掉之後直徑會增大,增大演算法是被吃掉的半徑的1/4。如果玩家被吃掉,會在任意地方重新開始。

那麼今天,我們就用C語言,來寫出我們的球球大作戰,一起來看看吧!

效果展示

游戲步驟

球球大作戰游戲分為幾個步驟:

①使用自定義空白圖片表示地圖;②繪製玩家,食物;③處理玩家移動,以及吃食物判斷;④繪製一個AI並實現其移動;

話不多說,接下來我們之間來看我們的代碼吧!需要素材以及相關資料源碼可以關註微信公眾號輸入關鍵詞領取,那先來看看代碼吧!

源碼分享

#include<graphics.h> //包含easyx圖形庫文件
#include<time.h>     //C語言時間頭文件
#include<mmsystem.h>//win32多媒體設備介面文件
#pragma comment(lib,"winmm.lib")//win32多媒體設備介面庫
#define WIN_WIDTH  1024  //屏幕的寬
#define WIN_HEIGHT 640//576   //屏幕高
#define MAP_WIDTH  (WIN_WIDTH*3) //地圖寬度
#define MAP_HEIGHT (WIN_HEIGHT*3)//地圖高度
#define FOOD_NUM 500  //食物數量
#define AI_NUM 200    //ai數量
IMAGE map(MAP_WIDTH, MAP_HEIGHT);
POINT  g_CameraPos;      // 攝像機(屏幕左上角)在地圖上的位置
struct Ball
{
    bool    flag;    // 是否被吃 活 1,死 0
    COLORREF  color;    // 顏色
    float    r;      //
    float    x;      // 坐標
    float    y;
    int      type;       //食物獨有屬性,決定是什麼類型的食物(圓?矩形?多邊形?)
};
struct Ball mover; //玩家
struct Ball food[FOOD_NUM]; //食物數組
struct Ball ai[AI_NUM]; //AI數量
void ChaseAlgorithom(Ball *chase, Ball *run);
float DisTance(Ball b1, Ball b2);
void Gameinit()
{
    //設置隨機數種子
    srand((unsigned)time(NULL));
    //播放背景音樂
    mciSendString("open BallGame.mp3 alias bk", 0, 0, 0);
    mciSendString("play bk repeat", 0, 0, 0);
    //初始化食物
    for (int i = 0; i < FOOD_NUM; i++)
    {
        food[i].x = (float)(rand() % MAP_WIDTH);
        food[i].y = (float)(rand() % MAP_HEIGHT);
        food[i].r = (float)(rand() % 5 + 1);
        food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);  // 隨機顏色
        food[i].flag = 1;
        food[i].type = rand() % 3;
    }
    //初始化AI
    for (int i = 0; i < AI_NUM; i++)
    {
        ai[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);   //rand()%256  隨機取值 0-255
        ai[i].flag = 1;
        ai[i].x = rand() % (MAP_WIDTH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);   //AI產生的位置不會出現一個越界
        ai[i].y = rand() % (MAP_HEIGHT - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
        ai[i].r = float(rand() % 10 + 10);
    }
    {//初始化玩家數據
        mover.color = BLUE;
        mover.r = 10;
        //玩家在視窗的位置
        mover.x = rand() % WIN_WIDTH;
        mover.y = rand() % WIN_HEIGHT;
        mover.flag = 1;
    }
}
//游戲地圖開始繪製位置判斷
void computeCameraPos()
{
    // 以人物位置為中心計算攝像機的理論位置
    g_CameraPos.x = mover.x - WIN_WIDTH / 2;
    g_CameraPos.y = mover.y - WIN_HEIGHT / 2;

    // 防止攝像機越界
    if (g_CameraPos.x < 0)    g_CameraPos.x = 0;
    if (g_CameraPos.y < 0)    g_CameraPos.y = 0;
    if (g_CameraPos.x > MAP_WIDTH - WIN_WIDTH)  g_CameraPos.x = MAP_WIDTH - WIN_WIDTH;
    if (g_CameraPos.y > MAP_HEIGHT - WIN_HEIGHT)  g_CameraPos.y = MAP_HEIGHT - WIN_HEIGHT;
}
//游戲繪製
void Gamedraw()
{
    SetWorkingImage(&map);
    setbkcolor(WHITE);          // 白色背景
    cleardevice();
    //畫食物
    for (int i = 0; i < FOOD_NUM; i++)
    {
        if (food[i].flag == 1)
        {
            setfillcolor(food[i].color);
            if (food[i].type == 0)
            {
                solidellipse((int)food[i].x, (int)food[i].y, (int)(food[i].x + food[i].r), (int)(food[i].y + food[i].r));
            }
            else if (food[i].type == 1)
            {
                solidpie((int)food[i].x, (int)food[i].y, (int)(food[i].x + food[i].r), (int)(food[i].y + food[i].r), 0.0, 1.5);
            }
            else
            {
                solidcircle(int(food[i].x), int(food[i].y), int(food[i].r));
            }
        }
        else
        {
            food[i].x = (float)(rand() % MAP_WIDTH);
            food[i].y = (float)(rand() % MAP_HEIGHT);
            food[i].r = (float)(rand() % 5 + 1);
            food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);  // 隨機顏色
            food[i].flag = 1;
            food[i].type = rand() % 3;
        }
    }
    //畫AI
    for (int i = 0; i < AI_NUM; i++)
    {
        if (ai[i].flag == 1)
        {
            setfillcolor(ai[i].color);
            solidcircle(ai[i].x, ai[i].y, ai[i].r);
        }
        else
        {
            ai[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);   //rand()%256  隨機取值 0-255
            ai[i].flag = 1;
            ai[i].x = rand() % (MAP_WIDTH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);   //AI產生的位置不會出現一個越界
            ai[i].y = rand() % (MAP_HEIGHT - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
            ai[i].r = float(rand() % 10 + 10);
        }
    }
    //繪製玩家
    setfillcolor(RED);
    fillcircle(mover.x, mover.y, mover.r);
    //繪製玩家名稱
    settextcolor(BLACK);
    setbkmode(TRANSPARENT);
    settextstyle(20, 0, "楷體");
    char pname[] = "微信公眾號:C語言編程學習基地";
    int twidth = textwidth(pname) / 2;//計算文字寬度為了居中顯示在玩家中央
    outtextxy(mover.x - twidth, mover.y, pname);
    //恢復預設工作區,即視窗
    SetWorkingImage();
    //更新攝像機位置
    computeCameraPos();
    //把地圖顯示到視窗上
    putimage(0, 0, WIN_WIDTH, WIN_HEIGHT, &map, g_CameraPos.x, g_CameraPos.y);
}
//玩家移動,參數為玩家移動的速度(單位像素)
void Gamemove(int speed)
{
    //獲取鍵盤按鍵
    if (GetAsyncKeyState(VK_UP) & 0x8000)
    {
        if (mover.y - mover.r > 0)
        {
            mover.y -= speed;
        }
    }
    if (GetAsyncKeyState(VK_DOWN) & 0x8000)
    {
        if (mover.y + mover.r < MAP_HEIGHT)
        {
            mover.y += speed;
        }
    }
    if (GetAsyncKeyState(VK_LEFT) & 0x8000)
    {
        if (mover.x - mover.r > 0)
        {
            mover.x -= speed;
        }
    }
    if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
    {
        if (mover.x + mover.r < MAP_WIDTH)
        {
            mover.x += speed;
        }
    }
    //作弊測試,按空格不斷增大,A縮小
    if (GetAsyncKeyState(VK_SPACE) & 0x8000)
    {
        mover.r += 3;
    }
    if (GetAsyncKeyState('A') & 0x8000)
    {
        if (mover.r > 1)
            mover.r -= 1;
    }
}
//玩家吃食物
void EatFood()
{
    for (int i = 0; i < FOOD_NUM; i++)
    {
        if (food[i].flag == 1 && DisTance(food[i], mover) < mover.r)
        {
            food[i].flag = 0;
            mover.r += food[i].r / 4;
        }
    }
}
//玩家吃Ai,Ai吃玩家
void EatAi()
{
    for (int i = 0; i < AI_NUM; i++)
    {
        if (ai[i].flag == 0)
            continue;
        //玩家吃Ai
        if (DisTance(ai[i], mover) < mover.r - ai[i].r / 3)
        {
            ai[i].flag = 0;
            mover.r += ai[i].r / 4;
            break;//吃到一個就退出
        }
        //ai吃玩家
        else if (DisTance(ai[i], mover) < ai[i].r - mover.r / 3)
        {
            mover.x = rand() % MAP_WIDTH;
            mover.y = rand() % MAP_HEIGHT;
            ai[i].r += mover.r / 4;
            mover.r = 10;
            break;
        }
    }
}
//AI吃食物,AI吃Ai
void AiEatFood()
{
    for (int i = 0; i < AI_NUM; i++)
    {
        if (ai[i].flag == 0)
            continue;
        //ai吃食物
        for (int j = 0; j < FOOD_NUM; j++)
        {
            if (food[j].flag == 1 && DisTance(ai[i], food[j]) < ai[i].r)
            {
                food[j].flag = 0;
                ai[i].r += food[i].r / 4;
            }
        }
        //Ai吃Ai
        for (int k = i + 1; k < AI_NUM; k++)
        {
            if (ai[k].flag == 1)
            {
                if (DisTance(ai[i], ai[k]) < ai[k].r - ai[i].r / 3)
                {
                    ai[i].flag = 0;
                    ai[k].r += ai[i].r / 4;
                }
                else if (DisTance(ai[i], ai[k]) < ai[i].r - ai[k].r / 3)
                {
                    ai[k].flag = 0;
                    ai[i].r += ai[k].r / 4;
                }
            }

        }
    }
}
//Ai移動演算法,追逐比自己半徑小的球
void AiMove()
{
    for (int i = 0; i < AI_NUM; i++)
    {
        double min_DISTANCE = MAP_WIDTH;//最大搜索距離
        int min = -1;//用來保存找到目標小球的下標
        if (ai[i].flag == 1)
        {
            //AI靠近AI
            for (int k = i + 1; k < AI_NUM; k++)
            {
                if (ai[i].r > ai[k].r&&ai[k].flag == 1)
                {//如果能吃,且距離達到要求則更新距離,並保存下標
                    if (DisTance(ai[i], ai[k]) < min_DISTANCE)
                    {
                        min_DISTANCE = DisTance(ai[i], ai[k]);
                        min = k;
                    }
                }
            }
        }
        //如果找到目標,則去追逐
        if ((min != -1))
        {
            ChaseAlgorithom(&ai[i], &ai[min]);
        }

    }
}
void  JudeEat()
{
    EatFood();
    EatAi();
    AiEatFood();
    AiMove();
}
int main()
{
    initgraph(WIN_WIDTH, WIN_HEIGHT, 1);
    Gameinit();
    DWORD t1, t2;
    t1 = t2 = GetTickCount();
    while (1)
    {
        Gamedraw();
        Gamemove(1);
        if (t2 - t1 > 50)
        {
            JudeEat();
            t1 = t2;
        }
        t2 = GetTickCount();
    }

    getchar();
    closegraph();
    return 0;
}

//追逐演算法
void ChaseAlgorithom(Ball *chase, Ball *run)
{
    if (rand() % 2 == 0)
    {
        if (chase->x < run->x)
        {
            chase->x += 2;
        }
        else
        {
            chase->x -= 2;
        }
    }
    else
    {
        if (chase->y < run->y)
        {
            chase->y += 2;
        }
        else
        {
            chase->y -= 2;
        }
    }
}
//求兩點之間的距離
float DisTance(Ball b1, Ball b2)
{
    return sqrt((b1.x - b2.x)*(b1.x - b2.x) + (b1.y - b2.y)*(b1.y - b2.y));
}

以上就是本篇文章的全部分享,希望對大家有幫助!

自學C/C++編程難度很大,不妨和一些志同道合的小伙伴一起學習成長!

C語言C++編程學習交流圈子,【點擊進入】微信公眾號:C語言編程學習基地

有一些源碼和資料分享,歡迎轉行也學習編程的伙伴,和大家一起交流成長會比自己琢磨更快哦!




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 沒有基礎怎麼學Web前端?相關學習路線是什麼?隨著互聯網的迅猛發展,互聯網項目對用戶體驗提出了更高的要求,Web前端開發人員成為了重要的研發角色。很多人想要快速加入前端開發這一高薪行列,對於想要學習Web前端的人而言,小編建議你做好以下準備。 1、多多實踐練習 代碼是程式員日常生活的重要組成部分,很 ...
  • 本文大部分問題來源:50道CSS基礎面試題(附答案),外加一些面經。 我對問題進行了分類整理,並給了自己的回答。大部分知識點都有專題鏈接(來源於本博客相關文章),用於自己前端CSS部分的查漏補缺。雖作為一個面試資料,但感覺也能幫助前端新手梳理CSS的知識點。 開胃餐-兩道常見考題 盒子模型 樣式與選 ...
  • 1.前端崗位飽和了? 隨著互聯網和移動終端的普及,雨後春筍般的互聯網項目的發展,用戶對於用戶體驗的需求不斷提升,前端工程師逐漸成為介於視覺工程師和後端工程師之間必不可少的角色,備受大家的追捧和關註。 隨著前端工程師崗位的發展,近期,網上不斷傳出前端工程師崗位飽和的言論。網上有人抱怨說,前端工程師人太 ...
  • 轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 原文出處:https://blog.bitsrc.io/es2020-has-been-finalized-here-is-what-im-excited-about-414959bc2f7f 最近這幾年,隨 ...
  • 題庫管理 22. 圖片庫:創建文件目錄,維護圖片,供題庫選擇調用 23. 單選題:維護單選試題,試題題目,選項,答案,類型,級別,狀態,解析 24. 多選題:維護多選試題,試題題目,選項,答案,類型,級別,狀態,解析 25. 判斷題:維護判斷試題,試題題目,答案,類型,級別,狀態,解析 26. 填空 ...
  • 簡介 AQS(AbstractQueuedSynchronizer)是併發開發中一個基礎組件。主要實現了同步狀態管理、線程隊列管理、線程等待、線程喚醒等底層操作。JDK中許多的併發類都是依賴AQS的。 ReentrantLock(可重入鎖)、Semaphore(信號量)、CountDownLatch ...
  • 寫在前面的話 第一次用博客園,正好要複習下Python,就在隨筆這裡記錄下我學習的知識點和心得,順帶著學習下寫博客的方法。(p≧w≦q) 博客主要還是記錄整理評價我寫過的課程設計和一些演算法。 話說真的有人會看到嘛 இ௰இ 第一章 Python語言概述 電腦常用數制和編碼 數制 任何的信息必須轉化成 ...
  • 【創建虛擬環境】 命令:mkvirtualenv 名字 -p /usr/bin/python3 # 配置環境 退出虛擬環境 deactivate 進入虛擬環境 workon 虛擬環境名稱 刪除虛擬環境 rmvitualenv 虛擬環境名稱 進入環境後:pip freeze #顯示環境中的應用 安裝D ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...