大多数游戏都有背包这个东西.
道具列表通常用 ScrollView 来实现.
这个ScrollView内部有一个Layout, 滑动都是由移动这个Layout来实现.
道具摆放通常从上往下, 从左到右.
假设你有一个道具数组, 你遍历这个数组来摆放道具.
因为数组长度是已知的, 你可以计算出Layout需要的尺寸, 再把道具摆上去.
这个实现是很容易的. 但是, 如果你提前不知道数组长度, 就是不知道道具数量,
可能随时会添加道具或者删除道具.
因为cocos2dx的坐标系是左下角为原点, 因此动态增加或删除都需要把所有的道具都移动位置,
光移动Layout是不行的.
%26nbsp;
说了一堆的废话.
1 -- 增加, 删除. 2 function scrollView:beginEditChilds(childWidth, childHeight) 3 self.contentSize = self:getContentSize(); 4 self.childCount = #(self:getChildren()); 5 self.colCount = math.floor(self.contentSize.width / childWidth); 6 self.childWidth = (self.contentSize.width - childWidth * self.colCount) / (self.colCount + 1) + childWidth; 7 self.childHeight = childHeight; 8 self.innerSize = self:getInnerContainerSize(); 9 self.innerOffsetY = self:getInnerContainerPosition().y + self.innerSize.height - self.contentSize.height; 10 end 11 12 function scrollView:endEditChilds() 13 local rowCount = math.ceil(self.childCount / self.colCount); 14 self.innerSize.height = math.max(self.contentSize.height, rowCount * self.childHeight); 15 self:setInnerContainerSize(self.innerSize); 16 self:setInnerContainerPosition( 17 cc.p(0, math.min(0, self.contentSize.height + self.innerOffsetY - self.innerSize.height))); 18 19 local offsetY = self.innerSize.height - self.childHeight; 20 self.childs = self:getChildren(); 21 for i = self.childCount, 1, -1 do 22 local row = math.floor((i - 1) / self.colCount); 23 local col = math.floor((i - 1) % self.colCount); 24 local x = col * self.childWidth + self.childWidth * 0.5; 25 local y = row * self.childHeight + self.childHeight * 0.5; 26 self.childs[i]:setPosition(x, self.innerSize.height - y); 27 self.childs[i].__pos = i - 1; 28 end 29 end 30 31 function scrollView:appendChild(child) 32 child:setAnchorPoint(cc.p(0.5, 0.5)); 33 self.childCount = self.childCount + 1; 34 self:addChild(child); 35 end 36 37 function scrollView:deleteChild(child) 38 self.childCount = self.childCount - 1; 39 self:removeChild(child); 40 end
scrollView 是指 ccui.ScrollView:create() 返回的对象.
可以通过一个工厂函数给对象扩展成员函数. 这个下面在贴代码.
使用方法就是, 在add, del之前调用 begin, 之后调用end.
begin和end的目的是, 避免每一次 add, del 都要全部排列节点, 并且省去了每次数值计算.
这段代码实现了ccui.ScrollView动态增加|删除子节点.
在end函数里面, 还调整了Layout的坐标, 每次修改不会察觉到Layout的坐标变化.
%26nbsp;
%26nbsp;
有些用ccui.ScrollView做城镇地图, 可以缩放, 顶点缩放.
直接缩放Layout会影响拖动效果, 这个问题直接修改引擎或者继承这个对象.
1 float Widget::getLeftBoundary() const 2 { 3 return getPosition().x - getAnchorPoint().x * _contentSize.width * _scaleX; 4 } 5 6 float Widget::getBottomBoundary() const 7 { 8 return getPosition().y - getAnchorPoint().y * _contentSize.height * _scaleY; 9 } 10 11 float Widget::getRightBoundary() const 12 { 13 return getLeftBoundary() + _contentSize.width * _scaleX; 14 } 15 16 float Widget::getTopBoundary() const 17 { 18 return getBottomBoundary() + _contentSize.height * _scaleY; 19 }
%26nbsp;
下面是顶点缩放, 直接缩放Layout会把锚点作为中心,
我们这个缩放也是以锚点作为中心, 但是会缩放的同时移动坐标, 效果就达到了.
1 -- 获取内容缩放值. 2 function scrollView:getInnerContainerScale() 3 return self:getInnerContainer():getScale(); 4 end 5 6 -- 获取内容高宽. 7 function scrollView:getInnerContainerSize() 8