Cocos2dx-js VS Cocos2dx-lua
从效率上编译成字节码的Lua效率肯定比JS高,从坑方面来说,目前Lua几乎没有太大的坑,JS除非团队有牛人。从已经上线成功的产品来说,大多采用Cocos2dx-lua。JS目前没有比较成功的产品。从入门方面,Lua更为合适。对于小团队而言,目前Lua比JS更加合适。
Cocos2d-x官方主推JS的解决方案,因为JS可以跨越移动设备、桌面的限制,实现一套程序跑任意平台。不过对于HTML5的发展与强调体验的游戏来说,也许H5还需一段时间。
从市场来说,Lua明显是更为理性的选择,因为它更加成熟、安全且大作采用。
开发环境搭建
- quick-3.3
- SublimeText
- QuickXDev
俄罗斯方块
1.场景
准备资源文件
创建公共函数
$ vim app/Common.lua
-- 每个方块占32个像素
gridSize = 32
-- 场景宽度:10个方块共320px
sceneWidth = 8+2
-- 场景高度:18个方块
sceneHeight = 18
-- 方块坐标转换为屏幕坐标
function grid2pos(x, y)
local director = cc.Director:getInstance()
-- 获取可视区域宽高
local size = director:getVisibleSize()
-- 获取原点
local origin = director:getVisibleOrigin()
local posX = origin.x + size.width/2 + gridSize*x - sceneWidth/2*gridSize
local posY = origin.y + size.height/2 + gridSize*y - sceneHeight/2*gridSize
return posX, posY
end
创建场景
$ vim app/Scene.lua
require "app.Common"
function makeKey(x, y)
return x*1000 + y
end
-- 8*18
local Scene = class("Scene")
function Scene:ctor(node)
self.map = {}
for x=0, sceneWidth-1 do
for y=0, sceneHeight-1 do
local posX,posY = grid2pos(x,y)
local sprite = cc.Sprite:create("brick.png")
sprite:setPosition(posX, posY)
node:addChild(sprite)
local visible = (x==0 or x==sceneWidth-1) or y==0
sprite:setVisible(visible)
self.map[makeKey(x,y)] = sprite
end
end
end
function Scene:clear()
for y=1,sceneHeight-1 do
self:clearLine(y)
end
end
function Scene:clearLine(y)
for x=1,sceneWidth-2 do
self.set(x,y,false)
end
end
function Scene:set(x,y,value)
local sprite = self.map[makeKey(x,y)]
if sprite==nil then
return
end
sprite:setVisible(value)
end
function Scene:get(x, y)
local sprite = self.map[makeKey(x,y)]
if sprite==nil then
return
end
return sprite:isVisible()
end
return Scene
主场景中添加
$ vim app/scenes/MainScene.lua
local Scene = require "app.Scene"
local MainScene = class("MainScene", function()
return display.newScene("MainScene")
end)
function MainScene:ctor()
end
function MainScene:onEnter()
self.scene = Scene.new(self)
end
function MainScene:onExit()
end
return MainScene
- 方块
$ vim app/Brick.lua
--[[
1. 方块的基本类型
2. 方块数据化
]]--
local brickArray= {
{
{
{1,1,1,0},
{0,1,0,0},
{0,0,0,0},
{0,0,0,0},
},
{
{0,1,0,0},
{1,1,1,0},
{0,0,0,0},
{0,0,0,0},
},
{
{0,1,0,0},
{1,1,0,0},
{0,1,0,0},
{0,0,0,0},
},
{
{0,1,0,0},
{0,1,1,0},
{0,1,0,0},
{0,0,0,0},
}
},
{
{
{0,1,1,0},
{0,1,1,0},
{0,0,0,0},
{0,0,0,0},
}
},
{
{
{0,1,1,0},
{1,1,0,0},
{0,0,0,0},
{0,0,0,0},
},
{
{0,1,0,0},
{0,1,0,0},
{0,0,1,0},
{0,0,1,0},
}
},
{
{
{1,1,0,0},
{0,1,1,0},
{0,0,0,0},
{0,0,0,0},
},
{
{0,0,1,0},
{0,1,1,0},
{0,1,0,0},
{0,0,0,0},
}
},
{
initOffset = 1,
{
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{0,0,0,0},
},
{
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
}
},
{
initOffset = 1,
{
{0,0,0,0},
{1,1,1,0},
{1,0,0,0},
{0,0,0,0},
},
{
{1,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,0,0,0},
},
{
{0,0,1,0},
{1,1,1,0},
{0,0,0,0},
{0,0,0,0},
},
{
{0,1,0,0},
{0,1,0,0},
{0,1,1,0},
{0,0,0,0},
}
},
{
initOffset = 1,
{
{0,0,0,0},
{1,1,1,0},
{0,0,1,0},
{0,0,0,0},
},
{
{0,1,0,0},
{0,1,0,0},
{1,1,0,0},
{0,0,0,0},
},
{
{1,0,0,0},
{1,1,1,0},
{0,0,0,0},
{0,0,0,0},
},
{
{0,1,1,0},
{0,1,0,0},
{0,1,0,0},
{0,0,0,0},
}
},
}
方块处理类
local Brick = class("Brick")
local initXoffset = sceneWidth/2 - 3
local function iterateBrick(index, trans, callback)
local transArray = brickArray[index]
local eachBrick = transArray[trans]
for y=1,#eachBrick do
local xData = eachBrick[y]
for x=1,#xData do
local data = xData[x]
if not callback(x, y, data~=0) then
return false
end
end
end
return true
end
function rawPlace(index, trans, scene, newX, newY)
local result = {}
local callback = function(x, y, b)
if b then
local finalX = newX + x
local finalY = newY - y
if scene:get(finalX, finalY) then
return false
end
table.insert(result, {x=finalX, y=finalY})
end
return true
end
if iterateBrick(index, trans, callback) then
for k,v in ipairs(result) do
scene:set(v.x, v.y, true)
end
return true
end
end
function Brick:ctor(scene, index)
self.x = initXoffset
self.y = sceneHeight
local offset = brickArray[index].initOffset
if offset then
self.y = self.y + offset
end
self.scene = scene
self.index = index
self.trans = 1
end
function Brick:move(deltaX, deltaY)
self:clear()
local x = self.x + deltaX
local y = self.y + deltaY
if rawPlace(self.index, self.trans, self.scene, x, y) then
self.x = x
self.y = y
return true
else
self.place()
return false
end
end
function Brick:rotate()
local offset = brickArray[self.index].initOffset
if offset and self.y==0 then
return
end
self:clear()
local transArray = brickArray[self.index]
local trans = self.trans + 1
if trans>#transArray then
trans = 1
end
if rawPlace(self.index, trans, self.scene, self.x, self.y) then
self.trans = trans
else
self:place()
end
end
function Brick:place()
return rawPlace(self.index, self.trans, self.scene, self.x, self.y)
end
function Brick:clear()
iterateBrick(self.index, self.trans, function(x,y,b)
local finalX = self.x + x
local finalY = self.y + y
if b then
self.scene:set(finalX, finalY, false)
end
return false
end)
end
return Brick
坦克大战
使用Texture对帧动画打包
动画帧数据文件 tex.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>frames</key>
<dict>
<key>brick0.png</key>
<dict>
<key>frame</key>
<string>{{182,2},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>brick1.png</key>
<dict>
<key>frame</key>
<string>{{148,2},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>brick2.png</key>
<dict>
<key>frame</key>
<string>{{114,2},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>brick3.png</key>
<dict>
<key>frame</key>
<string>{{80,2},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>bullet0.png</key>
<dict>
<key>frame</key>
<string>{{36,2},{6,6}}</string>
<key>offset</key>
<string>{1,-1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{14,14},{6,6}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>bullet1.png</key>
<dict>
<key>frame</key>
<string>{{36,86},{10,10}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{11,11},{10,10}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>explode0.png</key>
<dict>
<key>frame</key>
<string>{{2,240},{16,14}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{8,8},{16,14}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>explode1.png</key>
<dict>
<key>frame</key>
<string>{{36,64},{22,20}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,5},{22,20}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>explode2.png</key>
<dict>
<key>frame</key>
<string>{{90,98},{26,24}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,3},{26,24}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>grass.png</key>
<dict>
<key>frame</key>
<string>{{46,2},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>home.png</key>
<dict>
<key>frame</key>
<string>{{216,2},{30,26}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{1,3},{30,26}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>mud.png</key>
<dict>
<key>frame</key>
<string>{{2,206},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>road.png</key>
<dict>
<key>frame</key>
<string>{{2,172},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>sign_bullet.png</key>
<dict>
<key>frame</key>
<string>{{20,240},{10,24}}</string>
<key>offset</key>
<string>{0,-1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{11,5},{10,24}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>sign_tank_blue.png</key>
<dict>
<key>frame</key>
<string>{{238,78},{16,18}}</string>
<key>offset</key>
<string>{0,-1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{8,8},{16,18}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>sign_tank_green.png</key>
<dict>
<key>frame</key>
<string>{{238,58},{16,18}}</string>
<key>offset</key>
<string>{0,-1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{8,8},{16,18}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>steel0.png</key>
<dict>
<key>frame</key>
<string>{{2,138},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>steel1.png</key>
<dict>
<key>frame</key>
<string>{{2,104},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>steel2.png</key>
<dict>
<key>frame</key>
<string>{{2,70},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>steel3.png</key>
<dict>
<key>frame</key>
<string>{{2,36},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_fire0.png</key>
<dict>
<key>frame</key>
<string>{{62,194},{26,28}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{2,1},{26,28}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_fire1.png</key>
<dict>
<key>frame</key>
<string>{{46,226},{26,28}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{2,1},{26,28}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run0.png</key>
<dict>
<key>frame</key>
<string>{{36,98},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run1.png</key>
<dict>
<key>frame</key>
<string>{{206,58},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run2.png</key>
<dict>
<key>frame</key>
<string>{{174,36},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run3.png</key>
<dict>
<key>frame</key>
<string>{{142,36},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run4.png</key>
<dict>
<key>frame</key>
<string>{{110,36},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run5.png</key>
<dict>
<key>frame</key>
<string>{{78,36},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run6.png</key>
<dict>
<key>frame</key>
<string>{{46,36},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_blue_run7.png</key>
<dict>
<key>frame</key>
<string>{{216,30},{26,30}}</string>
<key>offset</key>
<string>{-1,1}</string>
<key>rotated</key>
<true/>
<key>sourceColorRect</key>
<string>{{2,0},{26,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_fire0.png</key>
<dict>
<key>frame</key>
<string>{{88,130},{24,28}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,1},{24,28}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_fire1.png</key>
<dict>
<key>frame</key>
<string>{{74,224},{24,28}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,1},{24,28}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run0.png</key>
<dict>
<key>frame</key>
<string>{{62,162},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run1.png</key>
<dict>
<key>frame</key>
<string>{{86,64},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run2.png</key>
<dict>
<key>frame</key>
<string>{{64,98},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run3.png</key>
<dict>
<key>frame</key>
<string>{{62,130},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run4.png</key>
<dict>
<key>frame</key>
<string>{{36,194},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run5.png</key>
<dict>
<key>frame</key>
<string>{{36,162},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run6.png</key>
<dict>
<key>frame</key>
<string>{{36,130},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>tank_green_run7.png</key>
<dict>
<key>frame</key>
<string>{{60,64},{24,30}}</string>
<key>offset</key>
<string>{0,1}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{4,0},{24,30}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
<key>water.png</key>
<dict>
<key>frame</key>
<string>{{2,2},{32,32}}</string>
<key>offset</key>
<string>{0,0}</string>
<key>rotated</key>
<false/>
<key>sourceColorRect</key>
<string>{{0,0},{32,32}}</string>
<key>sourceSize</key>
<string>{32,32}</string>
</dict>
</dict>
<key>metadata</key>
<dict>
<key>format</key>
<integer>2</integer>
<key>realTextureFileName</key>
<string>tex.png</string>
<key>size</key>
<string>{256,256}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:de153ba6091aa039f5da088c67aa2563$</string>
<key>textureFileName</key>
<string>tex.png</string>
</dict>
</dict>
</plist>
调整屏幕为横屏
$ app/config.lua
CONFIG_SCREEN_WIDTH = 960
CONFIG_SCREEN_HEIGHT = 640
显示坦克
创建对象类 app/Object.lua
- 对象类
local Object = class("Object")
-- 构造对象
function Object:ctor(node)
-- 创建精灵并添加到节点内
self.sprite = cc.Sprite:create()
self.node = node
self.node:addChild(self.sprite)
end
-- 判断对象是否有效
function Object:alive()
return self.sprite ~= nil
end
-- 销毁对象
function Object:destroy()
self.node:removeChild(self.sprite)
self.sprite = nil
end
return Object
创建坦克类 app/tank.lua
-- 加载对象
local Object = require "app.Object"
-- 坦克类派生自对象
local Tank = class("Tank", Object)
-- 构造函数
function Tank:ctor(node)
-- 父类初始化
Tank.super.ctor(self, node)
self.node = node
-- 临时代码
local director = cc.Director:getInstance()
-- 获取窗口大小
local size = director:getWinSize()
-- 设置精灵居中
self.sprite:setPosition(size.width/2, size.height/2)
-- 获取精灵甄
local spriteFrameCache = cc.SpriteFrameCache:getInstance()
local frame = spriteFrameCache:getSpriteFrame("tank_green_run0.png")
-- 设置精灵帧
self.sprite:setSpriteFrame(frame)
end
-- 析构函数
function Tank:destroy()
Tank.super.destroy(self)
end
return Tank
主场景加载并精灵帧并显示坦克app/scenes/MainScene.lua
local Tank = require "app.Tank"
local MainScene = class("MainScene", function()
return display.newScene("MainScene")
end)
function MainScene:ctor()
end
function MainScene:onEnter()
-- 加载游戏资源
local spriteFrameCache = cc.SpriteFrameCache:getInstance()
-- 加载精灵帧动画
spriteFrameCache:addSpriteFrames("res/tank/tex.plist")
-- 创建坦克
self.tank = Tank.new(self)
end
function MainScene:onExit()
end
return MainScene