86. UE5 RPG 技能面板实现监听数据

news2024/11/14 10:33:40

在上一篇文章里,我们创建了技能面板的控制器,接下来,我们将实现通过控制器绑定委托,来更新显示内容。

更新技能面板应用的技能

我们首先更新技能面板上面已经应用的技能,让其和WBP_Overlay上面一样,可以更新显示。
由于我们当前面板使用的是升级技能的UI按钮,所以,我们需要创建一个新的按钮,还能够通过点击按钮取消应用的技能。
在这里插入图片描述
复制一个按钮用户控件
在这里插入图片描述
将应用技能UI里的对应节点替换掉
在这里插入图片描述
在WBP_SpellMenuWidget里面,设置应用控制器,它们共同使用技能面板控制器SpellMenuWidgetController
在这里插入图片描述
然后,设置初始化
在这里插入图片描述
接着,我们在应用技能用户控件里,对每个按钮进行设置控制器
在这里插入图片描述
在按钮里面,我们首先将其转换为技能面板控制器
在这里插入图片描述
然后增加一个标签,用于设置技能的输入标签
在这里插入图片描述
被动技能没有对应的输入标签,我们创建两个被动技能标签用于识别

	FGameplayTag InputTag_Passive_1; //被动技能1
	FGameplayTag InputTag_Passive_2; //被动技能2

注册

	GameplayTags.InputTag_Passive_1 = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("InputTag.Passive.1"),
			FString("被动技能1")
			);
	
	GameplayTags.InputTag_Passive_2 = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("InputTag.Passive.2"),
			FString("被动技能2")
		);

在应用技能的组件里,设置其对应的标签
在这里插入图片描述
然后,在按钮里绑定技能事件,通过判断数据标签是否一致,来设置显示的笔刷
在这里插入图片描述
在其未设置技能时,我们将图标和背景设置为透明
在这里插入图片描述
在初始化构建是,我们去调用此函数
在这里插入图片描述
由于设置了笔刷半透明,而之前回调更新图标和背景的节点都是更新笔刷的,所以,我们要修改设置,在应用时创建一个新的笔刷
在这里插入图片描述
运行查看技能应用是否正确。
在这里插入图片描述

设置技能状态

接下来,我们将实现技能相关功能,在实现功能之前,我们将创建每个技能的状态Ability Status,它将分为:

  1. Locked已锁定,技能图标显示锁的状态
  2. Eligible 可解锁,当前技能可以通过技能点解锁,但处于未解锁状态,将显示技能图标
  3. Unlocked 已解锁,当前技能已通过技能点解锁,背景将被替换掉
  4. Equipped 已装配,当前技能已经被装配到技能栏,样式和已解锁没有区别

相应的,我们将创建对应的标签,通过标签来识别当前技能所处的状态。

我们还需要对技能的类型Ability Type进行识别:
它可以是主动技能,被动技能,以及空状态(受击技能,死亡技能,没错,它们也可以做成技能)

我们首先创建对应的标签

	FGameplayTag Abilities_HitReact; //受击技能标签

	FGameplayTag Abilities_Status_Locked; //技能状态 已锁定
	FGameplayTag Abilities_Status_Eligible; //技能状态 可解锁
	FGameplayTag Abilities_Status_Unlocked; //技能状态 已解锁
	FGameplayTag Abilities_Status_Equipped; //技能状态 已装配
	
	FGameplayTag Abilities_Type_Offensive; //技能类型 主动技能
	FGameplayTag Abilities_Type_Passive; //技能类型 被动技能
	FGameplayTag Abilities_Type_None; //技能类型 空 受击等技能设置

然后在函数中注册到标签管理器

