目前为止,角色除了基本的移动外还什么都不能做,于是我打算先实现角色的攻击动画。角色的普通攻击一共可以分为三个阶段:

一段斩
二段斩
三段斩
移动攻击
跳跃攻击
触发方式为角色站立时按下J(攻击)键,角色开始攻击,在此期间连续快速敲打J键,可继续触发后续攻击。最终效果如下:
(AD移动,K跳跃,J攻击,U冲刺)
 
 

// {
let loadBatch = {
count: 0,
total: assetList.length,
cb: callback
};

for (let i = 0; i {
onLoadedCallback(img, loadBatch);
};
img.src = assetName;
gCachedAssets[i] = img;
} else if (assetType === 1) {
let script = document.createElement('script');

script.addEventListener('load', () =>{
onLoadedCallback(script, loadBatch);
});

script.src = assetName;
gCachedAssets[i] = script;

document.getElementsByTagName('head')[0].appendChild(script);
}
} else {
onLoadedCallback(gCachedAssets[i], loadBatch);
}
}
},
onLoadedCallback = (asset, batch) =>{
batch.count++;
if (batch.count === batch.total) {
batch.cb(asset);
}
},
getAssetTypeFromExtension = (assetName) =>{
if (assetName.indexOf('.jpg') !== -1 || assetName.indexOf('.jpeg') !== -1 || assetName.indexOf('.png') !== -1) {
return 0;
}

if (assetName.indexOf('.js') !== -1 || assetName.indexOf('.json') !== -1) {
return 1;
}

return - 1;
};

(function() {
var canvas = document.createElement('canvas'),
a = document.getElementById('a');
canvas.id = 'c1';
canvas.width = 640;
canvas.height = 506;

a.appendChild(canvas);

var c = document.getElementById('c1'),
ctx = c.getContext('2d'),
lastTime = 0,
elapsed,
paused = false,
raqId,
playerSpriteSheet = new Image(),
canvasBG = new Image(),
now;

loadAssets(['http://files.cnblogs.com/files/undefined000/game.min.js?v=7'],function() {
playerSpriteSheet.src = imageData;
canvasBG.src = background;
let player = new Player(new Vector(5, 2), ctx, undefined, playerSpriteSheet);

function loop() {
draw();
}
function stop() {
cancelAnimationFrame(raqId)
}

function draw() {
ctx.clearRect(0, 0, c.width, c.height);
ctx.drawImage(canvasBG, 0, 0, 240, 160, 0, 0, 640, 506);
now = +new Date;
if (lastTime !== 0) {
elapsed = Math.min(now - lastTime, 16);
} else elapsed = 16;
player.update(elapsed);
lastTime = now;
raqId = requestAnimationFrame(draw);
}
loop();

window.addEventListener('keyup',(e) => {
if(e.keyCode === 80) {
paused = !paused;
if(paused) {
stop();
let txt = 'Pause';
ctx.font = '50px Source Han Serif';
ctx.fillStyle = '#f00';
ctx.fillText(txt, (c.width - ctx.measureText(txt).width) / 2, c.height / 2);
} else {
loop();
}
}
});
});
})();
// ]]>

之前已经使用了状态机来控制角色的行为,现在再用它来分析角色攻击阶段所发生的事情:

这里把攻击分为三种状态,目的是为了方便控制和在状态间转化,以下是updateIdle中的部分代码,用于站立过渡到攻击状态:

updateIdle:function() {
//省略部分代码
if (key[74]) { //攻击
if (!this.attacking && this.keyPressCounter++===1) {
this.attacking = true;
this.state = STATE.ATTACKING; this.play(); //播放攻击动画
}
} else {
this.attacking = false;
this.keyPressCounter = 0;
}
}

然后由攻击状态可以过渡到二段攻击状态,也可以不进行任何操作恢复到站立状态:

