IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> ★「C++游戏」BattleOfPhantom:大乱斗游戏升级版 -> 正文阅读

[C++知识库]★「C++游戏」BattleOfPhantom:大乱斗游戏升级版

(原创)
目前正在不断更新!

★ 一款超级有趣的大乱斗游戏,包含多种游戏模式,支持双人联机。
离线情况下也可以与多个(或一群)机器玩家进行疯狂的对战
直接上图
幻影之战标题画面

使用C++ with EGE图形库编写
有一定数量的BUG,请谅解。

双人离线模式下的一张截图
[ 双人离线的一张截图 ]

操作说明

A,W,S,D | 主玩家移动
1/2/3/4 | 主玩家选择武器或道具
J | 主玩家向面前方向攻击
Backspace | 主玩家删除当前武器或道具(注意:装备是靠刷新更好的,不能删)
鼠标左键 | 向鼠标方向攻击(非常方便),将被识别成八个方向之一(双人离线为了平等不能使用)

↑←↓→ | 双人离线时玩家2的移动
小键盘1/2/3/4 | 双人离线时玩家2选择武器或道具
小键盘5 | 双人离线时玩家2向面前方向攻击
Delete | 双人离线时玩家2删除当前武器或道具

F2 | 立即窗口截图,存入Screenshots文件夹中
Esc | 退出战斗

基本玩法

比如说人机离线对战模式(是可以使用鼠标攻击的),
开局就先随机获得两把武器,两个道具,没有装备。
你可以通过右侧的对方方位与距离锁定敌人的位置进行有效攻击。
机器玩家的算法还说得过去,有时真难弄死它。
人机对战的一张截图
[↑ 人机对战的一张截图 ]
普通模式下一般都是300滴血,只有比较容易死的模式会1000血甚至5000血。(自己探索)
有些武器带效果的,要注意防护与使用:
效果数据
有些剑是带剑气的;
有些弹药是会反弹/爆炸/分裂/追踪(分为3种等级)/穿墙的。
实体属性(局部)
武器千奇百怪,战斗场面琳琅满目:
混战模式的一张截图
[↑ 混战模式的一张截图 ——那个血量不是正常的血量,请忽视 ]
群殴模式是很难挺过去的,你可以尝试一下!!
群殴模式的一张截图
群殴模式会给你1000血加上长时间的矫捷效果与永久的穿人特权。就算这样也能死得很惨。
诀窍是不断逃跑,让他们自己误伤。逃跑的时候注意安全。

  • 离线团战的话一定要把对方所有人消灭,但自己死了就算失败了。
  • 作为红队头领,一定要学会保护自己!
    离线团战的一张截图
    右侧将会有两队活人数数据。

最后关于联机:

  • 在线模式下服务端开启后,客户端依次输入服务端IP地址和端口号即可
    (若无外网则必须同一局域网下)
    配置外网时映射的IP需要是服务端开启后显示的IP(也就是服务端电脑第一个能用的IP)
    服务端

  • 端口号一律填8888.
    使用外网时,在输入IP地址界面不得输入域名。
    客户端输入的端口号是映射后的端口号(一般是五位数而不是8888)
    需要使用IP地址。获取其IP地址可以通过ping命令获得:
    Win+R打开运行,输入cmd
    ping命令获取外网IP地址

  • 联机的时候经常会崩溃,应该是这个TCP连接太差劲的缘故,也么有办法,因此我尽量减少机器玩家的数量。凑合着玩吧。不要使用频率极高的武器,因为更容易致使崩溃。

这款游戏已经写了一年左右了,祝愿大家玩得愉快
源码真的很长(快一万行了)真的想要的话(也不给 XD )
无源码的游戏链接: https://download.csdn.net/download/cjz2005/86287023

★★★

为了造福广大苍生,我决定放一点源码给大家看看!
这是机器玩家的AI算法,原创,还行,有兴趣的同志可以好好研究一下。

//Dir Modes
#define DIR_NONE 0x00
#define DIR_4 0x01
#define DIR_8 0x02

//AI Modes
#define AAM_STILL 0		//静止
#define AAM_WANDER 1	//多逛
#define AAM_CHASE 2		//多追
#define AAM_FLEE 3		//多逃