void FRPGGameplayTags::InitializeGAGameplayTags()
{

	/*
	 * Abilities 技能标签
	 */
	
	GameplayTags.Abilities_Attack = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Attack"),
			FString("攻击技能标签")
			);
	GameplayTags.Abilities_Summon = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Summon"),
			FString("召唤技能标签")
			);
	GameplayTags.Abilities_Fire_FireBolt = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Fire.FireBolt"),
			FString("火球术技能标签")
			);

	/*
	 * 空类型技能标签
	 */
	GameplayTags.Abilities_HitReact = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.HitReact"),
			FString("受击技能标签")
			);

	/*
	 * 当前技能状态标签
	*/
	GameplayTags.Abilities_Status_Locked = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Status.Locked"),
			FString("已锁定")
			);
	GameplayTags.Abilities_Status_Eligible = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Status.Eligible"),
			FString("可解锁")
			);
	GameplayTags.Abilities_Status_Unlocked = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Status.Unlocked"),
			FString("已解锁")
			);
	GameplayTags.Abilities_Status_Equipped = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Status.Equipped"),
			FString("已装配")
			);

	/*
	 * 当前技能类型标签
	*/
	GameplayTags.Abilities_Type_Offensive = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Type.Offensive"),
			FString("主动技能")
			);
	GameplayTags.Abilities_Type_Passive = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Type.Passive"),
			FString("被动技能")
			);
	GameplayTags.Abilities_Type_None = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Type.None"),
			FString("啥也不是")
			);
	
}

还有一种添加标签的方式,就是使用宏的方式,我们在RPG.h文件里,来定义需要使用的标签

#define Abilities_Status_Locked FGameplayTag::RequestGameplayTag(FName("Abilities.Status.Locked"))
#define Abilities_Status_Equipped FGameplayTag::RequestGameplayTag(FName("Abilities.Status.Equipped"))

然后在使用时,直接使用定义的名称
在这里插入图片描述
接着,我们在ASC里增加一个用于获取技能的状态的函数

static FGameplayTag GetStatusTagFromSpec(const FGameplayAbilitySpec& AbilitySpec); //获取技能的状态标签

遍历动态标签容器,获取标签

FGameplayTag URPGAbilitySystemComponent::GetStatusTagFromSpec(const FGameplayAbilitySpec& AbilitySpec)
{
	for(FGameplayTag Tag : AbilitySpec.DynamicAbilityTags) //从技能实例的动态标签容器中遍历所有标签
	{
		if(Tag.MatchesTag(FGameplayTag::RequestGameplayTag(FName("Abilities.Status")))) //查找标签中是否设置以输入标签开头的标签
		{
			return Tag;
		}
	}

	return FGameplayTag();
}

给技能面板主动技能增加状态修改

我们上面增加了状态的对应的标签,接下来,我们将实现对技能的状态修改,并能够显示到技能框上面。
首先我们对技能按钮增加一个参数,可以设置当前按钮需要显示的技能
在这里插入图片描述
接着在WBP_OffensiveSpellTreel里对按钮设置应显示的技能标签
在这里插入图片描述
之前,我们已经对WBP_OffensiveSpellTree设置了控制器,在WBP_OffensiveSpellTree的事件里面,我们对每个按钮设置控制器
在这里插入图片描述
在WBP_SpellGlobe_Button里,我们在设置控制器回调后,将控制器转换为技能面板控制器,方便后续使用
在这里插入图片描述
由于技能数据里没有对应的数据状态标签,我们需要在结构体里增加对技能状态标签的设置
在这里插入图片描述
然后在广播时,我们通过代码获取它的状态标签,并设置到数据上
在这里插入图片描述
接下来,我们在WBP_SpellGlobe_Button里添加数据委托的监听,并调用函数
在这里插入图片描述
在数据处理函数里,我们首先判断技能标签和设置在按钮上的标签是否一致,然后根据状态去修改ui显示的图标和背景
在这里插入图片描述
设置状态笔刷的函数里面是将对应的传入的图片和材质应用
在这里插入图片描述
最后我们测试查看效果
在这里插入图片描述
在代码修改查看另外的效果
在这里插入图片描述

设置根据等级更新技能状态

我们实现了更新技能状态的UI,接下来,我们实现可以根据角色的等级去修改技能的状态

为了实现此功能,我们需要在AbilityInfo里增加两个配置项,一个是当前技能解锁角色等级,另一个是技能类

	//解锁技能所需角色的等级
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	int32 LevelRequirement;

	//当前技能使用的技能类
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	TSubclassOf<UGameplayAbility> Ability;

