Cocos2dx 搓牌效果

前端之家收集整理的这篇文章主要介绍了Cocos2dx 搓牌效果前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

先上效果图: cocos2dx 3D搓牌效果类如下:

  1. -- date:2017/9/26
  2. -- author:looyer
  3. -- purpose:3D搓牌效果层,-- 顶点着色器
  4. local strVertSource =
  5. [[
  6. attribute vec4 a_position;
  7. attribute vec2 a_texCoord;
  8. attribute vec4 a_color;
  9.  
  10. uniform float ratio; //牌初始状态到搓牌最终位置的完成度比例
  11. uniform float radius; //搓牌类似于绕圆柱滚起,其圆柱的半径
  12. uniform float width;
  13. uniform float finish; //是否完成搓牌
  14.  
  15. uniform float offx;
  16. uniform float offy;
  17.  
  18. varying vec4 v_fragmentColor;
  19. varying vec2 v_texCoord;
  20.  
  21. void main()
  22. {
  23. //注意OpenGL-ES中:1.attribute修饰的变量是常量。2.没有自动转类型float a = 1;或者5.0/3都是错误
  24. //这两个问题改了两天,可以通过修改CPP代码,打印log来调试cocos2dx程序
  25. vec4 tmp_pos = a_position;
  26.  
  27. //顺时针旋转90度
  28. tmp_pos = vec4(tmp_pos.y,-tmp_pos.x,tmp_pos.z,tmp_pos.w);
  29.  
  30. if(finish > 0.5) {
  31. tmp_pos = vec4(tmp_pos.x,-width - tmp_pos.y,tmp_pos.w);
  32.  
  33. }else {
  34. //计算卡牌弯曲的位置,类似于卡牌绕圆柱卷起的原理
  35. float halfPeri = radius * 3.14159; //半周长
  36. float hr = halfPeri * ratio;
  37. if(tmp_pos.y < -width + hr) {
  38. float dy = -tmp_pos.y - (width - hr);
  39. float arc = dy/radius;
  40. tmp_pos.y = -width + hr - sin(arc)*radius;
  41. tmp_pos.z = radius * (1.0-cos(arc)); //注意之前这里是1,是错误的,opengles不自动类型转换
  42. }
  43. }
  44.  
  45. tmp_pos += vec4(offx,offy,0.0,0.0);
  46.  
  47. gl_Position = CC_MVPMatrix * tmp_pos;
  48. v_fragmentColor = a_color;
  49. v_texCoord = a_texCoord;
  50. }
  51. ]]
  52.  
  53. -- 片段着色器
  54. local strFragSource =
  55. [[
  56. varying vec4 v_fragmentColor;
  57. varying vec2 v_texCoord;
  58.  
  59. void main()
  60. {
  61. //TODO,这里可以做些片段着色特效
  62.  
  63. gl_FragColor = texture2D(CC_Texture0,v_texCoord);
  64. }
  65. ]]
  66.  
  67. -- 通过图片取得纹理id,和该纹理在plist图中的纹理坐标范围
  68. local function getTextureAndRange(szImage)
  69. local FrameCache = cc.SpriteFrameCache:getInstance()
  70. local sprite = FrameCache:getSpriteFrameByName(szImage)
  71.  
  72. local rect = sprite:getRect()
  73. local tex = sprite:getTexture()
  74. local id = tex:getName() --纹理ID
  75. local bigWide = tex:getPixelsWide() --plist图集的宽度
  76. local bigHigh = tex:getPixelsHigh()
  77.  
  78. -- 左右上下的纹理范围
  79. local ll,rr,tt,bb = rect.x/bigWide,(rect.x + rect.width)/bigWide,rect.y/bigHigh,(rect.y + rect.height)/bigHigh
  80. return id,{ll,bb},{rect.width,rect.height}
  81. end
  82.  
  83. -- 创建3D牌面,所需的顶点和纹理数据,size:宽高,texRange:纹理范围,bFront:是否正面
  84. local function initCardVertex(size,texRange,bFront)
  85. local nDiv = 200 --将宽分成100
  86. local verts = {} --位置坐标
  87. local texs = {} --纹理坐标
  88. local dh = size.height
  89. local dw = size.width/nDiv
  90.  
  91. --计算顶点位置
  92. for c = 1,nDiv do
  93. local x,y = (c-1)*dw,0
  94. local quad = {}
  95. if bFront then
  96. quad = {x,y,x+dw,x,y+dh,y+dh}
  97. else
  98. quad = {x,y+dh}
  99. end
  100. for _,v in ipairs(quad) do table.insert(verts,v) end
  101. end
  102.  
  103. local bXTex = true --是否当前在计算横坐标纹理坐标,
  104. for _,v in ipairs(verts) do
  105. if bXTex then
  106. if bFront then
  107. table.insert(texs,v/size.width * (texRange[2] - texRange[1]) + texRange[1])
  108. else
  109. table.insert(texs,v/size.width * (texRange[1] - texRange[2]) + texRange[2])
  110. end
  111. else
  112. if bFront then
  113. table.insert(texs,(1-v/size.height) * (texRange[4] - texRange[3]) + texRange[3])
  114. else
  115. table.insert(texs,v/size.height * (texRange[3] - texRange[4]) + texRange[4])
  116. end
  117. end
  118. bXTex = not bXTex
  119. end
  120.  
  121. local res = {}
  122. local tmp = {verts,texs}
  123. for _,v in ipairs(tmp) do
  124. local buffid = gl.createBuffer()
  125. gl.bindBuffer(gl.ARRAY_BUFFER,buffid)
  126. gl.bufferData(gl.ARRAY_BUFFER,table.getn(v),v,gl.STATIC_DRAW)
  127. gl.bindBuffer(gl.ARRAY_BUFFER,0)
  128. table.insert(res,buffid)
  129. end
  130. return res,#verts
  131. end
  132.  
  133. -- 创建搓牌效果层,pList:图片合集.plist文件,szBack:牌背面图片名,szFont:牌正面图片名,注意:默认传入的牌在plist文件中是竖直的,scale缩放比
  134. local function createRubCardEffectLayer(pList,szBack,szFont,scale)
  135. scale = scale or 1.0
  136.  
  137. --预加载pList图集(注重复添加没关系,只会保存一份)
  138. local FrameCache = cc.SpriteFrameCache:getInstance()
  139. FrameCache:addSpriteFrames(pList)
  140.  
  141. -- 取得屏幕宽高
  142. local Director = cc.Director:getInstance()
  143. local WinSize = Director:getWinSize()
  144.  
  145. -- 创建广角60度,视口宽高比是屏幕宽高比,近平面1.0,远平面1000.0,的视景体
  146. local camera = cc.Camera:createPerspective(45,WinSize.width/WinSize.height,1,1000)
  147. camera:setCameraFlag(cc.CameraFlag.USER2)
  148. --设置摄像机的绘制顺序,越大的深度越绘制的靠上,所以默认摄像机默认是0,其他摄像机默认是1,这句很重要!!
  149. camera:setDepth(1)
  150. camera:setPosition3D(cc.vec3(0,800))
  151. camera:lookAt(cc.vec3(0,0),cc.vec3(0,0))
  152.  
  153. -- 创建用于OpenGL绘制的节点
  154. local glNode = gl.glNodeCreate()
  155. local glProgram = cc.GLProgram:createWithByteArrays(strVertSource,strFragSource)
  156. glProgram:retain()
  157. glProgram:updateUniforms()
  158.  
  159. -- 创建搓牌图层
  160. local layer = cc.Layer:create()
  161. layer:setCameraMask(cc.CameraFlag.USER2)
  162. layer:addChild(glNode)
  163. layer:addChild(camera)
  164. -- 退出时,释放glProgram程序
  165. local function onNodeEvent(event)
  166. if "exit" == event then
  167. glProgram:release()
  168. end
  169. end
  170. layer:registerScriptHandler(onNodeEvent)
  171.  
  172. local posNow = cc.p(0,0)
  173. --创建触摸回调
  174. local function touchBegin(touch,event)
  175. posNow = touch:getLocation()
  176. return true
  177. end
  178. local function touchMove(touch,event)
  179. local location = touch:getLocation()
  180. local dy = location.y - posNow.y
  181.  
  182. layer.ratioVal = cc.clampf(layer.ratioVal + dy/100,0.9) --最大程度默认0.9
  183. posNow = location
  184. return true
  185. end
  186. local function touchEnd(touch,event)
  187. layer.ratioVal = 0.0
  188. return true
  189. end
  190. local listener = cc.EventListenerTouchOneByOne:create()
  191. listener:registerScriptHandler(touchBegin,cc.Handler.EVENT_TOUCH_BEGAN )
  192. listener:registerScriptHandler(touchMove,cc.Handler.EVENT_TOUCH_MOVED )
  193. listener:registerScriptHandler(touchEnd,cc.Handler.EVENT_TOUCH_ENDED )
  194. local eventDispatcher = layer:getEventDispatcher()
  195. eventDispatcher:addEventListenerWithSceneGraPHPriority(listener,layer)
  196.  
  197. --创建牌的背面
  198. local id1,texRange1,sz1 = getTextureAndRange(szBack)
  199. local msh1,nVerts1 = initCardVertex(cc.size(sz1[1] * scale,sz1[2] * scale),true)
  200. --创建牌的正面
  201. local id2,texRange2,sz2 = getTextureAndRange(szFont)
  202. local msh2,nVerts2 = initCardVertex(cc.size(sz2[1] * scale,sz2[2] * scale),false)
  203.  
  204. --搓牌的程度控制, 搓牌类似于通过一个圆柱滚动将牌粘着起来的效果。下面的参数就是滚动程度和圆柱半径
  205. layer.ratioVal = 0.0
  206. layer.radiusVal = sz1[1]*scale/math.pi;
  207.  
  208. --牌的渲染信息
  209. local cardMesh = {{id1,msh1,nVerts1},{id2,msh2,nVerts2}}
  210. -- OpenGL绘制函数
  211. local function draw(transform,transformUpdated)
  212. gl.enable(gl.CULL_FACE)
  213. glProgram:use()
  214. glProgram:setUniformsForBuiltins()
  215.  
  216. for _,v in ipairs(cardMesh) do
  217. gl.bindTexture(gl.TEXTURE_2D,v[1])
  218.  
  219. -- 传入搓牌程度到着色器中,进行位置计算
  220. local ratio = gl.getUniformLocation(glProgram:getProgram(),"ratio")
  221. glProgram:setUniformLocationF32(ratio,layer.ratioVal)
  222. local radius = gl.getUniformLocation(glProgram:getProgram(),"radius")
  223. glProgram:setUniformLocationF32(radius,layer.radiusVal)
  224.  
  225. -- 偏移牌,使得居中
  226. local offx = gl.getUniformLocation(glProgram:getProgram(),"offx")
  227. glProgram:setUniformLocationF32(offx,WinSize.width/2 - sz1[2]/2*scale)
  228. local offy = gl.getUniformLocation(glProgram:getProgram(),"offy")
  229. glProgram:setUniformLocationF32(offy,WinSize.height/2 + sz1[1]/2*scale)
  230.  
  231. local width = gl.getUniformLocation(glProgram:getProgram(),"width")
  232. glProgram:setUniformLocationF32(width,sz1[1]*scale)
  233.  
  234. gl.glEnableVertexAttribs(bit._or(cc.VERTEX_ATTRIB_FLAG_TEX_COORDS,cc.VERTEX_ATTRIB_FLAG_POSITION))
  235. gl.bindBuffer(gl.ARRAY_BUFFER,v[2][1])
  236. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION,2,gl.FLOAT,false,0)
  237. gl.bindBuffer(gl.ARRAY_BUFFER,v[2][2])
  238. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORD,0)
  239. gl.drawArrays(gl.TRIANGLES,v[3])
  240. end
  241. gl.bindTexture(gl.TEXTURE_2D,0)
  242. gl.bindBuffer(gl.ARRAY_BUFFER,0)
  243. end
  244. glNode:registerScriptDrawHandler(draw)
  245.  
  246. return layer
  247. end
  248.  
  249. return createRubCardEffectLayer

演示类如下:

  1. -- date:2017/09/22
  2. -- author:looyer
  3. -- purpose:效果测试
  4.  
  5. local RubCardFunc = require("app.views.RubCardLayer")
  6.  
  7. local EffectTestNode = class("EffectTestNode",cc.load("mvc").ViewBase)
  8.  
  9. function EffectTestNode:onCreate()
  10. end
  11.  
  12. function EffectTestNode:onEnter()
  13. --显示搓牌效果
  14. local layer = RubCardFunc("res/UI/images/card_cor.plist","pkc_paimian.png","pkc1_1.png",2.0)
  15. self:addChild(layer)
  16. end
  17.  
  18. function EffectTestNode:onClickClose()
  19. self:getApp():removeView(self:getName())
  20. end
  21.  
  22. return EffectTestNode

猜你在找的Cocos2d-x相关文章