CreatorPrimer|飞机大战(一)

前两天在Cocos官方公众号上学习了「大掌教」的Cocos Creator 2.x Camera教程,总算是对摄像机组件有了一个初步的认识。乘热打铁,Shawn即刻就使用Camera摄像机练习了一个飞机游戏的,目前主要实现3个功能:

  1. 无限滚动背景
  2. 控制飞机移动
  3. 子弹发射

下面是游戏视频:

image.png

视频地址:https://v.youku.com/v_show/id_XNDA4NDAxODMyNA==.html?spm=a2hzp.8244740.0.0

1. 无限滚动背景

滚动背景我们当然是使用最新的摄像机来实现,我这里做了一个卷轴摄像机组件ScrollCamera,我们现来看一下组件暴露的属性:


滚动摄像机

ScrollCamera组件很像真实世界中的摄像机的推进器,Speed是推进速度,LoopGrounds是一个节点数组,他们是一组可首尾衔接的精灵节点,看下图:


可首尾衔接的精灵节点

我们再看一下ScrollCamera组件的代码:


cc.Class({
    editor: {
        requireComponent: cc.Camera,  //前置要求摄像机组件
    },
    extends: cc.Component,

    properties: {
        speed: 300,              //滚动速度
        loopGrounds: [cc.Node],  //循环节点
    },

    start () {
        //获取节点上的摄像机组件
        this.camera = this.getComponent(cc.Camera);
    },

    /**
    *每帧更新函数
    *1. 更新摄像机位置
    *2. 检查循环节点,设置新位置
    **/
    update(dt) {
        //获取当前节点
        let current = this.loopGrounds[0];
        //计算当前节点在摄像机中的位置
        let pt = this.camera.getWorldToCameraPoint(current.position);
        //当前节点超出摄像机范围(摄像机可视范围就是屏幕大小)
        if (pt.y <= -cc.winSize.height) {
            //取最后一个地图节点
            let last = this.loopGrounds[this.loopGrounds.length - 1];
            //将当前节点从数组中移除
            this.loopGrounds.shift();
            //将当前节点放到数组最后 
            this.loopGrounds.push(current);
            //将当前节点位置移动到最顶部位置
            current.y = last.y + (last.height + current.height) / 2;
        }
        //更新摄像机节点位置
        this.node.y += dt * this.speed;
    }
});

推动摄像机的代码很简单,看update函数中的最后一行:

this.node.y += dt * this.speed;

update中前面的几行代码是在做loopGrounds节点的检查和位置更新,每一行都注释,这里就不再过多赘述了。

将这个组件直接拖动到场景编辑器或层级管理器,设置background节点为background分组:

分组设置

同时设置ScrollCamera的cullingMask属性只勾选background,看下图:


摄像机分组

通过上面的设置和ScrollCamera的十几代码,无限滚动背景就搞定了。

2. 控制飞机移动

不知道大家还记得公众号之前的一篇文章《Cocos Creator基础教程(11)—可拖拽组件》,我直接将Dragable.js组件脚本拿过来,挂载到飞机节点上就OK了,代码也很简单:

/**
 * 可拖动组件
 */
cc.Class({
    extends: cc.Component,

    onLoad() {
        //注册TOUCH_MOVE事件
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
        cc.log('onload');
    },

    _onTouchMove(touchEvent) {
        //let location = touchEvent.getLocation();
        //this.node.position = this.node.parent.convertToNodeSpaceAR(location); 

        //获取触摸移动增量
        let delta = touchEvent.getDelta();
        //当前节点位置+增量,更新节点位置
        this.node.position = delta.add(this.node.position);
    }
});

_onTouchMove函数稍微调整了一下,之前使用方法的是当前节点设置为触摸点位置,需要将全局坐标转换为当前节点的父节点坐标(设置一个节点的位置,是设置它在其父节点中的位置),拖动时节点总是保持在移动点的中心,特别是在第一次拖动节点时会有一个跳跃感,不够平滑。

我这里简单改进了一下,通过获取移动增量再加上当前节点位置,可以拖动节点的任意位置,不会出现突然将节点拉动到手指中心的突兀感。