为了能够在服务器上获取到技能数据,我们在GameMode类里增加技能相关配置数据的参数
在这里插入图片描述
接着在蓝图函数库里增加一个获取技能数据的函数

	//获取玩家角色技能配置数据
	UFUNCTION(BlueprintCallable, Category="RPGAbilitySystemLibrary|CharacterClassDefaults", meta=(DefaultToSelf = "WorldContextObject"))
	static UAbilityInfo* GetAbilityInfo(const UObject* WorldContextObject);

实现是获取到当前客户端GameMode,并从中获取角色技能的配置项数据

UAbilityInfo* URPGAbilitySystemBlueprintLibrary::GetAbilityInfo(const UObject* WorldContextObject)
{
	//获取到当前关卡的GameMode实例
	const ARPGGameMode* GameMode = Cast<ARPGGameMode>(UGameplayStatics::GetGameMode(WorldContextObject));
	if(GameMode == nullptr) return nullptr;

	//返回关卡的角色的配置
	return  GameMode->AbilityInfo;
}

接下来编译,我们可以在技能的数据资产中设置对应的数据
在这里插入图片描述
然后在GameMode蓝图中设置对应的数据
在这里插入图片描述
为了方便测试,我们增加一个额外的技能,这个技能需要两级解锁,我们增加一个新的技能
在这里插入图片描述
这个技能是雷系的技能,雷击
在这里插入图片描述
在技能里,我们先链接调试代码,后续对其进行实现
在这里插入图片描述
技能还没有对应的技能标签,我们在代码中新增一个

FGameplayTag Abilities_Lightning_Electrocute; //雷击技能标签
	GameplayTags.Abilities_Lightning_Electrocute = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Lightning.Electrocute"),
			FString("电击技能标签")
			);

设置技能对应的内容
在这里插入图片描述
在技能面板的一个按钮上设置对应的技能标签
在这里插入图片描述
接下来,我们要实现根据角色等级更新,我们要遍历技能数据,并判断角色是否拥有。
所以我们先实现一个通过标签获取角色身上的技能实例

FGameplayAbilitySpec* GetSpecFromAbilityTag(const FGameplayTag& AbilityTag); //通过技能标签获取技能实例

在实现这里,我们需要先获取所有激活的技能实例,根据标签判断是否包含相同的,防止多线程出现问题,我们使用了域锁

FGameplayAbilitySpec* URPGAbilitySystemComponent::GetSpecFromAbilityTag(const FGameplayTag& AbilityTag)
{
	FScopedAbilityListLock ActiveScopeLoc(*this); //域锁
	//遍历已经应用的技能
	for(FGameplayAbilitySpec& AbilitySpec : GetActivatableAbilities())
	{
		for(FGameplayTag Tag : AbilitySpec.Ability.Get()->AbilityTags)
		{
			if(Tag.MatchesTag(AbilityTag))
			{
				return &AbilitySpec;
			}
		}
	}
	return nullptr;
}

接着增加根据角色等级更新技能状态

void UpdateAbilityStatuses(int32 Level); //根据角色等级更新技能数据状态

然后在实现这里,我们对技能数据遍历,判断角色是否拥有此技能,如果未拥有,我们将创建一个技能实例应用到角色的ASC上。

void URPGAbilitySystemComponent::UpdateAbilityStatuses(const int32 Level)
{
	//从GameMode获取到技能配置数据
	UAbilityInfo* AbilityInfo = URPGAbilitySystemBlueprintLibrary::GetAbilityInfo(GetAvatarActor());
	for(const FRPGAbilityInfo& Info : AbilityInfo->AbilityInformation)
	{
		if(!Info.AbilityTag.IsValid()) continue; //如果没有技能标签,取消执行
		if(Level < Info.LevelRequirement) continue; //如果当期等级未达到所需等级,取消执行
		//判断ASC中是否已存在当前技能实例
		if(GetSpecFromAbilityTag(Info.AbilityTag) == nullptr)
		{
			//如果没有技能实例,将应用一个新的技能实例
			FGameplayAbilitySpec AbilitySpec = FGameplayAbilitySpec(Info.Ability, 1);
			AbilitySpec.DynamicAbilityTags.AddTag(FRPGGameplayTags::Get().Abilities_Status_Eligible);
			GiveAbility(AbilitySpec);
			MarkAbilitySpecDirty(AbilitySpec); //设置当前技能立即复制到每个客户端
		}
	}
}

