LUA学习
待学习
- U3d
- 苹果支付
- http://121.40.116.12:13301/setNextCard?code=0192&card=38
- 开挂网址
-
http://120.27.251.188:10201/setNextCard?code=5283&card=42
http://120.27.251.188:10301/setNextCard?code=5283&card=42
http://120.27.251.188:10401/setNextCard?code=5283&card=42 - 线上token :f394366335514f3a75452b0c32e1a34a
警示
-
场景帧刷新内,就不要用runAction来做坐标变化,变化中坐标获取会不准确,待研究
-
使用:timer+runAction 做角色移动,在速度控制时会有异常,原因应该同上,待研究。
-
sprite使用了scale之后,如果使用getContentSize获取宽高,得到的应该是sprite的原始宽高,而不是scale之后的。
可以直接使用boundBox来获取size,这个获取到的是当前的size。
-
android 调用lua lua里要做延时调用(可0秒),防止UI等各种异常
-
lua 中 userdata 类型的数据不add到node上 过了定义范围就会被清除,空的class类型还是table
-
慎用 全局层级 全局布局上容易产生各种影响
-
接口请求 异常时 增加功能 从接口逻辑上
数学
local a = math.modf(1.3333)--a =1 取整
local vectorX = math.cos(math.rad(angle))
local vectorY = math.sin(math.rad(angle))
local t=math.random(360) --math.random(1,360)
函数名 描述 示例 结果
pi 圆周率 math.pi 3.1415926535898
abs 取绝对值 math.abs(-2012) 2012
ceil 向上取整 math.ceil(9.1) 10
floor 向下取整 math.floor(9.9) 9
max 取参数最大值 math.max(2,4,6,8) 8
min 取参数最小值 math.min(2,4,6,8) 2
pow 计算x的y次幂 math.pow(2,16) 65536
sqrt 开平方 math.sqrt(65536) 256
mod 取模 math.mod(65535,2) 1
modf 取整数和小数部分 math.modf(20.12) 20 0.12
randomseed 设随机数种子 math.randomseed(os.time())
random 取随机数 math.random(5,90) 5~90
rad 角度转弧度 math.rad(180) 3.1415926535898
deg 弧度转角度 math.deg(math.pi) 180
exp e的x次方 math.exp(4) 54.598150033144
log 计算x的自然对数 math.log(54.598150033144) 4
log10 计算10为底,x的对数 math.log10(1000) 3
frexp 将参数拆成x * (2 ^ y)的形式 math.frexp(160) 0.625 8
ldexp 计算x * (2 ^ y) math.ldexp(0.625,8) 160
sin 正弦 math.sin(math.rad(30)) 0.5
cos 余弦 math.cos(math.rad(60)) 0.5
tan 正切 math.tan(math.rad(45)) 1
asin 反正弦 math.deg(math.asin(0.5)) 30
acos 反余弦 math.deg(math.acos(0.5)) 60
atan 反正切 math.deg(math.atan(1)) 45
button
function tt.button(a, b, c)
a:"icon.png"(资源图片) or "#icon.png" (纹理图片)
b:"GRAY" 按钮置灰 or 空 正常
--封装后添加点击事件,本质还是在touchend时执行
function Button:listen(obj, method)
if method then
return self:addEndListener(handler(obj, method))
else
return self:addEndListener(obj)
end
end
--button 添加点击监听
button_close:addTouchEventListener(callback)
--按钮设置大小
btn:setContentSize(cc.size(100, 100))
btn:ignoreContentAdaptWithSize(false)
listen
function Button:listen(obj, method)
if method then
-- handler(obj, method)将lua对象及方法包装为一个匿名函数 obj.method(obj)等效于obj:method()
--C++ 无法识别 Lua对象方法,handler() 进行一下包装
return self:addEndListener(handler(obj, method))
else
return self:addEndListener(obj)
end
end
两个参数时
obj:lua对象
method:对象方法
一个参数时
obj:要执行的方法
按钮点击时,调用 obj:method
ccui.list
self.listView = ccui.ListView:create()
self.listView:setContentSize(1000, 380)
self.listView:setPosition(270, 5)
self.listView:setDirection(1)
self.listView:setItemsMargin(0)
self.listView:setBounceEnabled(true)
self.listView:setInertiaScrollEnabled(true)
self.listView:pushBackCustomItem("这里添加需要加入的子节点")
node的常用属性
--是否可见
v:setVisible(false)
v:setOpacity(200)--(0,255) --透明度
进度条
--条形进度条
local left = cc.ProgressTimer:create(tt.new("loading/01.png")):ppos(self, 5)
left:setType(cc.PROGRESS_TIMER_TYPE_BAR)
left:setMidpoint(cc.p(0, 0))--起点
left:setBarChangeRate(cc.p(1, 0))--变化方向
--圆形进度条
local left = cc.ProgressTimer:create(tt.new("ani_hall_room.png")):ppos(self.voiceBg, 5)
left:setType(cc.PROGRESS_TIMER_TYPE_RADIAL)
left:setMidpoint(cc.p(0.5, 0.5))--
left:setReverseDirection(true)--顺时针 flase 逆时针
left:runAction(cc.ProgressFromTo:create(10,100,0))
文本Label
--BMFont格式 1,2等效
1 local label = cc.Label:createWithBMFont ("huangshe.fnt","test",1,200)
2 ccui.TextBMFont:create('00000', "res/fonts/baishe.fnt")
label:setString("555")
--系统字性能最低
3 cc.Label:createWithTTF(title, TTF_NAME, size)
4 cc.Label:createWithTTF(scoreText, 'rS.ttf', 42, cc.size(180, 45), 2):setColor(cc.c3b(168, 88, 32)):ppos(node, 5, -650 -50+ k * x, 2)
--常用,项目内封装过
--正常体 tt.label(text, size, color, dimensions)
tt.label("文", 28, cc.c3b(1, 1, 1), cc.size(100, 40))
--粗圆
LabelTTF.new(text, 30, cc.c3b(241, 227, 219))
--对齐方式
label:setAlignment(2)--1,2,
--使用位图资源创建文本,一下两个等效 w
ccui.TextBMFont:create("hello","fonts/join.fnt"):ppos(self.bg, 2, 100 , 120)
cc.LabelBMFont:create("hello","fonts/zuan.fnt",40):ppos(self.bg, 2, 100 , 130)
--字体,文本,TextAlignment,maxwidth
cc.Label:createWithBMFont("fonts/join.fnt","hello",2,100):ppos(self.bg, 2, 100, 120)
导演
--导演对象
cc.Director:getInstance():getScheduler():setTimeScale(0.5)
--纹理图,图片资源管理器
:getTextureCache()
--时间控制器:0.5倍速度播放,全局
:getScheduler():setTimeScale(0.5)
场景
version: cocos2d-x 3.6
onEnter和onExit在lua中不会因节点别add和remove而直接被调用,当子节点被父节点add和remove时,会发送enter和exit的消息,所以需要再初始化节点的时候,监听消息,并在收到消息后调用onEnter或onExit。
local function onNodeEvent(event)
if event == "enter" then
self:onEnter()
elseif event == "exit" then
self:onExit()
end
end
self:registerScriptHandler(onNodeEvent)
在创建该节点时,加入上面的代码,那么onEnter和onExit就会在节点被add和remove是调用了。
层Layer
LayerColor :颜色布景层
LayerGradient :渐变色布景层
LayerMultiplex :多层布景层
ColorLayer
颜色布景层CCLayerColor有两个父类:CCLayerRGBA、CCBlendProtocol。相信有前面知识的积累,学到这也知道这两个类大致是干嘛的了。一个是颜色类,另一个是颜色混合协议。
所以CCLayerColor主要是在CCLayer类的基础上,扩展了三个属性:
(1)修改图层背景颜色,RGB颜色。
(2)修改图层透明度。
(3)颜色混合模式。
此外,CCLayerColor也继承于CCNode类。所以也可以进行放缩、旋转、执行动作等操作。
- 值得注意的是:CCLayerColor也是CCLayer类,所以它也忽略锚点设置,锚点始终为(0,0)。
CCLayerColor总共有三种创建方式,若不规定背景颜色、透明度,及尺寸大小,那么默认创建的与CCLayer效果类似。即:无背景色、不透明、尺寸大小为窗口大小。
static CCLayerColor* create();//无背景色、不透明、尺寸大小为窗口大小。
static CCLayerColor* create(const ccColor4B& color, float width, float height);
static CCLayerColor* create(const ccColor4B& color);
//更改图层尺寸大小
void changeWidth(float w);
void changeHeight(float h);
void changeWidthAndHeight(float w ,float h);
//设置背景颜色、透明度
virtual void setColor(const ccColor3B &color);
virtual void setOpacity(GLubyte opacity);
//设置混合模式
void setBlendFunc(ccBlendFunc);
ccBlendFunc getBlendFunc();
动作
self.role:runAction(cc.RotateTo:create(0.2, 0))
--顺序执行动作 runActionTable() 或者cc.Sequence:create()
cc.Sequence:create({action1, cc.CallFunc:create(function() end)})
--同时执行动作
cc.Spawn:create({action1,action2})
--重复执行
cc.Repeat:create(action,3)--重复N次
cc.RepeatForever:create()--一直重复
--回调
cc.CallFunc:create(function() end)
--延时
cc.DelayTime:create(0.5)
--移动
cc.MoveTo:create(0.1, cc.p(x,y))--移动到
cc.MoveBy:create(0.1, cc.p(x,y))--移动矢量x,y
--旋转
cc.RotateTo:create(0.1, x)--转到x°
--变色
local action1 = cc.TintTo:create(2, 255, 0, 255)
local action2 = cc.TintBy:create(2, -127, -255, -127)
local action2Back = action2:reverse()
kathia:runAction(cc.Sequence:create(action2, action2Back))
动画
--动画所在层 层级调整
--self:zorder(Constant.LAYER_ZORDER_ANIMATION)
local c = 'res/ccs/csb/chat_animation/donghua.csb‘
local node = cc.CSLoader:createNode(c)
local action = cc.CSLoader:createTimeline(c)
action:clearFrameEventCallFunc()
--同时播放多个动画,可直接run多个action
--播放方式1
action:gotoFrameAndPlay(0, true)--第几帧开始方法,是否循环
--播放方式2
action:play('animation_1', true)--.csb内动画文件名,是否循环
node:ppos(self, 4, 0, 0)--动画其实地点
node:runAction(action)--开始执行动画
--播放方式3 播放动画组 与node:runAction互斥
node:runActionTable({
cc.MoveTo:create(time, cc.p(100,100),
--cc标准动画完成后回调
cc.CallFunc:create(function()
Music:playSound("interact/" .. data.name .. ".mp3")
action:stop()--停止之前的循环动画
action:play('animation_2', false)
--序列帧动画完成后回调
action:setLastFrameCallFunc(function()
node:remove()--移除动画node
end)
end),
})
-- 设置层级关系 Constant.lua全局属性
node:setGlobalZOrder(1111)--设置全局的层级,约大约上层
node:setLocalZOrder(11) --设置在父类里的层级
--重复执行
cc.Repeat:create(action,3)--重复N次
cc.RepeatForever:create()--一直重复
--顺序执行一组act1,act2
cc.Sequence:create(act1,act2)
骨骼动画
local manager = ccs.ArmatureDataManager:getInstance()
manager:addArmatureFileInfo("res/run/man10.png", "res/run/man10.plist", "res/run/man1.ExportJson")
-- manager:addArmatureFileInfoAsync("res/run/man10.png", "res/run/man10.plist", "res/run/man1.ExportJson", self.callback)
local armature = ccs.Armature:create("man1"):ppos(self, 5)
armature:getAnimation():playWithIndex(1);
armature:getAnimation():play("动画名",0,loop);
-- @param durationTo The frames between two animation changing-over.
-- It's meaning is changing to this animation need how many frames
-- -1 : use the value from MovementData get from flash design panel
-- * @param loop Whether the animation is loop
-- loop < 0 : use the value from MovementData get from flash design panel
-- loop = 0 : this animation is not loop
-- loop > 0 : this animation is loop
--勉强实现播放骨骼动画的某一帧
self.role.figure:getAnimation():setSpeedScale(0.0001);
self.role.figure:getAnimation():play("attack", 0, 1);
self.role.figure:getAnimation():gotoAndPlay(index);
--水平翻转
armature->setScaleX(-1);
--播放速率
self.role:getAnimation():setSpeedScale(0.01);
帧动画
local adAnimition = cc.Sprite:createWithSpriteFrameName("enemy bow (1).png")
adAnimition:setPosition(cc.p(x, y));
adAnimition:setAnchorPoint(cc.p(1, 0))
self:addChild(adAnimition, 100);
local animation = cc.Animation:create()
local number, name
for i = 1, 17 do
name = "enemy bow (" .. i .. ").png"
animation:addSpriteFrame(cc.SpriteFrameCache:getInstance():getSpriteFrame(name))
end
animation:setLoops(1) --设置 -1,表示无限循环
animation:setDelayPerUnit(0.07)
animation:setRestoreOriginalFrame(true)
local action = cc.Animate:create(animation)
adAnimition:runAction(cc.Sequence:create(action, cc.RemoveSelf:create(), NULL))
粒子效果
--1播放plist的粒子效果
local waveEffect = cc.ParticleSystemQuad:create("res/role/lizi_shuihua_jian.plist"):ppos(self, 5)
waveEffect:setAutoRemoveOnFinish(true) --设置播放完毕之后自动释放内存
--2系统的粒子效果
local ps = cc.ParticleFire:create():ppos(self, 5)
ps:setAutoRemoveOnFinish(true) --设置播放完毕之后自动释放内存
--设置纹理图,也可不设置
ps:setTexture(cc.Director:getInstance():getTextureCache():addImage("res/role/dead.png"))
ps:setDuration(0.02)
矩形相接检测
--系统的
cc.rectIntersectsRect(rect1,rect2)
--自己瞎写的
function Scene:rectIntersectsRect(rect1, rect2)
if self:rectContainsPoint(rect1, cc.p(rect2.x, rect2.y)) then return true end
if self:rectContainsPoint(rect1, cc.p(rect2.x+rect2.width, rect2.y)) then return true end
if self:rectContainsPoint(rect1, cc.p(rect2.x, rect2.y+rect2.height)) then return true end
if self:rectContainsPoint(rect1, cc.p(rect2.x+rect2.width, rect2.y+rect2.height)) then return true end
if self:rectContainsPoint(rect2, cc.p(rect1.x, rect1.y)) then return true end
return false
end
function Scene:rectContainsPoint(rect, point)
if point.x >= rect.x and point.x <= (rect.x + rect.width) and point.y >= rect.y and point.y <= (rect.y + rect.height) then
return true
else
return false
end
end
事件
--添加事件监听 类似通知
self:addEvent('刷新用户信息', handler(self, self.moPaiAction))
--调用
Event:dispatch('刷新用户信息',table)--key,参数表
Event:call('LOADING说明', '正在重启')
触摸事件
--cocos2dx-lua封装了 Layer:onTouch(callback, isMultiTouches, swallowTouches)
self:onTouch(handler(self, self.eventTouch)) --使用
--参数解析
_layer:registerScriptTouchHandler(onTouchEvent,true,0,false);
@onTouchEvent 回调
@ture表示捕获要捕获多点触摸
@0优先级
@false 是否吞没触摸事件
如果是单点触摸 args[1] ->x,y,id
如果是多点触摸 args[1] ->x1,y1,id1,x2,y2,id2
--完整方法
function Layer:onTouch(callback, isMultiTouches, swallowTouches)
if type(isMultiTouches) ~= "boolean" then isMultiTouches = false end
if type(swallowTouches) ~= "boolean" then swallowTouches = false end
self:registerScriptTouchHandler(function(state, ...)
local args = {...}
local event = {name = state}
if isMultiTouches then
args = args[1]
local points = {}
for i = 1, #args, 3 do
local x, y, id = args[i], args[i + 1], args[i + 2]
points[id] = {x = x, y = y, id = id}
end
event.points = points
else
event.x = args[1]
event.y = args[2]
end
return callback( event )
end, isMultiTouches, 0, swallowTouches)
self:setTouchEnabled(true)
return self
end
音乐
Music:playSound("game/win.mp3")--..music/game/win.mp3
纹理图TextureCache
--路径src/之下完整路径
game.loadPlist(name)--文件路径
display.loadSpriteFrames('res/room.plist', 'res/romm.png')--加载纹理图配置 纹理图
--纹理图创建精灵
sprite = cc.Sprite:createWithSpriteFrameName("biaoqing_" .. biaoqingPos .. ".png")
--精灵换图
local texture = cc.Director:getInstance():getTextureCache():addImage("a.png")
self.tttt:setTexture(texture)
--删除图片缓存
cc.Director:getInstance():getTextureCache():removeTextureForKey(image)
--看图片资源信息
std::string getCachedTextureInfo() const;
--通过
--旋转,缩小,还希望有较好的抗锯齿效果
texture->generateMipmap();
ccTexParams texParams = {GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE};
texture->setTexParameters(&texParams);
地图编辑器
--CCTMXTiledMap .tmx
pMap = cc.TMXTiledMap:create("res/map1/map0.tmx"):ppos(self,5)
--CCTMXObjectGroup tmx内部的层,基本是对象层
group = pMap:getObjectGroup("对象层 1");
array = pMap:getObjectGroups()
--c++:group = pMap->objectGroupNamed("层名");
--层内获取 item
local p = group:getObject("up item名")
local plist = group:getObjects()
--c++: array = group:getObjects
function Model:ctor()
end
webp压缩
指令格式 webp [options] -q quality input.png -o output.webp
具体指令 webp hall_a_dl.png -q 70 -o hall_a_dl.webp
富文本使用
local x = {
{
["type"] = 1,
["content"] = "索是指用细绳串起来的雀鸟,表示消灭了多少雀患,因此一索。",
["color"] = { 255, 1, 1 }, --R,G,B,alpha
["alpha"] = 255, --1透明,255不透明
["font"] = 25, --字号
},
{
["type"] = 2,
["image"] = "res/b9.png", --完整图片路径 "#js_tongyi.png"
},
{
["type"] = 3 --换行
},
{
["type"] = 4, --设定行距
["rowledge"] = 50
},
}
function View:getRichText(data)
local richtext = ccui.RichText:create()
richtext:ignoreContentAdaptWithSize(false)
richtext:setContentSize(cc.size(600, 2100))
for _, v in ipairs(data) do
if v.type == 1 then
local re1 = ccui.RichElementText:create(0, cc.c3b(v.color[1], v.color[2], v.color[3]),
v.alpha, v.content, '', v.font);
richtext:pushBackElement(re1)
elseif v.type == 2 then
local reimg = ccui.RichElementImage:create(0, cc.c3b(1, 1, 1), 255, v.image);
richtext:pushBackElement(reimg)
elseif v.type == 3 then
richtext:pushBackElement(ccui.RichElementNewLine:create(0, cc.c3b(255, 1, 1), 255))
elseif v.type == 4 then
richtext:setVerticalSpace(v.rowledge)
end
end
richtext:formatText()
return richtext
end
前后台通知
-- game.lua-------------前后台切换
function game.initAppEvent()
local a = cc.EventListenerCustom:create("APP_ENTER_FOREGROUND_EVENT", function()
Event:call('切换到前台')
end)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(a, 1)
local b = cc.EventListenerCustom:create("APP_ENTER_BACKGROUND_EVENT", function()
Event:call('切换到后台')
end)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(b, 1)
end
与OC,Android互相调用
--OC
luaoc.callStaticMethod('类名', "方法名", { callBack = Model.nativeWxLogin })
--Android 3.传参,4 (传参类型)返回类型 I:方法,V:void Ljava/lang/String:字符串 ;隔开
luaj.callStaticMethod("包名.类名", "调用的方法名", { Model.payCallBack }, '(I)V')
贝塞尔曲线
--调用self:test(pointarray)
function View:test(posData)
local drawNode = cc.DrawNode:create()
self:addChild(drawNode)
drawNode:setPosition(cc.p(5,100))
--控制点
local startPos = posData[1] --起始点位置
local distance = 20 --虚线的点之间的间隔
local radius = 3 --点的半径
local color = cc.c4f(1,0,0,1) --点的颜色
local time = 0
while time < 1 do
local pos = self:getBezierPos(posData,time)
local d = cc.pGetDistance(pos,startPos)
if d >= distance then
drawNode:drawDot(pos,radius,color)
startPos = pos
end
time = time + 0.001
end
--查看配置相关控制点
-- for idx,pos in pairs(posData)do
-- drawNode:drawDot(pos,5,color)
-- end
end
function View:clone(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for key, value in pairs(object) do
new_table[_copy(key)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
--求阶乘
function View:factorial(n)
if n== 0 then
return 1
else
return n * self:factorial(n-1)
end
end
--获取贝塞尔曲线上面的点
function View:getBezierPos(posData,t)
-- local data = self:clone(posData)
local data = posData
local n = #data -1
local x = 0
local y = 0
for idx,pos in pairs(data) do
x = x + pos.x *(self:factorial(n)/(self:factorial(n-idx+1)*self:factorial(idx-1))) * math.pow(1-t,n-idx+1) * math.pow(t,idx-1)
y = y + pos.y *(self:factorial(n)/(self:factorial(n-idx+1)*self:factorial(idx-1))) * math.pow(1-t,n-idx+1) * math.pow(t,idx-1)
end
-- cclog("曲线"..x.."-"..y)
return cc.p(x,y)
end
function View:listLayout(fwidth, num, width, anchor, edgeOffset)
local post = {}
local pre;
local offset;
local chor
if anchor ~= nil then
chor = anchor -1
else
chor = 0
end
if edgeOffset ~= nil then
pre = (fwidth - edgeOffset * 2 - width * num) / (num - 1)
offset = edgeOffset
else
pre = (fwidth - width * num) / (num + 1)
offset = pre
end
for i = 1, num, 1 do
post[i] = offset + (i - 1) * pre + chor*pre/2
end
return post
end
function View:AddsonView(fview,sonViewlist,type){
local anchor = (type-1)%3+1
local plist =View:listLayout(fview:getWidtn(),#sonviewlist,sonViewlist[1].getWidtn(),)
for i, position in pairs(plist) do
sonViewlist[i]:ppos(self.bg,1,position,0)
end
}
更新流程:
-
修改config.lua
-
修改build.py
-
运行python build.py
-
将compile/src 和version.manifest传给小吴
小吴: -
将version.manifest放到oss : zzxx-chess/lanxi/debug/version.manifest
-
zzxx-chess/lanxi/debug/创建版本文件夹 如:1.1,然后将src下的东西上传到1.1下
Lua自写公共方法
对象设置全局层级带子界面
--暂时仅一级子界面 为了解决牌花跟财神角标 不随牌设置层级改变
function View:setGlobalZOrderWithChildren(node,order)
node:setGlobalZOrder(order)
for _,v in pairs(node:getChildren())do
if type(v) == 'userdata' then
v:setGlobalZOrder(order)
end
end
end
Lua绑定C++
参考网址:lua绑定c++类方法总结,Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
//手写的c++方法 供lua调用
static int tolua_cocos2d_utils_captureNode(lua_State* tolua_S)
{
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_istable(tolua_S,1,0, &tolua_err) ||
!tolua_isusertype(tolua_S, 2, "cc.Node", 0, &tolua_err)
)
goto tolua_lerror;
else
#endif
{
cocos2d::Node* node = static_cast<Node*>(tolua_tousertype(tolua_S, 2, nullptr));
Image* ret = cocos2d::utils::captureNode(node, 1);
object_to_luaval<Image>(tolua_S, "Image",(Image*)ret);
// cocos2d::RenderTexture* ret =cocos2d::utils::captureNode(node, 1);
// object_to_luaval<cocos2d::RenderTexture>(tolua_S, "cc.RenderTexture",(cocos2d::RenderTexture*)ret);
return 1;
}
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'tolua_cocos2d_utils_captureNode'.",&tolua_err);
return 0;
#endif
}
其他工具
位图字体工具Bitmap Font Tools
BMFont (Windows)
FonteditorGlyph
DesignerHieroLabelAtlasCreator
粒子编辑工具Particle Editing Tools
ParticleCreator
Particle Designer
物理编辑工具Physics Editing Tools
Mekanimo
PhysicsBench
PhysicsEditor
VertexHelper
场景编辑工具Scene Editing Tools
CocosBuilder
Cocoshop
LevelHelper
纹理地图集工具Texture Atlas Tools
DarkFunction Editor
SpriteHelper
TexturePacker
Zwoptex
瓦片地图编辑工具Tilemap Editing Tools
iTileMaps
Tiled Map Editor
声音特效编辑工具Audio Effect Editing Tools
cfxr
背景音乐编辑工具Background Music Editing Tools
GarageBand (MAC 系统自带)
BOX2D多边形定义工具VertexHelper
VertexHelperGIF
动画帧导出工具Ulead GIF Animator
UleadGifAnimator
网友评论