新手入门,Quick-Cocos2d-x,Cocos

2D游戏特效动画的播放机制

特效动画的播放机制

本文转载自逆水行舟的博客,版权归作者所有。

gitblog-logo

一. 简介

动画在2D游戏里用得十分广泛, 根据这些动画的特点,我们可以大概归为3类

1. 粒子动画

这种动画是由几百甚至上千个粒子构成, 所有粒子都共享一个纹理, 这些粒子都是从一个发射器发出, 加以一定的随机因素, 在不同发射速度和重力等外力作用下,每个粒子呈现不一样的运动状态, 大量粒子可以组合成各种各样不一样的效果, 比如烟花, 火焰. 粒子动画的实现一般都会使用批次渲染和对象池来保证性能.

2. 骨骼动画

这种动画通常用于表现有多个动作的角色, 它通常是由骨骼(bone)和绑定在骨骼上的蒙皮(skin/mesh)构成.

动画师通常在spine(2d)或者3dmax等工具里面对骨骼动作进行设计, 同时对蒙皮进行编辑.

3. 特效动画

特效动画不需要或者难以使用骨骼进行表达, 比如一个刀光效果或者一闪一闪的星星, 我们可以使用最原始的实现方式, 对动画的每一帧都画一张图片, 依次连续展示这些图片就可以达到动画效果.

但是这种方法实现的动画过于浪费空间和内存. 其中有非常多的特效我们可以通过关键帧动画的方式来实现, 常使用Flash工具进行关键帧动画的设计.

本文中下面只讨论关键帧动画的实现.

阅读全文»

子龙山人带你学习OpenGL ES 2.0 :使用VBO索引

大家好,我是子龙山人。我现在在厦门 Cocos2D-X 团队做游戏引擎开发。

我是一个技术 Geek,我喜欢研究好玩的技术,同时我也是一个 Emacs 党。

欢迎大家一起交流。

我的个人主页:http://zilongshanren.com/


上一篇文章中,我们介绍了uniform和模型-视图-投影变换,相信大家对于OpenGL ES 2.0应该有一点感觉了。在这篇文章中,我们不再画三角形了,改为画四边形。下篇教程,我们就可以画立方体了,到时候就是真3D了,哈哈。

为什么三角形在OpenGL教程里面这么受欢迎呢?因为在OpenGL的世界里面,所有的几何体都可以用三角形组合出来。我们的四边形也一样,它可以用两个三角形组合出来。

阅读全文»

子龙山人带你学习OpenGL ES 2.0 :初识MVP

大家好,我是子龙山人。我现在在厦门 Cocos2D-X 团队做游戏引擎开发。

我是一个技术 Geek,我喜欢研究好玩的技术,同时我也是一个 Emacs 党。

欢迎大家一起交流。

我的个人主页:http://zilongshanren.com/


上一篇文章中,我在介绍vertex shader的时候挖了一个坑:CC_MVPMatrix。它其实是一个uniform,每一个cocos2d-x预定义的shader都包含有这个uniform, 但是如果你在shader里面不使用这个变量的话,OpenGL底层会把它优化掉。

但是,CC_MVPMatrix是在什么时候设置进来的呢?我在shader里面明明没有看到它,它从哪儿来的?别急,请继续往下读。

初识Uniform

在回答上面几个问题之前,让我们先来介绍一下什么是uniform。简单来说,uniform是shader里面的一种变量,它是由外部程序设置进来的,它不像vertex的attribute,每个顶点都有一份数据。除非你显式地调用glUniformXXX函数来修改这个uniform的值,否则它的值恒定不变。接下来,让我们修改myFragmentShader.frag,给它添加一个新的uniform数据:

阅读全文»

子龙山人带你学习OpenGL ES 2.0 :编写自己的shader

大家好,我是子龙山人。我现在在厦门 Cocos2D-X 团队做游戏引擎开发。

我是一个技术 Geek,我喜欢研究好玩的技术,同时我也是一个 Emacs 党。

欢迎大家一起交流。

Emacs 交流:https://slackin-emacs-cn.herokuapp.com/

Cocos2D-x 交流: Cocos2D-X Github issue system. https://github.com/cocos2d/cocos2d-x/issues/new

我的 Email: guanghui8827@gmail.com

我的个人主页:http://zilongshanren.com/


上篇文章中,我给大家介绍了如何在cocos2d-x里面绘制一个三角形,当时我们使用的是cocos2d-x引擎自带的shader和一些辅助函数。在本文中,我将演示一下如何编写自己的shader,同时,我们还会介绍VBO(顶点缓冲区对象)和VAO(顶点数组对象)的基本用法。

阅读全文»

子龙山人带你学习OpenGL ES 2.0 :你的第一个三角形

大家好,我是子龙山人。我现在在厦门 Cocos2D-X 团队做游戏引擎开发。

我是一个技术 Geek,我喜欢研究好玩的技术,同时我也是一个 Emacs 党。

欢迎大家一起交流。

Emacs 交流:https://slackin-emacs-cn.herokuapp.com/

