一、 跳跃与移动的优化与完善

先给上一次的内容做一次补救,也就是上一次中还留存的,由于键盘按键事件的第一次回调与后续回调之间会间隔个小半秒带来的跳跃落地后动作延迟的情况。

最终的键盘按下回调的处理代码是这样的:

onKeyPressed: function (keyCode, event) {
        switch(keyCode) {
            case cc.KEY.left:
                this.direction = 'idle_left';
                if (this.stay) {
                    this.move = 'move_left';
                } else {
                    this.moveAfterJump = 'move_left';
                }
                break;
            case cc.KEY.right:
                this.direction = 'idle_right';
                if (this.stay) {
                    this.move = 'move_right';
                } else {
                    this.moveAfterJump = 'move_right';
                }
                break;
            case cc.KEY.alt:
                if(this.stay){
                    this.stay = false;
                    this.jumpSpeed = this.jump;
                    this.moveAfterJump = this.move;
                }
                break;
            case cc.KEY.down:
                if (this.stay) {
                    this.move = 4;
                } else {
                    this.moveAfterJump = 4;
                }
                break;
            default:
                break;
        }
    },

键盘松开的回调事件处理代码是这样的:

onKeyReleased: function (keyCode, event) {
        switch(keyCode) {
            case cc.KEY.left:
                if(!this.stay) {
                    if (this.moveAfterJump === 'move_left') {
                        this.moveAfterJump = 'idle_left';
                    }
                } else {
                    if (this.move === 'move_left') {
                        this.move = 'idle_left';
                    }
                }
                break;
            case cc.KEY.right:
                if(!this.stay) {
                    if (this.moveAfterJump === 'move_right') {
                        this.moveAfterJump = 'idle_right';
                    }
                } else {
                    if (this.move === 'move_right') {
                        this.move = 'idle_right';
                    }
                }
                break;
            default:
                break;
        }
    },

整体思路很简单:

1. 键盘按下事件区分当前是否正在跳跃(stay的值)

正在跳跃则只改变朝向并预定落地后的运动,否则直接改变朝向并执行运动

2. 键盘松开事件区分松开的按键是否与当前生效的按键一致(有可能是已经被覆盖掉无效了的按键,比如说左移时按下右移,左移其实已经失效了)

如果松开的按键正是当前正在生效的按键,那就停止它,否则不需要做什么处理。(当然还是要区分是否正在跳跃)

下一个问题就是角色离开当前平台(没有跳跃) 时会做到悬空效果,因为没有做碰撞离开事件的处理,现在就把它加上:

onCollisionExit: function (other, self) {
        var otherTop = other.world.aabb.y + other.world.aabb.height;
        var selfBottom = self.world.aabb.y;
        // 自身底部与目标顶部的偏移
        var out = otherTop - selfBottom;
        // 偏移
        if(Math.abs(out) < 10) {
            this.stay = false;
        }
    } 

与此同时,如代码中所见的,现在把方向与移动的值都改为了字符串值,而不再使用数字值,这是为了方便后续添加动画,并且其值更加明了,idle_left/right代表站立朝左/右,move_left/right代表左右移动。

二、 美术资源

现在开始小白要变身了,不能一直当小白,笔者就用自己一个周末学会得PS皮毛来把我们的第一个角色给画出来,想了想就选用画起来最简单的一只口袋妖怪好了,没错就是他:

纯PS画笔画出来的,这里要隔空感谢一下腾讯课堂上名叫战翼的CG免费课程老师的PS工具预设。下面是整套高清雷电球套图:

包括了左右两个朝向的雷电球,还有就是完整一圈的滚动动作帧,画得很丑还请包涵毕竟本职是个写代码的。

三、资源的使用

首先要把我们的雷电球套图制作成cocos的图集资源,使用的是TexturePacker工具,然后直接拖拽到CocosCreator中:

直接拖一帧到player的spirit上,角色就变身成为雷电球了:

四、动画资源

