《UE5_C++多人TPS完整教程》学习笔记22 ——《P23 记录加入的玩家(Couting Incoming Players)》


本文为B站系列教学视频 《UE5_C++多人TPS完整教程》 —— 《P23 记录加入的玩家(Couting Incoming Players)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C++ Multiplayer Shooter》 的中文字幕翻译版,UP主(也是译者)为 游戏引擎能吃么。


文章目录

  • P23 记录加入的玩家
  • 23.1 游戏模式和游戏状态
  • 23.2 追踪加入或离开游戏的玩家
  • 23.3 使用 Lobby 游戏模式
  • 23.4 进行测试
  • 23.5 Summary


P23 记录加入的玩家

本节课将创建一个游戏模式,以便追踪(Track)加入游戏会话的玩家、打印游戏人数,之后我们就可以利用统计的人数来决定是否要从关卡 “Lobby” 过渡(Transition)到实际的匹配中。
在这里插入图片描述


23.1 游戏模式和游戏状态

  1. 在多人游戏中,两个重要的类分别是游戏模式类和游戏状态类:
  • 游戏模式规定了游戏规则,这涉及了很多方面,如何时将玩家移动至关卡中、选择出生位等。游戏模式有几个继承的虚拟函数,可以在玩家加入或离开会话时进行追踪,例如每当玩家加入游戏时都会调用 “PostLogin()” 访问玩家的控制器;当玩家离开时调用 “Logout()” 函数。
  • 客户端可以监控游戏状态,游戏状态将保存游戏的状态信息,而非特定的单个玩家的信息。游戏状态包含玩家状态数组,玩家状态类中保存了特定的单个玩家的信息,比如得分和胜利次数等。
  • 游戏模式类可以访问游戏状态类的玩家状态数组,通过查看该数组的大小可以得出玩家的个数。
    在这里插入图片描述

    两个主要类负责处理进行中游戏的相关信息:Game Mode 和 Game State。
    即使最开放的游戏也拥有基础规则,而这些规则构成了 Game Mode。在最基础的层面上,这些规则包括:

    • 出现的玩家和观众数量,以及允许的玩家和观众最大数量。
    • 玩家进入游戏的方式,可包含选择生成地点和其他生成/重生成行为的规则。
    • 游戏是否可以暂停,以及如何处理游戏暂停。
    • 关卡之间的过渡,包括游戏是否以动画模式开场。

    基于规则的事件在游戏中发生,需要进行追踪并和所有玩家共享时,信息将通过 Game State 进行存储和同步。这些信息包括:

    • 游戏已运行的时间(包括本地玩家加入前的运行时间)。
    • 每个个体玩家加入游戏的时间和玩家的当前状态。
    • 当前 Game Mode 的基类。
    • 游戏是否已开始。

    Game Modes
    特定的基础(如进行游戏所需要的玩家数量,或玩家加入游戏的方法)在多种类型的游戏中具有共通性。可根据开发的特定游戏进行无穷无尽的规则变化。无论规则如何,Game Modes 的任务都是定义和实现规则。Game Modes 当前常用的基类有两个。
    4.14 版本中加入了 AGameModeBase,这是所有 Game Mode 的基类,是经典的 AGameMode 简化版本。AGameMode 是 4.14 版本之前的基类,仍然保留,功能 如旧,但现在是 AGameModeBase 的子类。由于其比赛状态概念的实现,AGameMode 更适用于标准游戏类型(如多人射击游戏)。AGameModeBase 简洁高效,是新代码项目中包含的全新默认游戏模式。


    Game State
    Game State 负责启用客户端监控游戏状态。从概念上而言,Game State 应该管理所有已连接客户端已知的信息(特定于 Game Mode 但不特定于任何个体玩家)。它能够追踪游戏层面的属性,如已连接玩家的列表、夺旗游戏中的团队得分、开放世界游戏中已完成的任务,等等。
    Game State 并非追踪玩家特有内容(如夺旗比赛中特定玩家为团队获得的分数)的最佳之处,因为它们由 Player State 更清晰地处理。整体而言,Game State 应该追踪游戏进程中变化的属性。这些属性与所有人皆相关,且所有人可见。Game Mode 只存在于服务器上,而 Game State 存在于服务器上且会被复制到所有客户端,保持所有已连接机器的游戏进程更新。


    —— 虚幻引擎官方文档《Game Mode 和 Game State》

  1. 打开虚幻引擎,在内容浏览器中展开 “C++类/MenuSystem”,添加游戏模式基础(Game mode base)C++ 类,命名为 “LobbyGameMode”,选择模块为我们上节课新建的插件 “MenuSystem (Runtime)”。
    在这里插入图片描述
    在这里插入图片描述
  2. 点击 “创建类” 按钮,VS 中出现弹窗,选择 “全部重新加载(A)”。
    在这里插入图片描述

