lua 游戏架构 之 游戏 AI (四)ai_autofight_find_target

news2024/11/17 2:25:21

定义一个名为 `ai_autofight_find_target` 的类,继承自 `ai_base` 类。

lua 游戏架构 之 游戏 AI (一)ai_base-CSDN博客文章浏览阅读237次。定义了一套接口和属性,可以基于这个基础类派生出具有特定行为的AI组件。例如,可以创建追逐敌人的AI、巡逻的AI或使用特定策略的AI等,都继承自这个基础类https://blog.csdn.net/heyuchang666/article/details/140624481?spm=1001.2014.3001.5502

这个类用于处理游戏中AI自动战斗中寻找目标的逻辑。以下是对代码的具体解释:

1. **引入基类**: 使用 `require` 函数引入 `ai_base` 类,作为基础类。

2. **定义 `ai_autofight_find_target` 类**: 使用 `class` 关键字定义了 `ai_autofight_find_target` 类,并继承自 `BASE`(即 `ai_base`)。

3. **构造函数 (`ctor`)**:

  •    - 构造函数 `entity` 游戏实体,并设置 `_type` 属性为 `eAType_AUTOFIGHT_FIND_TARGET`,表示自动战斗中寻找目标的行为。
  •    - 初始化 `_target` 为 `nil`,用于后续存储找到的目标。

4. **`IsValid` 方法**:

  •    - 这个方法用于验证AI是否应该寻找目标。它首先检查实体是否开启了自动战斗(`_AutoFight`),是否死亡或无法攻击。
  •    - 计算警报范围 `filterdist`,可能基于实体的属性或世界配置。
  •    - 检查实体的预命令类型,如果是点击移动或摇杆移动,则返回 `false`。
  •    - 检查实体的当前技能 `_curSkill`,根据技能类型(伤害、诅咒、祝福)和相关逻辑来确定目标。

5. **`OnEnter` 方法**:
   - 当AI组件进入激活状态时执行。如果已经找到目标 `_target`,则根据当前技能设置目标或移动到目标位置。

6. **`OnLeave` 方法**:
   - 当AI组件离开激活状态时执行。清除目标 `_target`。

7. **`OnUpdate` 方法**:
   - 每帧调用,用于更新AI状态。如果基类的 `OnUpdate` 方法返回 `true`,则当前方法也返回 `true`。

8. **`OnLogic` 方法**:
   - 逻辑更新方法,如果基类的 `OnLogic` 方法返回 `true`,则当前方法返回 `false`,表示只执行一次。

9. **创建组件函数**:
   - `create_component` 函数用于创建 `ai_autofight_find_target` 类的新实例,传入一个实体和一个优先级。

代码中的一些关键点:

  • - `IsDead()`:检查实体是否死亡。
  • - `CanAttack()`:检查实体是否可以攻击。
  • - `GetPropertyValue(ePropID_alertRange)`:获取实体的警报范围属性。
  • - `game_get_world()`:获取游戏世界配置。
  • - `GetEnmities()`:获取实体的敌对列表。
  • - `GetRadius()`:获取实体的半径。
  • - `MoveTo()`:移动到指定位置。
  • - `SetTarget()`:设置目标实体。

这个脚本为游戏中的AI提供了一个自动战斗中寻找目标的基础框架,可以根据具体游戏的需求进行扩展和修改。

----------------------------------------------------------------

local require = require

local BASE = require("logic/entity/ai/ai_base").ai_base;


ai_autofight_find_target = class("ai_autofight_find_target", BASE);
function ai_autofight_find_target:ctor(entity)
	self._type		= eAType_AUTOFIGHT_FIND_TARGET;
	self._target	= nil;
end

