第二章 第五节 统一输入接口

Gemini国内合规接入指南:API身份链构建与镜像站选型 生成式AI服务接入本质是服务可用性工程,而非单纯网络连通问题。理解大模型API调用原理,关键在于掌握身份认证、权限控制与数据流向三大技术要素。Gemini作为主流多模态模型,其国内可用路径已从‘模拟访问’转向‘能力映射’——聚焦文本生成等核心能力的稳定调用。通过构建七步Google Cloud身份链(含+86实名、国际信用卡核验、Service Account最小权限配置),可实现99.2%高成功率的合规API接入;而教育型、企业型、开发者型三类镜像站则提供差异化过渡方案,均需满足端到端加密、境内CDN托管 阅读详情

统一输入接口

目前我们已经会怎样和输入硬件通信的基本方法(Now that we have the basics down on how to communicate with the input hardware),是时候把这些信息整合进游戏引擎了。游戏引擎只有一个类,封装了三种输入设备,并为游戏提供了一个统一的接口。这个类,我们把它叫做GameInput,从IDisposable接口继承而来。此接口定义了一个Dispose方法,提供清除函数,在C++里一般是析构函数。此类的构造函数会创建所有的输入设备,并只接受一个参数,即前面提到过的应用程序的窗口句柄。

 

虽然我们可以强加让游戏在游戏循环里查询GameInput来取得击键,但是有更好的方式:我们可以使用action映射。Action映射把一个键盘的键或者鼠标的按钮与一个指定的函数相关联。在每帧里有键或者按钮被按下(或者按下的状态被改变)则调用特定的函数。这让输入系统基于事件而不是基于查询,这会提供效率。DirectInput有内建的action映射功能。我们这个游戏引擎实现了分离的action映射系统,目的是示范action映射究竟是如何工作的。一旦你理解了其中的思想,只要你喜欢你可以直接使用微软内置的版本。

 

Action映射里的每一个实体包含mapping结构或者axis mapping结构的实例,如列表2-2所示:

列表:Mapping结构

struct Mapping

{

   public int key;

   public ButtonAction action;

   public bool bOnTransition;

}

struct AxisMapping

{

   public int key;

   public AxisAction action;

}

结构中的key是索引,是键盘状态数据或者鼠标按钮数据,指示了控制action映射到什么上。开头的256个值表示键盘实体,接下来的8个是表示鼠标按钮,最后的32个是表示操纵杆按钮。ButtonAction委托(delegate)表示一个不需要参数也没有返回值的函数。此函数通常用来在游戏中执行一些动作,例如移动主角,开火或者游戏开发者想做的其他动作。AxisAction委托(delegate)使用这个数据为此轴每一帧都被调用。两个委托的定义如下:

public delegate void ButtonAction();

public delegate void AxisAction(int nCount);