接下来,我们将在角色升级时,去更新技能的状态,在玩家角色类里的提升等级函数中增加对技能数据状态的调用

void ARPGHero::AddToPlayerLevel_Implementation(int32 InPlayerLevel)
{
	ARPGPlayerState* PlayerStateBase = GetPlayerState<ARPGPlayerState>();
	check(PlayerStateBase); //检测是否有效,无限会暂停游戏
	PlayerStateBase->AddToLevel(InPlayerLevel);

	if(URPGAbilitySystemComponent* RPGASC = Cast<URPGAbilitySystemComponent>(GetAbilitySystemComponent()))
	{
		RPGASC->UpdateAbilityStatuses(PlayerStateBase->GetPlayerLevel());
	}
}

我们还要在自定义ASC增加一个委托用于广播新状态标签

DECLARE_MULTICAST_DELEGATE_TwoParams(FAbilityStatusChanged, const FGameplayTag& /*技能标签*/, const FGameplayTag& /*技能状态标签*/);

在ASC中增加委托参数

FAbilityStatusChanged AbilityStatusChanged; //技能状态更新委托

ASC是在服务器运行,我们再增加一个客户端执行的函数,用于广播到每个客户端

	UFUNCTION(Client, Reliable)
	void ClientUpdateAbilityStatus(const FGameplayTag& AbilityTag, const FGameplayTag& StatusTag); //技能状态更新后回调

在函数内对委托进行广播

void URPGAbilitySystemComponent::ClientUpdateAbilityStatus_Implementation(const FGameplayTag& AbilityTag, const FGameplayTag& StatusTag)
{
	AbilityStatusChanged.Broadcast(AbilityTag, StatusTag);
}

接着在之前更新技能数据状态的函数中,如果需要更新,那么,我们对数据进行广播
在这里插入图片描述
接着在技能面板控制器中,绑定对技能状态修改后的回调,并将数据广播给UI

void USpellMenuWidgetController::BindCallbacksToDependencies()
{
	//绑定技能状态修改后的委托回调
	GetRPGASC()->AbilityStatusChanged.AddLambda([this](const FGameplayTag& AbilityTag, const FGameplayTag& StatusTag)
	{
		if(AbilityInfo)
		{
			FRPGAbilityInfo Info = AbilityInfo->FindAbilityInfoForTag(AbilityTag); //获取到技能数据
			Info.StatusTag = StatusTag;
			AbilityInfoDelegate.Broadcast(Info);
		}
	});
}

运行查看效果。
在这里插入图片描述
如果在技能面板打开的情况下升级,那么技能将通过委托去更新状态数据,如果在关闭状态,升级时,那么技能的状态标签将会更新到技能实例的动态标签里,然后在开启技能面板时,通过技能标签去更新图标的状态。

更新所拥有的技能点显示

接下来,我们实现对技能点的显示更新,在技能面板中正确显示玩家角色所拥有的技能点数。
我们在控制器基类里有对玩家状态更新声明的宏
在这里插入图片描述
我们在技能面板控制器里,增加一个参数声明

	UPROPERTY(BlueprintAssignable)
	FOnPlayerStateChangedSignature SpellPointChanged;

在初始化时,广播技能点
在这里插入图片描述
接下来就是在变动时,监听更新变动,在PlayerState上,我们拥有了技能点数变动的委托
在这里插入图片描述

那么,在绑定更改函数里,我们绑定对变动后的监听即可,并在函数内广播给UI

//绑定技能点变动回调
	GetRPGPS()->OnSpellPointsChangedDelegate.AddLambda([this](const int32 SpellPoints)
	{
		SpellPointChanged.Broadcast(SpellPoints); //广播拥有的技能点
	});

代码实现完毕,接着我们就是修改UI,将显示技能点的UI设置成变量
在这里插入图片描述
然后给控件增加一个函数,更新它的值
在这里插入图片描述
在调用初始化之前,我们监听变动,并调用函数更新值,这样在初始化时,就能准确获取到值进行更新。
在这里插入图片描述
接着运行测试,打开技能面板显示默认一点技能点
在这里插入图片描述
然后杀怪升到三级,奖励给了我们两点技能点
在这里插入图片描述

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

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