23.2 追踪加入或离开游戏的玩家

  1. 在 “LobbyGameMode.h” 中添加头文件 “GameFramework/GameStateBase.h” 和 “GameFramework/PlayerState.h”,避免出现错误 “使用了未定义类型 AGameStateBase” 和 “使用了未定义类型 APlayerState。接着,声明重写 “virtual void PostLogin()” 和 “virtual void Logout()”。

    // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
    #include "GameFramework/GameModeBase.h"/* P23 记录加入的玩家(Couting Incoming Players)*/
    #include "GameFramework/GameStateBase.h"
    #include "GameFramework/PlayerState.h"
    /* P23 记录加入的玩家(Couting Incoming Players)*/#include "LobbyGameMode.generated.h"/*** */
    UCLASS()
    class MENUSYSTEM_API ALobbyGameMode : public AGameModeBase
    {GENERATED_BODY()/* P23 记录加入的玩家(Couting Incoming Players)*/
    public:// 成功登录后调用。这是首个在 PlayerController 上安全调用复制函数之处。// OnPostLogin 可在蓝图中实现,以添加额外的逻辑。virtual void PostLogin(APlayerController* NewPlayer) override;	// 重写 virtual void PostLogin()// 玩家离开游戏或被摧毁时调用。可实现 OnLogout 执行蓝图逻辑。virtual void Logout(AController* Exiting) override;				// virtual void Logout()
    /* P23 记录加入的玩家(Couting Incoming Players)*/
    };
    
  2. 在 “LobbyGameMode.cpp” 中实现“virtual void PostLogin()” 和 “virtual void Logout()” 的覆写。如果 “GameState” 和 “PlayerState” 标红且错误提示为 “不允许指针指向不完整的类类型 AGameStateBase” 和 “不允许指针指向不完整的类类型 APlayerState”,则添加头文件 “GameFramework/GameStateBase.h” 和 “GameFramework/PlayerState.h

    // Fill out your copyright notice in the Description page of Project Settings.#include "LobbyGameMode.h"/* P23 记录加入的玩家(Couting Incoming Players)*/
    void ALobbyGameMode::PostLogin(APlayerController* NewPlayer)
    {Super::PostLogin(NewPlayer);if (GameState) {int32 NumberOfPlayers = GameState.Get()->PlayerArray.Num();if (GEngine) {GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上1,				// Key 不是 -1 时,则更新现有消息60.f,			// 调试信息的显示时间FColor::Red,	// 字体颜色:黄色FString::Printf(TEXT("Players in game: %d!"), NumberOfPlayers)	// 打印玩家人数);APlayerState* PlayerState = NewPlayer->GetPlayerState<APlayerState>();if (PlayerState) {FString PlayerName = PlayerState->GetPlayerName();GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上2,				// Key 不是 -1 时,则更新现有消息60.f,			// 调试信息的显示时间FColor::Cyan,	// 字体颜色:蓝绿色FString::Printf(TEXT("%s has joined the game!"), *PlayerName)	// 打印进入游戏的玩家昵称);}	}}
    }void ALobbyGameMode::Logout(AController* Exiting)
    {Super::Logout(Exiting);APlayerState* PlayerState = Exiting->GetPlayerState<APlayerState>();if (PlayerState) {int32 NumberOfPlayers = GameState.Get()->PlayerArray.Num();GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上1,				// Key 不是 -1 时,则更新现有消息60.f,			// 调试信息的显示时间FColor::Red,	// 字体颜色:红色FString::Printf(TEXT("Players in game: %d!"), NumberOfPlayers - 1)	// 打印玩家人数,// 此时 PlayerArray.Num() 还未更新,这里进行减 1 操作只是为了方便测试时显示正确的人数,在实际项目中不会如此操作);FString PlayerName = PlayerState->GetPlayerName();GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上2,				// Key 不是 -1 时,则更新现有消息60.f,			// 调试信息的显示时间FColor::Cyan,	// 字体颜色:蓝绿色FString::Printf(TEXT("%s has exited the game!"), *PlayerName)	// 打印进入游戏的玩家昵称);}}
    /* P23 记录加入的玩家(Couting Incoming Players)*/
    

    这里可以复习一下函数 “AddOnScreenDebugMessage()” 第一个入参 “int32 Key” 取不同值的含义。这里 打印玩家人数打印进入或退出游戏的玩家昵称 设置了不同的 “Key” 是为了都能在屏幕上显示,如果设置为 -1 则 玩家人数消息 会被 进入或退出游戏的玩家昵称消息 覆盖。

    调用全局变量 GEngine 指针调用函数 AddOnScreenDebugMessage节点,进行屏幕输出。

    void AddOnScreenDebugMessage {int32 Key,float TimeToDisplay,FColor Di splayColor,const FString & DebugMessage,bool bNewerOnTop,const FVector2D & TextScale
    }
    
    • Key = -1 时,则添加新的消息,不会覆盖旧有消息(当 Key = -1 时,bNewerOnTop 有效,直接添加到队列最上层)
    • Key != -1 时,则更新现有消息,效率更高。

    —— 《虚幻引擎基础入门(C++) — 【日志输出篇 03】》

  3. 在 “MultiplayerSessionsSubsystem.cpp” 的 “CreateSession()” 函数中加入一条会话设置的代码行,用来设置唯一构建标识,防止不同的构建在搜索过程中可以互相搜索到。

    void UMultiplayerSessionsSubsystem::CreateSession(int32 NumpublicConnections, FString MatchType)
    {...// FOnlineSessionSettings 在头文件 "OnlineSessionSettings.h" 中LastSessionSettings = MakeShareable(new FOnlineSessionSettings());	// 创建会话设置,利用函数 MakeShareable 初始化// 会话设置成员变量参阅及含义:https://docs.unrealengine.com/5.0/en-US/API/Plugins/OnlineSubsystem/FOnlineSessionSettings/LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;	// 会话设置:如果找到的子系统名称为 “NULL”,则使用 LAN 连接,否则不使用LastSessionSettings->NumPublicConnections = NumpublicConnections;	// 会话设置:设置最大公共连接数为函数输入变量 NumpublicConnections.../* P23 记录加入的玩家(Couting Incoming Players)*/LastSessionSettings->BuildUniqueId = 1;								// 会话设置:设置唯一构建标识,防止不同的构建在搜索过程中可以互相搜索到。/* P23 记录加入的玩家(Couting Incoming Players)*/...}
    
  4. 在 “MenuSystem\Config” 目录下打开 “DefaultGame.ini”,设置最大玩家数为 100。创建会话中设置最大公共连接数 “NumPublicConnections”区别开,设置最大公共连接数是指定加入会话的最大连接数,而设置最大玩家数是指定连接到游戏项目最大人数。

    [/Script/EngineSettings.GeneralProjectSettings]
    ProjectID=6A5F83AB4DEB75FB9BB586AC8DE40CDA
    ProjectName=Third Person Game Template[StartupActions]
    bAddPacks=True
    InsertPack=(PackSource="StarterContent.upack",PackName="StarterContent")[/Script/Engine.GameSession]
    MaxPlayers=100	
    
  5. (选做)注释掉 “MenuSystemCharacter.cpp” 获取在线子系统并打印在线子系统名称到屏幕上的代码,并删除 “BP_ThirdPersonCharacter” 角色蓝图中按下数字键 “1” 和 “2” 对应的事件。

    // AMenuSystemCharacterAMenuSystemCharacter::AMenuSystemCharacter() :	// 为委托绑定回调函数CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete)),FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete)),JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplete))
    {.../* P23 记录加入的玩家(Couting Incoming Players)*///IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();			// 获取当前的在线子系统指针//if (OnlineSubsystem) {													// 如果当前在线子系统有效//	OnlineSessionInterface = OnlineSubsystem->GetSessionInterface();	// 获取会话接口智能指针//	if (GEngine) {//		GEngine->AddOnScreenDebugMessage(	// 添加调试信息到屏幕上//			-1,				// 使用 -1 不会覆盖前面的调试信息//			15.f,			// 调试信息的显示时间//			FColor::Blue,	// 字体颜色//			FString::Printf(TEXT("Found subsystem %s!"),//				*OnlineSubsystem->GetSubsystemName().ToString())	// 打印在线子系统的名称//		);//	}//}/* P23 记录加入的玩家(Couting Incoming Players)*/}
    

    在这里插入图片描述


23.3 使用 Lobby 游戏模式

  1. 打开虚幻引擎,在内容浏览器中目录 “/内容/ThirdPerson/Blueprints/” 下新建 “LobbyGameMode” 蓝图类,命名为 “BP_LobbyGameMode”。
    在这里插入图片描述
    在这里插入图片描述
  2. 双击 “BP_LobbyGameMode”,进入蓝图编辑器,在右侧 “细节” 面板 “类” 选项卡下设置 “默认 pawn 类” 为 “BP_ThirdPersonCharacter”,编译、保存。
    在这里插入图片描述
  3. 在目录 “/内容/ThirdPerson/Maps/” 下打开地图 “Lobby”,在右下方 “世界场景设置” 面板设置 “游戏模式” 为“BP_LobbyGameMode”,保存。
    在这里插入图片描述

    如果没有看到右下方的 “世界场景设置” 面板,可以点击工具栏右侧 “项目和编辑器设置” 按钮(虚幻引擎窗口右上方),在下拉菜单栏中选中 “世界场景设置”。
    在这里插入图片描述


23.4 进行测试

  1. 将项目打包之后发送到另一台设备上。在设备 1 上运行游戏(保证 Steam 已经运行),点击 “Host” 按钮,当前关卡跳转至 “Lobby”,且左上角显示会话创建成功消息。
    在这里插入图片描述
    在这里插入图片描述

  2. 在设备 2 上运行游戏(保证 Steam 已经运行且登录的账户与设备1 上登录的账号不同),点击 “Join” 按钮,当前关卡跳转至 “Lobby”,并且可以看到有两个玩家存在,说明设备 2 成功找到并加入到了设备 1 创建的会话中,但是设备 2 屏幕左上角没有显示玩家人数和加入游戏信息,而创建会话的设备 1 上有显示。
    在这里插入图片描述
    在这里插入图片描述

  3. 在设备 2 上退出游戏,可以看到设备 1 屏幕左上角显示了设备 2 上的玩家离开游戏的消息,玩家人数也发生了变化。
    在这里插入图片描述


23.5 Summary

本节课了解了游戏模式和游戏状态的基本概念,并在虚幻引擎创建了游戏模式基础(Game mode base)C++ 类 “LobbyGameMode”。接着我们在 “LobbyGameMode.cpp” 中实现“virtual void PostLogin()” 和 “virtual void Logout()” 的覆写,以便能够打印在线玩家人数以及玩家加入或退出游戏的消息。为了能够使用这个游戏模式,我们以 “LobbyGameMode” 为父类新建了蓝图类 “BP_LobbyGameMode”,设置蓝图类的 “默认 pawn 类” 为 “BP_ThirdPersonCharacter”,并将地图 “Lobby” 的 “游戏模式” 设置为“BP_LobbyGameMode”。最后,我们在两台设备上以玩家加入和退出游戏的方式进行来了测试,玩家人数以及玩家加入和退出游戏的消息都能正常显示。
在这里插入图片描述
23.2 追踪加入或离开游戏的玩家步骤 2 中使用函数 AddOnScreenDebugMessage() 进行屏幕消息输出时,若函数第一个入参 “int32 Key” 为 -1 ,则添加新的消息,不会覆盖旧有消息(当 Key 为 -1 时,bNewerOnTop 有效,直接添加到队列最上层),若 Key 不为 -1 ,则更新现有消息。这里打印 玩家人数 和 打印进入或退出游戏的玩家昵称 设置了不同的 “Key” 是为了都能在屏幕上显示,如果设置为 -1 则 玩家人数消息 会被 进入或退出游戏的玩家昵称消息 覆盖。


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

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

相关文章

如何使用Docker部署MongoDB并结合内网穿透实现远程访问本地数据库

文章目录 前言1. 安装Docker2. 使用Docker拉取MongoDB镜像3. 创建并启动MongoDB容器4. 本地连接测试5. 公网远程访问本地MongoDB容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 …

2024最佳住宅代理IP服务商有哪些?

跨境出海已成为了近几年的最热趋势&#xff0c;大批量的企业开始开拓海外市场&#xff0c;而海外电商领域则是最受欢迎的切入口。新兴的tiktok、Temu&#xff0c;老牌的Amazon、Ebay&#xff0c;热门的Etsy、Mecari等等都是蓝海一片。跨境入门并不难&#xff0c;前期的准备中不…

Spring Boot打war包部署到Tomcat,访问页面404 !!!

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 Spring Boot打war包部署到Tomcat&#xff0c;访问页面404 &#xff01;&#xff01;&#xff01;解决办法&#xff1a;检查Tomcat版本和Jdk的对应关系&#xff0c;我的Tomcat是6.x&#x…

Sping基础篇----掌握Sping的控制反转/依赖注入的概念【实战案例总结】

作为一名对技术充满热情的学习者&#xff0c;我一直以来都深刻地体会到知识的广度和深度。在这个不断演变的数字时代&#xff0c;我远非专家&#xff0c;而是一位不断追求进步的旅行者。通过这篇博客&#xff0c;我想分享我在某个领域的学习经验&#xff0c;与大家共同探讨、共…

KVM虚拟机的克隆方式

话不多说&#xff0c;直接上操作 首先确定我们要克隆的模板机器&#xff0c;这样可以方便我们后续克隆许多机器 IP获取最好就是dhcp模式&#xff0c;这样克隆出来的机器就不需要自己再去改ip了 确定需要克隆的模板机以后&#xff0c;先关机再执行克隆操作 virsh shutdown ser…

【SiamFC】《Fully-Convolutional Siamese Networks for Object Tracking》

ECCV 2016 Workshops 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method5 Experiments5.1 Datasets and Metrics5.2 The OTB-13 benchmark5.3 The VOT benchmarks5.4 Dataset size 6 Conclusion&#xff08;own&#xff09;/ Future wo…

Android系统启动流程

android的启动流程是从底层开始进行的&#xff0c;具体如下所示&#xff1a; Android是基于Linux内核的系统&#xff0c;Android的启动过程主要分为两个阶段&#xff0c;首先是Linux内核的启动&#xff0c;然后是Android框架的启动。 可以将Andorid系统的启动流程分为以下五个…

【QT 5 +Linux下软件桌面快捷方式+qt生成软件创建桌面图标+学习他人文章+第二篇:编写桌面文件.desktop】

【QT 5 Linux下软件桌面快捷方式qt生成软件创建桌面图标学习他人文章第二篇&#xff1a;编写桌面文件.desktop】 1、前言2、实验环境3、自我学习总结-本篇总结1、新手的疑问&#xff0c;做这件事目的2、了解.desktop3、三个关键目录以及文件编写1、目录&#xff1a;/opt/2、目录…

【鸿蒙 HarmonyOS 4.0】开发工具安装

一、准备开发环境 1.1、安装IDE 鸿蒙应用开发需要使用配套的IDE——HUAWEI DevEco Studio。 DevEco Studio基于IntelliJ IDEA Community&#xff08;IDEA社区版&#xff09;构建&#xff0c;为鸿蒙应用提供了一站式开发环境&#xff0c;集成了开发、运行、调试以及发布应用的…

Stable Diffusion 模型分享:AstrAnime(Astr动画)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五 下载地址 模型介绍 AstrAnime 是一个动漫模型&#xff0c;画风色彩鲜明&#xff0c;擅长绘制漂亮的小姐姐。 条目内容类型大模型…

fastjson解析自定义get方法导致空指针问题

背景 为了在日志中把出入参打印出来&#xff0c;以便验证链路和排查问题&#xff0c;在日志中将入参用fastjson格式化成字符串输出&#xff0c;结果遇到了NPE。 问题复现 示例代码 public static void main(String[] args) {OrganizationId orgId new OrganizationId();N…

【Java多线程】分析线程加锁导致的死锁问题以及解决方案

目录 1、线程加锁 2、死锁问题的三种经典场景 2.1、一个线程一把锁 2.2、两个线程两把锁 2.3、N个线程M把锁&#xff08;哲学家就餐问题&#xff09; 3、解决死锁问题 1、线程加锁 其中 locker 可以是任意对象&#xff0c;进入 synchronized 修饰的代码块, 相当于加锁&…

⭐北邮复试刷题LCR 052. 递增顺序搜索树__DFS (力扣119经典题变种挑战)

LCR 052. 递增顺序搜索树 给你一棵二叉搜索树&#xff0c;请 按中序遍历 将其重新排列为一棵递增顺序搜索树&#xff0c;使树中最左边的节点成为树的根节点&#xff0c;并且每个节点没有左子节点&#xff0c;只有一个右子节点。 示例 1&#xff1a; 输入&#xff1a;root [5,…

DataX - 全量数据同步工具

前言 今天是2024-2-21&#xff0c;农历正月十二&#xff0c;相信今天开始是新的阶段&#xff0c;尽管它不是新的周一、某月一日、某年第一天&#xff0c;尽管我是一个很讲究仪式感的人。新年刚过去 12 天&#xff0c;再过 3 天就开学咯&#xff0c;开学之后我的大学时光就进入了…

TypeScript01:安装TypeScript

一、TypeScript 官方网站&#xff1a;https://www.tslang.cn/docs/index.html 练习场&#xff1a;https://www.typescriptlang.org/zh/play 好处&#xff1a; 强类型语言&#xff0c;对JS弱类型的一个良好补充&#xff1b;TS利于大型项目团队合作&#xff0c;可以一定程度…

ChatGPT实战100例 - (17) 用ChatGPT实现音频长度测量和音量调整

文章目录 ChatGPT实战100例 - (17) 用ChatGPT实现音频长度测量和音量调整获取音频长度pydub获取音频长度获取时长精确到秒格式设定 mutagen获取音频长度 调整音量视频音量调整注意事项 ChatGPT实战100例 - (17) 用ChatGPT实现音频长度测量和音量调整 老王媳妇说上次那个pip挺好…

《VitePress 简易速速上手小册》第7章 高级功能与动态内容(2024 最新版)

文章目录 7.1 动态路由与 API 集成7.1.1 基础知识点解析7.1.2 重点案例&#xff1a;技术博客7.1.3 拓展案例 1&#xff1a;电商网站7.1.4 拓展案例 2&#xff1a;事件管理网站 7.2 状态管理与 Vuex 使用7.2.1 基础知识点解析7.2.2 重点案例&#xff1a;用户认证系统7.2.3 拓展案…

力扣精选算法100道——Z字形变换(模拟专题)

目录 &#x1f388;了解题意 &#x1f388;算法原理 &#x1f6a9;先处理第一行和最后一行 &#x1f6a9;再处理中间行 &#x1f388;实现代码 &#x1f388;了解题意 大家看到这个题目的时候肯定是很迷茫的&#xff0c;包括我自己也是搞不清楚题目什么意思&#xff0c;我…

[linux]进程间通信(IPC)———共享内存(shm)(什么是共享内存,共享内存的原理图,共享内存的接口,使用演示)

一、什么是共享内存 共享内存区是最快的&#xff08;进程间通信&#xff09;IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。注意&#xff1a;…

Three.js初学(2)

Three.js初学&#xff08;2&#xff09; 三维坐标系的认识1. 辅助坐标系 光源的影响1. 光材质的影响2. 光源介绍点光源环境光平行光 3. 光源衰减/位置 相机控件1. 引入扩展库2. 使用方法 三维坐标系的认识 这一章节的主要作用是加强自我对三维坐标空间的认识。 1. 辅助坐标系…