Cocos2dx-lua游戏开发指南:从环境配置到精灵创建 | 南锋

南锋

南奔万里空,脱死锋镝余

Cocos2dx-lua游戏开发指南:从环境配置到精灵创建

开发环境: mac,Cocos2dx 3.17
开发语言: lua

前言

Cocos2dx 英文官网:http://www.Cocos2d-x.org/
Cocos2dx 中文社区:http://www.Cocos.com/

横屏竖屏

打开工程目录下的config.json文件,横屏竖屏由isLandscape控制,true为横屏,flase为竖屏,其中widthheight是控制模拟器的大小

屏幕适配

打开工程目录下src/config.lua文件,修改CC_DESIGN_RESOLUTION下的参数,具体修改方法可参考博客

添加精灵

打开工程目录下src/app/views/MainScene.lua文件,添加一下代码

1
2
3
4
local png = "2.png" --文件路径
local sprite = cc.Sprite:create(png)--,cc.rect(0,0,0,0))
self:addChild(sprite)
sprite:setPosition(display.width/2,display.height/2)

具体可以参考博客Cocos2dx-lua中sprite精灵的3种创建方法

创建按钮及按钮事件

  • 方法1:
    1
    2
    3
    4
    5
    6
    7
    8
    local playBotton = cc.MenuItemImage:create("botton.png","botton.png")
    :onClicked(function ( )
    print("点击按钮,到MainScene")
    self:getApp():enterScene("PlayScene")
    end)
    cc.Menu:create(playBotton)
    :move(display.cx-200, display.cy+200)
    :addTo(self)
  • 方法2:
    1
    2
    3
    4
    local button = ccui.Button:create()
    button:setPosition(display.centor)
    button:addTo(self)
    button:setEnable(true) --是否禁用
    链接

单点触摸事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
local layer = cc.Layer:create()
self:addChild(layer)

local sprite = cc.Sprite:create("res/13.png")
--sprite:setPosition(cc.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 80))
sprite:setPosition(300,300)
layer:addChild(sprite, 10)

--实现事件触发回调
local function onTouchBegan(touch, event)
local target = event:getCurrentTarget()

local locationInNode = target:convertToNodeSpace(touch:getLocation())
local s = target:getContentSize()
local rect = cc.rect(0, 0, s.width, s.height)

if cc.rectContainsPoint(rect, locationInNode) then
return true
end
return false
end
local function onTouchMoved(touch, event)
end
local function onTouchEnded(touch, event)
print("触摸事件")
sprite:setPosition(300,500)
end


local listener = cc.EventListenerTouchOneByOne:create() -- 创建一个事件监听器
listener:setSwallowTouches(true)
listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
listener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED)
listener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED)

local eventDispatcher = self:getEventDispatcher() -- 得到事件派发器
eventDispatcher:addEventListenerWithSceneGraphPriority(listener, sprite) -- 将监听器注册到派发器中

存放数据

1
2
3
4
cc.UserDefault:getInstance():setIntegerForKey("hightscore1", self.hightscore1)

如果数据是表格
cc.UserDefault:getInstance():setStringForKey("biaoge", json.encode(sss))

读取数据

1
2
3
4
self.hightscore1 = cc.UserDefault:getInstance():getIntegerForKey("hightscore1")

如果数据是表格
cc.UserDefault:getInstance():getStringForKey("biaoge")

艺术字体

首先在res文件中加入字体文件:”.fnt”以及”.png”文件
然后调用下面命令

1
2
3
4
5
local bmFont  = ccui.TextBMFont:create()
:move(display.cx, display.cy -200 ) --坐标
:addTo(self) --加入场景
bmFont:setFntFile("res/myFont.fnt")
bmFont:setString("内容")

字体

1
2
3
4
local label = cc.Label:createWithTTF("用户登录","res/font1.ttf",50 )
:setColor(ccc3(0,0,0)) --设置字体颜色
:move(display.cx - 500 ,display.cy)
:addTo(self)

AtlasLabel 数字标签

1
2
local AtlasLabel = ccui.TextAtlas:create("0123456789",img, 9, 12, "0")
-- 参数分别是 数字 图片 宽 高 首个数字

延时函数

1
2
3
4
5
6
global.countDown.createTimer("time", time )
local node = cc.Node:create()
node:addTo(self)
performWithDelay(node,function()
print("时间到")
end,time)

滚动容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
-- 测试 pageView  
local pageView = ccui.PageView:create()
--设置pageView长宽
pageView:setContentSize(600,600)
--设置是否响应触摸事件
pageView:setTouchEnabled(true)
--设置锚点
pageView:setAnchorPoint(cc.p(0.5,0.5))
--设置位置在中心位置
pageView:setPosition(display.center)