接下来就是本文的重头戏动画了,首先要给player添加动画组件:

然后就把我们需要的四种动画给编辑出来,分别是:朝左静止,朝右静止,向左滚动,向右滚动,也就是4个动画clip:

最终得到的就是下图中这么四个动画,把他们都像上图中一样拖到player的动画clip里。

关于CocosCreator的动画编辑器感觉没什么难度虽然笔者也并没有用的很多,但是想达到的目的也只是创建最简单的帧动画而已,要做的事情无非就是:

给角色添加动画组件 -> 选中角色进入动画编辑器 -> 创建新clip -> 一帧一帧拖图片 -> 选择循环播放或者别的 -> 保存并拖到角色动画组件的clip数组中

五、脚本控制动画

接下来要使用脚本来控制动画。

要实现的效果是:角色左右移动时会展现滚动的动画,停下时会根据当前朝向展现左右站立的形象,原地跳跃时不会滚动,移动跳跃时会保持滚动形态。

说白了就是根据前面定义好的direction和move值来控制动画clip的播放啦。

正是为此才将这两个变量值改用字符串,也就是直接是动画clip的名字,在播放动画时能比较方便。

现在新建一个function专门接收朝向和运动参数,并判断出需要播放何种动画。并在键盘按下、键盘松开、碰撞进入、碰撞离开这四个事件发生时执行:

currentAnim: '',
    DoAnim: function(od, nd, om, nm) {
        if (this.stay) {
            // 移动优先
            if (om != nm && nm != this.currentAnim) {
                this.anim.play(nm);
            }
        } else {
            // 朝向优先
            if (od != nd && nd != this.currentAnim) {
                this.anim.play(nd);
            }
        }
    },

currentAnim用于存放当前正在播放的动画,因为cocos的机制动画重复调用play()时会先停止当前然后重新播放,这是不符合我们想要的效果的,所以只有当需要播放的动画当前不在播放时才需要播放它。

并且播放那种动画的判断需要根据新旧朝向和新旧移动来判断,因为只有朝向或移动发生改变时才需要更改当前的动画不是吗。

在前面讲到的四种事件中,要在事件处理的一开始就记录旧的朝向和移动,并在最后记录新的朝向和移动(这些事件做的事情就是将朝向或移动从旧的变成新的),然后再执行这个DoAnim方法,就可以了:

onKeyReleased: function (keyCode, event) {
        var oldDirection = this.direction;
        var oldMove = this.move;
        switch(keyCode) {
            ...
        }
        this.DoAnim(oldDirection, this.direction, oldMove, this.move);
    },

至此putsangto的第一个场景下,雷电球已经可以走走跳跳了,对于笔者边学边做来说好歹是迈出了一两步,接下来要做的事情还有很多,待续待续。

