当前位置: 首页 > news >正文

游戏落地页网站建设/网络服务投诉平台

游戏落地页网站建设,网络服务投诉平台,阜新建设网站,科讯网站发布文章实现角色的技能存档保存和加载 首先,我们在LoadScreenSaveGame.h文件里,增加一个结构体,用于存储技能相关的所有信息 //存储技能的相关信息结构体 USTRUCT(BlueprintType) struct FSavedAbility {GENERATED_BODY()//需要存储的技能UPROPERT…

实现角色的技能存档保存和加载

首先,我们在LoadScreenSaveGame.h文件里,增加一个结构体,用于存储技能相关的所有信息

//存储技能的相关信息结构体
USTRUCT(BlueprintType)
struct FSavedAbility
{GENERATED_BODY()//需要存储的技能UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="ClassDefaults")TSubclassOf<UGameplayAbility> GameplayAbility;//当前技能的等级UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)int32 AbilityLevel = 0;//当前技能的标签UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)FGameplayTag AbilityTag = FGameplayTag();//当前技能的状态标签UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)FGameplayTag AbilityStatus = FGameplayTag();//当前技能装配到的插槽,如果技能未装配则为空UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)FGameplayTag AbilityInputTag = FGameplayTag();//当前技能的类型(主动技能还是被动技能)UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)FGameplayTag AbilityType = FGameplayTag();
};

然后重新设置==运算符的方法,如果我们在判断FSavedAbility是否相等时,会通过此函数运算返回布尔结果。

//自定义运算符==,如果左右都是FSavedAbility类型的值,将通过函数内的值判断是否相等。
inline bool operator==(const FSavedAbility& Left, const FSavedAbility& Right)
{return Left.AbilityTag.MatchesTagExact(Right.AbilityTag);
}

然后我们在SaveGame类里添加一个属性,用于保存所有技能属性。

	/************************** 技能 **************************/UPROPERTY()TArray<FSavedAbility> SavedAbilities;

有了相关数据可以存储到存档后,我们可以在角色保存时,实现保存技能相关数据。
在保存数据的时候,我们先将存档里的技能数组清空,然后使用RPGASC->ForEachAbility技能委托遍历所有应用到角色身上的技能,通过结构体设置技能数据,并通过AddUnique添加到数组(前面我们添加了operator==覆写了获取相等的设置)