类GameInput的公开方法如列表2-3所示。我将在随后的几页里为这些方法提供简短的说明。如果你对实现的细节有兴趣,请参考GameInput.cs 源文件(源代码的一部分,可以从Apress Web网站下载 http://www.apress.com)

列表2.3:GameInput方法列表

GameInput(System.Windows.Forms.Form form)

void Poll()

bool IsMouseButtonDown( int nButton )

bool IsKeyPressed()

bool IsKeyPressed(Key key)

void MapKeyboardAction( Key key, ButtonAction proc, bool bTransition )

void MapMouseButtonAction( int nButton, ButtonAction proc, bool bTransition )

void MapJoystickButtonAction( int nButton, ButtonAction proc, bool bTransition )

void MapMouseAxisAction( int nAxis, AxisAction proc )

void MapJoystickAxisAction( int nAxis, AxisAction proc )

void UnMapKeyboardAction( Key key )

void UnMapMouseButtonAction( int nButton )

void UnMapJoystickButtonAction( int nButton )

void UnMapMouseAxisAction( int nAxis )

void UnMapJoystickAxisAction( int nAxis )

void ClearActionMaps()

Point GetMousePoint()

int GetMouseX()

int GetMouseY()

int GetMouseZ()

int GetJoystickX( )

int GetJoystickY( )

int GetJoystickNormalX( )

int GetJoystickNormalY( )

int GetJoystickZ( )

bool GetJoystickButton( int nIndex )

int GetJoystickSlider( int nIndex )

void Dispose()

 

Poll方法被游戏应用每一帧调用一次。此方法测试每一个硬件设备来取得输入,然后它检查action映射里的每个实体,看是否有被映射的函数需要被调用。如果是,则调用函数来响应玩家的动作。对于一个特殊的轴action的情况呢,函数则使用轴的当前值调用自己(In the case of the actions for a particular axis, the functions are called every time with the current value for that axis)。列表2-4中的这段代码位于Poll方法中,用来处理action映射。

列表2.4:action映射处理

foreach ( AxisMapping map in m_AxisActionMap )

{

   switch ( map.key )

   {

      case 0:

         map.action(m_mousedata.X);

         break;

      case 1:

         map.action(m_mousedata.Y);

         break;

      case 2:

         map.action(m_mousedata.Z) ;

         break;

      case 3:

         map.action(m_joystick.X);

         break;

      case 4:

         map.action(m_joystick.X);

         break;

      case 5:

         map.action(m_joystick.X);

         break;

   }

}

// Only process the action map if the console is not visible.

if ( !Game Engine.Console.IsVisible )

{

   foreach ( Mapping map in m_ActionMap )

   {

      // If this mapping is against the keyboard

      if ( map.key < 256 )

      {

          // take the action if the key is down or transitioning.

         if ( m_keydata[(Key)map.key] )

        {

            if ( !map.bOnTransition | | oldkeydata[(Key)map.key] )

            {

               map.action();

            }

        }

      }

      else if ( map. key < 264 ) // Space for 8 mouse buttons

      {

         if ( (m_mousedata.GetMouseButtons()[map.key-256] & 0×80) != 0 )

         {

            if ( !map.bOnTransition | |

               (oldmousedata. GetMouseButtons() [map.key-256] & 0×80) == 0 )

            {

               map.action();

            }

         }

      }

      else // joystick buttons

      {

         if ( (m_joystick.GetButtons()[map.key-264] & 0×80) != 0 )

         {

            if ( !map.bOnTransition | |

               (oldjoystickdata.Buttons[map.key-264] & 0×80) == 0 )

            {

               map.action();

            }

         }

      }

   }

}

 

这些Is和Get方法提供了访问输入数据的低层方式。如果因为某种原因,游戏需要显式的检查一个输入而不是使用映射的动作,这些方法就可以被使用。

 

HybridCLR热更新打包报错全解析:从原理到实战解决方案 热更新技术是现代游戏和应用开发中实现动态内容交付与Bug修复的核心机制,它允许开发者在无需重新发布完整应用的情况下更新代码逻辑。其原理通常涉及在运行时加载并执行新的代码模块,这要求框架在底层实现安全的代码隔离、内存管理与元数据桥接。在Unity生态中,HybridCLR作为基于IL2CPP的高性能热更新解决方案,通过补充元数据和AOT泛型引用技术,实现了对C#代码的原生级热更支持,显著提升了开发迭代效率与线上问题修复能力。然而,在实际的工程实践中,尤其是在面向Android、iOS等多平台打包构建时,开发者 阅读详情

相关推荐

Unreal Engine鸿蒙移植实战:环境配置、构建流程与性能优化指南

游戏引擎移植是跨平台开发中的关键技术环节,其核心原理在于通过适配目标操作系统的底层接口和工具链,实现同一套代码在不同硬件和软件环境下的高效运行。这项技术的价值在于最大化代码复用率,降低多平台维护成本,并能让应用快速触达新兴生态系统的用户。在移动游戏和XR应用领域,随着鸿蒙HarmonyOS生态的快速发展,将成熟的商业引擎如Unreal Engine迁移至此平台,成为开发者探索新市场机会的重要路径。本文聚焦于Unreal Engine项目向鸿蒙系统的移植实践,详细解析了从环境搭建、源码适配到构建打包的全链路流

weixin_29011395的博客 404

教训:时间一定要用统一输入接口

        程序web端部署在web服务器,数据库部署在数据库服务器;当发起一个添加请求时,用的是数据库服务器当前时间添加,而在用户立刻对这个添加后的进行操作,采用的是web端当前时间,这样导致一个问题就是:用户操作的时间有可能就比添加的时间要早。因为数据库服务器时间和web端服务器时间存在一定的偏差。        教训:使用当前时间要么都用web端时间,要么就都用数据库端时间!!!

赤道与北极 819

CMakeTestCCompiler.cmake错误解决

CMakeTestCCompiler.cmake错误解决欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 最近编译项目的时候,遇到一个cmake的错误,具体错误信息如下: /path-to-pr

昨夜星辰的博客 2万+

《人性的弱点》第二章 获取喜爱的十二大技巧:读后感

永远避免正面的冲突,那才是对的。 一个真正成功的推销员,他决不会跟顾客争辩,即使轻微的争辩,也加以避免。人类的思想,不是那么容易改变的 当我们有错误的时候,或许我们会对自己承认。如果对方能给我们承认的机会,我们会非常地感激,不用对方说,极自然地我们就承认了。如果有人硬把不合胃口的事实,往我们的喉咙塞下去,我们是无法接受下来的。 我很细心地查看,发现我们并没有错误。我知道这是他和他的朋友们,

zhudaPengzz的博客 7887

为什么类型论是函数式编程的理想基础?

函数式编程(如Haskell、Scala、OCaml)以“函数为核心”“无副作用”“不可变数据”等特性著称,但它的“安全高效”并非凭空而来——背后的关键支撑是类型论。本文将聚焦“类型论如何支撑函数式编程”,从基础概念到具体案例,解释两者的本质联系。本文将按“故事引入→核心概念解释→关系拆解→原理+代码案例→实际应用→总结”的逻辑展开,用“乐高积木”“菜谱”等比喻贯穿全文,确保抽象理论可视化。类型论:程序的“接口规则手册”,定义类型和函数的约束;函数式编程。

AI天才研究院 694

stm32f103运行FreeRTOS使用DMA实现USART1不定长接收

使用DMA是实现USART1的不定长接收和发送数据。接收采用FIFO缓存和队列的方式向应用层抛数据。首先定义接收和发送的缓存区,缓存区的大小根据收发数据量确定。DMA接收开启转移完成和转移一般中断。在中断中从缓存向FIFO转移数据。串口开启空闲中断,实现接收数据的分帧。分帧后的数据节点通过写入到队列。发送数据缓存的大小根据发送数据量调整。然后初始化串口和DMA。串口的发送数据接口函数。...

polaris_zgx的博客 1991

《人性的弱点》第二章:故事总结

司华伯管理下的一家工厂,那位负责的厂长,无法使他管理的工人达到标准化的生产量。 司华伯问那个厂长:这到底是怎么回事?像你这样一个能干的人,竟不能使那些工人达到工厂预计的生产量? 厂长回答说:我也弄不清楚是怎么回事。我用温和的话鼓励他们,有时不得已去斥责他们,甚至用降职、撤职来恐吓他们,可是那些工人就是不肯辛勤工作。 他们谈话的时候,是日班快结束,夜班要开始之时。 司华伯向那厂长说:你给我一

zhudaPengzz的博客 5979

工程师必看:如何用功率谱密度搞定随机振动测试(附Grms计算实例)

本文为工程师详解如何通过功率谱密度(PSD)曲线计算Grms(总均方根加速度),从而量化随机振动测试的强度。文章拆解了平直谱、斜谱的计算公式,提供了完整的Grms计算实例,并指出了单位换算、对数坐标等常见工程陷阱,帮助工程师精准完成测试准备与设备推力评估。

3c4x5z6v7b的博客 625

什么是静态路由,Windows,Linux服务器如何配置静态路由实现连通多网段(附案例)

默认路由的作用:默认路由的作用是在路由表中没有匹配的路由条目时,确保数据包能够被转发到某个已知的路由器。静态路由(Static Routing)‌是一种由网络管理员手工配置的路由信息,这些路由信息在缺省情况下是私有的,不会传递给其他的路由器。‌默认路由(Default route)‌是指当路由器在路由表中找不到到达目的网络的路由时所选择的路由。1、服务器需要连接两个网段,但是只能配置一个网关(如配置两个网关,则最后配置的网关会生效,前一个则失效),需要配置静态路由实现网络互通。是目标网络的IP地址,

qq_40680147的博客 2841

DataEase 未授权+远程代码执行漏洞复现(CVE-2025-49001、CVE-2025-49002)

DataEase 是一款开源的数据分析平台,提供丰富的数据可视化和分析功能,帮助用户轻松地进行数据探索和决策支持。近日,有关DataEase 被爆出多个漏洞,其中 CVE-2025-49001 是由于JWT校验机制错误导致攻击者可伪造JWT令牌绕过身份验证流程,CVE-2025-49002 是由于H2数据库模块没有严格过滤用户输入的JDBC连接参数,可使用大小写绕过补丁。攻击者可利用这些漏洞实现未授权代码执行,威胁用户数据和系统的安全。

李同學AI安全 1947

PyTorch实战(19)——变分自编码器(Variational Autoencoder,VAE)

变分自编码器 (Variational Autoencoder, VAE) 是一种结合了自编码器和概率建模的生成模型,通过编码器将输入数据映射到潜在空间中的概率分布,并通过解码器将从潜在空间采样得到的潜在变量映射回原始数据空间,实现了数据的生成和特征学习。本节中,将介绍变分自编码器的基本概念,并使用 PyTorch 实现变分自编码器生成新图像。

盼小辉丶的博客 2868

linux静态转windows,linux、windows路由配置(静态)

路由配置(静态)1、windows下的配置a、在本地连接中配置ip地址及子网掩码,勿配置网关;b、运行cmd,输入 route print 命令,查看本机的路由情况;c、配置动态路由,输入 route add -p 192.168.0.0 mask 255.255.0.0 192.168.30.129 metric 256 回车d、ping 卫生厅提供的ip 192.168.30.97 ,如果可以...

weixin_42297727的博客 167

UCIE Specification详解(八)

Logical Physical Layer(逻辑物理层)

Crazzy_M的博客 1607

linux、windows路由配置(静态)

  路由配置(静态) 1、windows下的配置a、在本地连接中配置ip地址及子网掩码,勿配置网关;b、运行cmd,输入 route print 命令,查看本机的路由情况;c、配置动态路由,输入 route add -p 192.168.0.0 mask 255.255.0.0 192.168.30.129 metric 256 回车d、ping 卫生厅提供的ip 192.168.30.97...

iteye_4979的博客 182

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

linux和windows配置IPV4/IPV6地址、静态路由、查看路由、ping命令

linux配置IPV4/IPV6地址、静态路由、查看路由命令以及ipv4和ipv6 ping命令

LJ511100的博客 8796

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

校园网双网卡路由冲突解决:Windows与Linux静态路由配置指南

在多网卡环境中,操作系统通过路由表决定数据包从哪块网卡发出,默认路由的单一性常导致校园网与公网访问冲突。静态路由通过为特定网段指定网关和接口,实现流量分流,是解决双网卡路由冲突的核心技术。在校园网场景下,合理配置静态路由可让校内资源走校园网、公网流量走宽带,兼顾访问速度与资源可达性。Windows下使用route add -p添加永久路由,Linux下通过netplan或NetworkManager实现持久化配置,配合跃点数调整和验证清单,可有效避免路由冲突和重启丢失问题。

weixin_30225755的博客 247

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

静态路由配置与排障详解:从eNSP实验到Windows/Linux实战

在计算机网络中,路由表决定了数据包的转发路径,而静态路由作为最基础的路由方式,依靠管理员手动指定下一跳和出接口,具有稳定、可控、不依赖协议交互的特点。与OSPF等动态路由协议相比,静态路由无需计算开销,适合网络规模稳定、拓扑结构清晰的场景,如企业出口、多网段互联以及服务器多网卡环境。掌握静态路由的核心在于理解路由逐跳转发与回程路由的对称性,同时熟悉命令行下的配置与验证方法。本文从网络工程师的视角出发,结合eNSP模拟器实验,展示路由器之间的静态路由配置流程,并延伸至Windows系统下的route add命

weixin_29290379的博客 65

静态路由从ensp到Linux/Windows:配置、排错与实验全解析

路由转发是网络通信的基石,路由器依据路由表决定每个数据包的去向。静态路由作为最朴素的人工指路方式,通过目标网段、掩码与下一跳的定义,让设备在无动态协议时也能准确送达数据。其配置简单、可控性强,广泛用于小型组网、分支互联与默认出口场景。然而实际工程中,ensp模拟器里的回程路由缺失、Linux下ip route add报错RTNETLINK answers: File exists、Windows上route命令持久化失败等问题常常困扰学习者。理解路由表核心字段与转发方向,才能灵活应对多系统环境。本文以综合实

weixin_31766003的博客 330

静态路由从原理到实战:华为、Linux与Windows配置排错全解析

路由设置是网络互联的基础,静态路由作为最基础的路由方式,决定了数据包如何跨网段转发。理解路由表、下一跳与回程路由的关系,是网络工程师和运维人员的核心基本功。在华为设备中,通过路由表的flags字段可快速识别静态路由与直连路由,而路由优先级则控制着路径选择的逻辑。在Linux系统中,添加静态路由时需要处理RTNETLINK answers: File exists的冲突报错,掌握ip route add、replace等命令可有效规避。Windows环境下,使用route add配合-p参数可实现持久化静态路

weixin_29597551的博客 290

静态路由综合实验:从ensp到Linux/Windows的配置与排错

静态路由是网络工程师必须掌握的基础技术之一,它通过手动指定目的网段与下一跳,让数据包按预期路径转发。在实际组网中,路由方向性、逐跳转发以及回程路由的设计,往往比命令本身更考验工程思维。掌握静态路由的配置与排错,不仅适用于华为ensp模拟器,也同样适用于Linux和Windows等主机环境。当在Linux系统中执行ip route add时,常会遇到“RTNETLINK answers: File exists”的报错,这背后是内核路由表的冲突保护机制;而Windows下route add忘加-p参数则会导致

weixin_31423955的博客 311

静态路由配置全解析:华为、Linux、Windows实战与排障

静态路由是网络基础架构中不可或缺的转发机制,它通过人工指定的下一跳地址,让设备在非直连网段间建立通信通路。理解路由表的结构与最长匹配原则,是掌握静态路由原理的关键。在实际工程中,静态路由具备不占用带宽、行为可控等优势,适合小型网络、分支互联及备份链路等场景。本文从华为设备、Linux系统到Windows平台,系统梳理了静态路由配置的具体命令与常见故障排查方法,帮助网络工程师快速构建清晰的排障思路。

weixin_29227425的博客 133

静态路由配置实战:华为Linux Windows跨网段互通与排障

静态路由是网络运维中最基础的技能之一,它通过手动指定目标网段与下一跳,在路由表中建立精确的转发路径,无需动态协议交互,天然具备稳定、可控、省资源的优势。理解路由表的最长匹配原则、路由优先级以及直连路由与静态路由的差异,是掌握网络通信的核心。静态路由广泛应用于小型网络、多网段互联、双网卡选路等场景,同时也常因回程路由缺失、防火墙拦截或Linux下ip route add报“File exists”等问题引发排障需求。本文从网络拓扑规划出发,完整演示华为设备ip route-static命令、Linux的ip

weixin_31364787的博客 323

linux系统rc路由配置_windows系统配置静态路由

同网段内有234和254两个网关,计划访问10.0.1.0网段走网关234,其它网段走默认路由254,实现基于用户终端的手动分流。操作需要以管理员身份使用route命令实现。如无说明,掩码都是/24。操作方法:1,开始,输入cmd,右击cmd.exe,选择以管理员身份运行。2,配置静态路由,命令格式如下route add目标网段mask点分十进制掩码 下一跳route add 10...

weixin_42303112的博客 168

linux添加路由的方式,linux和windows路由条目添加方法。

在windows添加一条静态路由1、添加一条路由表route add 60.232.142.25 mask 255.255.255.248 192.168.100.250 metric 3 if 2添加一条路由记录,所有到60.232.142.25/29网段的数据包,都通过2号网络接口卡走192.168.100.250的网关,优先级为3。route add –p 60.232.142.25 mas...

weixin_34540432的博客 758

linux添加静态路由(附windows添加静态路由)

添加静态路由:

weixin_44850446的博客 2468

linux和windows手动添加路由条目命令

如何 在windows添加一条静态路由1、添加一条路由表Route add 60.232.142.40 mask 255.255.255.248 192.168.100.250 metric 3 if 2添加一条路由记录,所有到60.232.142.40/29网段的数据包,都通过2号接口卡(网卡)走192.168.100.250的网关,优先级为3。(结果会怎样?)Route add –p 60.2...

weixin_34293246的博客 1992
上一篇: 第二章 第四节 获得操纵杆的输入
下一篇: 第二章 第六节 绘制Splash Screens
刮风
博客等级 码龄19年 30粉丝 5原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值