相关文章

从零开始掌握tcpdump:参数详解

Linux tcpdump命令详解 1. 语法 tcpdump [-adeflnnNOpqStvxX] [-c <数据包数目>] [-dd] [-ddd] [-F <表达文件>] [-i <网络界面>] [-r <数据包文件>] [-s <数据包大小>] [-tt] [-T <数据包类型>] [-vv] [-w <数据包文件>] [输出数…

https执行过程,特点,作用

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

免费的短剧机器人,一键获取资源,每日自动更新,自动转存+定时删除!

今天分享一个免费的短剧机器人&#xff0c;配合网盘拉新可实现变现的项目&#xff01;可以轻松实现全自动化&#xff0c;解放双手&#xff01; 具体怎么实现&#xff0c;我们往下看&#xff1a; 我经常说&#xff0c;想赚钱&#xff0c;离不开人性! 短剧为啥火呢&#xff1f;…

深入学习并发编程中的synchronized

第一章:并发编程中的三个问题 可见性 可见性概念 可见性( Visibility ):是指一个线程对共享变量进行修改,另一个先立即得到修改后的最新值。 可见性演示 案例演示:一个线程根据 boolean 类型的标记 flag , while 循环,另一个线程改变这个 flag 变量的值,另 一个线…

【C++BFS算法 二分查找】1631. 最小体力消耗路径

本文涉及知识 CBFS算法 C二分查找 LeetCode1631. 最小体力消耗路径 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights &#xff0c;其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) &#xff0c;且你希望去最右下…

【无标题】智能加速计算卡设计原理图:628-基于VU3P的双路100G光纤加速计算卡 XCVU3P板卡

基于VU3P的双路100G光纤加速计算卡 一、板卡概述 基于Xilinx UltraScale16 nm VU3P芯片方案基础上研发的一款双口100 G FPGA光纤以太网PCI-Express v3.0 x16智能加速计算卡&#xff0c;北京太速科技该智能卡拥有高吞吐量、低延时的网络处理能力以及辅助CPU进行网络功…

【深入探秘Hadoop生态系统】全面解析各组件及其实际应用

深入探秘Hadoop生态系统&#xff1a;全面解析各组件及其实际应用 引言 在大数据时代&#xff0c;如何高效处理和存储海量数据成为企业面临的重大挑战。根据Gartner的统计&#xff0c;到2025年&#xff0c;全球数据量将达到175泽字节&#xff08;ZB&#xff09;&#xff0c;传…

07 输入捕获和编码器接口

前言 前面介绍了定时器和输出比较&#xff0c;这一节主要介绍一下输入捕获测量输入频率和PWM占空比&#xff0c;然后介绍一下编码器接口。 一、输入捕获 1.什么是输入捕获 当输入的引脚有指定电平跳变时&#xff0c;会将计数器CNT中的值保存在CCR中&#xff0c;这个就称为输…

JDK 1.8从下载、安装、配置、以及检查是否安装成功,最详细教学教程

参考&#xff1a; JDK1.8下载、安装和环境配置教程(2024年6月5日)-CSDN博客 以下所有步骤&#xff0c;jjycheng作者亲测,所以截图是我自己截取的&#xff0c;和原文略有不同。这也是为什么我可耻的选择“原创”的原因。。。哈哈。。。 一、下载安装包 链接&#xff1a;https:/…

pycharm安装与配置Pyqt5

pycharm安装与配置Pyqt5 1、创建项目、虚拟环境 打开pycharm&#xff0c;File->New Project 2、安装pyqt5库 在pycharm下方Terminal终端窗口输入&#xff1a; pip install PyQt5 -i https://pypi.douban.com/simple pip install PyQt5-tools -i https://pypi.douban.c…

【C++】简约与清晰的编程艺术

C编程的艺术&#xff1a;简约与清晰的实践之道 一、基础之美&#xff1a;基本类型与数据结构的力量二、函数与库类的艺术三、简约与清晰的实践之道 在C这一既古老又充满活力的编程语言世界里&#xff0c;程序员们常常面临着一个重要的选择&#xff1a;是追求代码的极致抽象与封…

【Elasticsearch】Elasticsearch的分片和副本机制

文章目录 &#x1f4d1;前言一、分片&#xff08;Shard&#xff09;1.1 分片的定义1.2 分片的重要性1.3 分片的类型1.4 分片的分配 二、副本&#xff08;Replica&#xff09;2.1 副本的定义2.2 副本的重要性2.3 副本的分配 三、分片和副本的机制3.1 分片的创建和分配3.2 数据写…

发送邮件API接口的安全性保障措施有哪些?

发送邮件API接口的性能如何评估&#xff1f;API接口的使用方法&#xff1f; 发送邮件API接口已经成为了许多应用和服务的核心功能之一。确保发送邮件API接口的安全性对于保护用户隐私和数据完整性至关重要。AokSend将详细探讨发送邮件API接口的安全性保障措施。 发送邮件API接…

查找算法:线性查找,golang实现

目录 前言 线性查找 代码示例 1. 算法包 2. 线性查找代码 3. 模拟程序 4. 运行程序 循环次数 假如目标值正好在数组中的第一位 假如目标值正好在数组中的第五位 假如目标值正好在数组中的最后一位 假如目标值不在数组中 线性查找的思想 1. 顺序遍历 2. 比较 3.…

使用GPT-4插件增强LLM的功能

文章目录 GPT-4插件概述插件清单OpenAPI规范描述GPT-4插件 尽管包括GPT-4在内的LLM在各种任务上都现出色,但它们仍然存在面有的局限性。比如,这些模型只能从训练数据中学习,这些数据往往过时或不造用于特定的应用。此外,它们的能力仅限于文本生成。我们还发现,LLM不适应于…

人工智能深度学习系列—深度学习中的边界框回归新贵:GHM(Generalized Histogram Loss)全解析

文章目录 1. 背景介绍2. Loss计算公式3. 使用场景4. 代码样例5. 总结 1. 背景介绍 目标检测作为计算机视觉领域的核心技术之一&#xff0c;其精确度的提升一直是研究者们追求的目标。边界框回归作为目标检测中的关键步骤&#xff0c;其性能直接影响到检测的准确性。本文将详细…

“火炬科企对接”先进计算产业推进会 | 麒麟信安受邀参加,并签署开源生态合作协议

7月30日&#xff0c;“火炬科企对接”先进计算产业推进会在长沙隆重召开。大会由工业和信息化部火炬高技术产业开发中心、湖南省科学技术厅、湖南省工业和信息化厅、湖南湘江新区管理委员会、中国邮政储蓄银行联合举办。麒麟信安与来自国内先进计算领域的专家学者&#xff0c;2…

25考研数据结构复习·7.3树形查找

目录 二叉排序树 平衡二叉树 平衡二叉树的删除 红黑树 红黑树的插入 红黑树的删除 二叉排序树 二叉排序树的定义 &#x1f469;‍&#x1f4bb; 左子树结点值 < 根节点值 < 右子树结点值默认不允许两个结点的关键字相同查找操作 从根节点开始&#xff0c;目标值更…

用 VS Code 开发 uni-app 项目

文章目录 1.为什么选择 VS Code &#xff1f;2.安装相关插件2.1 安装uni-app插件2.2 安装ts类型检验 3.在微信小程序中运行 1.为什么选择 VS Code &#xff1f; ⚫ HbuilderX 对 TS 类型支持暂不完善 ⚫ VS Code 对 TS 类型支持友好&#xff0c;同时VS Code 也是我们熟悉的编辑…

移远通信LTE-A模组EM060K-GL成为ChromeOS准入供应商

近日&#xff0c;全球领先的物联网整体解决方案移远通信宣布&#xff0c;其先进的LTE-A模组EM060K-GL已进入谷歌Chrome OS准入供应商名录&#xff0c;后续将作为候选模组用于搭载Chrome OS系统的笔记本电脑中&#xff0c;为其提供“始终在线”的网络连接体验。这一重要里程碑彰…