//Constants
#define AA_CHANGE_MODE_RATE 25			//模式更改机率
#define AA_CHANGE_MODE_MIN_T 1000*6	//模式更改最小周期
#define AA_CHANGE_WEAPON_RATE 32			//武器切换概率
#define AA_CHANGE_WEAPON_MIN_T 1000*8	//武器切换最小周期
#define AA_LEVEL_UP_T 1000*43		//等级提升周期
#define AA_DRINK_POTION_RATE 8		//喝药水概率
#define AA_DODGE_BASE_RATE 13	//基础闪避概率
#define AA_DODGE_RATE_MAX 60	//闪避概率最大值
#define AA_DODGE_UP_RATIO 0.5	//闪避提升率
#define AA_DODGE_T 1000*0.9		//闪避周期
#define AA_EXTRA_DODGE_RATE_T 1000*65	//闪避概率微调周期
#define AA_CHANGE_TARGET_MIN_T 11000	//目标切换最小周期 
#define AA_CHANGE_TARGET_RATE 8		//目标切换概率 
#define AA_REVENGE_RATE 40		//复仇概率

class AIControl {	//AI控制玩家算法
public:
	bool enabled;	//是否启用 
	
	int my_index;		//附着玩家下标 
	int target_index;	//目标玩家下标(可变) 
	int team_index;		//队伍下标
	