function ai_autofight_find_target:IsValid()
	local entity = self._entity;
	if not entity._AutoFight then
		return false;
	end
	if entity:IsDead() or not entity:CanAttack() then
		return false;
	end
	
	local filterdist = entity:GetPropertyValue(ePropID_alertRange)
	local world = game_get_world();
	if world._cfg.autofightradius then
		filterdist = world._cfg.autofightradius
	end
	local r1 = entity:GetRadius();
	if entity._PreCommand == ePreTypeClickMove or entity._PreCommand == ePreTypeJoystickMove then
		return false;
	end	

	if entity._curSkill then
		local target = nil;
		local ignoreDist = false;
		local stype = entity._curSkill._cfg.type;
		if stype == eSE_Damage or stype == eSE_DBuff then -- 伤害、诅咒
			if entity._forceAttackTarget and not entity._forceAttackTarget:IsDead() then
				ignoreDist = true;
				target = entity._forceAttackTarget;
			else
				local enmities = entity:GetEnmities();
				if enmities then
					local enmity = enmities[1];
					if enmity then
						ignoreDist = true;
						target = enmity;
					end
				end
					
				if not target or target._groupType == eGroupType_N then
					
					local tentity = nil
					local mapType = game_get_map_type();
					for i,v in ipairs(entity._alives[2]) do
						local r2 =  entity._alives[2][i].entity:GetRadius();
						local radius = r1 + r2;	
						if radius then
							if mapType then
								if mapType == g_ARENA_SOLO or mapType == g_TAOIST then
									break;
								end
							end
							
							if entity._alives[2][i].dist < entity._curSkill._range + radius then
								tentity = entity._alives[2][i];
								if entity._alives[2][i+1] and entity._alives[2][i+1].dist then
									if tentity.dist <  entity._alives[2][i+1].dist then
										tentity = entity._alives[2][i+1];
									else
										tentity = entity._alives[2][i];
									end
								else
									tentity = entity._alives[2][i];
									break;
								end
							else
								if v.entity:GetEntityType() == eET_Player and v.dist > filterdist then
									if entity._alives[2][i+1] and entity._alives[2][i+1].dist < filterdist then
										tentity = entity._alives[2][i+1];
										break;	
									end
								else
									tentity = entity._alives[2][i-1];
									break;	
								end
							end		
						end
					end
					
					if entity._groupType == eGroupType_O then
						
						local nentity = tentity or entity._alives[2][1] or entity._alives[3][1]
						if target and nentity and nentity.entity and nentity.entity._groupType ~= eGroupType_N  then
							target = nentity.entity;
						elseif not ignoreDist then
							target = tentity or entity._alives[2][1];
							if entity._alives[3][1] then
								local trap =  entity._alives[3][1];
								if trap.entity and trap.entity._traptype == eSTrapActive then
									target = entity._alives[3][1];			
								end
							end
						
							if nentity and nentity.entity._groupType == eGroupType_N and nentity.dist > db_common.droppick.AutoFightMapbuffAutoRange then
								target = nil;
								return false;
							end
						end
					else
						target = tentity or entity._alives[2][1] -- 敌方
					end
				end
			end
		elseif stype == eSE_Buff then -- 祝福
		
			if entity._target and entity._target._guid == entity._guid then
				return false;
			end 
			self._target = entity;
			
			return true;
		end

		if target then
			if ignoreDist then
				if not (target:GetEntityType() == eET_Pet and (not entity._enmities or #entity._enmities <= 0)) then
					self._target = target;
				end

				if not entity._target or entity._target:IsDead() then
					return true;
				end
	
				return target._guid ~= entity._target._guid;
			else
				local r2 = target.entity:GetRadius();
				local radius = r1 + r2;
				if target.dist < filterdist + radius then
					
					if not (target.entity:GetEntityType() == eET_Pet and (not entity._enmities or #entity._enmities <= 0)) then
						self._target = target.entity;
					end
					if not entity._target or entity._target:IsDead() then
						return true;
					end
					if target.dist < entity._curSkill._range + radius then
						return false;
					end
					return target.entity._guid ~= entity._target._guid;
				end
			end
		end
	end

	return false;
end

function ai_autofight_find_target:OnEnter()
	if BASE.OnEnter(self) then
		local entity = self._entity;
		--log("ai_autofight_find_target")
		entity._behavior:Clear(eEBGuard);

		if self._target then
			if entity._curSkill then
				entity:SetTarget(self._target);
			else
				entity:MoveTo(self._target._curPos);
			end
		end

		return true;
	end

	return false;
end

function ai_autofight_find_target:OnLeave()
	if BASE.OnLeave(self) then
		self._target = nil;

		return true;
	end

	return false;
end

function ai_autofight_find_target:OnUpdate(dTime)
	if BASE.OnUpdate(self, dTime) then
		return true;
	end

	return false;
end

function ai_autofight_find_target:OnLogic(dTick)
	if BASE.OnLogic(self, dTick) then
		return false; -- only one frame
	end

	return false;
end

function create_component(entity, priority)
	return ai_autofight_find_target.new(entity, priority);
end


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1949658.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python系列】isin用法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

简单使用nginx

打开下载的nginx文件夹下的。。具体地址 打开并编辑nginx.conf文件 server {listen 8089;//访问端口号server_name localhost;//访问地址#charset koi8-r;#access_log logs/host.access.log main;location / {root D:/development/dist/;//dist包地址index index.h…

无人机之降落操作及紧急情况处理

一、无人机降落操作 1、选择降落地点 a.提前选择一个平坦且没有障碍物的降落点&#xff1b; b.确认降落点周围没有行人或障碍物&#xff0c;保证降落的安全性。 2、降低飞行高度 a.缓慢降低飞行高度&#xff0c;尽量保持匀速下降&#xff0c;防止因下降过快导致无人机受损…

用户管理与高级SQL语句(数据库管理与高可用)

1.表&#xff08;Table &#xff09; 数据库中的表与我们日常生活中使用的表格类似&#xff0c;它也是由行&#xff08;Row&#xff09; 和列&#xff08;Column&#xff09;组成的。列由同类的信息组成&#xff0c;每列又称为一个字段&#xff0c;每列的标题称为字段名。行包…

NeRF:从二维图像到三维重建【初识!原理通俗讲解】

NeRF&#xff1a;从二维图像到三维重建 反渲染&#xff08;Inverse Rendering&#xff09;可以理解为成像渲染的反过程&#xff0c;是指从一组二维图像重建三维场景的过程&#xff0c;这在计算机视觉和图形学中具有重要意义。NeRF&#xff08;Neural Radiance Fields&#xff…

Profinet转ModbusTCP网关模块的配置与应用详解

Profinet转ModbusTCP网关模块&#xff08;XD-ETHPN20&#xff09;是一种常见的工业通信设备&#xff0c;广泛应用于现代工业自动化系统中。通过使用Profinet转Modbus TCP网关模块&#xff08;XD-ETHPN20&#xff09;将Profinet协议转换成Modbus TCP协议&#xff0c;实现了不同网…

【Web】LitCTF 2024 题解(全)

目录 浏览器也能套娃&#xff1f; 一个....池子&#xff1f; 高亮主题(划掉)背景查看器 百万美元的诱惑 SAS - Serializing Authentication exx 浏览器也能套娃&#xff1f; 随便试一试&#xff0c;一眼ssrf file:///flag直接读本地文件 一个....池子&#xff1f; {…

昇思25天学习打卡营第23天|LSTM+CRF序列标注

Mindspore框架CRF条件随机场概率图模型实现文本序列命名实体标注|&#xff08;一&#xff09;序列标注与条件随机场的关系 Mindspore框架CRF条件随机场概率图模型实现文本序列命名实体标注|&#xff08;二&#xff09;CRF模型构建 Mindspore框架CRF条件随机场概率图模型实现文本…

IEC104转MQTT网关快速实现了IEC104到MQTT的转换和数据交互

随着智能电网技术的不断进步&#xff0c;IEC 104&#xff08;IEC 60870-5-104&#xff09;协议作为电力系统中重要的远动通信标准&#xff0c;正逐步融入更广泛的物联网生态系统中。亚马逊AWS&#xff08;Amazon Web Services&#xff09;&#xff0c;作为全球领先的云计算服务…

神经网络与注意力机制的权重学习对比:公式探索

神经网络与注意力机制的权重学习对比&#xff1a;公式探索 注意力机制与神经网络权重学习的核心差异 在探讨神经网络与注意力机制的权重学习时&#xff0c;一个核心差异在于它们如何处理输入数据的权重。神经网络通常通过反向传播算法学习权重&#xff0c;而注意力机制则通过学…

python通过omniORBpy调用CORBA

omniORB参考地址&#xff1a; omniORB omniORB - Browse Files at SourceForge.net omniORB - Browse /omniORBpy/omniORBpy-4.3.0 at SourceForge.net Windows 普通使用好像不需要安装omniorb。就对接北向接口业务需要使用python3.10的windows包&#xff0c;但目前好像没有…

vue接入google map自定义marker教程

需求背景 由于客户需求&#xff0c;原来系统接入的高德地图&#xff0c;他们不接受&#xff0c;需要换成google地图。然后就各种百度&#xff0c;各种Google&#xff0c;却不能实现。----无语&#xff0c;就连google地图官方的api也是一坨S-H-I。所以才出现这篇文章。 google地…

SpringBoot整合elasticsearch-java

一、依赖 系统使用的是ElasticSearch8.2.0 <dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.1.0</version> </dependency> 二、配置 1、yml文件配置 elastics…

移动式气象站:便携科技的天气守望者

在科技日新月异的今天&#xff0c;我们身边的许多设备都在向着更加智能化、便携化的方向发展。而在气象观测领域&#xff0c;移动式气象站的出现&#xff0c;不仅改变了传统气象观测的固有模式&#xff0c;更以其灵活性和实时性&#xff0c;在气象监测、灾害预警等领域发挥着越…

苹果电脑暂存盘已满怎么清理 Mac系统如何清理磁盘空间 清理MacBook

Mac电脑用户在长时间使用电脑之后&#xff0c;时常会看到“暂存盘已满”的提示&#xff0c;这无疑会给后续的电脑使用带来烦恼&#xff0c;那么苹果电脑暂存盘已满怎么清理呢&#xff0c;下面将给大家带来一些干货帮你更好地解决这个问题。 首先我们要搞明白为什么暂存盘会满&…

IEC104转MQTT网关支持MQTT对接Ignition、阿里云、华为云、亚马逊AWS、ThingsBoard、Zabbix平台助力远程管理

钡铼推出了一款专为电力系统设计的数据采集网关——IEC104转MQTT网关BE113&#xff0c;感兴趣的朋友接着往下看&#xff1a; 一、网关概述 IEC104转MQTT(Ignition)网关BE113是一款专为电力系统设计的数据采集网关&#xff0c;支持DL/T645和IEC104等协议的设备。上行支持MQTT协…

The Sandbox:虚拟游戏世界生态系统详解

元宇宙由区块链、软件基础、移动应用、控制台等组成&#xff0c;是一个虚拟空间&#xff0c;结合了增强现实&#xff08;AR&#xff09;、虚拟现实&#xff08;VR&#xff09;和在线游戏等元素。它强调互操作性&#xff0c;允许用户在不同的虚拟平台之间自由切换。与传统的现实…

Tensorflow2.0全套学习(持续更新中)

0 简介 1.学习目标 两大核心模块&#xff1a;深度学习经典算法与Tensorflow项目实战 从零开始&#xff0c;详细的网络模型架构与框架实现方法 2.tensorflow&#xff1a;核心开源库&#xff0c;深度学习框架&#xff0c;帮助开发和训练机器学习模型 3.版本2比1有哪些优势 …

【深度学习】GoogLeNet实战

目录 1.猫狗识别 1.1data_partitioning.py 1.2mean_std.py 1.3model.py 1.4model_train.py 1.5model_test.py 2.水果识别 2.1data_partitioning.py 2.2mean_std.py 2.3model.py 2.4model_train.py 2.5model.test.py 1.猫狗识别 1.1data_partitioning.py import o…

杂项——电阻式角度传感器使用

三个引脚&#xff0c;分别接3.3V&#xff0c;GND&#xff0c;ADC引脚。12位ADC有4096份&#xff0c;将360分成4096份&#xff0c;再乘以单片机返回的模拟量的值&#xff0c;即可得到角度。 M0代码 #include "ti_msp_dl_config.h"volatile bool gCheckADC; volatile …