quick-cocos2d-x tips

前端之家收集整理的这篇文章主要介绍了quick-cocos2d-x tips前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

原文请猛戳:
http://galoisplusplus.coding....

承接上一篇,这篇主要谈谈本渣在quickx用的一些脚本或自己折腾的一些定制,本文也将不时更新。

如无特殊说明,相关函数放在一个MyPackage的lua global table中:

  1. MyPackage = MyPackage or {}

UI组件

滚动列表相关

  1. --[[--
  2. Refresh UIListView at the current postion.
  3. NOTE: only needed in async mode
  4. ]]
  5. function MyPackage.refreshUIListView(listView)
  6. if not listView.bAsyncLoad then
  7. listView:reload()
  8. return
  9. end
  10.  
  11. if #listView.items_ <= 0 then
  12. listView:reload()
  13. return
  14. end
  15.  
  16. local originPos = MyPackage.getOriginPosOfUIListView(listView)
  17. -- index of the prevIoUs beginning item
  18. local beginIdx = listView.items_[1].idx_
  19.  
  20. listView:removeAllItems()
  21. listView.container:setPosition(0,0)
  22. listView.container:setContentSize(cc.size(0,0))
  23.  
  24. MyPackage.drawUIListViewFromIdx(listView,beginIdx,originPos.x,originPos.y)
  25. end
  26.  
  27. --[[--
  28. NOTE: only needed in async mode
  29. ]]
  30. function MyPackage.getOriginPosOfUIListView(listView)
  31. if not listView.bAsyncLoad then
  32. return
  33. end
  34.  
  35. local getContainerCascadeBoundingBox = function (listView)
  36. local boundingBox
  37. for i,item in ipairs(listView.items_) do
  38. local w,h = item:getItemSize()
  39. local x,y = item:getPosition()
  40. local anchor = item:getAnchorPoint()
  41. x = x - anchor.x * w
  42. y = y - anchor.y * h
  43.  
  44. if boundingBox then
  45. boundingBox = cc.rectUnion(boundingBox,cc.rect(x,y,w,h))
  46. else
  47. boundingBox = cc.rect(x,h)
  48. end
  49. end
  50.  
  51. local point = listView.container:convertToWorldSpace(cc.p(boundingBox.x,boundingBox.y))
  52. boundingBox.x = point.x
  53. boundingBox.y = point.y
  54. return boundingBox
  55. end
  56.  
  57. local cascadeBound = getContainerCascadeBoundingBox(listView)
  58. -- local cascadeBound = listView.scrollNode:getCascadeBoundingBox()
  59.  
  60. local localPos = listView:convertToNodeSpace(cc.p(cascadeBound.x,cascadeBound.y))
  61.  
  62. local originPosX = 0
  63. local originPosY = 0
  64. if cc.ui.UIScrollView.DIRECTION_VERTICAL == listView.direction then
  65. -- ahead part of view
  66. originPosY = localPos.y + cascadeBound.height - listView.viewRect_.y - listView.viewRect_.height
  67. else
  68. -- left part of view
  69. originPosX = - listView.viewRect_.x + localPos.x
  70. end
  71.  
  72. return cc.p(originPosX,originPosY)
  73. end
  74.  
  75. --[[--
  76. Draw UIListView from the `beginIdx`th item at position (`originPosX`,`originPosY`).
  77. NOTE: only needed in async mode
  78. ]]
  79. function MyPackage.drawUIListViewFromIdx(listView,originPosX,originPosY)
  80. if not listView.bAsyncLoad then
  81. listView:reload()
  82. return
  83. end
  84.  
  85. listView:removeAllItems()
  86. listView.container:setPosition(0,0))
  87.  
  88. local beginIdx = beginIdx or 1
  89. local originPosX = originPosX or 0
  90. local originPosY = originPosY or 0
  91.  
  92. local count = listView.delegate_[cc.ui.UIListView.DELEGATE](listView,cc.ui.UIListView.COUNT_TAG)
  93. listView.items_ = {}
  94. local itemW,itemH = 0,0
  95. local item
  96. local containerW,containerH = 0,0
  97. for i = beginIdx,count do
  98. item,itemW,itemH = listView:loadOneItem_(cc.p(originPosX,originPosY),i)
  99. if cc.ui.UIScrollView.DIRECTION_VERTICAL == listView.direction then
  100. originPosY = originPosY - itemH
  101. containerH = containerH + itemH
  102. else
  103. originPosX = originPosX + itemW
  104. containerW = containerW + itemW
  105. end
  106. if containerW > listView.viewRect_.width + listView.redundancyViewVal
  107. or containerH > listView.viewRect_.height + listView.redundancyViewVal then
  108. break
  109. end
  110. end
  111.  
  112. if cc.ui.UIScrollView.DIRECTION_VERTICAL == listView.direction then
  113. listView.container:setPosition(listView.viewRect_.x,listView.viewRect_.y + listView.viewRect_.height)
  114. else
  115. listView.container:setPosition(listView.viewRect_.x,listView.viewRect_.y)
  116. end
  117.  
  118. listView:increaSEOrReduceItem_()
  119. end
  120.  
  121. function MyPackage.elasticMoveUIScrollView(scrollView,scrollToBottom,scrollToRight)
  122. local cascadeBound = scrollView:getScrollNodeRect()
  123. local disX,disY = 0,0
  124. local viewRect = scrollView:getViewRectInWorldSpace()
  125.  
  126. if cascadeBound.width < viewRect.width then
  127. if scrollToRight then
  128. disX = viewRect.x + viewRect.width - cascadeBound.x - cascadeBound.width
  129. else
  130. disX = viewRect.x - cascadeBound.x
  131. end
  132. else
  133. if cascadeBound.x > viewRect.x then
  134. disX = viewRect.x - cascadeBound.x
  135. elseif cascadeBound.x + cascadeBound.width < viewRect.x + viewRect.width then
  136. disX = viewRect.x + viewRect.width - cascadeBound.x - cascadeBound.width
  137. end
  138. end
  139.  
  140. if cascadeBound.height < viewRect.height then
  141. if scrollToBottom then
  142. disY = viewRect.y - cascadeBound.y
  143. else
  144. disY = viewRect.y + viewRect.height - cascadeBound.y - cascadeBound.height
  145. end
  146. else
  147. if cascadeBound.y > viewRect.y then
  148. disY = viewRect.y - cascadeBound.y
  149. elseif cascadeBound.y + cascadeBound.height < viewRect.y + viewRect.height then
  150. disY = viewRect.y + viewRect.height - cascadeBound.y - cascadeBound.height
  151. end
  152. end
  153.  
  154. if 0 == disX and 0 == disY then
  155. return
  156. end
  157.  
  158. local posX,posY = scrollView.scrollNode:getPosition()
  159. scrollView.position_ = cc.p(posX + disX,posY + disY)
  160. scrollView.scrollNode:setPosition(scrollView.position_)
  161. end

