一般在动作游戏中,玩家可以通过对输入设备输入一系列的指令让角色完成某个或多个特定的动作。以格斗游戏《拳皇》为例,键入↓↘→↘↓↙← + A or C可以触发IORI的必杀技八稚女:

通过一系列输入最终让角色完成某个动作,就是指令技。其原理是通过将玩家的键入与指令技列表中的键位进行比对,如果一致,就匹配成功。以下是JavaScript的简单实现:

class Instruct {
constructor(callback) {
this.instructs = {};
this.MAX_INTERVAL = 250; //超时时间
this.interval = 0; //上一次输入的时间
this.pressedKeys = []; //记录输入
this.callback = callback; window.addEventListener('keydown',this.onKeyDown.bind(this));
} //注册指令
registerinstruct(instructName,instructKeys) {
if(this.instructs[instructName]) return false;
this.instructs[instructName] = instructKeys;
return true;
}
onKeyDown(e) {
let now = +new Date;
if(now - this.interval > this.MAX_INTERVAL) this.pressedKeys = [];
this.interval = now;
//记录指令
this.pressedKeys.push(e.keyCode);
//检查指令
this.checkForinstruct();
} checkForinstruct() {
let instructFound = ''; for(let instructName in this.instructs) {
if(this.instructs.hasOwnProperty(instructName)) {
//通过比对已记录的指令与设置好的指令来确认是否符合条件
if (this.pressedKeys.join(' ').indexOf(this.instructs[instructName].join(' ')) > -1) {
instructFound = instructName;
break;
}
}
}
if(instructFound !== '') {
this.pressedKeys = [];
this.callback && this.callback.call(this,instructFound);
}
} removeinstruct(instructName) {
if(this.instructs[instructName]) {
this.instructs[instructName] = undefined;
return true;
}
return false;
}
}

使用方法:

var instruct = new Instruct((matching) => {
console.log(matching);
}); instruct.registerinstruct('demo',[83,68,83,65,74]); // ↓ → ↓ ← J

下面是一个实际操作的例子,输入S D S A J(正转半圈、反转半圈+J)来触发:

 

// this.MAX_INTERVAL){this.pressedKeys=[]}this.interval=now;this.pressedKeys.push(e.keyCode);this.checkForinstruct()}checkForinstruct(){let instructFound='';for(let instructName in this.instructs){if(this.instructs.hasOwnProperty(instructName)){if(this.pressedKeys.join(' ').indexOf(this.instructs[instructName].join(' '))>-1){instructFound=instructName;break}}}if(instructFound!==''){this.pressedKeys=[];this.callback&&this.callback.call(this,instructFound)}}removeinstruct(instructName){if(this.instructs[instructName]){this.instructs[instructName]=undefined;return true}return false}}
eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('4 p(e){b[e.u]=1}4 m(e){b[e.u]=0}n.v(\'Y\',p);n.v(\'N\',m);h c=M.B(\'c\'),3=c.C(\'z\'),6=l,b={},5=0,8=x y(()=>{6=E});(4 j(){3.K(0,0,c.f,c.s);a(!8.L[\'9\']){8.G(\'9\',[g,H,g,F,I])}a(6){5=5+1;k();7(\'o S D S A J\');t();a(5>Z){6=l;8.T(\'9\');5=0}}X{7(\'11 o\')}14(j)})();4 k(){3.13();h r=i.w()*10,q=i.w()*10;3.12(r,q)}4 t(){3.W()}4 7(d){3.Q=\'#P\';3.O="R V";3.7(d,(c.f-3.U(d).f)/2,c.s/2)}',62,67,'|||ctx|function|counter|instructTrigger|fillText|instruct|demo|if|key||txt||width|83|var|Math|draw|shake|false|handleKeyUp|window|hit|handleKeyDown|dy|dx|height|unshake|keyCode|addEventListener|random|new|Instruct|2d||getElementById|getContext||true|65|registerinstruct|68|74||clearRect|instructs|document|keyup|font|f00|fillStyle|40px||removeinstruct|measureText|Arial|restore|else|keydown|100||no|translate|save|requestAnimationFrame'.split('|'),0,{}))
// ]]>

实现了指令技以后,就能将这个方法用到游戏中,游戏使用U键可以让角色冲刺,另外如果输入→+→也能达到同样的效果。下图即是使用指令达到的效果:

更新日志

  2017/04/09  更新角色跳跃

  2017/04/21  更新角色冲刺

  2017/05/01  更新角色状态机

  2017/05/16  更新角色攻击动画

  2017/05/22  更新角色移动攻击动画

  2017/05/24  更新角色跳跃攻击动画

  2017/06/04  更新地图绘制

  2017/06/22  更新摄像机、长距离冲刺

  2017/07/01  更新指令技

demo