for i=1,5 do
---然后layout,每个layout保存一个page
local layout = ccui.Layout:create()
--为了演示这里做个小图片
layout:setContentSize(600,600)
layout:setPosition(0,0)
--创建一个button
local btn= ccui.Button:create("game/dian/Maininterface/tuichu.png","game/dian/Maininterface/tuichi.png","game/dian/Maininterface/weizi.png"):setPosition(300,300)
layout:addChild(btn)
pageView:addChild(layout)---一个layout 为一个page内容 page:addPage(layout)
end
--添加pageView 到场景中
self:addChild(pageView)

--添加事件响应
pageView:addEventListener(handler(self, self.onEvent))

--事件响应方法
function MainScene:onEvent(sender,event)
print("1234")
-- if event == ccui.PageViewEventType.turning then
-- local pageNum = sender:getCurrentPageIndex()
-- print("is turning,this PageNum:"..pageNum)
-- end
end

拖动精灵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
local sprite = cc.Sprite:create("")--自己随便找个图片试一试
local function onTouchBegan( touch, event )
local point = touch:getLocation() --获取鼠标坐标
local rect = sprite:getBoundingBox() -- 获取精灵的范围
if (cc.rectContainsPoint(rect,point)) then --判断鼠标是否在精灵范围内,是触发
return true;
end
return false
--这里必须判断,不然拖动屏幕精灵也会移动
end
local function onTouchEnded( touch, event )
-- body
end

local function onTouchMoved(touch, event)
local target = sprite --获取当前的控件(这里是精灵)
local posX,posY = target:getPosition() --获取当前的位置
local delta = touch:getDelta() --获取滑动的距离
target:setPosition(cc.p(posX + delta.x, posY + delta.y)) --给精灵重新设置位置
end

local listener1 = cc.EventListenerTouchOneByOne:create() --创建一个单点事件监听
listener1:setSwallowTouches(true) --是否向下传递
listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
listener1:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED )
listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )
local eventDispatcher = self:getEventDispatcher()
eventDispatcher:addEventListenerWithSceneGraphPriority(listener1, sprite) --分发监听事件

获取鼠标点击位置

1
2
3
4
local location = touch:getLocation()   --获取鼠标的位置
local event_x = location["x"] or 0
local event_y = location["y"] or 0
print("event_x = " .. event_x .. " event_y = " .. event_y)

游戏暂停

说明,点击“go”按钮,按钮变成“stop”

1
2
3
4
5
6
7
8
9
10
11
local spriteFrame = cc.SpriteFrameCache:getInstance()
spriteFrame:addSpriteFrames("Plist.plist")
local goSprite = cc.Sprite:createWithSpriteFrameName("go.png")
local stopSprite = cc.Sprite:createWithSpriteFrameName("stop.png")
local goToggleMenuItem = cc.MenuItemSprite:create(goSprite, goSprite)
local stopToggleMenuItem = cc.MenuItemSprite:create(stopSprite,stopSprite)
local toggleMenuItem = cc.MenuItemToggle:create(goToggleMenuItem,stopToggleMenuItem)
toggleMenuItem:setPosition(cc.Director:getInstance():convertToGL(cc.p(930,540)))
local a = cc.Menu:create(toggleMenuItem)
a:setPosition(cc.p(0,0))
self:addChild(a)

滑动条的使用

1
2
3
4
5
self.jindutiao = self.root:getChildByName('jindutiao')
self.jindutiao:addEventListener(function(sender ,eventType)
local volume = self.jindutiao:getPercent()
pritn(volume)
end)

说明:

1
2
3
4
5
6
getPercent()  --获取滑动条当前值
getMaxPercent() --获取滑动条最大值
getMinPercent()--获取滑动条最小值
setPercent() --设置滑动条当前值
setMaxPercent() --设置滑动条最大值
setMinPercent()--设置滑动条最小值

播放帧动画

该方法需要提前Cocos studio上将帧动画创建好

1
2
3
4
5
6
7
8
9
self.root = cc.CSLoader:createNode('game/basketball/Node.csb')
self.root:move(x,y)
self.root:addTo(self)
local action = cc.CSLoader:createTimeline('game/basketball/Node.csb')
self.root:runAction(action)
action:pause()
action:clearFrameEventCallFunc()
action:gotoFrameAndPlay(0,20,false)
--从第0帧播放到20帧,直播一次

求夹角

1
2
3
4
5
6
7
8
9
10
    local p1 = {x = x1 , y = y1}