Shawn在做这个飞机游戏过程中也尝试了一下消灭病毒当下这个火热的游戏,他的整个屏幕任意位置都可以控制飞机的移动,它是怎么做的呢,大家先可以思考一下?

我们这里再修改一下Dragable组件,增加一个target节点属性,将它从飞机节点上移到外层foreground节点,看下图:

可拖拽目标节点

触摸事件发生在foreground节点上,但移动的是target属性所指向的节点,我们看下代码:

/**
 * 可拖动组件
 */
cc.Class({
    extends: cc.Component,
    properties: {
        target: cc.Node,
    },
    ...
    _onTouchMove(touchEvent) {
        //获取触摸移动增量
        let delta = touchEvent.getDelta();
        //如果this.target未设置,使用移动当前节点(兼容之前的用法)
        let node = this.target || this.node;
        //当前节点位置+增量,更新节点位置
        node.position = delta.add(node.position);
    }
});

代码就增加了一个target节点的定义,在TouchMove事件中检查this.target存在就用它,不存在默认移动当前节点,这样可以兼容曾经该组件的地方,不用做修改。

3. 子弹发射

飞机游戏的一个亮点就是子弹发射的华丽视觉效果,Shawn这里在网上找了些子弹特效图片,然后编辑了一个子弹Bullet的预制体,使用到之前文章《Cocos Creator基础教程(12)—精灵变身》中的SpriteEx.js组件,在上面配置了几张子弹图片,使用index属性可以方便切换子弹的表现效果,看下图:

SpriteEx.gif

Bullet子弹只是表现效果,要让子弹运动起来,我这里编写了一个LineEmmiter.js(线性发射器)的脚本,将它挂载到飞机节点上,用它来实例化Bullet预制体并让它动起来,先看一下LineEmmiter组件的属性:

线性发射器.png

之前的文章中提到过:组件为节点赋予能力,飞机节点上有一个Sprite可显示图片纹理,我们再挂上LineEmmiter组件,让它具有发射子弹的能力。

发射器的主要属性是子弹预制体、发射频率、子弹飞行速度,OffsetX属性要特别一点,它可以控制子弹与飞机的偏移位置,以实现同时发射多行子弹的效果,看下图:

多行发射.png

我们再看下发射器的组件代码:

cc.Class({
    extends: cc.Component,

    properties: {
        prefab: cc.Prefab,
        rate: 1,        //发射间隔
        speed: 1000,    //移动速度
        offsetX: 0,
    },

    start() {
        this.schedule(this._emmitNode, this.rate);
    },

    _emmitNode() {
        //实例化节点,设置位置&父节
        let node = cc.instantiate(this.prefab);
        node.position = this.node.position;
        node.x += this.offsetX;
        node.parent = this.node.parent;
        //计算子弹需要飞行的距离,飞行时间 = 距离 / 速度
        let distance = ((cc.winSize.height / 2) - this.node.y);
        let duration = distance / this.speed;
        //使用moveBy动作,完成后删除子弹节点
        let moveBy = cc.moveBy(duration, cc.v2(0, distance));
        let removeSelf = cc.removeSelf();
        let sequence = cc.sequence(moveBy, removeSelf);
        node.runAction(sequence);    
    }
});

发射器代码也很简单:

  1. 实例化子弹节点
  2. 让子弹飞起来

我们这里子弹是垂直飞行的,直接使moveBy动作就可以完成,子弹从当前飞机节点出发直到屏幕顶部结束,这是它飞行的距离根据公式:距离/速度=时间,计算每颗子弹的飞行时间,保证飞机在不同位置,所有子弹都是按同样的速度飞行。

4. 小结

本次教程我们实现了一个最小飞机游戏的简单原型,我们的核心地图滚动与子弹发射代码只有70多行,有没有觉得使用Cocos Creator开发游戏飞一般的简单呢...

不过还有很多欠缺的地方,比如:限制飞机不要跑出屏幕之外、子弹应该使用内存池进行优化,在功能上还缺少敌机生成、少子弹碰撞、得分计算等等,这些内容我们留到下次继续。

想获得源码的同学可以在,公众号回复:“飞机”或“飞机大战”,如果你对飞机游戏有不同的实现方案,欢迎一起讨论!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容