一、进入游戏场景PlayLevelScene
接着上篇http://www.cocoachina.com/bbs/read.php?tid=234098的内容,回到MenuScene后,点击StartButton 进入 游戏关卡选择场景ChooseLevelScene
但是我没还打算讲解这个场景的内容,而且跳过它,先从游戏场景PlayLevelScene 开始讲解。原因有二:
1、 游戏关卡选择场景ChooseLevelScene使用的控件并不是单纯的Quick框架定义的控件,而且自己封装的(比起上篇的自定义按钮BubbleButton难度不是一个级别),我打算另外单独讲解;
2、另外一个原因就是提前进入 进行游戏的场景PlayLevelScene了解该游戏的核心不是更让人提起精神吗?所以我想先讲PlayLevelScene
那么我们就随便选择一个等级的关卡进入游戏场景吧,(我点击6,因为我学号是6班6号:14:)
<img title = '新标签页(1).png' src='http://cdn.cocimg.com/bbs/attachment/Fid_56/56_371891_ad62619377bc019.png' >
我们以视觉分析该场景的组成元素:
有好多的银币;
每个硬币下面有一块半透明的方块;
背景图
一个后退键
一信息条
还有一个“Level:6”的等级文本
好,带着这些“视觉认知”,我们打开PlayLevelScene.lua,看看其中的ctor()函数是怎样定义界面的吧
local Levels = import("..data.Levels")
local Board = import("..views.Board")
local AdBar = import("..views.AdBar")
local PlayLevelScene = class("PlayLevelScene", function()
return display.newScene("PlayLevelScene")
end)
function PlayLevelScene:ctor(levelIndex)
-- 1、背景
local bg = display.newSprite("#PlayLevelSceneBg.png")
-- make background sprite always align top
bg:setPosition(display.cx, display.top - bg:getContentSize().height / 2)
self:addChild(bg)
-- 2、标题
local title = display.newSprite("#Title.png", display.left + 150, display.top - 50)
title:setScale(0.5)
self:addChild(title)
-- 3、信息条
local adBar = AdBar.new()
self:addChild(adBar)
-- 4、等级文本
local label = cc.ui.UILabel.new({
UILabelType = 1,
text = string.format("Level: %s", tostring(levelIndex)),
font = "UIFont.fnt",
x = display.left + 10,
y = display.bottom + 120,
align = cc.ui.TEXT_ALIGN_LEFT,
})
self:addChild(label)
-- 5、硬币板
self.board = Board.new(Levels.get(levelIndex))
self.board:addEventListener("LEVEL_COMPLETED", handler(self, self.onLevelCompleted))
self:addChild(self.board)
-- 6、后退按钮
cc.ui.UIPushButton.new({normal = "#BackButton.png", pressed = "#BackButtonSelected.png"})
:align(display.CENTER, display.right - 100, display.bottom + 120)
:onButtonClicked(function()
app:enterChooseLevelScene()
end)
:addTo(self)
End
```
哈,看样子猜中很多啊,出差错的地方就是那个“硬币板”,所以我认为所以的硬币与半透明方块都在内嵌在这个“硬币板”中。先不管它了,我们从头分析起:1、背景;2、标题;3、信息条;这三个没什么好讲得,前面都已经理解基本能独立看懂与使用,重点我们先讲讲4、等级文本;学学文本控件的用法
了解UILabel的用法
根据cc.ui.UILabel.new,我打开quick-cocos2d-x-3.2rc0\quick\framework\cc\ui 找到了UILabel.lua,打开它,我们就可以来查看源码了!我们找到创建UILabel.类的这段代码
----
quick UILabel控件
]]
local UILabel
UILabel = class("UILabel", function(options)
if not options then
return
end
if 1 == options.UILabelType then
return UILabel.newBMFontLabel_(options)
elseif not options.UILabelType or 2 == options.UILabelType then
return UILabel.newTTFLabel_(options)
else
printInfo("UILabel unkonw UILabelType")
end
end)
```
因为UILabelType = 1 ,根据上面代码,我们知道了接下来执行的应该是UILabel.newBMFontLabel_(options),接着我们在UILabel.lua 找到了
----
用位图字体创建文本显示对象,并返回 LabelBMFont 对象。
BMFont 通常用于显示英文内容,因为英文字母加数字和常用符号也不多,生成的 BMFont 文件较小。如果是中文,应该用 TTFLabel。
可用参数:
- text: 要显示的文本
- font: 字体文件名
- align: 文字的水平对齐方式(可选)
- x, y: 坐标(可选)
~~~ lua
local label = UILabel:newBMFontLabel({
text = "Hello",
font = "UIFont.fnt",
})
~~~
@param table params 参数表格对象
@return LabelBMFont LabelBMFont对象
]]
function UILabel.newBMFontLabel_(params)
return display.newBMFontLabel(params)
end
```
噢耶:2:找到了这段代码加注释后就完全明白UILabel的用法了,根本就不需我解释了啊!所以,希望大家以后看到类似不懂的情况,也要懂得这样找框架源码,里面的注释极其强大,对我们菜鸟的学习很有帮助的。
对于6、后退按钮;大家也可以用这种方法,学会UIPushButton的用法,我也就省省口水不用讲了(说多错多啊)。
二、游戏进行场景的重要组件:Level.lua、Coin.lua
重新看会“硬币板”的那段代码,我知道知道接下要去打开src\app\views\Board.lua,在Board.lua这个脚本上出现了两个代码:
local Levels = import("..data.Levels")
local Coin = import("..views.Coin")
```
明显的,我们先应该了解Levels.lua和Coin.lua后再来看Board.lua会更清晰易懂
1、Level.lua
好,那我们从Level.lua入手:
local Levels = {}
Levels.NODE_IS_WHITE = 1 -- 金色面 正
Levels.NODE_IS_BLACK = 0 -- 白色面 。。。写BLACK是干嘛,色盲? 反
Levels.NODE_IS_EMPTY = "X" -- 空,就是没有硬币
local levelsData = {}
levelsData = {
rows = 4, -- 行数
cols = 4, -- 列类
grid = { -- 网格,也就是硬币状态的布局
{1, 1, 1, 1},
{1, 1, 0, 1},
{1, 0, 0, 0},
{1, 1, 0, 1}
}
}
--中间省略了99个关卡布局数据
function Levels.numLevels()
-- 长度操作符#用于返回一个数组或者线性表的最后的一个索引值
return #levelsData
end
function Levels.get(levelIndex)
--assert (v , message])
--参数:
--v:当表达式v为nil或false将触发错误,
--message:发生错误时返回的信息,默认为"assertion failed!"
-- 确保levelIndex >= 1 and levelIndex <= #levelsData,如果不是,将输出错误信息 :levelsData.get() - invalid levelIndex %s,
assert(levelIndex >= 1 and levelIndex <= #levelsData, string.format("levelsData.get() - invalid levelIndex %s", tostring(levelIndex)))
return clone(levelsData)
end
return Levels
```
Level.lua脚本相对简单,就是游戏关卡的硬币布局相关的数据,总共有100个levelsData,量真大!理解请看代码注释,应该不难懂。但想更大家统一下思路,反面后面思路混乱。
就是对硬币状态的规定:正面—金色面—1—Levels.NODE_IS_WHITE
:反面—银色面—0—Levels.NODE_IS_BLACK
:空—X—Levels.NODE_IS_EMPTY
2、Coin.lua
打开Coin.lua,先看前面一份的代码:
local Levels = import("..data.Levels")
local Coin = class("Coin", function(nodeType)
-- 先设定为1,正面
local index = 1
-- 判断
if nodeType == Levels.NODE_IS_BLACK then
index = 8 -- 8是反面
end
-- 依靠index选择创建的coin是用哪张图片资源
local sprite = display.newSprite(string.format("#Coin%04d.png", index))
-- 为该精灵添加一个属性,是否为正面
sprite.isWhite = index == 1
return sprite
end)
```
思路是这样的:以传入参数决定决定 index的值,再已index的值创建精灵,最后继续依靠index的值决定sprite.isWhite 此属性。
从此可看出index的值很重要,起决定性作为,但它为什么是1或8 呢?
好,现在是解密时间!这回打开res\AllSprites.plist,找到这几个:
大家可以看到Coin0001到Coin0008是硬币由正面(金)到反面(银)的8张图片,所以上面代码才会以index = 1代表正面,index = 8代表反面。
接着我们把Coin.lua剩下需要解析的代码看完:
-- 创建并执行硬币翻转特效的函数
function Coin:flip(onComplete)
-- 1、创建并执行翻转动画
-- 创建8张精灵帧,1到8 是 正面到反面的翻转
-- 注意:第四个参数,当其为false,按正常引索创建,为true是,按递减引索的方式创建
local frames = display.newFrames("Coin%04d.png", 1, 8, not self.isWhite)
-- 以上面创建的8张精灵帧集 创建动画,第二个参数是每一桢动画之间的间隔时间
local animation = display.newAnimation(frames, 0.3 / 8)
self:playAnimationOnce(animation, false, onComplete) -- 播放动画
-- 2、翻转后的一系列的缩放动作
self:runAction(transition.sequence({
-- 两个参数:第一个参数是时间(s),第二个参数是缩放倍数
cc.ScaleTo:create(0.15, 1.5),
cc.ScaleTo:create(0.1, 1.0),
cc.CallFunc:create(function()
local actions = {}
local scale = 1.1
local time = 0.04
for i = 1, 5 do
-- 三个参数,第一个是时间,第二个是X方向的缩放倍数,第三个是Y方向的缩放倍数
actions#actions + 1] = cc.ScaleTo:create(time, scale, 1.0)
actions#actions + 1] = cc.ScaleTo:create(time, 1.0, scale)
scale = scale * 0.95
time = time * 0.8
end
actions#actions + 1] = cc.ScaleTo:create(0, 1.0, 1.0)
self:runAction(transition.sequence(actions))
end)
}))
-- 3、翻转结束后,修改“是否为正面”这个属性
self.isWhite = not self.isWhite
end
```
1、创建并执行翻转动画:先分清一点,动画与动作是不一样的哦!这样的动画是所刚才看过的Coin0001到Coin0008所创建的帧动画。首先,先创建动画要播放的精灵帧集合local frames = display.newFrames("Coin%04d.png", 1, 8, not self.isWhite)
为了学习我们去找源码吧!里面肯定解析清楚用法了,还记得怎么找吗?
----
以特定模式创建一个包含多个图像帧对象的数组。
~~~ lua
-- 创建一个数组,包含 Walk0001.png 到 Walk0008.png 的 8 个图像帧对象
local frames = display.newFrames("Walk%04d.png", 1, 8)
-- 创建一个数组,包含 Walk0008.png 到 Walk0001.png 的 8 个图像帧对象
local frames = display.newFrames("Walk%04d.png", 1, 8, true)
~~~
@param string pattern 模式字符串
@param integer begin 起始索引
@param integer length 长度
@param boolean isReversed 是否是递减索引
@return table 图像帧数组
]]
function display.newFrames(pattern, begin, length, isReversed)
```
简单明了,只要注意一点,就是第四个参数,我们是以sprite.isWhite该属性为基础,很代码更为灵活与智能:是正面的话就正序创建精灵帧集合(正面到反面),是反面的话则相反。精灵帧集合创建完成后,再以其为基础创建动画,再播放动画就OK了!不懂的地方记得查框架源码!!
2、翻转后的一系列的缩放动作:一系列的动作组合。
3、翻转结束后,修改“是否为正面”这个属性:切记这一步很重要,该属性是判断硬币当前的状态的一个接口,对于该游戏的核心玩法和动画的创建都起的决定的作用。
OK,本篇先讲到这里,在了解完Board.lua的组件,下篇我们在开好好谈论下Board.lua吧,谢谢。