PuTsangTo-单撸游戏开发04 给角色添加基本动画的更多相关文章

  1. PuTsangTo-单撸游戏开发02 测试场景与单轴移动

    且不说立项与设计阶段的工作量,一个完整的游戏在开发阶段设计的职责范围也是很广,还有个大问题就是PuTsangTo项目也是本人在边学边做,截止目前还是满满的无从下手的感觉,一方面是技能与经验不足,另一方 ...

  2. Unity3D 游戏开发构架篇 ——角色类的设计与持久化

    在游戏开发中,游戏角色占了很大的篇幅,可以说游戏中所有的内容都是由主角所带动.这里就介绍一下角色类的设计和持久化. 一.角色类应用场景和设计思想 游戏中的角色类型不一而足,有不同的技能,有不同的属性等 ...

  3. PuTsangTo-单撸游戏开发01 Flag与计划

    先立下flag,至少1年之内坚持并2年之内完成自己的一个梦想--游戏开发. 没有参加培训也不打算参加培训,就纯靠业余时间自学并用自己的思路完成一整套游戏体系.做出此决心时也已经做好准备烂尾了,但是有种 ...

  4. Unity引擎入门——制作第一个2D游戏(2)角色移动与动画

    在上一节的内容里,我们已经创建出了一个主角,也搭建了一个简单的场景. 传送门:https://www.cnblogs.com/zny0222/p/12653088.html 既然有了主角,要怎样才能让 ...

  5. PuTsangTo-单撸游戏开发03 碰撞与跳跃瑕疵版

    继续上一部分,游戏的定位是横版平台动作类游戏,所以得有跳跃动作,首先想到的就是物理引擎,不过在2D游戏里,仅为了角色的跳跃而引入物理引擎,目前想来有些不至于,仅使用cocos默认带有的碰撞系统也足够了 ...

  6. Android游戏开发实践(1)之NDK与JNI开发04

    Android游戏开发实践(1)之NDK与JNI开发04 有了前面几篇NDK与JNI开发相关基础做铺垫,再来通过代码说明下这方面具体的操作以及一些重要的细节.那么,就继续NDK与JNI的学习总结. 作 ...

  7. Unity3D手机斗地主游戏开发实战(04)_出牌判断大小(已完结)

    之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...

  8. Unity3D手机斗地主游戏开发实战(04)_出牌判断大小

    之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...

  9. 算法、数据结构、与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design)

    算法.数据结构.与设计模式等在游戏开发中的运用 (一):单例设计(Singleton Design) 作者: Compasslg 李涵威 1. 什么是单例设计(Singleton Design) 在学 ...

随机推荐

  1. 【吐血整理】SVN命令行,Subversion的正确使用姿势,让版本控制更简单~

    一.写在前面 前面一直博主一直用svn的桌面版本,但看项目经理一直都用的命令行方式,不为性能,还能直接装逼呀!在这里先感谢赵哥,也把它分享给感兴趣的你们~ 二.直接上干货 1. svn checkou ...

  2. html5_canvas初学

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 网易云直播SDK使用总结

    前言: 最近公司的项目中加入中直播这部分的功能,现在的直播平台真的很多很多,以前在朋友圈看到过这张图片,没办法一次性给大家看,就只能这样截成几张给大家看看.其实按照我自己的看法,现在的直播已经没办法做 ...

  4. JavaScript中的this关键字的用法和注意点

    JavaScript中的this关键字的用法和注意点 一.this关键字的用法 this一般用于指向对象(绑定对象); 01.在普通函数调用中,其内部的this指向全局对象(window); func ...

  5. [Hadoop] - Mapreduce自定义Counter

    在Hadoop的MR程序开发中,经常需要统计一些map/reduce的运行状态信息,这个时候我们可以通过自定义Counter来实现,这个实现的方式是不是通过配置信息完成的,而是通过代码运行时检查完成的 ...

  6. 《C++ Primer》读书笔记—第一章 开始

    声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程. 1.一个函数的定义包含四个部分:返回类型(retur ...

  7. redis安装(针对2.8以上版本)

    1. 下载安装包 http://redis.io/ 2. 下载tcl/tck http://124.202.164.12/files/41060000061B56BD/downloads.source ...

  8. ThinkPHP5.0学习1 — 命名空间

    定义命名空间:namespace sp1: 访问命名空间:\sp1\somefunction(); 非限定名称访问方式     //访问当前命名空间内容:somefunction(); 限定名称访问方 ...

  9. 简学Python第四章__装饰器、迭代器、列表生成式

    Python第四章__装饰器.迭代器 欢迎加入Linux_Python学习群  群号:478616847 目录: 列表生成式 生成器 迭代器 单层装饰器(无参) 多层装饰器(有参) 冒泡算法 代码开发 ...

  10. ZOJ 1492 Maximum Clique 搜索最大团

    ZOJ1492 题意:给一个无向图 求最大团的大小.节点数小于50 数据有限,考虑记忆化搜索,方程很好给出. 令 Si={vi,vi+1.....vn} mc[i]表示Si最大团的大小,倒着推算. 必 ...