	clock_t lastModeChanged;	//上一次切换模式 
	clock_t lastWeaponChanged;	//上一次切换武器 
	clock_t lastChangeTarget;	//上一次切换攻击目标 
	clock_t lastUp;				
	clock_t lastDodge;			//上一次闪避 
	clock_t lastExtraRateChanged;	//上一次改变额外躲闪率 
	int extraDodgeRate;		//额外躲闪率 
	int mode;		//AI模式 
	int xp;		//经验值
	BYTE extraMode;		//作弊额外模式 
	float adjust;
	const vector<int> mode_prob = { 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3 };	//带比重
	const vector<int> curw_prob = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3 };	//带比重

	AIControl()
	{
		target_index = 0;	//默认主角为目标
		team_index = 0;
		adjust = 0;
		enabled = false;
		Init();
	}
	void Init()	//initialize
	{
		my_index = 1;	//<!>
		target_index = 0;	//默认主角为目标
		extraDodgeRate = 0;
		extraMode = AAE_NONE;
		mode = AAM_CHASE;
		lastModeChanged = clock() + 5000;
		lastWeaponChanged = clock();
		lastExtraRateChanged = clock();
		lastChangeTarget = clock();
		lastUp = clock();
		lastDodge = clock();
		xp = 0;
		adjust = (GetPlayerCount() * 5 + 10101 + RandomRange(0, 100, true, false)) % 100 / 100.0;
	}
	void Close()	//关闭 
	{
		enabled = false;
		mode = AAM_STILL;
		xp = 0;
		target_index = 0;
	}
	void Update()	//更新
	{
		if (!enabled || !IsPlayerAlive(my_index))	//未启用状态或死亡状态直接退出 
			return;

		CheckLevelUp();
		int r;
		//离线模式下,玩家2成为AI玩家
		//在线模式下,自己成为AI玩家(自动攻击)
		r = RandomRange(0, 100, true, false);	//percent
		if (r > 100 - AA_CHANGE_MODE_RATE - adjust*6 && (clock() - lastModeChanged > AA_CHANGE_MODE_MIN_T))
		{
			mode = mode_prob.at(RandomRange(0, mode_prob.size() - 1, true, true));
			lastModeChanged = clock();
		}
		if (clock() - lastExtraRateChanged > AA_EXTRA_DODGE_RATE_T)
		{
			extraDodgeRate = Varience(0, 5+adjust*6);
			lastExtraRateChanged = clock();
		}
		Move();		//根据模式进行移动
		if (clock() - lastDodge > AA_DODGE_T + adjust * 3)
		{
			TryToDodge();	//checking inside
		}
		if (g_bIdt != IDT_OFFLINE)
		{
			if(GetDirMode(GetPlayerCurWeapon(my_index)) == DIR_8)
				GetPlayerFace(my_index) = FaceDir8(target_index);
			else
				GetPlayerFace(my_index) = FaceDir4(target_index);
		}
		
#ifndef AI_CONCENTRATE
		if(g_mode != 0 && g_mode != 1 && g_mode != 2 	//就两个玩家时无需切换 
			&& g_mode != 3	//离线群殴始终只有一个目标
		&& (!IsPlayerAlive(target_index)	//目标死了就赶紧换目标 没有CD和概率要求
			|| (
		RandomRange(0,100,true,false) < AA_CHANGE_TARGET_RATE + adjust * 9	//还有概率 
		&& clock() - lastChangeTarget >= AA_CHANGE_TARGET_MIN_T)))
		{	//切换目标 
			int new_target_index = this->target_index;
			int min_dist = 9999;
			for(int i = 0; i < GetPlayerCount(); ++i)
			{
				if (!IsPlayerAlive(i) || i == my_index)
					continue;
				if ((g_mode == 5 || g_mode == 9)
					&& GetPlayerTeam(i) == team_index)
				{	//团战时 放过队友
					continue;
				}
				if ((g_mode == 6 || g_mode == 7) && i != 0 && i != 1)
					continue;	//在线群殴只能以人为目标
				auto _dist = Distance(GetX(),GetY(),GetPlayerX(i),GetPlayerY(i));
				if(_dist < min_dist)
				{
					new_target_index = i;
					min_dist = _dist;
				}
			}
			this->target_index = new_target_index;
			/*if(mode != AAM_CHASE && RandomRange(0,100,true,false) < AA_CHANGE_MODE_RATE + adjust * 8)
			{	//追赶加强
				this->mode = AAM_CHASE;
			}*/
		}
#endif
		if (RandomRange(0, 100, true, false) < 20 + adjust * 10)
			this->mode = AAM_CHASE;
		Attack();	//根据模式进行攻击
	}
	void CheckLevelUp()
	{
		if (clock() - lastUp > AA_LEVEL_UP_T)
		{
			int upv = 1;	//升级默认1级
			if (GetPlayerHp(my_index) > 1 && GetPlayerHp(target_index) > GetPlayerHp(my_index) * 1.8)
				upv = 2;	//当血量差得太远的时候,升级加速
			xp += upv; 
			lastUp = clock();
		}
	}
	void OnHurt(int hurt_by)	//受伤时调用
	{
		if(!enabled)
		    return;
		lastUp += 1000 * RandomRange(0,3,true,true);	//经验有增长的趋势
		if(mode == AAM_STILL || mode == AAM_WANDER)		//迅速进入正常状态
			lastModeChanged += 1000 * 4 + adjust * 100;
		if (PlayerHasAffect(my_index,3) || PlayerHasAffect(my_index,7) || PlayerHasAffect(my_index,11) || PlayerHasAffect(my_index,12))
		{
			extraDodgeRate += RandomRange(5, 9 + adjust * 2, true, false);	//躲闪率微调
		}
		else {
			extraDodgeRate += RandomRange(4, 7 + adjust * 2, true, false);	//躲闪率微调
		}

		if (hurt_by != my_index && hurt_by != target_index	//非我非你
			&& (g_mode == 5 || g_mode == 9) || (GetPlayerTeam(hurt_by) != team_index)	//异队
			&& g_mode != 3 //<!>离线群殴没有复仇;在线群殴还是有复仇的
			)
		{
			if (RandomRange(0, 100, true, false) < AA_REVENGE_RATE)
			{	//复仇
				target_index = hurt_by;
			}
		}
	}
	DIR FaceDir8(int i) const
	{
		POINT et{GetPlayerX(i),GetPlayerY(i)};
		if (IsOuttaField(POINT2(et.x, et.y)))
			return 0;
		int x = GetX();
		int y = GetY();
		int ex = GetPlayerX(target_index); 
		int ey = GetPlayerY(target_index); 
		if (x < ex)
		{
			if (y > ey)	return RIGHTUP;
			else if (y < ey)	return RIGHTDOWN;
			else	return RIGHT;
		}
		else if (x > ex)
		{
			if (y > ey)	return LEFTUP;
			else if (y < ey)	return LEFTDOWN;
			else	return LEFT;
		}
		else {
			if (y > ey)	return UP;
			else	return DOWN;
		}
	}
	DIR FaceDir4(int i) const
	{
		POINT et{GetPlayerX(i),GetPlayerY(i)};
		if (IsOuttaField(POINT2(et.x, et.y)))
			return 0;
		int x = GetX();
		int y = GetY();
		int ex = GetPlayerX(target_index); 
		int ey = GetPlayerY(target_index); 
		if (ex > x)
		{
			if (ey > y)
				return (abs(ex - x) > abs(ey - y) ? (RandomRange(1, 10) > 7 ? RIGHT : DOWN) : (RandomRange(1, 10) > 7 ? DOWN : RIGHT));
			else if (ey < y)
				return (abs(ex - x) > abs(ey - y) ? (RandomRange(1, 10) > 7 ? RIGHT : UP) : (RandomRange(1, 10) > 7 ? UP : RIGHT));
			else
				return RIGHT;
		}
		else if (ex < x)
		{
			if (ey > y)
				return (abs(ex - x) > abs(ey - y) ? (RandomRange(1, 10) > 7 ? LEFT : DOWN) : (RandomRange(1, 10) > 7 ? DOWN : LEFT));
			else if (ey < y)
				return (abs(ex - x) > abs(ey - y) ? (RandomRange(1, 10) > 7 ? LEFT : UP) : (RandomRange(1, 10) > 7 ? UP : LEFT));
			else
				return LEFT;
		}
		else {
			if (ey > y)
				return DOWN;
			else
				return UP;
		}
	}
	UINT GetI() const {			//获取下标
		/*if (enabled == false)
			return 2;	//无
		else if (g_bIdt == IDT_OFFLINE)
			return 1;
		else
			return g_p_i;*/
		return my_index;
	}
	UINT GetOppoI() const {
		return target_index;	
	}
	int GetX() const
	{
		return GetPlayerX(GetI());
	}
	int GetY() const
	{
		return GetPlayerY(GetI());
	}
	void _Tag(string text) const
	{
		setcolor(WHITE);
		setbkmode(OPAQUE);
		setfont(20, 0, "微软雅黑");
		xyprintf(20, 500, "TAG:%s", text.c_str());
	}
	void Move()
	{
		EXCEPTION_L
		//debug _Tag("Move");

		/*if (mode == AAM_STILL)
		{
			return;
		}
		else */
		if (mode == AAM_WANDER)
		{
			if (!PlayerTimeToMove(my_index))
				return;
			DIR dir;
			int x, y;
		_retry:
			dir = 2 * RandomRange(1, 4, true, true) - 1;
			x = GetX();
			y = GetY();
			if (PlayerHasAffect(GetI(), 12))
				dir = OppoDir(dir);
			DirOffsetPos(x, y, dir, "AIControl::Move");
			if (IsOuttaField(POINT2(x,y)) || 
				IsBarrier(bk(x, y, "AIControl::Move")))
			{
				goto _retry;
			}
			//Move
			GetPlayerX(my_index) = x;
			GetPlayerY(my_index) = y;
			bool sendMsg = (g_bIdt != IDT_OFFLINE);
			if (sendMsg)
				SendTCP(UM_SETPOS, x, y, GetI());
//			p[GetI()].lastMove = clock();
			LastMove(my_index);
		}
		else if (mode == AAM_CHASE || mode == AAM_FLEE 
			|| mode == AAM_STILL)
		{
			if (!PlayerTimeToMove(my_index))
				return;
			int x = GetX();
			int y = GetY();
			int ex = GetPlayerX(target_index);
			int ey = GetPlayerY(target_index);
			DIR xd, yd;

			if (ex > x)
				xd = RIGHT;
			else if (ex < x)
				xd = LEFT;
			else
				xd = 0;
			if (ey > y)
				yd = DOWN;
			else if (ey < y)
				yd = UP;
			else
				yd = 0;

			int r = RandomRange(0, 1, true, true);
			DIR dir;	//final dir
			if (xd == RIGHT)
			{
				if (yd == 0)
					dir = RIGHT;
				else {
					dir = (r ? RIGHT : yd);
				}
			}
			else if (xd == LEFT)
			{
				if (yd == 0)
					dir = LEFT;
				else {
					dir = (r ? LEFT : yd);
				}
			}
			else {
				dir = yd;
			}
			if (mode == AAM_FLEE)	//相反逃离
				dir = OppoDir(dir);
			if (PlayerHasAffect(GetI(), 12))
				dir = OppoDir(dir);	//混沌效果 直接再反
			
			//Move(CHASE)
			DirOffsetPos(x, y, dir,"AIControl::Move");
			if (!IsOuttaField(POINT2(x, y)) &&
				!IsBarrier(bk(x,y,"AIControl::Move")) && 
				//!(x == ex && y == ey)	&&	//不能与对方重叠
				!HasPlayerTouch(my_index,dir)	//不能与别的玩家重叠
				)	
			{
				if (mode != AAM_STILL)
				{
					bool sendMsg = (g_bIdt != IDT_OFFLINE);
					GetPlayerX(my_index) = x;
					GetPlayerY(my_index) = y;
					if (sendMsg)
						SendTCP(UM_SETPOS, x, y, GetI());
				}
				GetPlayerFace(my_index) = dir;
//				p[GetI()].lastMove = clock();
				LastMove(my_index);
				//return;
			}else
				LastMove(my_index);
		}
		else {

		}

		EXCEPTION_R_TITLED("BOP AIControl::Move EXCEPTION")
	}
	DIR GetComingDir(const Entity& et) const
	{
		if (IsOuttaField(POINT2(et.x, et.y)))
			return 0;
		int x = GetX();
		int y = GetY();
		int ex = GetPlayerX(target_index);
		int ey = GetPlayerY(target_index);
		DIR eface = et.face;
		if (eface == RIGHT && y == ey && x > ex)
			return LEFT;
		else if (eface == LEFT && y == ey && x < ex)
			return RIGHT;
		else if (eface == DOWN && x == ex && y > ey)
			return UP;
		else if (eface == UP && x == ex && y < ey)
			return DOWN;
		else if (eface == LEFTDOWN && (x - ex < 0) && (x - ex) / float(y - ey) == -1.0f)
			return RIGHTUP;
		else if (eface == LEFTUP && (x - ex < 0) && (x - ex) / float(y - ey) == 1.0f)
			return RIGHTDOWN;
		else if (eface == RIGHTDOWN && (x - ex > 0) && (x - ex) / float(y - ey) == 1.0f)
			return LEFTUP;
		else if (eface == RIGHTUP && (x - ex > 0) && (x - ex) / float(y - ey) == -1.0f)
			return LEFTDOWN;
		else
			return 0;
	}
	void TryToDodge()
	{	//尝试躲闪 
		if (entities.empty())
			return;

		int x = GetX();
		int y = GetY();
		int dp;
		int r;
		dp = Varience(AA_DODGE_BASE_RATE,4)	//基础也在变动
			+ xp * AA_DODGE_UP_RATIO 
			+ adjust * 3
			+ extraDodgeRate;
		//各种效果对其的影响
		if (PlayerHasAffect(my_index, 6))
			dp -= 4;
		if (PlayerHasAffect(my_index, 7))
			dp -= 3;
		if (PlayerHasAffect(my_index, 9))
			dp -= 6;
		if (PlayerHasAffect(my_index, 11))
			dp -= 10;
		else if (PlayerHasAffect(my_index, 12))
			dp -= 9;
		if (PlayerHasAffect(my_index, 1))
			dp -= 2;
		if (PlayerHasAffect(my_index, 14))
			dp -= 8;	//隐身的时候得削弱一下,否则太难玩了

		ClampA(dp, AA_DODGE_BASE_RATE-5, AA_DODGE_RATE_MAX);	//限制

		if (PlayerHasAffect(my_index, 4))	//矫捷
			dp += 3 + adjust * 1;

		  //debug _Tag(ToString(dp));

		for (int i = 0; i < entities.size(); i++)
		{
			double dist = Distance(x, y, entities.at(i).x, entities.at(i).y);
			DIR aimdir=0;
			if (aimdir = GetComingDir(entities.at(i)))
			{
				int dextra_rate = 0;	//根据距离决定的 额外 补充/扣除 概率
				if (dist < 2.1f)
					dextra_rate = 4;
				else if (dist < 4.4f)
					dextra_rate = 0;
				else if (dist < 6.3f)
					dextra_rate = -4;
				else if (dist < 10.5f)
					dextra_rate = -8;
				else {
					dextra_rate = -16;
				}

				r = RandomRange(0, 100, true, false);
				if (r < dp + dextra_rate)
				{
					Dodge(aimdir);	//尽力闪避
				}
				//continue;
				break;
			}
		}//end of for
	}
	bool FaceBarrier(int _x, int _y, DIR face)
	{
		int nx = _x, ny = _y;
		DirOffsetPos(nx, ny, face, "FaceBarrier");
		if (IsBarrier(bk(nx, ny, string(__func__))) || IsOuttaField(POINT2(nx, ny)))
			return true;
		return false;
	}
	bool Dodge(DIR aimdir)
	{	//调用此函数时,必须尽力闪避
		if (aimdir == 0)
			return false;
		if (PlayerHasAffect(my_index, 2) || PlayerHasAffect(my_index, 10))	//不能动的效果一定要中止,否则会被视为作弊
			return false;
		const vector<DIR> _choices{1,3,5,7};	//四向
		vector<DIR> choices{};
		DIR oppdir = 0;	//最终选择
		for (int i = 0; i < _choices.size(); i++)
		{
			if (_choices.at(i) != aimdir && _choices.at(i) != OppoDir(aimdir))
			{
				choices.push_back(_choices.at(i));
			}
			else if (_choices.at(i) == OppoDir(aimdir))
			{
				oppdir = _choices.at(i);
			}
		}
		if (oppdir != 0)
		{
			choices.push_back(oppdir);	//最后选择
		}
		bool sendMsg = (g_bIdt != IDT_OFFLINE);
		for (int k = 0; k < choices.size(); k++)
		{
			if (!HasPlayerTouch(GetI(),choices.at(k))		//不碰玩家
			&&  !FaceBarrier(GetX(),GetY(),choices.at(k))	//不碰壁,不出图
				)
			{
				int x = GetX(), y = GetY();
				DirOffsetPos(x, y, choices.at(k), "Dodge");
				SetPlayerPos(GetI(), x, y);		//闪避
				if (sendMsg)
					SendTCP(UM_SETPOS, x, y, GetI());
				return true;					//成功
			}
		}
		return false;	//闪避失败
	}
