源碼介紹:https://blog.csdn.net/alzzw/article/details/100043938
#include "stdafx.h"是win32程序系統生成的
創建項目時選擇win32程序項目
除了下面代碼外,無其他改動
#include "stdafx.h"
#include <SDKDDKVer.h>
#include <graphics.h> //圖形庫界面 自己安裝的庫文件
#include <conio.h>
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <math.h>
#define WIDTH 1024 //屏幕的寬
#define HEIGHT 576 //屏幕高
#define MAPW (WIDTH*4)
#define MAPH (HEIGHT*4)
#define AINUM 200 //AI數量
#define FNUM 2000 //食物數量
#define DISTANCE(x1,y1,x2,y2) (sqrt((float)(x1-x2)*(float)(x1-x2)+(float)(y1-y2)*(float)(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 };
DWORD *pBuffer; //顯存指針
//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 eaten = 0; //玩家喫AI的數量
int ai_eaten = 0; //AI喫AI的數量
/*
一款遊戲最基本的要求是什麼?
1.界面
2.數據初始化
3.更改其中的數據
4.判斷數據是否達到一個臨界點
5.退出遊戲
*/
void start();
void setall();
void move(BALL* ball); //如果實參傳入的是地址 形參必定是一個指針變量
void draw();
void AI();
int _tmain(int argc, _TCHAR* argv[])
{
initgraph(WIDTH, HEIGHT);
//遊戲的初始化
start();
setall(); //初始化所有數據
BeginBatchDraw();
while (true)
{
move(&mover);
draw();
AI();
FlushBatchDraw();
Sleep(10);
}
return 0;
}
//AI的位置是否固定 食物的位置又是否固定 隨機出現在任何一個位置的
void setall()
{
srand((unsigned int)time(NULL)); //隨機函數種子
mover.color = RGB(rand() % 256, rand() % 256, rand() % 256); //rand()%256 隨機取值 0-255
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[i].color = RGB(rand() % 256, rand() % 256, rand() % 256); //rand()%256 隨機取值 0-255
ai[i].life= 1;
ai[i].x = rand() % (MAPW - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5); //AI產生的位置不會出現一個越界
ai[i].y = rand() % (MAPH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
ai[i].r = float(rand()%10+10);
}
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, "宋體");
}
void start()
{
setbkcolor(WHITE);
cleardevice();
settextcolor(RED); //函數 設置文字顏色
setbkmode(TRANSPARENT); //設置窗口透明
settextstyle(128, 0, "宋體"); //字符集問題
outtextxy(100, 40, "球球大作戰");
settextstyle(32, 0, "宋體");
outtextxy(384, 500, "按任意鍵開始遊戲");
getch();
}
void move(BALL* ball)
{
if (ball->r <= 0) ball->life = false; //false 0 true 1
if (ball->life == false)
{
HWND hwnd = GetHWnd(); //獲取窗口句柄
MessageBox(hwnd, "你已經死亡", "遊戲結束", 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;
//玩家喫AI
for (int i = 0; i < AINUM; i++)
{
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 += (ai[i].r*ai[i].r / 2) / ball->r;
eaten++;
}
}
}
//食物被喫
for (int n = 0; n < FNUM; n++)
{
if (food[n].eat == 0) continue;
if (DISTANCE((float)ball->x, (float)ball->y, (float)food[n].x, (float)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 -= 3, mx += 3; } //獲取鍵盤的值
if (GetAsyncKeyState(87) & 0x8000) { ball->y -= 3, my += 3; }
if (GetAsyncKeyState(83) & 0x8000) { ball->y += 3, my-= 3; }
if (GetAsyncKeyState(68) & 0x8000) { ball->x += 3, mx -= 3; }
/*awsd*/
setorigin(mx, my); //座標修正
}
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;
}
}
//畫出AI
for (int i = 0; i < AINUM; i++)
{
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++)
{
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));
SetWorkingImage(); //恢復之前的繪圖界面
putimage(mover.x + int(0.5*WIDTH) - 150, mover.y - int(0.5*HEIGHT), 150, 100, &map, 0, 0);
}
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) < 2 / 3.0*ai[i].r + mover.r)
{
ai[i].r += (mover.r*mover.r) / ai[i].r;
mover.life = 0;
mover.r = 0;
}
}
//AI喫AI
for (int j = 0; j < AINUM;j++)
{
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_eaten++;
}
}
}
double min_DISTANCE = 100000;
int min = -1;
//AI靠近AI
for (int k = 0; k < AINUM; k++)
{
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 += 2;
else ai[i].x-=2;
}
else
{
if (ai[i].y < ai[min].y) ai[i].y += 2;
else ai[i].y -= 2;
}
}
for (int n = 0; n < FNUM; n++)
{
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;
}
}
}
}