更新:以上改动已挪到yszheda/quickx-extensions的UIScrollView或UIListView中。

lua语言相关

bool转数字

  1. function MyPackage.bool2number(bool)
  2. return bool and 1 or 0
  3. end

table相关

  1. function MyPackage.removeValueFromArray(array,value)
  2. local idx
  3. for i,v in ipairs(array) do
  4. if v == value then
  5. idx = i
  6. break
  7. end
  8. end
  9. if idx then
  10. table.remove(array,idx)
  11. end
  12. end
  13.  
  14. function MyPackage.hasValueInArray(array,value)
  15. local hasValue = false
  16. for i,v in ipairs(array) do
  17. if v == value then
  18. hasValue = true
  19. break
  20. end
  21. end
  22. return hasValue
  23. end

UTF8字符串

cocos2d-x的label默认为UTF8编码,一般场景下主要需要以下两个功能

  • 字符串长度

  • 截取子串

原先本渣用cocos2d-x时写了个C++函数来求长度:

  1. long long utf8StringSize(const std::string& str)
  2. {
  3. char* charArray = new char[str.length() + 1];
  4. strcpy(charArray,str.c_str());
  5. char* s = charArray;
  6. /*-----------------------------------------------------------------------------
  7. * References: http://stackoverflow.com/questions/4063146/getting-the-actual-length-of-a-utf-8-encoded-stdstring
  8. *-----------------------------------------------------------------------------*/
  9. long long len = 0;
  10. while (*s) len += (*s++ & 0xc0) != 0x80;
  11. delete [] charArray;
  12. return len;
  13. }

cocos2d-x Helper也提供了接口来做字符串截取

  1. static std::string getSubStringOfUTF8String(const std::string& str,std::string::size_type start,std::string::size_type length);

在lua方面,quickx已经提供string.utf8len来求字符串长度,本渣仿照其实现写了个截取子串的函数

  1. function MyPackage.utf8str(str,start,num)
  2. local function utf8CharSize(char)
  3. local size = 0
  4.  
  5. local arr = {0,0xc0,0xe0,0xf0,0xf8,0xfc}
  6. local size = #arr
  7. while arr[size] do
  8. if char >= arr[size] then
  9. break
  10. end
  11. size = size - 1
  12. end
  13.  
  14. return size
  15. end
  16.  
  17. local startIdx = 1
  18. while start > 1 do
  19. local char = string.byte(str,startIdx)
  20. startIdx = startIdx + utf8CharSize(char)
  21. start = start - 1
  22. end
  23.  
  24. local endIdx = startIdx
  25. while num > 0 do
  26. if endIdx > #str then
  27. endIdx = #str
  28. break
  29. end
  30. local char = string.byte(str,endIdx)
  31. endIdx = endIdx + utf8CharSize(char)
  32. num = num - 1
  33. end
  34.  
  35. return str:sub(startIdx,endIdx - 1)
  36. end