#define AA_CANREACH_RANGE_MAX 30
	bool CanReach(int x, int y, DIR face, int ex, int ey) const
	{	//能否打得到
		if (face == 0)
			return false;
		int _x = x, _y = y;
		int i = 0;
		if (face == RIGHT || face == LEFT)
		{
			if (y != ey)
				return false;
			while (!IsOuttaField(POINT2(_x, _y)) && !IsBarrier(bk(_x, _y, "AIControl::CanReach")) && i < AA_CANREACH_RANGE_MAX)
			{
				if (_x == ex && _y == ey)
					return true;
				DirOffsetPos(_x, _y, face, "AIControl::CanReach");
				i++;
				//DebugLog(ToString(i),false);
			}
			return false;
		}else if (face == DOWN || face == UP)
		{
			if (x != ex)
				return false;
			while (!IsOuttaField(POINT2(_x, _y)) && !IsBarrier(bk(_x, _y, "AIControl::CanReach")) && i < AA_CANREACH_RANGE_MAX)
			{
				if (_x == ex && _y == ey)
					return true;
				DirOffsetPos(_x, _y, face, "AIControl::CanReach");
				i++;
				//DebugLog(ToString(i), false);
			}
			return false;
		}
		else {
			if (x == ex || y == ey)
				return false;
			while (!IsOuttaField(POINT2(_x, _y)) && !IsBarrier(bk(_x, _y, "AIControl::CanReach")) && i < AA_CANREACH_RANGE_MAX)
			{
				if (_x == ex && _y == ey)
					return true;
				DirOffsetPos(_x, _y, face, "AIControl::CanReach");
				i++;
				//DebugLog(ToString(i), false);
			}
			return false;
		}
	}
	double GetTargetDistance()	const
	{	//获取目标距离 
		return Distance(GetPlayerX(my_index),GetPlayerY(my_index),GetPlayerX(target_index),GetPlayerY(target_index));
	}
	void Attack()
	{
		EXCEPTION_L
		//_Tag("Attack");

		int r = RandomRange(0, 100, true, false);
		if (r > 100 - AA_CHANGE_WEAPON_RATE && (clock() - lastWeaponChanged) > AA_CHANGE_WEAPON_MIN_T)
		{
			do {
				GetPlayerCurWeaponIndex(my_index) = curw_prob.at(RandomRange(0, curw_prob.size() - 1, true, true));
			} while (GetPlayerCurWeaponIndex(my_index) == 0);	//不能选空的格子

			lastWeaponChanged = clock();
		}
//		double distance = GetOppoDistance();
		double distance = GetTargetDistance();
		UINT type = GetItemType(GetPlayerCurWeapon(my_index));
		int x = GetX();
		int y = GetY();
		int ex = GetPlayerX(target_index);
		int ey = GetPlayerY(target_index);

		DIR face = GetPlayerFace(my_index);
		UINT ptype;
		ITEM_ID id = GetPlayerCurWeapon(my_index);

		if(type == ITT_PROP)
			ptype = GetItemPropType(GetPlayerCurWeapon(my_index));
		if (type == ITT_BOW || type == ITT_GUN
			|| (type == ITT_PROP && ptype == ITPT_THROWABLE))	//远程武器
		{
			bool reach = CanReach(x, y, face, ex, ey);
			r = RandomRange(0, 100, true, false);

			int blind_prob = 10;
			if (mode == AAM_FLEE)
				blind_prob = 2;
			else if (type == ITT_PROP && ptype == ITPT_THROWABLE)
				blind_prob = 1;
			else
				blind_prob = 11;
			if(reach && r > (mode == AAM_CHASE ? 49 : 62) || r < blind_prob)
//				p[GetI()].TryToAttack(GetI(), (g_bIdt != IDT_OFFLINE));	//checking is inside
				PlayerTryToAttack(my_index, (g_bIdt != IDT_OFFLINE));	//checking is inside
		}
		else if (type == ITT_CLOSE_WEAPON)	//近战武器
		{	
			bool reach = distance < 3.3;
			r = RandomRange(0, 100, true, false);
			if(reach && r > (mode == AAM_CHASE ? 43 : 45) || r > (mode == AAM_FLEE ? 86 : 97))
				PlayerTryToAttack(my_index, (g_bIdt != IDT_OFFLINE));	//checking is inside
		}
		else if (type == ITT_PROP)	//道具
		{
			if (ptype == ITPT_PUT)	//放置类
			{
				if (id == 33)	//地雷
				{
					int prob = 5;
					if (distance < 6.0)
					{
						if (mode == AAM_FLEE)
						{	//逃亡中布地雷对方很容易中招
							prob = 40;
						}
						else if (mode == AAM_CHASE)
						{	//追的时候就不一定了
							prob = 12;
						}
						else if (mode == AAM_STILL)
						{	//判断对手是否朝自己方向来
							bool come = false;
							int delta_x, delta_y;
							DIR eface = GetPlayerFace(target_index);
							delta_x = ex - x;
							delta_y = ey - y;
							if (delta_x > 0 && eface == LEFT
								|| delta_x < 0 && eface == RIGHT
								|| delta_y > 0 && eface == UP
								|| delta_y < 0 && eface == DOWN)
								come = true;
							prob = (come?76:33);
							
						}
					}
					else {
						prob = 11;
					}
					r = RandomRange(0, 100, true, false);
					if (r < prob)
					{	//布地雷
						PlayerTryToAttack(my_index, (g_bIdt != IDT_OFFLINE));	//checking is inside
					}
				}
				else {
					//<!>other PUTs...
				}
			}
			else if (ptype == ITPT_POTION)	//药水类,好的药水
			{
				r = RandomRange(0, 100, true, false);
				float t = AA_DRINK_POTION_RATE;	//概率
				if (id >= 71 && id <= 73)
				{
					if (GetPlayerHp(my_index) < GetPlayerMaxHp(my_index) * 0.10)
						t *= 5.0;
					else if (GetPlayerHp(my_index) < GetPlayerMaxHp(my_index) * 0.25)
						t *= 3.0;
					else if (GetPlayerHp(my_index) < GetPlayerMaxHp(my_index) * 0.45)
						t *= 1.6;
				}
				if (r < t)
				{	//喝药水
//					p[GetI()].TryToAttack(GetI(), (g_bIdt != IDT_OFFLINE));
					PlayerTryToAttack(my_index, (g_bIdt != IDT_OFFLINE));
				}
			}
			else {
				//other ITPTs...
			}
		}
		else {
			return;
		}

		EXCEPTION_R_TITLED("BOP AIControl::Attack EXCEPTION")
	}
};
//AIControl g_aic;
AIControl& GetPlayerAI(int index);

大致就包括自动移动、攻击、躲闪、喝药、埋地雷等,特别是那个躲闪很有意思,经验值越高躲闪越容易成功。
以后打算搞个游击模式算法。。等更新吧

下载: https://download.csdn.net/download/cjz2005/86287023

喜欢的朋友别忘了点赞关注!!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:25:04  更:2022-08-06 10:27:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:10:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码