updateAttacking:function() {
let walked = false;
//若此阶段没有按下攻击键,则将连发锁重置
if (!key[74]) this.keyPressCounter = 0; if (key[85]) this.dashing = true; //在攻击过程中如果按下移动键,则在动画第8帧时就能移动而不用等到动画结束
if (key[65] || key[68]) {
walked = true;
if (this.getCurrentFrameIndex() >= 8) {
this.state = STATE.WALKING;
this.play();
}
} //仅动画帧<=7时按下攻击键可出现二段斩
if (this.getCurrentFrameIndex() <= 7) {
//如果没有连发锁,一直按住攻击键就能触发二段斩,不符合游戏逻辑
if (key[74] && this.keyPressCounter++===1) {
this.comboCounter = 2;
}
}
//动画开始到结束期间没有执行任何操作则执行此段分支恢复到Idle状态
else if (this.isAnimationEnd()) {
this.state = STATE.IDLE;
this.play();
} if (this.comboCounter === 2) { //执行二段斩
if (this.getCurrentFrameIndex() <= 7) {
this.state = STATE.ATTACKING_2ND;
this.play();
}
}
}

根据这种思路,可以很快完成updateAttacking2ndupdateAttacking3nd方法。

除此之外,角色还有很多种攻击方式,有时间的话会继续更新。

更新日志

  2017/4/09  更新角色跳跃

  2017/4/21  更新角色冲刺

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

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

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

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

HTML5 2D平台游戏开发#5攻击的更多相关文章

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

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

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

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

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

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

  4. HTML5 2D平台游戏开发#8指令技

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

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

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

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

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

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

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

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

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

  9. HTML5 2D平台游戏开发#3冲刺

    断断续续地把Demo又写了一阵,终于把角色的冲刺动作完成了.冲刺的作用是使角色能够快速移动,闪避攻击或障碍.其完成效果如下: 首先,仍需要一些变量来表示角色的冲刺状态: //标识角色是否处于冲刺中 v ...

随机推荐

  1. Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法

    类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...

  2. 用SparkSQL构建用户画像

    用SparkSQL构建用户画像 二.  前言 大数据时代已经到来,企业迫切希望从已经积累的数据中分析出有价值的东西,而用户行为的分析尤为重要. 利用大数据来分析用户的行为与消费习惯,可以预测商品的发展 ...

  3. sqldeveloper 英文设置

    在软件ide\bin目录下找到sqldeveloper.conf或ide.conf,加入 C:\Program Files (x86)\sqldeveloper\ide\bin AddVMOption ...

  4. 单条sql性能分析与优化

    性能分析 1. explain 查看sql执行计划,得出索引使用情况等信息 2. show profiling 查看sql所有执行步骤以及用时,使用步骤如下 1)开启性能剖析 mysql> se ...

  5. 一些 iOS 常用的第三方库

    网络通信 AFNetworking 轻量级的通讯类库,使用非常简单.建议更新到最新版,前几天看新闻说之前有个逻辑性的 bug https://github.com/AFNetworking/AFNet ...

  6. 使用ARC也可能发生内存泄露

    1,循环参照 A有个属性参照B,B有个属性参照A,如果都是strong参照的话,两个对象都无法释放. 这种问题常发生于把delegate声明为strong属性了. 例, @interface Samp ...

  7. Android Developer -- Bluetooth篇 开发实例之一 扫描设备

    第一步:声明Bluetooth Permissions <!-- 设置蓝牙访问权限 --> <uses-permission android:name="android.p ...

  8. Tomcat部署多个应用时日志文件路径相同引起的问题

    今天给客户部署新系统,一个 前台应用,一个后台应用,由于用的是同一个架子,日志文件路径也没改,所以两个应用的日志文件是同一个文件,这样应用运行时,就会出现只能访问一个应用的情况,如果两个应用同时访问, ...

  9. BAT文件使程序具有以系统权限运行的效果

    @echo off if "%1" == "h" goto begin mshta vbscript:createobject("wscript.sh ...

  10. ES怎么进行字段添加索引,并保留原有数据

    1.先将原索引进行备份 curl -XPOST '192.168.46.163:9200/_reindex?pretty' -H 'Content-Type: application/json' -d ...