Cocos2D-x 交流: Cocos2D-X Github issue system. https://github.com/cocos2d/cocos2d-x/issues/new

我的 Email: guanghui8827@gmail.com

我的个人主页:http://zilongshanren.com/

简介

欢迎来到我的 OpenGLES 系列教程,这个系列的教程我打算以时下最流行的开源游戏引擎 Cocos2D-X 为基础来介绍 OpenGLES。 我写作这个系列教程的原因是,一方面对我自己学习 OpenGLES 的一个总结,另一方面也希望通过一些具体的、 容易理解的示例,让大家更好地学习 OpenGLES。

阅读全文»

目前最全的Cocos资料集

@偶尔e网事,任职于触控科技,这里是他的博客

某天,他写了个爬虫,把Cocos引擎的中英文文档,全版本引擎,全版本配套工具以及一些第三方工具下载地址抓了下来,大概有三四百个,按照类别整理了一下,方便搜索。贡献在Github

Cocos 资料大全

本文定期更新,欢迎提交PR,托管在Cocos-Resource Github

阅读全文»

Cocos2016春季开发者大会:Cocos游戏引擎进入VR领域

由触控科技主办的2016年Cocos春季开发者大会于3月31日在北京召开。会上,Cocos引擎创始人王哲发表了主题为“变革:以内容生产为核心”的演讲,从VR领域、引擎工具升级、引擎商业化服务和案例三个方面,全面阐释了触控科技及Cocos引擎未来一段时间中的新动向。

阅读全文»

[Bugfix]CCFileUtils 解析 UTF8+BOM 字节文件时“key not found”的问题

存在 bug 的版本

Quick-Cocos2dx-Community 3.6 Release 以及 Cocos2d-x 3.3 final中。

bug 将在 Quick-Cocos2dx-Community 3.6.1 中修正。

bug 描述

CCFileUtils.cpp 文件中有一个用于帮助解析文本的 DictMaker 类。当解析带有 UTF8+BOM 的文件时,程序会首先调用 DictMaker 类的 textHandler 方法来解析文本。如下所示:

阅读全文»

Quick-Cocos2d-x初学者游戏教程12

上章我们讲解了物体之间的碰撞检测,而本章开始,我们将讲解触摸事件的实现,同时,我们还将给 Player 加上血量条。

需求说明

在开始之前,我们先来看看本节游戏的一些需求。

对于本教程游戏来说,我们的需求是在点击屏幕的时候,给 Player 一个向上的速度,让它能飞起来,否则它会受到重力的影响向下掉落。当掉落到地面上时,Player 会掉血,所以我们必须不停的点击屏幕以避免 Player 掉落到地上。在避免 Player 掉落的同时,我们还可以通过控制 Player 的飞起和降落来躲开障碍物和拾取心心。

游戏开始后 Player 精力充沛,有满满的血量,但当 Player 撞到障碍物和地面时,会根据碰撞到的类型来扣除不同点数的血量,当 Player 碰到心心时,可以增加一定的血量,并且会消除心心,消除的同时给它一个消除特效,这个特效用粒子系统来完成。Player 血量为0或地图跑外时,游戏结束。

需求分析清楚以后,下面我们就开始实现也上所描述的功能。

添加触摸事件

首先,我们来添加触摸事件。

触摸响应是游戏开发中一个很重要的模块,它是手游中玩家与游戏交互的主要途径。在 Quick 中,触摸事件机制是非常简单的,它允许任何一个 Node 接受触摸事件,而不局限于 Layer。

在我们的游戏中,我们需要在 Player 开始下落的时候启动触摸事件的响应,所以,我们将在 playerFlyToScene 函数的 startDrop 方法中启动触摸事件的响应,相关代码如下所示:

local function startDrop()
self.player:getPhysicsBody():setGravityEnable(true)
self.player:drop()
self.backgroundLayer:startGame()

self.backgroundLayer:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
return self:onTouch(event.name, event.x, event.y)
end)
self.backgroundLayer:setTouchEnabled(true)

end

这里,我们给 self.backgroundLayer 背景层添加了触摸事件的监听,其中 addNodeEventListener 方法用于注册系统事件的监听,如上所诉的触摸事件,以及帧事件、按键事件等等。

可能你会问:为什么是给 self.backgroundLayer 添加触摸事件的监听呢,为什么不是 self 场景自身,或者 Player?这里我们需要解释一下的是:触摸响应不能直接给 scene 添加事件监听,而如果只给 Player 添加触摸监听,那么我们只能在 Player 这个很小的范围内响应到触摸事件,所以我们需要用一个层来完成。在游戏中又只创建了一个背景层,所以我们就将就着把触摸事件的监听添加到它身上。当然,你也可以新建一个层来添加触摸监听,这里我们就不那么讲究了!

setTouchEnabled 方法用于开启触摸功能,如果 setTouchEnabled(false),那么背景层将不能接受到触摸响应。

另外,onTouch 方法是触摸事件回调,其定义如下:

function GameScene:onTouch(event, x, y)
if event == "began" then

