1.为什么我们需要外部输入模块?
在游戏中我们常常用到类似这样的操作:鼠标点击某位置,玩家对象移动到该位置,或者按鼠标方向键,玩家向不同方向移动,等等。这些操作无一不用与外部输入设备打交道。作为游戏的设计者,我们很需要在任何时候知道鼠标目前的位置,键盘的点击状况等,从而方便我们对游戏元素加以控制。因此作为一个游戏框架,外部输入模块也是必不可少的。
2.提供哪些功能,怎样使用?
外部输入模块主要实现的功能就是动态记录鼠标相对于canvas的位置,以及记录键盘上哪些键是按下的,哪些键刚刚松开,并触发相应的回调函数。
我们可以通过框架保存的两个字段获取鼠标当前在canvas的位置:
var x=cnGame.input.mouseX; var y=cnGame.input.mouseY;
由于canvas下的游戏编程模式是通过一个游戏循环来实现的帧动画(关于游戏循环请看:HTML5游戏框架cnGameJS开发实录(游戏循环篇)),因此单纯对键盘keyup与keydown的绑定,往往并不能达到期望效果,举个例子,我们如果想在键盘按下左键时使元素一直向左移动:
cnGame.input.onKeyDown("left",(){ player.move(-10); })
我们会发现这种方法并不能很好的运用在帧动画的编程模型。由于当我们按着键盘左方向键时,其回调函数会不断触发,因此触发频率并不能和你的帧动画的频率一致(要么太快要么太慢,取决于你的帧频率),所以更好的选择是每次帧更新时,判断左键是否按下,如果是按下游戏元素就向左移动一定位置,这样游戏元素就成为帧动画的一部分,随着每次帧的更新而更新:
/*每次帧更新调用的函数*/ var update=function(){ cnGame.input.isPressed("left",function(){player.move(-10);}) }
3.代码实现
首先看如何保持鼠标在canvas的位置。鼠标相对于canvas的位置,其实就是鼠标相对于页面的位置和canvas的位置之差。在之前的HTML5游戏框架cnGameJS开发实录(核心函数模块篇)里已经介绍过,在框架的初始化函数里,我们已经通过getCanvasPos获取到canvas在页面的位置,因此鼠标相对于canvas的位置可以如此计算:
/** *记录鼠标在canvas内的位置 **/ var recordMouseMove=function(eve){ var pageX,pageY,x,y; eve=cg.core.getEventObj(eve); pageX = eve.pageX || eve.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft; pageY = eve.pageY || eve.clientY + document.documentElement.scrollTop - document.documentElement.clientTop; cg.input.mouseX=pageX-cg.x; cg.input.mouseY=pageY-cg.y; }
之后再看看键盘输入的记录如何实现,我们需要一个数组,保存每个键的名值对(键名和键编码),以及一些对象,保存每个键对应的按下和松开的回调函数,还有最后一个对象,保存那些需要禁止默认行为的键名。(禁止键盘默认行为在游戏开发中很必要,可以防止玩家在操控时游戏对象时触发不必要的浏览器默认行为,例如滚动条滚动等)。
首先是建立键名和键编码的字典:
/** *键盘按键编码和键名 **/ var k=[]; k[8] = "backspace" k[9] = "tab" k[13] = "enter" k[16] = "shift" k[17] = "ctrl" k[18] = "alt" k[19] = "pause" k[20] = "capslock" k[27] = "esc" k[32] = "space" k[33] = "pageup" k[34] = "pagedown" k[35] = "end" k[36] = "home" k[37] = "left" k[38] = "up" k[39] = "right" k[40] = "down" k[45] = "insert" k[46] = "delete" k[91] = "leftwindowkey" k[92] = "rightwindowkey" k[93] = "selectkey" k[106] = "multiply" k[107] = "add" k[109] = "subtract" k[110] = "decimalpoint" k[111] = "divide" k[144] = "numlock" k[145] = "scrollock" k[186] = "semicolon" k[187] = "equalsign" k[188] = "comma" k[189] = "dash" k[190] = "period" k[191] = "forwardslash" k[192] = "graveaccent" k[219] = "openbracket" k[220] = "backslash" k[221] = "closebracket" k[222] = "singlequote" var numpadkeys = ["numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9"] var fkeys = ["f1","f2","f3","f4","f5","f6","f7","f8","f9"] var numbers = ["0","1","2","3","4","5","6","7","8","9"] var letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] for(var i = 0; numbers[i]; i++) { k[48+i] = numbers[i] } for(var i = 0; letters[i]; i++) { k[65+i] = letters[i] } for(var i = 0; numpadkeys[i]; i++) { k[96+i] = numpadkeys[i] } for(var i = 0; fkeys[i]; i++) { k[112+i] = fkeys[i] }
有点长,不过其实没啥技术含量,就是方便我们以后知道某个编码的键名是什么。例如我们按下左键,那么流程就是:获取到左键的键盘编码->在字典中得到键名->在对象中通过键名获取到之前同样通过键名保存的处理程序,并执行。
为键盘绑定处理程序的代码如下:
/** *记录键盘按下的键 **/ var recordPress=function(eve){ eve=cg.core.getEventObj(eve); var keyName=k[eve.keyCode]; pressed_keys[keyName]=true; if(keydown_callbacks[keyName]){ for(var i=0,len=keydown_callbacks[keyName].length;i<len;i++){ keydown_callbacks[keyName][i](); } } if(keydown_callbacks["allKeys"]){ for(var i=0,len=keydown_callbacks["allKeys"].length;i<len;i++){ keydown_callbacks["allKeys"][i](); } } if(preventDefault_keys[keyName]){ cg.core.preventDefault(eve); } }
每个键的处理程序可以有多个,所以这里保存处理程序的对象保存的是一个数组。另外需要注意通过pressed_keys数组保存了按下的键(pressed_keys[keyName]=true;),就是为了方便实现之前说过的在帧更新中进行一致的参数更新(可以在每次update时通过isPressed(keyName)判断某个键是否按下)。
最后附上该输入模块所有源代码:
/** * *输入记录模块 * **/ cnGame.register("cnGame.input",function(cg){ this.mouseX=0; this.mouseY=0; /** *记录鼠标在canvas内的位置 **/ var recordMouseMove=function(eve){ var pageX,pageY,x,y; eve=cg.core.getEventObj(eve); pageX = eve.pageX || eve.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft; pageY = eve.pageY || eve.clientY + document.documentElement.scrollTop - document.documentElement.clientTop; cg.input.mouseX=pageX-cg.x; cg.input.mouseY=pageY-cg.y; } cg.core.bindHandler(window,"mousemove",recordMouseMove); /** *被按下的键的集合 **/ var pressed_keys={}; /** *要求禁止默认行为的键的集合 **/ var preventDefault_keys={}; /** *键盘按下触发的处理函数 **/ var keydown_callbacks={}; /** *键盘弹起触发的处理函数 **/ var keyup_callbacks={}; /** *键盘按键编码和键名 **/ var k=[]; k[8] = "backspace" k[9] = "tab" k[13] = "enter" k[16] = "shift" k[17] = "ctrl" k[18] = "alt" k[19] = "pause" k[20] = "capslock" k[27] = "esc" k[32] = "space" k[33] = "pageup" k[34] = "pagedown" k[35] = "end" k[36] = "home" k[37] = "left" k[38] = "up" k[39] = "right" k[40] = "down" k[45] = "insert" k[46] = "delete" k[91] = "leftwindowkey" k[92] = "rightwindowkey" k[93] = "selectkey" k[106] = "multiply" k[107] = "add" k[109] = "subtract" k[110] = "decimalpoint" k[111] = "divide" k[144] = "numlock" k[145] = "scrollock" k[186] = "semicolon" k[187] = "equalsign" k[188] = "comma" k[189] = "dash" k[190] = "period" k[191] = "forwardslash" k[192] = "graveaccent" k[219] = "openbracket" k[220] = "backslash" k[221] = "closebracket" k[222] = "singlequote" var numpadkeys = ["numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9"] var fkeys = ["f1","f2","f3","f4","f5","f6","f7","f8","f9"] var numbers = ["0","1","2","3","4","5","6","7","8","9"] var letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] for(var i = 0; numbers[i]; i++) { k[48+i] = numbers[i] } for(var i = 0; letters[i]; i++) { k[65+i] = letters[i] } for(var i = 0; numpadkeys[i]; i++) { k[96+i] = numpadkeys[i] } for(var i = 0; fkeys[i]; i++) { k[112+i] = fkeys[i] } /** *记录键盘按下的键 **/ var recordPress=function(eve){ eve=cg.core.getEventObj(eve); var keyName=k[eve.keyCode]; pressed_keys[keyName]=true; if(keydown_callbacks[keyName]){ for(var i=0,len=keydown_callbacks[keyName].length;i<len;i++){ keydown_callbacks[keyName][i](); } } if(keydown_callbacks["allKeys"]){ for(var i=0,len=keydown_callbacks["allKeys"].length;i<len;i++){ keydown_callbacks["allKeys"][i](); } } if(preventDefault_keys[keyName]){ cg.core.preventDefault(eve); } } /** *记录键盘松开的键 **/ var recordUp=function(eve){ eve=cg.core.getEventObj(eve); var keyName=k[eve.keyCode]; pressed_keys[keyName]=false; if(keyup_callbacks[keyName]){ for(var i=0,len=keyup_callbacks[keyName].length;i以上是HTML5游戏框架cnGameJS开发实录-外部输入模块篇的详细内容。更多信息请关注PHP中文网其他相关文章!

H5和HTML5是不同的概念:HTML5是HTML的一个版本,包含新元素和API;H5是基于HTML5的移动应用开发框架。HTML5通过浏览器解析和渲染代码,H5应用则需要容器运行并通过JavaScript与原生代码交互。

HTML5的关键元素包括、、、、、等,用于构建现代网页。1.定义头部内容,2.用于导航链接,3.表示独立文章内容,4.组织页面内容,5.展示侧边栏内容,6.定义页脚,这些元素增强了网页的结构和功能性。

HTML5和H5没有区别,H5是HTML5的简称。1.HTML5是HTML的第五个版本,增强了网页的多媒体和交互功能。2.H5常用于指代基于HTML5的移动网页或应用,适用于各种移动设备。

HTML5是超文本标记语言的最新版本,由W3C标准化。HTML5引入了新的语义化标签、多媒体支持和表单增强,提升了网页结构、用户体验和SEO效果。HTML5引入了新的语义化标签,如、、、等,使网页结构更清晰,SEO效果更好。HTML5支持多媒体元素和,无需第三方插件,提升了用户体验和加载速度。HTML5增强了表单功能,引入了新的输入类型如、等,提高了用户体验和表单验证效率。

如何写出干净高效的HTML5代码?答案是通过语义化标签、结构化代码、性能优化和避免常见错误。1.使用语义化标签如、等,提升代码可读性和SEO效果。2.保持代码结构化和可读性,使用适当缩进和注释。3.优化性能,通过减少不必要的标签、使用CDN和压缩代码。4.避免常见错误,如标签未闭合,确保代码有效性。

H5通过多媒体支持、离线存储和性能优化提升网页用户体验。1)多媒体支持:H5的和元素简化开发,提升用户体验。2)离线存储:WebStorage和IndexedDB允许离线使用,提升体验。3)性能优化:WebWorkers和元素优化性能,减少带宽消耗。

HTML5代码由标签、元素和属性组成:1.标签定义内容类型,用尖括号包围,如。2.元素由开始标签、内容和结束标签组成,如内容。3.属性在开始标签中定义键值对,增强功能,如。这些是构建网页结构的基本单位。

HTML5是构建现代网页的关键技术,提供了许多新元素和功能。1.HTML5引入了语义化元素如、、等,增强了网页结构和SEO。2.支持多媒体元素和,无需插件即可嵌入媒体。3.表单增强了新输入类型和验证属性,简化了验证过程。4.提供了离线和本地存储功能,提升了网页性能和用户体验。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3 Linux新版
SublimeText3 Linux最新版

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Atom编辑器mac版下载
最流行的的开源编辑器

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中