不过目前lua5.3已经有UTF8库,可以不用自行造轮子了。另外,关于其他UTF8相关的lua问题可以参考Lua Unicode

其他Helper Functions

更新view的callbackWrapper

我们经常碰到如下的情景:
游戏向后端请求数据,在拿到数据之后执行某个callback去更新某个view。
这种网络请求通常是异步的,如果所请求的数据回来时相关的view被释放,则执行操作该view的callback会导致问题(例如访问非法内存地址)。
这时候我们可以用tolua.isnull来判断相关的view对象是否被释放。
由于每个这种类型的callback都有必要加上这样的guard code,所以本渣干脆做了如下的接口:

  1. function MyPackage.callbackWrapper(views,callback)
  2. return function(...)
  3. for _,view in pairs(views) do
  4. if tolua.isnull(view) then
  5. return
  6. end
  7. end
  8. if callback ~= nil then
  9. callback(...)
  10. end
  11. end
  12. end

拿到一个node九个端点的坐标

  1. --[[--
  2. get the nine positions of a node (the following variables are defined in display.lua of quickx):
  3. display.CENTER
  4. display.LEFT_TOP
  5. display.CENTER_TOP
  6. display.RIGHT_TOP
  7. display.CENTER_LEFT
  8. display.CENTER_RIGHT
  9. display.BOTTOM_LEFT
  10. display.BOTTOM_RIGHT
  11. display.BOTTOM_CENTER
  12. ]]
  13. function MyPackage.getPositionOfNode(node,alignType)
  14. if not node or tolua.isnull(node) then
  15. return
  16. end
  17.  
  18. local size = node:getContentSize()
  19. if size.width == 0 and size.height == 0 then
  20. size = node:getCascadeBoundingBox()
  21. end
  22.  
  23. local pos = cc.p(node:getPosition())
  24. local anchorPoint = cc.p(node:getAnchorPoint())
  25.  
  26. if alignType == display.LEFT_TOP or
  27. alignType == display.LEFT_CENTER or
  28. alignType == display.LEFT_BOTTOM then
  29. pos.x = pos.x - size.width * anchorPoint.x
  30. elseif alignType == display.CENTER_TOP or
  31. alignType == display.CENTER or
  32. alignType == display.CENTER_BOTTOM then
  33. pos.x = pos.x - size.width * anchorPoint.x + size.width * 0.5
  34. elseif alignType == display.RIGHT_TOP or
  35. alignType == display.RIGHT_CENTER or
  36. alignType == display.RIGHT_BOTTOM then
  37. pos.x = pos.x - size.width * anchorPoint.x + size.width
  38. end
  39.  
  40. if alignType == display.BOTTOM_LEFT or
  41. alignType == display.BOTTOM_CENTER or
  42. alignType == display.BOTTOM_RIGHT then
  43. pos.y = pos.y - size.height * anchorPoint.y
  44. elseif alignType == display.CENTER_LEFT or
  45. alignType == display.CENTER or
  46. alignType == display.CENTER_RIGHT then
  47. pos.y = pos.y - size.height * anchorPoint.y + size.height * 0.5
  48. elseif alignType == display.TOP_LEFT or
  49. alignType == display.TOP_CENTER or
  50. alignType == display.TOP_RIGHT then
  51. pos.y = pos.y - size.height * anchorPoint.y + size.height
  52. end
  53.  
  54. return pos
  55. end

在某个container中加入sprite,可指定根据container大小进行缩放及对齐方式

  1. function MyPackage.displaySpriteOnContainer(sprite,container,scaleToFit,alignType)
  2. if tolua.isnull(container) then
  3. return
  4. end
  5.  
  6. -- default settings
  7. local scaleToFit = (scaleToFit ~= false)
  8. local alignType = alignType or display.CENTER
  9.  
  10. if not tolua.isnull(sprite) then
  11. local originSize = sprite:getContentSize()
  12. if originSize.width == 0 or originSize.height == 0 then
  13. originSize = sprite:getCascadeBoundingBox()
  14. end
  15.  
  16. local targetSize = container:getContentSize()
  17. if targetSize.width == 0 or targetSize.height == 0 then
  18. targetSize = container:getCascadeBoundingBox()
  19. end
  20.  
  21. if scaleToFit then
  22. sprite:setScale(targetSize.width / originSize.width,targetSize.height / originSize.height)
  23. end
  24.  
  25. -- NOTE: ignore container's anchor point
  26. local pos = MyPackage.getPositionOfNode(container,alignType)
  27. local leftBottomPos = MyPackage.getPositionOfNode(container,display.LEFT_BOTTOM)
  28. local posX = pos.x - leftBottomPos.x
  29. local posY = pos.y - leftBottomPos.y
  30. display.align(sprite,alignType,posX,posY)
  31. container:addChild(sprite)
  32. end
  33. end

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