self.player:flying()
self.player:getPhysicsBody():setVelocity(cc.p(0, 98))

return true
-- elseif event == "moved" then

elseif event == "ended" then
self.player:drop()
-- else event == "cancelled" then
end
end

因为我们要实现点击屏幕就给 Player 一个向上的速度,不点的时候 Player 向下掉落。所以,这里我们只需在触摸开始时,让 Player 处于飞行状态且给它一个方向向上的速度(0, 98);在触摸结束时,让 Player 下落就可以了。而不必去考虑在触摸移动 "moved" 和触摸取消 "cancelled" 时的状态。

还有一点要注意的是:在触摸开始时,必须返回 true,不然之后的 "ended" 等消息将不会被响应。

添加血条

接下来我们来给 Player 添加血量条,这可以用引擎中已经封装好的进度条(ProgressTimer)来实现。

以下是在 Player 中添加的相关代码,我们先来看看。

function Player:createProgress()
self.blood = 100 -- 1
local progressbg = display.newSprite("#progress1.png") -- 2
self.fill = display.newProgressTimer("#progress2.png", display.PROGRESS_TIMER_BAR) -- 3

self.fill:setMidpoint(cc.p(0, 0.5)) -- 4
self.fill:setBarChangeRate(cc.p(1.0, 0)) -- 5
-- 6
self.fill:setPosition(progressbg:getContentSize().width/2, progressbg:getContentSize().height/2)
progressbg:addChild(self.fill)
self.fill:setPercentage(self.blood) -- 7

-- 8
progressbg:setAnchorPoint(cc.p(0, 1))
self:getParent():addChild(progressbg)
progressbg:setPosition(cc.p(display.left, display.top))
end

function Player:setProPercentage(Percentage)
self.fill:setPercentage(Percentage) -- 9
end

其中 createProgress 方法的作用是添加一个进度条,setProPercentage 方法的作用是设置进度条的百分比。下面我们一一讲解下代码:

  1. 添加血量属性 self.blood,这里初始值我设为了 100,这样我们后面就可以根据血量来设置进度条的百分比了(懒人做法)。
  2. 给进度条创建一个底,也就是在进度条的下面放一个背景,这样当进度条逐渐变短时,用户可以更直观的看到它减少了多少。
    进度条背景和进度条图片分别如下所示:
    progress1 progress2
  3. 创建进度条 self.fill,display.newProgressTimer 方法的两个参数分别表示创建进度条所用的图片,以及进度条的类型。引擎中进度条的类型有两种:

    • display.PROGRESS_TIMER_BAR:条形,这种类型的进度条通常用于创建类似生命条,等级条的一类进度条。
    • display.PROGRESS_TIMER_RADIAL:环形,它通常用于创建类似加载功能的进度条,比如游戏加载资源时页面上旋转的菊花(PS:词穷,就是菊花吧,不要想歪)。
  4. 设置进度条的起始点,(0,y)表示最左边,(1,y)表示最右边,(x,1)表示最上面,(x,0)表示最下面。
  5. 设置进度条变化方向,如果不用变化的方向,则设置该方向为0,否则设置为1。所以(1,0)表示横方向,(0,1)表示纵方向。
  6. 把进度条的位置设置在 progressbg 上,并将进度条添加到 progressbg 上。
  7. 调用 ProgressTimer 的 setPercentage 方法设置进度条的百分比为 100%(因为 self.blood 的值为100)。
    ProgressTimer 类有一个很最要的percentage属性。它代表当前进度条的进度值。其中 setPercentage 方法能设置 ProgressTimer 的 percentage 值。
  8. 把 progressbg 加入屏幕的左上角。这里做了三件事:
    • 首先要把 progressbg 的锚点设置到它的左上角,锚点这个概念我忘了前面讲没讲过了,这里还是简单说明一下。
      锚点的两个参数在0~1之间。一般节点的锚点默认值都是(0.5, 0.5),也就是在节点的最中间。(0, 1)就表示左上角,将一个节点添加到父节点里面时,需要设置节点在父节点上的位置,其本质上就是设置节点的锚点在父节点坐标系上的位置。
    • 接着,我们把 progressbg 加到了 Player 的父节点上,这里也就是 GameScene 场景中。这样,进度条才不会随着 Player 的移动而移动了。
    • 最后,这里我们把 progressbg 放到屏幕的左上角。 anchor
  9. setProPercentage 是我们来设置进度条百分比的。

好了,以上创建血条的代码段应该讲解的够清楚了吧,接下来我们需要做的就是在合适的地方调用它。这里我们在 GameScene 中调用:

self.player = Player.new()
self.player:setPosition(-20, display.height * 2 / 3)
self:addChild(self.player)
self:playerFlyToScene()

self.player:createProgress() -- here

此刻,运行游戏,我们就可以看到如下的效果了。

smallw

好了,本章就到处为止,下章将是我们教程的最后一章,大家期待的完整代码将放出,敬请期待吧。

转载请注明出自:http://shannn.com/archives/437

?>