local p2 = {x = x2 , y = y2 }
self:getAngleByPos(p1,p2)
function GameScene:getAngleByPos(p1,p2)
local p = {}
p.x = p2.x - p1.x
p.y = p2.y - p1.y
local r = math.atan2(p.y , p.x) * 180/math.pi
print("夹角为:" .. r)
end

画二次贝塞尔曲线

1
2
3
4
5
6
7
8
9
function GameScene:testBezier()
if not self.drawNode then
self.drawNode = cc.DrawNode:create(). --创建节点
self:addChild(self.drawNode)
end
self.drawNode:clear() --删除节点
self.drawNode:drawQuadBezier(cc.p(self.xp0,self.yp0),cc.p(self.xp1,self.yp1),cc.p(self.xp2,self.yp2),1000,cc.c4f(1,1,0,1))
end
--p0,p1,p2 分别为曲线起点,控制点,终点

精灵的运动

旋转

1
self.sprite:runAction(cc.RepeatForever:create(cc.RotateBy:create(1,360))) --以锚点为中心不停的旋转,速度为每秒中360度

直线运动

1
2
3
4
self:runAction(cc.MoveTo:create(time,cc.p(x , y)))
self:runAction(cc.MoveBy:create(time,cc.p(x , y)))
--To移动到指定位置
--By移动到相对位置

跳跃运动

1
2
3
self:runAction(cc.JumpTo:create(time,cc.p(x , y),a,b))
self:runAction(cc.JumpBy:create(time,cc.p(x , y),a,b))
--参数time表示时间,a表示最高点,b表示跳跃次数

停止运动

1
self:stopAllActions()

按顺序运动

1
2
3
4
local run1 = self:runAction(cc.RotateTo:create(1,-80))
local run2 = self:runAction(cc.RotateTo:create(1,80))
local delay = cc.DelayTime:create(0.01)
self:runAction(cc.RepeatForever:create(cc.Sequence:create(run1,delay,run2,delay)))

渐入渐出

1
2
self:runAction(cc.FadeIn:create(0.1)) -- 渐入
self:runAction(cc.FadeOut:create(0.1)) --渐出

放大缩小

1
2
self:runAction(cc.ScaleTo:create(0.5,1)) --放大,参数:时间和缩放尺寸
self:runAction(cc.ScaleTo:create(0.2,0.6)) --缩小

画直线

1
2
3
self.Yg_DrawNode = cc.DrawNode:create()
self:addChild(self.Yg_DrawNode)
self.Yg_DrawNode:drawLine(cc.p(qidian_x,qidian_y),cc.p(zhongdian_x ,zhongdian_y),cc.c4f(0,0,0,5)) --参数 起点坐标,终点坐标,线条的颜色

游戏暂停、继续

1
2
CCDirector.sharedDirector():pause() --游戏暂停
CCDirector.sharedDirector():resume() --游戏继续

两个矩形的碰撞

1
2
3
4
5
local juxingA = A:getBoundingBox()
local juxingB = B:getBoundingBox()
if (cc.rectIntersectsRect(juxingA,juxingB))then
print("撞到了")
end

点是否在矩形内

1
2
3
4
5
6
local juxingA = A:getBoundingBox()
local Point = {x = x1, y = y1}

if (cc.rectContainsPoint(juxingA,Point)) then
print("撞到了")
end

解析json数据

1
2
在文件中添加下面语句
local json = cc.load("tools").json

背景音乐与音效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
AudioEngine.playMuisc(“bg.mp2”, true)      --播放背景音乐,第二个参数为true表示循环播放,默认情况下为false
AudioEngine.stopMusic() --停止播放背景音乐

AudioEngine.pauseMusic() --暂停播放背景音乐

AudioEngine.resumeMusic() --恢复播放背景音乐

AudioEngine.isMusicPlaying() --判断背景音乐是否播放

AudioEngine.preloadEffect(“effect.mp3”) --预加载音效

AudioEngine.playEffect(“effect.mp3”) --播放音效

AudioEngine.pauseEffect(id) --暂停播放音效,id是playEffect返回的参数

AudioEngine.pauseAllEffect() --暂停所有音效的播放

AudioEngine.resumeEffect(id) --继续播放某个音效

AudioEngine.resumeAllEffect() --继续播放所有音效

AudioEngine.stopEffect(id) --停止播放某一音效

AudioEngine.stopAllEffect() --停止所有音效播放

AudioEngine.setMusicVolume(0.5) --设置背景音乐音量

AudioEngine.setEffectsVolume(0.5) --设置音效音量

AudioEngine.getMusicVolume() --获得背景音乐音量

AudioEngine.getEffectsVolume() --获得音效音量

容器添加点击事件

1
2
3
4
Panel:addTouchEventListener(function(sender,eventType)
if 2 == eventType then
end
end)
+