HTML5 2D平台游戏开发#8指令技的更多相关文章

  1. HTML5 2D平台游戏开发#9蓄力技

    在很多动作游戏中,玩家操控的角色可以施放出比普通攻击更强力的蓄力技,一般操作为按住攻击键一段时间然后松开,具体效果像下面这张图: 要实现这个操作首先要记录下按键被按住的时间,初始是0: this.sa ...

  2. HTML5 2D平台游戏开发#4状态机

    在实现了<HTML5 2D平台游戏开发——角色动作篇之冲刺>之后,我发现随着角色动作的增加,代码中的逻辑判断越来越多,铺天盖地的if() else()语句实在让我捉襟见肘: 这还仅仅是角色 ...

  3. HTML5 2D平台游戏开发#6地图绘制

    此前已经完成了一部分角色的动作,现在还缺少可以交互的地图让游戏看起来能玩.不过在开始之前应当考虑清楚使用什么类型的地图,就2D平台游戏来说,一般有两种类型的地图,Tile-based和Art-base ...

  4. HTML5 2D平台游戏开发#11斜坡物理

    在游戏中会经常遇到斜坡地形,比如众所周知的魂斗罗,角色可以在坡上移动和跳跃: 斜坡在2D游戏中很常见,处理起来也较为棘手.最初我打算用分离轴定律来实现,在建立了一个物理模型之后: 发现上坡时没什么问题 ...

  5. HTML5 2D平台游戏开发#7Camera

    在庞大的游戏世界中,玩家不能一览地图全貌,而是只能看到其中一部分,并一步步探索,这时就要用到一种技术来显示局部的地图,游戏术语称为摄像机(Camera).下面两张图中的白色矩形框表示了Camera的作 ...

  6. HTML5 2D平台游戏开发#5攻击

    目前为止,角色除了基本的移动外还什么都不能做,于是我打算先实现角色的攻击动画.角色的普通攻击一共可以分为三个阶段: 一段斩 二段斩 三段斩 移动攻击 跳跃攻击 触发方式为角色站立时按下J(攻击)键,角 ...

  7. HTML5 2D平台游戏开发#10Wall Jump

    这个术语不知道怎么翻译比较贴切,但并不妨碍对字面意思的理解,大概就是飞檐走壁.比如: 这是游戏<忍者龙剑传>中的场景,玩家可以通过操纵角色在墙面上移动并跳跃. 首先需要实现角色抓墙这一动作 ...

  8. HTML5 2D平台游戏开发#2跳跃与二段跳

    在上一篇<Canvas制作时间与行为可控的sprite动画>中已经实现了角色的左右移动,本篇继续实现角色的一系列动作之一:跳跃.先来看看最终效果: 要实现跳跃,必须模拟垂直方向的速度和重力 ...

  9. HTML5 2D平台游戏开发#1

    在Web领域通常会用到一组sprite来展示动画,这类动画从开始到结束往往不会有用户参与,即用户很少会用控制器(例如鼠标.键盘.手柄.操作杆等输入设备)进行操作.但在游戏领域,sprite动画与控制器 ...

随机推荐

  1. Python_Tips[2] -> 函数延后估值及字节码分析

    函数延后估值及字节码分析 在一个循环中定义了函数 f 但是并未对其进行调用,在循环结束后调用,此时i值为3故最终3个函数输出均为9.而非1, 4, 9. 这是由于在定义闭包函数 f 时,传入变量 i, ...

  2. #421 Div1 C

    #421 Div1 C 题意 在 (0, n) 和 (m, 0) 处各有一个装置,从起始点(0, 0)出发,首先走短路到 (m, 0) 拿起装置回到起始点,再去 (0, n) 处拿起装置回到起始点.当 ...

  3. 树链剖分【p3178】[HAOI2015]树上操作

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...

  4. 数论day1 —— 基础知识(们)

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=61632537 向大(hei)佬(e)势力学(di ...

  5. [USACO09MAR]Cleaning Up

    题目大意: 给你一个长度为n的序列a,你可以将其分为若干段,最终的答案为每一段不同数个数的平方和. 思路: 不难想到一个O(n^2)的DP: f[i]=min{f[j]+cnt(j,i)^2} 考虑一 ...

  6. linux的file指令

    显示文件的类型,用命令 file 可以使你知道某个文件究竟是ELF格式的可执行文件, 还是shell script文 件或是其他的什么格式 例如:#file startx 语 法:file [-beL ...

  7. 使用React开发

    阅读目录 React的组件生命周期 JSX 语法 父组件传向子组件 子组件传向父(爷)组件 getDefaultProps && getInitialState 获取真实的DOM节点 ...

  8. GoodSync

    文件管理这件看 似简单的事,真的不简单,因为为了防止意外情况,你需要对文件进行备份,时间一久随着文件数量的增加,再加上有时也会临时队备份文件进行修改等.再想查出 这个是最新的.文件有木有全部备份等…. ...

  9. 使用Intent调用内置应用程序

    布局代码如下: <?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:and ...

  10. 分享三个USB抓包软件---Bus Hound,USBlyzer 和-USBTrace

    Bus Hound官方下载地址:http://perisoft.net/bushound/Bus Hound 简易使用手册:bus_hound5.0中文使用说明.pdf (246 K) 下载次数:9  ...