void ARPGHero::SaveProgress_Implementation(const FName& CheckpointTag)
{if(const ARPGGameMode* GameMode = Cast<ARPGGameMode>(UGameplayStatics::GetGameMode(this))){...SaveGameData->bFirstTimeLoadIn = false; //保存完成将第一次加载属性设置为falseif(!HasAuthority()) return;URPGAbilitySystemComponent* RPGASC = Cast<URPGAbilitySystemComponent>(AbilitySystemComponent);SaveGameData->SavedAbilities.Empty(); //清空数组//使用ASC里创建的ForEach函数循环获取角色的技能,并生成技能结构体保存FForEachAbility SaveAbilityDelegate;SaveAbilityDelegate.BindLambda([this, RPGASC, SaveGameData](const FGameplayAbilitySpec& AbilitySpec){//获取技能标签和const FGameplayTag AbilityTag = URPGAbilitySystemComponent::GetAbilityTagFromSpec(AbilitySpec);UAbilityInfo* AbilityInfo = URPGAbilitySystemLibrary::GetAbilityInfo(this);FRPGAbilityInfo Info = AbilityInfo->FindAbilityInfoForTag(AbilityTag);//创建技能结构体FSavedAbility SavedAbility;SavedAbility.GameplayAbility = Info.Ability;SavedAbility.AbilityLevel = AbilitySpec.Level;SavedAbility.AbilityTag = AbilityTag;SavedAbility.AbilityStatus = RPGASC->GetStatusTagFromAbilityTag(AbilityTag);SavedAbility.AbilityInputTag = RPGASC->GetInputTagFromAbilityTag(AbilityTag);SavedAbility.AbilityType = Info.AbilityType;SaveGameData->SavedAbilities.AddUnique(SavedAbility);});//调用ForEach技能来执行存储到存档RPGASC->ForEachAbility(SaveAbilityDelegate);//保存存档GameMode->SaveInGameProgressData(SaveGameData);}
}

ForEach技能就是传入一个委托,然后遍历所有的应用技能。
在这里插入图片描述
接着,在ASC里增加一个通过存档数据设置角色技能的函数。
我们遍历存储的技能,根据技能是主动技能还是被动技能,应用给角色。

void URPGAbilitySystemComponent::AddCharacterAbilitiesFormSaveData(ULoadScreenSaveGame* SaveGameData)
{for(const FSavedAbility& Data : SaveGameData->SavedAbilities){const TSubclassOf<UGameplayAbility> LoadedAbilityClass = Data.GameplayAbility;FGameplayAbilitySpec LoadedAbilitySpec = FGameplayAbilitySpec(LoadedAbilityClass, Data.AbilityLevel);LoadedAbilitySpec.DynamicAbilityTags.AddTag(Data.AbilityInputTag); //设置技能激活输入标签LoadedAbilitySpec.DynamicAbilityTags.AddTag(Data.AbilityStatus); //设置技能状态标签//主动技能的处理if(Data.AbilityType == FRPGGameplayTags::Get().Abilities_Type_Offensive){GiveAbility(LoadedAbilitySpec); //只应用不激活}//被动技能的处理else if(Data.AbilityType == FRPGGameplayTags::Get().Abilities_Type_Passive){//确保技能已经装配if(Data.AbilityStatus.MatchesTagExact(FRPGGameplayTags::Get().Abilities_Status_Equipped)){GiveAbilityAndActivateOnce(LoadedAbilitySpec); //应用技能并激活}else{GiveAbility(LoadedAbilitySpec); //只应用不激活}}}bStartupAbilitiesGiven = true;AbilityGivenDelegate.Broadcast();
}

接下来,我们编译打开UE,查看现在角色身上装配的技能,这些技能我们保存需要技能对应的资产数据
在这里插入图片描述
接着,我们给一些不需要操作的被动技能添加标签,这个被动技能主要是监听属性加点,我们通过加点是,会发送事件,此技能会接受事件通过GE给角色增加属性值。
在这里插入图片描述
我们在技能的数据资产里增加对应的配置,由于不需要显示,我们不需要设置Icon
在这里插入图片描述
还有之前制作的眩晕技能也需要配置数据
在这里插入图片描述
删除多余的测试技能,就可以去测试。
在这里插入图片描述

处理加载时的一些bug

首先,第一个bug是我这边通过存档进入时,激活的技能不显示,这个问题的原因是初始化时,对应的面板控制器没有初始化,不使用存档时没这个问题是因为我们打开对应面板时进行的初始化。
解决方案是,在HUD初始化面板时,我们将对应的控制器都初始化一下即可
在这里插入图片描述
第二个问题,被动技能特效无法显示,出现这个问题的原因是因为在ASC通过存档初始化技能时,对应的被动技能效果组件还没有执行绑定监听,解决这个问题的方式是,我们在绑定监听时,调用一次即可。
在这里插入图片描述

实现保存场景状态

我们实现了对技能的保存,接下来,我们实现可以在存档里,将角色进入过的场景的状态也保存。
我们要在存档里保存场景的数据,首先在场景里创建对应的数据类型,对于场景的Actor,我们考虑使用结构体保存,并通过UE内置的序列器,进行对Actor的数据进行序列化存储到存档,并在使用的时候,通过反序列化,应用会角色身上。
这里,我们增加两个结构体,一个用于保存关卡场景里的Actor,另一个是保存所在的关卡,这样 ,我们可以通过进入的关卡,获取到对应关卡的Actor数据,并应用回去。

//保存场景中的Actor结构体
USTRUCT()
struct FSavedActor
{GENERATED_BODY()UPROPERTY()FName ActorName = FName();UPROPERTY()FTransform Transform = FTransform();//Actor身上序列号的数据,必须通过UPROPERTY定义过,只在保存存档时使用。UPROPERTY()TArray<uint8> Bytes;
};//自定义运算符==,如果结构体内的ActorName相同,这代表这两个结构体为相同结构体
inline bool operator==(const FSavedActor& Left, const FSavedActor& Right)
{return Left.ActorName == Right.ActorName;
}//地图相关数据保存
USTRUCT()
struct FSavedMap
{GENERATED_BODY()UPROPERTY()FString MapAssetName = FString();UPROPERTY()TArray<FSavedActor> SavedActors;
};

接着,我们在存档类里,添加一个属性,可以通过此属性可以获取到所有保存的关卡数据,并增加两个函数 ,用于获取对应的关卡数据和判断存档里是否有对应关卡的数据。

	UPROPERTY()TArray<FSavedMap> SavedMaps;//通过地图名称获取地图数据FSavedMap GetSavedMapWithMapName(const FString& InMapName);//判断存档是否含有对于地图数据bool HasMap(const FString& InMapName);

实现对应的函数,通过遍历判断名称来实现。

FSavedMap ULoadScreenSaveGame::GetSavedMapWithMapName(const FString& InMapName)
{for(const FSavedMap& Map : SavedMaps){if(Map.MapAssetName == InMapName){return Map;}}return FSavedMap();
}bool ULoadScreenSaveGame::HasMap(const FString& InMapName)
{for(const FSavedMap& Map : SavedMaps){if(Map.MapAssetName == InMapName){return true;}}return false;
}

接着,我们增加一个新的接口,新的接口可以用于判断当前场景中的哪些Actor需要保存到存档里
在这里插入图片描述
我们命名新接口
在这里插入图片描述
需要保存的场景的Actor都需要继承此接口。
在这里插入图片描述
我们在接口里增加两个函数,一个是用于判断是否需要修改位置变换,这个功能可以在解密游戏里,解开机关后,开启了某扇密门后,将其保存起来,防止下次还需要继续重新开启。另一个是在从存档里读取数据后,更新Actor。

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "SaveInterface.generated.h"// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class USaveInterface : public UInterface
{GENERATED_BODY()
};/*** */
class RPG_API ISaveInterface
{GENERATED_BODY()// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public://设置Actor是否需要修改位置变换UFUNCTION(BlueprintCallable, BlueprintNativeEvent)bool ShouldLoadTransform();//在存档读取完数据后,调用更新ActorUFUNCTION(BlueprintCallable, BlueprintNativeEvent)void LoadActor();
};

接着,我们修改检查点的类,我们需要将检查点的数据存储到存档里,这里增加了一个变量,用于判断当前检查点是否被激活,并且覆写继承接口的函数。我们不需要修改存档点的位置变换,这里直接返回false,如果像机关密门那种,则需要保存,我们可以设置为true。
将bReached,设置SaveGame时,如果我们将实例序列化存档数据时,它的值将会被存入到存档中,在反序列化时,将存档数据重新设置回来。

	/*   Save Interface   */virtual bool ShouldLoadTransform_Implementation() override { return false; } //是否需要修改变换,检查点不需要virtual void LoadActor_Implementation() override; //通过存档二进制修改Actor数据后,更新Actor/*   End Save Interface   *///当前检查点是否已经被激活,设置SaveGame表示该值将会被存储到存档文件中UPROPERTY(BlueprintReadOnly, SaveGame)bool bReached = false;

我们实现一下LoadActor函数,在从存档读取数据设置完Actor,调用它实现一些处理。

void ACheckPoint::LoadActor_Implementation()
{if(bReached){HandleGlowEffects();}
}

实现场景状态的存储和读取

要实现场景状态的存储和读取,我们在GameMode里增加两个函数,分别处理存储和读取。

	//保存关卡中的状态到当前存档中void SaveWorldState(UWorld* World) const;//从存档中加载当前关卡的状态void LoadWorldState(UWorld* World) const;

首先我们实现对关卡的状态存储,这里说一下逻辑,首先获取到关卡名称,和游戏实例,游戏实例有存档的相关信息,获取到存档对象,判断对应关卡在存档内是否有对应的数据存储,如果没有,新创建一个。
然后获取到对应的关卡数据,将数据内存储的Actor数据清除,遍历关卡内的所有Actor,找到继承保存接口的Actor,创建一个对应Actor的存储数据结构体,通过FMemoryWriter将Actor身上需要保存到存档的数据设置到存档结构体内。
最后,将地图的数据存储到存档对象里。

void ARPGGameMode::SaveWorldState(UWorld* World) const
{//获取关卡名称FString WorldName = World->GetMapName();WorldName.RemoveFromStart(World->StreamingLevelsPrefix); //从关卡名称这里移除指定前缀,当前为移除通常用于标识流式加载的关卡文件前缀//获取到游戏实例URPGGameInstance* RPGGI = Cast<URPGGameInstance>(GetGameInstance());check(RPGGI);//获取存档if(ULoadScreenSaveGame* SaveGame = GetSaveSlotData(RPGGI->LoadSlotName, RPGGI->LoadSlotIndex)){if(!SaveGame->HasMap(WorldName)){//如果存档不包含对应关卡内容,将创建一个对应的数据结构体存储FSavedMap NewSavedMap;NewSavedMap.MapAssetName = WorldName;SaveGame->SavedMaps.Add(NewSavedMap);}//获取对应的存档关卡数据结构体FSavedMap SavedMap = SaveGame->GetSavedMapWithMapName(WorldName);SavedMap.SavedActors.Empty(); //存储的内容//使用迭代起,便利场景里的每一个Actor,将需要保存Actor数据保存到结构体内for(FActorIterator It(World); It; ++It){AActor* Actor = *It;//判断Actor是否存在,并判断Actor是否需要存储if(!IsValid(Actor) || !Actor->Implements<USaveInterface>()) continue;//创建存储结构体FSavedActor SavedActor;SavedActor.ActorName = Actor->GetFName();SavedActor.Transform = Actor->GetTransform();//创建一个 FMemoryWriter,用于将数据写入SavedActor.BytesFMemoryWriter MemoryWriter(SavedActor.Bytes);//创建一个序列化器,将对象的成员以名称和值的形式保存到 MemoryWriter。FObjectAndNameAsStringProxyArchive Archive(MemoryWriter, true);Archive.ArIsSaveGame = true; //设置序列化方式为保存到存档的模式//将Actor所需要保存的数据写入到Archive,Archive将把数据存储到SavedActor.BytesActor->Serialize(Archive);SavedMap.SavedActors.AddUnique(SavedActor);}//找到对应的名称的结构体,将数据存储到存档对象内for(FSavedMap& MapToReplace : SaveGame->SavedMaps){if(MapToReplace.MapAssetName == WorldName){MapToReplace = SavedMap;}}//保存存档UGameplayStatics::SaveGameToSlot(SaveGame, RPGGI->LoadSlotName, RPGGI->LoadSlotIndex);}
}

接着是加载关卡状态,我们通过关卡名称和游戏实例获取到存档实例,判断存档实例是否存在此关卡的存档数据。
如果存在此关卡数据,我们将遍历此关卡的所有Actor,如果Actor包含存储接口,我们将判断存档里是否存储了此Actor对应的数据,然后通过MemoryReader读取存档数据,进行反序列化,将数据应用回Actor。
最后通过接口函数,调用Actor更新自身状态。

void ARPGGameMode::LoadWorldState(UWorld* World) const
{//获取关卡名称FString WorldName = World->GetMapName();WorldName.RemoveFromStart(World->StreamingLevelsPrefix); //从关卡名称这里移除指定前缀,当前为移除通常用于标识流式加载的关卡文件前缀//获取到游戏实例URPGGameInstance* RPGGI = Cast<URPGGameInstance>(GetGameInstance());check(RPGGI);//判断获取的存档是否存在if(UGameplayStatics::DoesSaveGameExist(RPGGI->LoadSlotName, RPGGI->LoadSlotIndex)){//获取存档ULoadScreenSaveGame* SaveGame = Cast<ULoadScreenSaveGame>(UGameplayStatics::LoadGameFromSlot(RPGGI->LoadSlotName, RPGGI->LoadSlotIndex));if(SaveGame == nullptr){UE_LOG(LogRPG, Error, TEXT("加载对应存档失败"));}//判断存档是否含有对应关卡的数据if(SaveGame->HasMap(WorldName)){//遍历场景内的所有Actor,寻找存档内对应的数据并应用到场景for(FActorIterator It(World); It; ++It){AActor* Actor = *It;if(!Actor->Implements<USaveInterface>()) continue;//遍历存档里对应关卡的所有actor数据for(FSavedActor SavedActor : SaveGame->GetSavedMapWithMapName(WorldName).SavedActors){//查找到对应的actor的存档数据if(SavedActor.ActorName == Actor->GetFName()){//判断当前Actor是否需要设置位置变换if(ISaveInterface::Execute_ShouldLoadTransform(Actor)){Actor->SetActorTransform(SavedActor.Transform);}//反序列化,创建一个FMemoryReader实例用于从二进制数据中读取内容FMemoryReader MemoryReader(SavedActor.Bytes);//FObjectAndNameAsStringProxyArchive 代理类,用于序列化和反序列化对象的属性 true:表示允许使用字符串形式的对象和属性名称(便于调试和可读性)。FObjectAndNameAsStringProxyArchive Archive(MemoryReader, true);Archive.ArIsSaveGame = true; //指定反序列化是用于加载存档数据。Actor->Serialize(Archive); //执行反序列化,将二进制数据设置到actor属性上//修改Actor上的属性后,调用函数更新Actor的显示ISaveInterface::Execute_LoadActor(Actor);}}}			}}
}

实现场景存储和读取

对应的函数实现了,最后一步,我们需要知道在什么时候存储和什么时候去读取。
存储我们选择在玩家角色激活检查点时,我们将bReached设置为true,并调用保存状态函数,将数据保存到关卡内。

void ACheckPoint::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{//if(OtherActor->ActorHasTag("Player")) //如果只需要判断是不是玩家角色通过标签判断即可if(OtherActor->Implements<UPlayerInterface>()){//设置当前检查点已被玩家激活bReached = true;if(ARPGGameMode* RPGGameMode = Cast<ARPGGameMode>(UGameplayStatics::GetGameMode(this))){//保存场景状态RPGGameMode->SaveWorldState(GetWorld());}//修改存档当的检测点IPlayerInterface::Execute_SaveProgress(OtherActor, PlayerStartTag);//如果与碰撞体重叠的是HandleGlowEffects();}
}

在读取时,我们选择在玩家PossessedBy里,它将调用加载存档函数,我们将读取写在读取完技能之后,实现场景的加载。
在这里插入图片描述
最后,测试即可。

相关文章:

111. UE5 GAS RPG 实现角色技能和场景状态保存到存档

实现角色的技能存档保存和加载 首先&#xff0c;我们在LoadScreenSaveGame.h文件里&#xff0c;增加一个结构体&#xff0c;用于存储技能相关的所有信息 //存储技能的相关信息结构体 USTRUCT(BlueprintType) struct FSavedAbility {GENERATED_BODY()//需要存储的技能UPROPERT…...

抖音短视频矩阵源代码部署搭建流程

抖音短视频矩阵源代码部署搭建流程 1. 硬件准备 需确保具备一台性能足够的服务器或云主机。这些硬件设施应当拥有充足的计算和存储能力&#xff0c;以便支持抖音短视频矩阵系统的稳定运行。 2. 操作系统安装 在选定的服务器或云主机上安装适合的操作系统是关键步骤之一。推…...

leetcode - LRU缓存

什么是 LRU LRU (最近最少使用算法), 最早是在操作系统中接触到的, 它是一种内存数据淘汰策略, 常用于缓存系统的淘汰策略. LRU算法基于局部性原理, 即最近被访问的数据在未来被访问的概率更高, 因此应该保留最近被访问的数据. 最近最少使用的解释 LRU (最近最少使用算法), 中…...

计算机网络八股整理(一)

计算机网络八股文整理 一&#xff1a;网络模型 1&#xff1a;网络osi模型和tcp/ip模型分别介绍一下 osi模型是国际标准的网络模型&#xff0c;它由七层组成&#xff0c;从上到下分别是&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff0c;…...

了解 CSS position 属性

CSS position 属性 在前端开发中&#xff0c;布局是一个至关重要的部分&#xff0c;而 CSS 的 position 属性是控制元素在页面中位置的核心工具。 本文将解释 CSS 中的 position 属性&#xff0c;包括其不同的值、效果及典型使用场景&#xff0c;以帮助你更好地理解和应用这一…...

数据结构 【二叉树(上)】

谈到二叉树&#xff0c;先来谈谈树的概念。 1、树的概念及结构 树是一种非线性的数据结构&#xff0c;它的逻辑关系看起来像是一棵倒着的树&#xff0c;也就是说它是根在上&#xff0c;而叶子在下的&#xff0c; 在树这种数据结构中&#xff0c;最顶端的结点称为根结点。在树的…...

C++11(中)

C11&#xff08;中&#xff09; 1.可变参数模板1.1.使用场景 2.lambda表达式&#xff08;重要&#xff09;2.1.使用说明2.2.函数对象与lambda表达式 3.线程库3.1.thread3.2.atomic原子库操作3.3.mutex3.3.1.mutex的种类3.3.2.lock_guard3.3.3.unique_lock &#x1f31f;&#x…...

下拉选择器,选择框,支持单选、多选、筛选和清空功能,支持vue2和vue3

下拉选择器&#xff0c;选择框&#xff0c;支持单选、多选、筛选和清空功能&#xff0c;支持vue2和vue3https://ext.dcloud.net.cn/plugin?id8159 点击即可。 注意数据来源&#xff1a; 选择的&#xff1a;valueName&#xff1a;选择下拉选择显示的显示屏...

HTTP中GET和POST的区别是什么?

HTTP定义&#xff1a; GET&#xff1a;用于获取资源&#xff0c;通常用于请求数据而不改变服务器的状态 POST&#xff1a;用于提交数据到服务器&#xff0c;通常会改变服务器的状态或产生副作用&#xff08;如创建或更新资源&#xff09; 参数传递方式&#xff1a; GET&…...

day04 企业级Linux安装及远程连接知识实践

1. 使用传统的网卡命名方式 在启动虚拟机时&#xff0c;按tab键进入编辑模式 添加命令&#xff1a; net.ifnames0 biosdevname0 这样linux系统会使用传统的网卡命名&#xff0c;例如eth0、eth1…… 2. 快照 做系统关键操作时&#xff0c;一定要使用快照(先将系统关机) 3.…...

jvm核心组件介绍

1. 类加载器&#xff08;ClassLoader&#xff09;&#xff1a; • 想象它是一个快递员&#xff0c;负责把Java类&#xff08;.class文件&#xff09;这个“包裹”从磁盘这个“发货地”送到JVM内部这个“目的地”。类加载器确保每个类只被加载一次&#xff0c;并维护一个类的层级…...

uname -m(machine) 命令用于显示当前系统的机器硬件架构(Unix Name)

文章目录 关于 arm64 架构检查是否安装了 Rosetta 2其他相关信息解释&#xff1a;命令功能&#xff1a;示例&#xff1a; dgqdgqdeMac-mini / % uname -m arm64您运行的 uname -m 命令显示您的系统架构是 arm64。这意味着您的 Mac Mini 使用的是 Apple 的 M1 或更新的芯片&…...

Pgsql:json字段查询与更新

1.查询json字段的值 SELECT attribute_data->>设施类别 mycol, * FROM gis_coord_data WHERE attribute_data->>设施类别阀门井 查询结果如下&#xff1a; 2.更新json字段中的某个属性值 UPDATE gis_coord_data SET attribute_data(attribute_data::jsonb ||{&quo…...

类的加载机制

类加载的概念 类加载是 Java 虚拟机&#xff08;JVM&#xff09;把字节码文件&#xff08;.class 文件&#xff09;转变为 Java 类型的复杂且关键的过程。这就如同把一份详细的设计图纸&#xff08;字节码文件&#xff09;加工成一个可以实际运行和使用的软件模块&#xff08;J…...

基于vite创建的react18项目的单元测试

题外话 最近一个小伙伴进了字节外包&#xff0c;第一个活就是让他写一个单元测试。 嗯&#xff0c;说实话&#xff0c;在今天之前我只知道一些理论&#xff0c;但是并没有实操过&#xff0c;于是我就试验了一下。 通过查询资料&#xff0c;大拿们基本都说基于vite的项目&…...

fiddler抓包工具与requests库构建自动化报告

一. Fiddler 抓包工具 1.1 Fiddler 工具介绍和安装 Fiddler 是一款功能强大的 HTTP 调试代理工具&#xff0c;能够全面记录并深入检查您的计算机与互联网之间的 HTTP 和 HTTPS 通信数据。其主界面布局清晰&#xff0c;主要包含菜单栏、工具栏、树形标签栏和内容栏。 1.2 Fid…...

Docker login 报证书存储错误的解决办法

文章目录 docker login 出现错误&#xff0c;提示&#xff1a;Error saving credentials: error storing credentials - err: exit status 1, out: Cannot autolaunch D-Bus without X11 $DISPLAY 环境 使用的是 Mint Linux &#xff0c;容器为 docker-ce 最新版 1 2 3 4 $…...

【自动化Selenium】Python 网页自动化测试脚本(上)

目录 1、Selenium介绍 2、Selenium环境安装 3、创建浏览器、设置、打开 4、打开网页、关闭网页、浏览器 5、浏览器最大化、最小化 6、浏览器的打开位置、尺寸 7、浏览器截图、网页刷新 8、元素定位 9、元素交互操作 10、元素定位 &#xff08;1&#xff09;ID定位 &…...

什么是MyBatis?

MyBatis简介 MyBatis是一款优秀的持久层框架&#xff0c;用于简化Java应用程序对数据库的操作。它曾是Apache的一个开源项目&#xff0c;名为iBatis&#xff0c;2010年迁移到Google Code并改名为MyBatis&#xff0c;2013年11月又迁移到了GitHub。 一、MyBatis的作用 在JavaE…...

TortoiseGit 将本地已有仓库推送到远程

TortoiseGit 将本地已有仓库推送到远程 一、创建线上仓库二、创建本地仓库三、提交内容到本地仓库四、添加远程仓库地址补充 一、创建线上仓库 在gitlab管理面页面按这前讲过的步骤创建一个空仓库。&#xff08;通常我们把服务器上这个仓库叫远程仓库&#xff0c;把我们自己电…...

腾讯云OCR车牌识别实践:从图片上传到车牌识别

在当今智能化和自动化的浪潮中&#xff0c;车牌识别&#xff08;LPR&#xff09;技术已经广泛应用于交通管理、智能停车、自动收费等多个场景。腾讯云OCR车牌识别服务凭借其高效、精准的识别能力&#xff0c;为开发者提供了强大的技术支持。本文将介绍如何利用腾讯云OCR车牌识别…...

TailwindCss 总结

目录 一、简介 二、盒子模型相关 三、将样式类写到一个类里面apply 四、一款TailWind CSS的UI库 一、简介 官方文档&#xff1a;Width - TailwindCSS中文文档 | TailwindCSS中文网 Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类…...

Java与C#

Java和C#&#xff08;C Sharp&#xff09;是两种流行的面向对象编程语言&#xff0c;它们在很多方面非常相似&#xff0c;因为它们都受到了类似的编程范式和语言设计理念的影响。然而&#xff0c;它们之间也存在一些重要的区别。 平台依赖性&#xff1a; Java&#xff1a;Java是…...

leetcode:222完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最…...

[STM32]从零开始的STM32 FreeRTOS移植教程

一、前言 如果能看到这个教程的话&#xff0c;说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗&#xff1f;是的&#xff0c;我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS&#xff0c;再到最…...

java——Tomcat连接池配置NIO、BIO、APR

Tomcat连接池的配置涉及不同的IO模型&#xff0c;包括NIO&#xff08;Non-blocking IO&#xff0c;非阻塞IO&#xff09;、APR&#xff08;Apache Portable Runtime&#xff0c;Apache可移植运行库&#xff09;和BIO&#xff08;Blocking IO&#xff0c;阻塞IO&#xff09;。以…...

跨域相关的一些问题 ✅

当网页从一个源&#xff08;https://baidu.com&#xff09;请求另一个源&#xff08;如 https://taobao/api&#xff09;的资源时&#xff0c;就发生了跨域。由于安全原因&#xff08;防止恶意网站通过脚本访问用户在其他网站上的数据&#xff09;&#xff0c;浏览器对跨域请求…...

RPC学习

一、什么是 RPC RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;即远程过程调用&#xff0c;是一种计算机通信协议&#xff0c;它允许运行在一台计算机上的程序调用另一台计算机上的子程序或函数&#xff0c;就好像调用本地程序中的函数一样&#xff0c;无需程序…...

coe文件转mif(c语言)

1 mif文件格式 DEPTH=1024; --The size of data in bits WIDTH=16; --The size of memory in words ADDRESS_RADIX = DEC; --The radix for address values DATA_RADIX = UNS...

【leetcode】动态规划

31. 873. 最长的斐波那契子序列的长度 题目&#xff1a; 如果序列 X_1, X_2, ..., X_n 满足下列条件&#xff0c;就说它是 斐波那契式 的&#xff1a; n > 3对于所有 i 2 < n&#xff0c;都有 X_i X_{i1} X_{i2} 给定一个严格递增的正整数数组形成序列 arr &#xff0…...