109. UE5 GAS RPG 实现检查点的存档功能
在这一篇文章里,我们接着实现存档的功能,保存当前玩家的生成位置,游戏里有很多中方式去实现玩家的位置存储,这里我们采用检查点的方式,当玩家接触到当前检查点后,我们可以通过检查点进行保存玩家的状态,后续也能够实现检查点移动玩家等等功能。
实现定义角色生成位置
存档加载关卡后,需要一个出生位置,如果场景里有多个PlayerStart,我们如何确定让角色在哪个PlayerStart生成呢?
答案是,我们可以为每个PlayerStart设置标签,然后覆写GameMode的选择初始点的函数来实现。
首先,我们实现对数据的全局存储,这里需要使用到GameInstance,我们将其作为父类,实现一个派生类,来实现自定义的需求。
设置自定义命名
在类里,我们存储几个值,一个是切换关卡时需要获取的PlayerStart的标签命名,另外就是如果需要保存,所需的存档名称和索引。
UCLASS()
class RPG_API URPGGameInstance : public UGameInstance
{GENERATED_BODY()public://角色进入关卡后默认生成的PlayerStart的TagUPROPERTY()FName PlayerStartTag = FName();//当前使用的或后续保存内容到的存档名称UPROPERTY()FString LoadSlotName = FString();//当前使用活后续保存的存档索引UPROPERTY()int32 LoadSlotIndex = 0;
};
然后在我们自定义的GameMode里增加一个参数用于设置玩家生成的PlayerStart的标签
//角色切换关卡后默认生成位置的PlayerStart的标签UPROPERTY(EditDefaultsOnly)FName DefaultPlayerStartTag;//覆写父类的选择PlayerStart函数,修改为可以通过Tag获取生成位置virtual AActor* ChoosePlayerStart_Implementation(AController* Player) override;
函数实现这里,我们会获取到关卡里的所有的PlayerStart,然后从GameInstance获取需要生成的标签,遍历获取到对应的PlayerStart生成,所以,只需要在进入关卡前,将GameInstance的标签修改了然后进入场景时,就可以自动寻找对应的PlayerStart去生成。
AActor* ARPGGameMode::ChoosePlayerStart_Implementation(AController* Player)
{const URPGGameInstance* RPGGameInstance = Cast<URPGGameInstance>(GetGameInstance());//获取关卡里的所有PlayerStart实例TArray<AActor*> Actors;UGameplayStatics::GetAllActorsOfClass(GetWorld(), APlayerStart::StaticClass(), Actors);if(Actors.Num() > 0){//获取到第一个实例对象AActor* SelectedActor = Actors[0];for(AActor* Actor : Actors){if(APlayerStart* PlayerStart = Cast<APlayerStart>(Actor)){//判断PlayerStart的Tag设置是否为指定的Tagif(PlayerStart->PlayerStartTag == RPGGameInstance->PlayerStartTag){SelectedActor = PlayerStart;break;}}}return SelectedActor;}return nullptr;
}
添加PlayerStart标签配置
我们需要在存档里实现对关卡里的开始标签的存储,在读取存档进入关卡时,可以明确知道角色需要在哪里生成。
所以,我们需要在LoadScreenSaveMode(存档类)和存档ViewModel视图模型里增加PlayerStart标签配置属性。
//存储玩家关卡出生位置的标签UPROPERTY()FName PlayerStartTag;
在创建新存档时,使用GameMode设置的默认PlayerStart标签
接着在GameMode存储存档时,将存档的视图模型的中的PlayerStart标签存储到存档
存储没问题了,就是读取存档时,将存档里存储的PlayerStart标签设置给存档的视图模型
最后,在我们在加载界面视图模型进入游戏的函数里,在调用加载关卡之前,将PlayerStart标签存储到GameInstance里,进入关卡后,然后再通过我们覆写的函数获取对应标签的PlayerStart
void UMVVM_LoadScreen::EnterGameButtonPressed(const int32 Slot)
{ARPGGameMode* RPGGameMode = Cast<ARPGGameMode>(UGameplayStatics::GetGameMode(this));//设置全局数据,方便后续使用URPGGameInstance* RPGGameInstance = Cast<URPGGameInstance>(RPGGameMode->GetGameInstance());RPGGameInstance->LoadSlotName = LoadSlots[Slot]->GetSlotName();RPGGameInstance->LoadSlotIndex = LoadSlots[Slot]->SlotIndex;RPGGameInstance->PlayerStartTag = LoadSlots[Slot]->PlayerStartTag;//进入场景RPGGameMode->TravelToMap(LoadSlots[Slot]);
}
创建蓝图
接下来,我们编译打开UE,在BP_GameMode里设置默认选择的PlayerStart的标签
接着,我们基于GameInstance类创建一个蓝图
设置命名
在项目设置里,将默认的GameInstance修改为我们所需的GameInstance
最后,我们在场景里设置PlayerStart的标签,注意,如果多个PlayerStart设置了相同的对应的标签,角色将在第一个获取的PlayerStart的位置生成。
创建检查点
在正常游戏流程里,为了保存游戏进度,开发者会使用某种方式让进度保存下来,比如到达某个进度后自动保存,又或者像生化危机里的打字机。
这里,我们将实现一种检查点的类,在角色接触后,自动保存当前进度。
命名为检查点类,我们将在里面增加一些额外的内容。
在类里,我们将增加两个属性,用于显示检查点的模型和触发保存游戏的碰撞盒子
private://检查点显示的模型UPROPERTY(VisibleAnywhere)TObjectPtr<UStaticMeshComponent> CheckpointMesh;//检查点模型使用的碰撞体UPROPERTY(VisibleAnywhere)TObjectPtr<USphereComponent> Sphere;
然后增加一个函数,用于玩家角色和碰撞球碰撞后的逻辑处理
/*** 球碰撞体和物体发生碰撞后的回调* @param OverlappedComponent 发生重叠事件的自身的碰撞体对象* @param OtherActor 目标的actor对象* @param OtherComp 目标的碰撞体组件* @param OtherBodyIndex 目标身体的索引* @param bFromSweep 是否为瞬移检测到的碰撞* @param SweepResult 如果位置发生过瞬移(直接设置到某处),两个位置中间的内容会记录到此对象内*/UFUNCTION()virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
接着增加一个函数,玩家角色碰撞后的函数处理,主要里面是创建了一个新的材质实例,修改自发光,表示检查点已经激活。
//当玩家角色和检测点产生碰撞后,检查点被激活触发此函数void HandleGlowEffects();
由于自发光亮起需要时间轴,这个比较方便在蓝图里实现,我们再增加一个需蓝图实现的函数。
/*** 检查点激活后的处理,需要在蓝图中对其实现* @param DynamicMaterialInstance 传入检查点模型的材质实例*/UFUNCTION(BlueprintImplementableEvent)void CheckpointReached(UMaterialInstanceDynamic* DynamicMaterialInstance);
以下是整个.h文件
// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "GameFramework/PlayerStart.h"
#include "CheckPoint.generated.h"class USphereComponent;
/*** */
UCLASS()
class RPG_API ACheckPoint : public APlayerStart
{GENERATED_BODY()public://构造函数ACheckPoint(const FObjectInitializer& ObjectInitializer);protected:virtual void BeginPlay() override;/*** 球碰撞体和物体发生碰撞后的回调* @param OverlappedComponent 发生重叠事件的自身的碰撞体对象* @param OtherActor 目标的actor对象* @param OtherComp 目标的碰撞体组件* @param OtherBodyIndex 目标身体的索引* @param bFromSweep 是否为瞬移检测到的碰撞* @param SweepResult 如果位置发生过瞬移(直接设置到某处),两个位置中间的内容会记录到此对象内*/UFUNCTION()virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);/*** 检查点激活后的处理,需要在蓝图中对其实现* @param DynamicMaterialInstance 传入检查点模型的材质实例*/UFUNCTION(BlueprintImplementableEvent)void CheckpointReached(UMaterialInstanceDynamic* DynamicMaterialInstance);//当玩家角色和检测点产生碰撞后,检查点被激活触发此函数void HandleGlowEffects();
private://检查点显示的模型UPROPERTY(VisibleAnywhere)TObjectPtr<UStaticMeshComponent> CheckpointMesh;//检查点模型使用的碰撞体UPROPERTY(VisibleAnywhere)TObjectPtr<USphereComponent> Sphere;
};
在cpp里,我们对函数进行实现,首先在构造函数里,我们实例化模型和碰撞体。
ACheckPoint::ACheckPoint(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer)
{//关闭帧更新PrimaryActorTick.bCanEverTick = false;//创建检测点显示模型CheckpointMesh = CreateDefaultSubobject<UStaticMeshComponent>("CheckpointMesh");CheckpointMesh->SetupAttachment(GetRootComponent());CheckpointMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); //设置查询并产生物理CheckpointMesh->SetCollisionResponseToChannels(ECR_Block); //设置阻挡所有物体与其重叠//设置球碰撞体Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");Sphere->SetupAttachment(CheckpointMesh);Sphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly); //设置其只用作查询使用Sphere->SetCollisionResponseToChannels(ECR_Ignore); //设置其忽略所有碰撞检测Sphere->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap); //设置其与Pawn类型物体产生重叠事件
}
在游戏开始时,绑定球碰撞体的重叠函数
void ACheckPoint::BeginPlay()
{Super::BeginPlay();//绑定重叠事件Sphere->OnComponentBeginOverlap.AddDynamic(this, &ACheckPoint::OnSphereOverlap);
}
接着实现重叠函数,在触发重叠时,我们需要实现保存当前的检查点标签,然后在调用碰撞后处理函数
void ACheckPoint::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{//if(OtherActor->ActorHasTag("Player")) //如果只需要判断是不是玩家角色通过标签判断即可if(OtherActor->Implements<UPlayerInterface>()){//修改存档当的检测点IPlayerInterface::Execute_SaveProgress(OtherActor, PlayerStartTag);//如果与碰撞体重叠的是HandleGlowEffects();}
}
然后我们取消碰撞检测,提升性能,并创建一个新的材质实例,调用蓝图函数实现渐变发光效果。
void ACheckPoint::HandleGlowEffects()
{//取消碰撞检查Sphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);//创建一个新材质实例,修改效果UMaterialInstanceDynamic* DynamicMaterialInstance = UMaterialInstanceDynamic::Create(CheckpointMesh->GetMaterial(0), this);CheckpointMesh->SetMaterial(0, DynamicMaterialInstance);CheckpointReached(DynamicMaterialInstance); //触发检查点修改材质后的回调
}
编译代码,打开UE,创建一个基于类的蓝图
在检测点里,我们需要修改碰撞体大小和检查点的模型
大致效果如下,可以按需设置
在平视角,我们需要将PlayerStart和模型水平,这样保证放置的时候,防止PlayerStart的位置靠下,生成角色生成到地面以下。
拖入场景中,点击End建,检测点将会自动附着到地面,青蓝色箭头是玩家在检查点生成位置和朝向,黄色碰撞球是激活检测点范围。
接着,我们修改材质,增加自发光相关节点,设置GlowEnd最大亮度,以及GlowControl来控制进度,GlowControl值为1时,将达到亮度的最大值。
接着,我们创建一个实例,去调节对应的参数。
接着,在蓝图里,实现碰撞函数回调,使用时间轴修改GlowControl
在时间轴里去修改更新的值
我们将放置到场景里的检查点的设置其标签,可以用来实现保存通过标签去寻找位置。
实现PlayerStart标签的保存
我们要实现玩家角色在场景中接触到检查点后,更新存档,将当前的检查点的值保存到存档里。
首先在GameMode类里增加两个函数,一个用于获取当前使用的存档,另一个是将修改后的存档保存下来。
//获取到当前游戏进行中所使用的存档数据ULoadScreenSaveGame* RetrieveInGameSaveData() const;/*** 保存游戏中的进度* @param SaveObject 需要保存的数据*/void SaveInGameProgressData(ULoadScreenSaveGame* SaveObject) const;
实现这里,我们可以在GameInstance身上获取到存档使用的Name和Index,通过这两项获取到存档数据。
保存函数这里,我们还需要使用存档的标签去修改GameInstance身上的PlayerStart的标签。然后保存。
ULoadScreenSaveGame* ARPGGameMode::RetrieveInGameSaveData() const
{const URPGGameInstance* RPGGameInstance = Cast<URPGGameInstance>(GetGameInstance());//从游戏实例获取到存档名称和索引const FString InGameLoadSlotName = RPGGameInstance->LoadSlotName;const int32 InGameLoadSlotIndex = RPGGameInstance->LoadSlotIndex;//获取已保存的存档数据return GetSaveSlotData(InGameLoadSlotName, InGameLoadSlotIndex);
}void ARPGGameMode::SaveInGameProgressData(ULoadScreenSaveGame* SaveObject) const
{URPGGameInstance* RPGGameInstance = Cast<URPGGameInstance>(GetGameInstance());//修改下一次复活的检测点RPGGameInstance->PlayerStartTag = SaveObject->PlayerStartTag;//从游戏实例获取到存档名称和索引const FString InGameLoadSlotName = RPGGameInstance->LoadSlotName;const int32 InGameLoadSlotIndex = RPGGameInstance->LoadSlotIndex;//保存存档UGameplayStatics::SaveGameToSlot(SaveObject, InGameLoadSlotName, InGameLoadSlotIndex);
}
接着在玩家角色接口这里增加一个函数,用于碰撞触发后保存存档使用
//保存游戏进度UFUNCTION(BlueprintNativeEvent, BlueprintCallable)void SaveProgress(const FName& CheckpointTag);
在玩家基类里覆写
virtual void SaveProgress_Implementation(const FName& CheckpointTag) override;
实现这里,我们获取到GameMode,然后获取存档,修改存档数据,并保存回去。
void ARPGHero::SaveProgress_Implementation(const FName& CheckpointTag)
{if(const ARPGGameMode* GameMode = Cast<ARPGGameMode>(UGameplayStatics::GetGameMode(this))){//获取存档ULoadScreenSaveGame* SaveGameData = GameMode->RetrieveInGameSaveData();if(SaveGameData == nullptr) return;//修改存档数据SaveGameData->PlayerStartTag = CheckpointTag;//保存存档GameMode->SaveInGameProgressData(SaveGameData);}
}
我们在与检查点碰撞时,已经调用此函数,实现了存档的修改保存。
最后,我们在场景里多加几个检查点,来测试效果。创建文档,角色会生成在一个检查点上,然后我们走到另一个检查点上,重新进入游戏,查看角色下一次会不会生成在最后退出的检查点旁边,如果能够证明代码无误。
实现角色已经激活的检测点一直高亮
我们现在制作的当前检查点效果,还没有实现的一项是,让玩家已经激活的检查点一直保持高亮状态,这样,如果玩家迷路了,可以清除的得知这一段路之前探索过。
为了实现这个效果,我们需要将之前已经探索到的检查点都记录下来,然后在进入场景后,每次激活,将信息记录到存档里。在进入一个新关卡时,在GameMode的BeginPlayer会触发,我们会在此函数里处理检查点是否需要高亮。
首先,我们在SaveGame类增加一个参数,用于存储检查点数组,用于存储角色已经激活的检查点
//当前已经激活的检测点UPROPERTY()TArray<FName> ActivatedPlayerStatTags = TArray<FName>();
然后将检查点类的激活函数修改为public,这样,可以在类以外调用
接着,我们增加一个私有函数用于高亮已经激活的检查点
private://高亮已经激活的检查点void HighlightEnabledCheckpoints(TArray<AActor*> CheckPoints) const;
函数实现,我们将获取存档,并遍历所有的检查点,如果检查点的Tag存在于已激活的数组内,我们将检查点进行高亮显示。
void ARPGGameMode::HighlightEnabledCheckpoints(TArray<AActor*> CheckPoints) const
{//获取存档ULoadScreenSaveGame* SaveGameData = RetrieveInGameSaveData();if(SaveGameData == nullptr) return;//遍历关卡内的所有的检查点,如果数组里存在,将高亮显示for(AActor* Actor : CheckPoints){if(ACheckPoint* CheckPoint = Cast<ACheckPoint>(Actor)){if(SaveGameData->ActivatedPlayerStatTags.Contains(CheckPoint->PlayerStartTag)){CheckPoint->HandleGlowEffects();}}}
}
在关卡打开后,生成角色时,我们调用此函数,进行场景关卡的检查点进行初始化高亮
最后,还有保存已经激活的检查点,我们可以选择在保存角色的存档时候,将当前检查点的标签保存进去。
重点,你每个添加到关卡的检查点,要做到全局不同,也就是每个关卡的检查点都不要重名,我们可以考虑关卡+检查点的索引方式去设置检查点的tag。
相关文章:
109. UE5 GAS RPG 实现检查点的存档功能
在这一篇文章里,我们接着实现存档的功能,保存当前玩家的生成位置,游戏里有很多中方式去实现玩家的位置存储,这里我们采用检查点的方式,当玩家接触到当前检查点后,我们可以通过检查点进行保存玩家的状态&…...
springboot005基于springboot学生心理咨询评估系统得设计与实现。
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…...
ESC算法/逃生:一种基于人群疏散行为的优化方法
文章介绍了一种有用的算法,称为逃生或逃生算法(ESC),受人群疏散行为的启发,用于解决现实世界的案例和基准问题。ESC算法模拟了疏散过程中人群的行为,其中人群在探索阶段被分为平静、羊群和恐慌组࿰…...
构建安全的数据库环境:群晖NAS安装MySQL和phpMyAdmin详细步骤
文章目录 前言1. 安装MySQL2. 安装phpMyAdmin3. 修改User表4. 本地测试连接MySQL5. 安装cpolar内网穿透6. 配置MySQL公网访问地址7. 配置MySQL固定公网地址8. 配置phpMyAdmin公网地址9. 配置phpmyadmin固定公网地址 前言 本文将详细讲解如何在群晖NAS上安装MySQL及其数据库管理…...
【人工智能】深入理解图神经网络(GNN):用Python实现社交网络节点分类与分子结构分析
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 图神经网络(Graph Neural Network, GNN)是近年来在深度学习领域迅速发展的新兴方向,主要用于处理图结构数据。GNN在社交网络分析、化学分…...
Qt 日志文件的滚动写入
Qt 日志文件的滚动写入 flyfish 日志文件的滚动写入功能。在日志文件达到10MB时创建新的日志文件,并且在总日志文件大小达到10GB时开始覆盖最早的日志文件 以监控一个文件夹的写日志为例 日志文件创建与管理 初始化日志文件:在FileMonitor类的构造函…...
【c语言】数据包捕获和分析工具
请解释一下数据包捕获和分析工具(如Wireshark)的工作原理和用途。 数据包捕获和分析工具,如Wireshark(前身为Ethereal),是一种网络协议分析软件,它允许用户实时监控、抓取并分析计算机网络中的网…...
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(2)(模拟实现)
1.概念介绍 1.1开散列 开散列(Open Hashing),也叫链地址法,是一种解决哈希冲突的方法。每个哈希表槽位保存一个链表,所有散列到同一位置的元素都存储在该链表中。当插入元素发生冲突时,将新元素添加到相应…...
请描述一下JVM(Java虚拟机)的生命周期及其对应用程序性能的影响
1、请描述一下JVM(Java虚拟机)的生命周期及其对应用程序性能的影响。 JVM(Java虚拟机)的生命周期主要涉及以下几个阶段:加载、验证、准备、解析、执行、卸载。每个阶段都有其特定的作用和影响。 加载:JVM…...
展会邀约|加速科技与您相约IC China 2024!
第二十一届中国国际半导体博览会( IC China 2024)将于 2024 年11月18日—11月20日在北京国家会议中心举行。加速科技将携高性能测试机ST2500EX、ST2500E、eATE及全系测试解决方案亮相E2馆B150展位。博览会期间,将同期举办"半导体产业前沿…...
鸿蒙中服务卡片数据的获取和渲染
1. 2.在卡片中使用LocalStorageProp接受传递的数据 LocalStorageProp("configNewsHead") configNewsHeadLocal: ConfigNewsHeadInfoItem[] [] 注意:LocalStorageProp括号中的为第一步图片2中的键 3.第一次在服务卡片的第一个卡片中可能会获取不到数据…...
运维篇-修复centos7无法下载docker问题
修复centos7无法下载docker问题 1、安装docker时报错2、docker无法下载镜像 1、安装docker时报错 linux的centos系统,安装docker时会报错 –> Finished Dependency Resolution Error: Package: glibc-2.17-307.el7.1.i686 (base) Requires: glibc-common 2.17…...
【论文阅读】WaDec: Decompiling WebAssembly Using Large Language Model
论文阅读笔记:WaDec: Decompiling WebAssembly Using Large Language Model 1. 来源出处 论文标题: WaDec: Decompiling WebAssembly Using Large Language Model作者: Xinyu She, Yanjie Zhao, Haoyu Wang会议: 39th IEEE/ACM International Conference on Automated Softwar…...
redis类型介绍
1. 字符串(String): • 简介:最基础的数据类型,可以存储任何形式的字符串,包括文本数据和数字数据。 • 常用操作:SET、GET、INCR、DECR等。 2. 列表(List): …...
kubernetes如何配置默认存储
如果不想每次都创建PV,希望k8s集群中能够配置号默认存储,然后根据你的PVC自动创建PV,就需要安装一个默认存储,也就是storageclass 什么是storageclass Kubernetes提供了一套可以自动创建PV的机制,即:Dyna…...
【微服务】Spring AI 使用详解
目录 一、前言 二、Spring AI 概述 2.1 什么是Spring AI 2.2 Spring AI 特点 2.3 Spring AI 带来的便利 2.4 Spring AI 应用领域 2.4.1 聊天模型 2.4.2 文本到图像模型 2.4.3 音频转文本 2.4.4 嵌入大模型使用 2.4.5 矢量数据库支持 2.4.6 数据工程ETL框架 三、Sp…...
DataGrip 连接 dm
参考链接 使用DataGrip链接达梦数据库_datagrip连接达梦数据库-CSDN博客 下载 jdbc 驱动包 第一种 通过链接下载:下载 第二种【特指 window 安装包】 在达梦安装包 iso 文件里面 source/drivers/jdbc 将驱动添加进 DataGrip 选中 jdbc 驱动包,然后选…...
数据库监控工具DBdoctor v3.2.4.3版本发布,新增对openGauss、Vastbase G100的支持!
新引擎扩展 新增对openGauss数据库的支持:支持对openGauss数据库的SQL审核、实例巡检、性能洞察、锁透视、根因诊断、基础监控、索引推荐、存储分析; 新增对Vastbase G100数据库的支持:支持对Vastbase G100数据库的SQL审核、实例巡检、性能洞…...
Git 常用命令大全与详解
Git 是一种广泛使用的分布式版本控制系统。无论是管理个人项目还是进行团队协作,掌握 Git 的常用命令都是开发者必备的技能之一。本文将介绍一些常用的 Git 命令,并对其进行详细说明。 1. 基础命令 初始化仓库 git init:在当前目录下初始化…...
执行flink sql连接clickhouse库
手把手教学,flink connector打通clickhouse大数据库,通过下发flink sql,来使用ck。 组件版本jdk1.8flink1.17.2clickhouse23.12.2.59 1.背景 flink官方不支持clickhouse连接器,工作中难免会用到。 2.方案 利用GitHub大佬提供…...
什么是C++中的友元函数和友元类?
友元函数(Friend Function)和 友元类(Friend Class)是用于控制类的访问权限的机制。这允许特定的函数或类访问另一个类的私有成员和保护成员,打破了 C 的封装性规则。 友元函数 定义 友元提供了不同类的成员函数之间…...
基于Spring Boot+Vue的多媒体素材管理系统的设计与实现
一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构:B/S架构 运行环境:win10/win11、jdk17 前端: 技术:框架Vue.js;UI库:ElementUI; 开发工具&…...
Inpaint-Web:纯浏览器端实现的开源图像处理工具
之前在刷短视频的时候,经常看到一些情侣在景区拍照,结果被路人“抢镜”。有时男朋友会拿出手机,帮忙把那些路人“P”掉,简直是既贴心又有趣。最近我在逛 GitHub 时,发现了一个可以在浏览器端删除照片中部分内容的纯前端…...
商业物联网详细指南:优势与挑战
物联网是信息技术行业最具前景的领域之一。为什么它如此热门呢?原因在于全球连接性。设备可以像人群一样相互协作。正如我们所知,协作能显著提高生产力。 物联网对普通用户和企业都有益处。许多日常流程可以通过传感器、扫描仪、摄像头和其他设备实现自…...
如何在项目中用elementui实现分页器功能
1.在结构部分复制官网代码: <template> 标签: 这是 Vue 模板的根标签,包含所有的 HTML 元素和 Vue 组件。 <div> 标签: 这是一个普通的 HTML 元素,包裹了 el-pagination 组件。它没有特别的意义,只是为了确保 el-pagi…...
Nginx参数配置-笔记
文章目录 upstream实现后台应用服务负载均衡&高可用proxy_set_header参数 upstream实现后台应用服务负载均衡&高可用 角色IPnginx172.168.110.2后端应用服务1172.168.110.3后端应用服务2172.168.110.4后端应用服务3(备用)172.168.110.5 示例如下: upstre…...
衡量神经网络表征相似度
目录 1.中心核对齐技术(CKA)2.Hilbert-Schmidt independence criterion(HSIC)HSIC的计算步骤:HSIC的性质:应用:矩阵中心化操作对于单个数据集的中心化对于两个数据集的中心化(例如,用于HSIC)Python代码示例1.中心核对齐技术(CKA) CKA通过计算两个表征的Gram矩阵(即…...
Javascript高级:深度解析与多种实现方式数组扁平化
数组扁平化:深度解析与多种实现方式 在JavaScript编程中,数组扁平化是一个常见的操作,指的是将一个多维数组转换成一个一维数组。这个过程中,所有嵌套的数组元素都会被“拉平”到同一个层级。数组扁平化在处理嵌套数据结构时非常…...
SpringBoot Data Redis连接Redis-Cluster集群
使用SpringBoot Data Redis无法连接Redis-Cluster集群 最近在研究系统高并发下的缓存架构,因此自己在自己买的云服务器上搭建好Redis 5.0 版本的集群后,使用springboot的 RedisTemplate连接是发现总是访问不到集群节点。上网百度了发现没有好的解决办法&…...
计算机网络——TCP篇
TCP篇 基本认知 TCP和UDP的区别? TCP 和 UDP 可以使用同一个端口吗? 可以的 传输层中 TCP 和 UDP在内核中是两个完全独立的软件模块。可以根据协议字段来选择不同的模块来处理。 TCP 连接建立 TCP 三次握手过程是怎样的? 一次握手:客户端发送带有 …...
四川酒店网站建设/google推广妙招
在前面的文章中,我们了解CoreData据是什么。本文我们将深入到Core Data框架的内部,掌握一下Core Data Stack的重要组成部分 managed object modelmanaged object contextpersistent store coordinatorJietu20200407-1932362x.jpg文章推荐 SwiftUI CoreD…...
网站 手机兼容/如何做免费网络推广
最近被OSD折腾了个半死。RP问题都出了,甚至还有几个遗留问题没有解决。 不过倒是好好学习了一下SCCM OSD排错方面的知识,给大家分享一下。 要进行故障分析,我们先要了解一下OSD的原理。 我们从需要被部署的客户机从开机分析整个流程ÿ…...
成都网站建设哪家专业/营销平台是什么意思
今天来说说软件测试工程师的面试吧。毕竟,面试,决定了你以后一段时间内的薪资待遇。 最近自己因为跟外包公司出现了些问题,让我非常不满,所以重新投了简历观望有没有合适的机会跳槽。 我才转行3个月,现在跳槽其实是非…...
网站建设好不好/网站托管服务商
需求 有个需求是根据点击树节点后,根据树节点的父级节点结构查询数据 element plus 树节点点击事件有4个参数 Tree 树形控件 | Element Plusa Vue 3 based component library for designers and developershttps://element-plus.gitee.io/zh-CN/component/tree.h…...
老域名新网站推广/百度一下百度主页
今天注意到JavaScript里的一个特性:一个变量被重新声明后,其之前的赋值还是存在的。 var test "test"; console.debug(test) ;//output: test var test; console.debug(test);// also output: test转载于:https://www.cnblogs.com/buhaiqing/a…...
wordpress 官方网站/服务营销策划方案
--select into 从一个表复制数据值内容到另外一个表里面,把数据插入到另外一个新表中/* 一般插入语句都是insert into 表 () values ()特殊需要就要用这种方法了insert into 表1 () select ....from 表2 复杂一点的,比如涉及到2个以上的表:insert into 表名1(字段1,字段2,字…...