0

0

HTML5游戏框架cnGameJS开发实录-外部输入模块篇

黄舟

黄舟

发布时间:2017-03-24 16:13:37

|

2050人浏览过

|

来源于php中文网

原创

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.代码实现

LobeHub
LobeHub

LobeChat brings you the best user experience of ChatGPT, OLLaMA, Gemini, Claude

下载

  首先看如何保持鼠标在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


  每个键的处理程序可以有多个,所以这里保存处理程序的对象保存的是一个数组。另外需要注意通过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					

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

65

2026.01.16

全民K歌得高分教程大全
全民K歌得高分教程大全

本专题整合了全民K歌得高分技巧汇总,阅读专题下面的文章了解更多详细内容。

119

2026.01.16

C++ 单元测试与代码质量保障
C++ 单元测试与代码质量保障

本专题系统讲解 C++ 在单元测试与代码质量保障方面的实战方法,包括测试驱动开发理念、Google Test/Google Mock 的使用、测试用例设计、边界条件验证、持续集成中的自动化测试流程,以及常见代码质量问题的发现与修复。通过工程化示例,帮助开发者建立 可测试、可维护、高质量的 C++ 项目体系。

32

2026.01.16

java数据库连接教程大全
java数据库连接教程大全

本专题整合了java数据库连接相关教程,阅读专题下面的文章了解更多详细内容。

39

2026.01.15

Java音频处理教程汇总
Java音频处理教程汇总

本专题整合了java音频处理教程大全,阅读专题下面的文章了解更多详细内容。

19

2026.01.15

windows查看wifi密码教程大全
windows查看wifi密码教程大全

本专题整合了windows查看wifi密码教程大全,阅读专题下面的文章了解更多详细内容。

84

2026.01.15

浏览器缓存清理方法汇总
浏览器缓存清理方法汇总

本专题整合了浏览器缓存清理教程汇总,阅读专题下面的文章了解更多详细内容。

19

2026.01.15

ps图片相关教程汇总
ps图片相关教程汇总

本专题整合了ps图片设置相关教程合集,阅读专题下面的文章了解更多详细内容。

9

2026.01.15

ppt一键生成相关合集
ppt一键生成相关合集

本专题整合了ppt一键生成相关教程汇总,阅读专题下面的的文章了解更多详细内容。

47

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 6.7万人学习

HTML+CSS基础与实战
HTML+CSS基础与实战

共132课时 | 9.6万人学习

前端开发(基础+实战项目合集)
前端开发(基础+实战项目合集)

共60课时 | 3.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号