quick-cocos2d-x 学习系列之十六 塔防完结

1.math2d.lua文件

该文件实现了常用的数学函数。

dist函数实现两点的距离。

radians4point求两点的夹角(弧度)

pointAtCircle求圆上一个点的位置

pointAtLinetoPoint求线段上与指定点距离最近的点

degrees2radians角度转换为弧度

radians2degrees弧度转换为角度

2.utils.lua文件

2.1drawCircle

返回newCircle.

根据utils.useNVGDrawNode变量采用不同的方式。

如果utils.useNVGDrawNode为true,则返回NVGDrawNode.

2.2drawRect

同drawCircle函数,返回矩形。

2.3drawpolygon

同drawCircle函数,返回多变形。

Editor文件夹

这个文件夹中都是和地图编辑相关的文件。

1.AutoLayout.lua

定义了函数function AutoLayout.alignItemsHorizontally(items,x,y,padding,lines)

用于实现Item水平对齐。

2.EditorConstants.lua

该文件定义里一个表结构EditorConstants

local EditorConstants = {}

EditorConstants.CHECK_POINT_disT= 6

EditorConstants.SELECTED_COLOR= {255,255, 255}

EditorConstants.SELECTED_LABEL_COLOR= {0,0,255}

EditorConstants.UNSELECTED_COLOR= {180,180, 180}

EditorConstants.UNSELECTED_LABEL_COLOR = {0,0}

EditorConstants.LABEL_OFFSET_Y= 4

EditorConstants.LABEL_FONT= display.DEFAULT_TTF_FONT

EditorConstants.LABEL_FONT_SIZE= 14

EditorConstants.LABEL_ZORDER= 100

EditorConstants.polyGON_ZORDER= 1000

EditorConstants.CIRCLE_ZORDER= 2000

EditorConstants.FLAG_ZORDER= 3000

EditorConstants.RANGE_HANDLER_ZORDER= 4000

EditorConstants.BINDING_LABEL_ZORDER= 5000

EditorConstants.PANEL_ZORDER= 10000

EditorConstants.MAP_PADDING= 200

EditorConstants.MAP_TOOLBAR_HEIGHT= 48

EditorConstants.PROPERTY_PREFIX_LEN= 16

EditorConstants.BEHAVIOR_LABEL_WIDTH= 110

EditorConstants.INSPECTOR_WIDTH= 360

EditorConstants.PANEL_BUTTON_SIZE= 40

EditorConstants.PANEL_BUTTON_OFFSET= 4

EditorConstants.PANEL_OFFSET= 4

EditorConstants.PANEL_LABEL_FONT= "Courier"

EditorConstants.PANEL_LABEL_FONT_SIZE= 13

EditorConstants.TOOLBAR_PADDING= 40

return EditorConstants

3.EditorScene.lua

定义一个EditorScene类。是编辑类的入口。

ctor

构造函数,设置变量self.toolbarLines = 1

self.editorUIScale = 1

self.statusCount_ = 1,根据平台设置变量editorUIScale,toolbarLines。

通过图片EditorBg创建newTilessprite。

创建mapLayer,包含地图的整个视图

self.mapLayer_ = display.newNode()

self.mapLayer_:align(display.LEFT_BottOM,0)

self:addChild(self.mapLayer_)

创建touchLayer用于接收触摸事件

self.touchLayer_ = display.newLayer()

self:addChild(self.touchLayer_)

创建uiLayer 用于显示编辑器的 UI(工具栏等)

self.uiLayer_ = display.newNode()

self.uiLayer_:setPosition(display.cx,display.cy)

self:addChild(self.uiLayer_)

-- 创建地图对象,地图项次查看app.map.Map.lua文件

self.map_ = require("app.map.Map").new(LEVEL_ID,true) -- 参数:地图ID,是否是编辑器模式

self.map_:init()

self.map_:createView(self.mapLayer_)

-- 创建工具栏

self.toolbar_ = require("editor.Toolbar").new(self.map_)

self.toolbar_:addTool(require("editor.GeneralTool").new(self.toolbar_,self.map_))

self.toolbar_:addTool(require("editor.ObjectTool").new(self.toolbar_,self.map_))

self.toolbar_:addTool(require("editor.PathTool").new(self.toolbar_,self.map_))

self.toolbar_:addTool(require("editor.Rangetool").new(self.toolbar_,self.map_))

-- 创建工具栏的视图

self.toolbarView_ =self.toolbar_:createView(self.uiLayer_, "#ToolbarBg.png",EditorConstants.TOOLBAR_PADDING,self.editorUIScale,self.toolbarLines)

self.toolbarView_:setPosition(display.c_left,display.c_bottom)

self.toolbar_:setDefaultTouchTool("GeneralTool")

self.toolbar_:selectButton("GeneralTool",1)

-- 创建对象信息面板

local objectInspectorScale = 1

self.objectInspector_ = require("editor.ObjectInspector").new(self.map_,objectInspectorScale,self.toolbarLines)

self.objectInspector_:addEventListener("UPDATE_OBJECT",function(event)

self.toolbar_:dispatchEvent(event)

end)

self.objectInspector_:createView(self.uiLayer_)

-- 创建地图名称文字标签

self.mapNameLabel_ = cc.ui.UILabel.new({

text= string.format("module: %s,image: %s",self.map_.mapModuleName_,self.map_.imageName_),

size= 16 *self.editorUIScale,

align = cc.ui.TEXT_ALIGN_LEFT,

x= display.left + 10,

y= display.bottom + EditorConstants.MAP_TOOLBAR_HEIGHT *self.editorUIScale * self.toolbarLines + 20,

}):align(display.CENTER)

self.mapNameLabel_:enableOutline(cc.c4b(255,0), 2)

self.mapLayer_:addChild(self.mapNameLabel_)

-- 注册工具栏事件

self.toolbar_:addEventListener("SELECT_OBJECT",function(event)

self.objectInspector_:setobject(event.object)

end)

self.toolbar_:addEventListener("UPDATE_OBJECT",function(event)

self.objectInspector_:setobject(event.object)

end)

self.toolbar_:addEventListener("UNSELECT_OBJECT",function(event)

self.objectInspector_:removeObject()

end)

self.toolbar_:addEventListener("PLAY_MAP",function()

self:playMap()

end)

-- 创建运行地图时的工具栏

self.playToolbar_ = display.newNode()

if (device.platform == "mac" or device.platform == "windows") then

cc.ui.UIPushButton.new({normal = "#ToggleDebugButton.png",pressed = "#ToggleDebugButtonSelected.png"})

:onButtonClicked(function(event)

self.map_:setDebugViewEnabled(notself.map_:isDebugViewEnabled())

end)

:align(display.CENTER,display.left + 32 *self.editorUIScale,display.top - 32 * self.editorUIScale)

:addTo(self.playToolbar_)

:setScale(self.editorUIScale)

cc.ui.UIPushButton.new({normal = "#StopMapButton.png",pressed = "#StopMapButtonSelected.png"})

:onButtonClicked(function(event)

self:editMap()

end)

:align(display.CENTER,display.left + 88 * self.editorUIScale,display.top - 32 *self.editorUIScale)

:addTo(self.playToolbar_)

:setScale(self.editorUIScale)

else

self.recordBtnBg_ =cc.LayerColor:create(cc.c4b(255, 120)):addTo(self)

self.recordBtnBg_:setTouchEnabled(false)

self.recordBtn_ = cc.ui.UIPushButton.new("GreenButton.png",{scale9 = true})

:setButtonLabel(cc.ui.UILabel.new({text= "开始性能测试",size = 20,color =display.COLOR_BLACK}))

:setButtonSize(130, 40)

:align(display.CENTER,display.cx,display.cy)

:addTo(self.recordBtnBg_)

:onButtonClicked(function()

self.mapLayer_:setPositionY(60)

-- self.mapRuntime_:setPositionY(60)

self.mapRuntime_:startPlay()

self:disabelResult()

self:disableStatus()

self:showStatusCurve()

self:statusTimerBegin()

self.recordBtnBg_:removeSelf()

self.recordBtnBg_ = nil

end)

end

self.playToolbar_:setVisible(false)

self:addChild(self.playToolbar_)

--根据运行平台选择运行editMap还是playMap

if (device.platform == "mac" or device.platform == "windows") then

self:editMap()

else

self:playMap()

end

1.1playMap

隐藏编辑器界面,保存地图当前状态,强制垃圾回收,执行地图.

1.2editMap

编辑地图

1.3tick

1.4onTouch

1.5onEnter

1.6onExit

1.7showStatusCurve

1.8disableStatus

1.9addFPS

1.10statusTimerBegin

1.11statusTimerEnd

1.12showResult

1.13disabelResult

4.GeneralTool.lua

基于ToolBase类。

5.ObjectInspector.lua

创建类ObjectInspector。

6.ObjectTool.lua

基于ToolBase类。

7.PathTool.lua

基于ToolBase类。

8.Rangetool.lua

基于ToolBase类。

9.Toolbar.lua

创建类Toolbar。

10.ToolBase.lua

创建类toolbase。是其他tool类的基类。

创建变量如下

ToolBase.TOUCH_IGnorED= "ignored"

ToolBase.DEFAULT_TOUCH_ENDED = "ended"

初始化构造函数中设置类中变量

self.name_ = name

self.toolbar_= toolbar

self.map_= map

self.selectedButtonName_= nil

APP.properties文件夹

这个文件夹中的文件定义的是全是属性,包括建筑、NPC、Player、静态对象、静态对象装饰以及箭塔。

1.BuildingProperties.lua(完)

该文件定义建筑的属性。

返回一个变量BuildingProperties,该变量中实现了一个函数

BuildingProperties.get(id)

2.NPCProperties.lua(完)

定义NPC的属性,返回变量NPCProperties,其中规定函数

function NPCProperties.get(id)

return clone(defines[id])

end

3.PlayerProperties.lua(完)

定义Player的属性,返回变量PlayerProperties,其中规定函数

function PlayerProperties.get(id)

return clone(defines[id])

end

4.StaticObjectsdecorationProperties.lua(完)

定义静态物体的装饰属性,StaticObjectsdecorationProperties

包括建筑和舰船。

5.StaticObjectsProperties.lua(完)

定义了所有的静态对象,StaticObjectsProperties

6.TowerProperties.lua(完)

定义塔的属性,返回TowerProperties,箭塔4个级别。

App.map文件夹

定义的是和地图相关文件,主要入口是MAP.LUA文件。包含了bullets文件夹和behaviors文件夹。Bullets文件夹中定义了和子弹相关的类。Behaviors文件夹中定义了以BehaviorBase为基类的类。

1.Map.lua

这个是地图相关的入口。

该文件中先导入4个文件如下:

local MapConstants = require("app.map.MapConstants")

local MapCamera = require("app.map.MapCamera")

local ObjectFactory = require("app.map.ObjectFactory")

local Path = require("app.map.Path")

创建一个Map类。

Map.new() 创建 Map 对象实例

Map:init() 初始化 Map 对象

Map:createView() 创建 Map 对象的视图

Map:removeView() 删除 Map 对象的视图

Map:updateView() 更新 Map 对象的视图

Map:destroy() 销毁 Map 对象

Map:newObject() 创建新的地图子对象,并绑定行为

如果此时视图已经创建,则调用子对象的 createView()

1.1ctor

EditorScene.lus的构造函数中调用,如下:

self.map_ = require("app.map.Map").new(LEVEL_ID,是否是编辑器模式

self.map_:init()

self.map_:createView(self.mapLayer_)

构造函数中两个参数一个是id,一个是debug

self.mapModuleName_ = string.format("maps.Map%sData", id)

self.eventModuleName_ = string.format("maps.Map%sEvents",id)

得到地图的数据文件和时间文件。指向maps.MapA0002Data,maps.MapA0002Events.

此处会使用pcall函数,获取maps.Map0002Data中数据,详解后面解释。

见该数据复制给self.data_变量。(注意clone函数并非lua脚本的命令)

1.2Init函数

从self.data_变量中获取

self.width_ = self.data_.size.width

self.height_= self.data_.size.height

self.imageName_ = self.data_.imageName

如果没有得到imageName_值,则再手动创建之。

-- 添加地图数据中的对象,state本身还是个table类。其中string.split函数

--传入字符串和分隔符,返回分割后的tableclassId此处是range,path,static3种字符串。

for id,state in pairs(self.data_.objects) do

local classId = unpack(string.split(id,":"))

self:newObject(classId,state,id)

end

-- 验证所有的路径

for i,path in pairs(self:getobjectsByClassId("path")) do

path:validate()

if not path:isValid() then

echoInfo(string.format("Map:init() - invalid path %s",path:getId()))

self:removeObject(path)

end

end

-- 验证其他对象

for id,object in pairs(self.objects_) do

local classId = object:getClassId()

if classId ~= "path" then

object:validate()

if not object:isValid() then

echoInfo(string.format("Map:init() - invalid object %s",object:getId()))

self:removeObject(object)

end

end

end

-- 计算地图位移限定值

self.camera_ = MapCamera.new(self)

self.camera_:resetoffsetLimit()

-- 地图已经准备好

self.ready_ = true

--init函数完成map的初始化工作。

1.3newObject

输入参数classId,state,id

State是object的table变量,包含一个索引为points的x,y坐标集。Id是一个类似 path:1的字符串,classId是一个path,static或则range

函数中调用ObjectFactory.newObject函数。

ObjectFactory是在ObjectFactory.lua文件中定义的函数。

调用object:setDebug(self.debug_)函数

调用object:setDebugViewEnabled(self.debugViewEnabled_)

object:resetAllBehaviors()

这些函数都在ObjectBase类中定义的原型。

1.4removeObject

1.5getClassId

1.6getobjectsByClassId

2.BulletFactory.lua

创建一个子弹对象。

3.BulletType.lua(完)

该文件定义里子弹类型

定义了变量BulletType

local BulletType = {}

BulletType.ARROW = 1

BulletType.CANNON = 2

return BulletType

4.decoration.lua

创建一个decoration类,这个是个装饰类。

5.MapConstants(完)

该文件中定义里一个表结构MapConstants,相关变量都设置在此处。

local MapConstants = {}

MapConstants.SIDE_BAR_WIDTH= 110

MapConstants.PLAY_DEFAULT_SCALE= 0.7

MapConstants.ZOOM_TIME= 0.1

MapConstants.FIRE_RANGE_SIZE= 128

MapConstants.FIRE_RANGE_SCALE_Y= 0.8

MapConstants.FIRE_RANGE_ZORDER= 150

MapConstants.DEFAULT_OBJECT_ZORDER= 100

MapConstants.MAX_OBJECT_ZORDER= 20000

MapConstants.BULLET_ZORDER= 21000

MapConstants.norMAL_TRACKING_SPEED= 3

MapConstants.FAST_TRACKING_SPEED= 12

MapConstants.SET_FAST_TRACKING_disT = display.height / 3

MapConstants.CROSS_POINT_TAP_RADIUS = 50

MapConstants.HP_BAR_ZORDER= 30000

MapConstants.HP_BAR_OFFSET_Y= 20

MapConstants.RADIUS_CIRCLE_SCALE_Y= 0.85

MapConstants.LEVEL_LABEL_OFFSET_Y= 26

MapConstants.LEVEL_LABEL_FONT= display.DEFAULT_TTF_FONT

MapConstants.LEVEL_LABEL_FONT_SIZE= 16

MapConstants.PLAYER_CAMP= 1

MapConstants.ENEMY_CAMP= 2

return MapConstants

6.MapCamera

该函数导入MapConstants变量,创建MapCamera类。

主要是实现地图的一些视角。主要函数如下:

1.1getMargin

1.2setMargin

1.3getScale

地方

1.4setScale

1.5zoomTo

1.6getoffset

1.7setoffset

1.8moveOffset

1.9getoffsetLimit

1.10resetoffsetLimit

1.11convertToMapPosition

1.12convertToWorldPosition

1.13convertToCameraPosition

7.MapEvent.lua

地图中相关事件的定义。如下:

local MapEvent = {}

MapEvent.MAP_PREPARE_PLAY= "MAP_PREPARE_START"

MapEvent.MAP_START_PLAY= "MAP_START_PLAY"

MapEvent.MAP_STOP_PLAY= "MAP_STOP_PLAY"

MapEvent.MAP_PAUSE_PLAY= "MAP_PAUSE_PLAY"

MapEvent.MAP_RESUME_PLAY= "MAP_RESUMT_PLAY"

MapEvent.MAP_TIME= "MAP_TIME"

MapEvent.OBJECT_ENTER_RANGE= "OBJECT_ENTER_RANGE"

MapEvent.OBJECT_EXIT_RANGE= "OBJECT_EXIT_RANGE"

MapEvent.OBJECT_IN_RANGE= "OBJECT_IN_RANGE"

MapEvent.OBJECT_COLLISION_BEGAN= "OBJECT_COLLISION_BEGAN"

MapEvent.OBJECT_COLLISION_ENDED= "OBJECT_COLLISION_ENDED"

MapEvent.OBJECT_DESTROY= "OBJECT_DESTROY"

return MapEvent

8.MapEventHandler.lua

定义一个类。需要其他文件

local MapConstants = require("app.map.MapConstants")

local MapEvent = require("app.map.MapEvent")

local MovableBehavior = require("app.map.behaviors.MovableBehavior")

local BulletBase = require("app.map.bullets.BulletBase")

9.MapRuntime.lua

创建一个MapRuntime类。

10.ObjectFactory

导入3个文件如下

local StaticObject = require("app.map.StaticObject")

local Path = require("app.map.Path")

local Range = require("app.map.Range")

1.1newObject

在ObjectFactory文件中主要定义了这个函数。

输入4个参数classId,id,map.

根据map是否是debug,设置变量debug.

根据classId的三个字符串static,range设置3条执行路径。

分别是

StaticObject.new(id,map)

Path.new(id,map)

Range.new(id,map)

注:StaticObject,Path,Range都是基于ObjectBase的 类,

最后返回得到一个object对象,然后调用object:init().

如果不是三个字符串static,range字符串中一个则退出。

此外还判断是否是isDebug,如果是调试则分别执行

object:bindBehavior("StaticObjectEditorBehavior")

object:bindBehavior("PathEditorBehavior")

object:bindBehavior("RangeEditorBehavior")

(完)

11.Path

该文件创建了一个Path类,基于ObjectBase类。

1.1Path:ctor

三个参数id,map.其中state是一个表结构object,里面有一个points={}的值。其索引必定是path:1之类的。

获取points表结构的x,赋值给state.x,state.y同时调用父类的ctor(self,map),参数和传给path:ctor 相比多了一个self参数。说明Path:ctor把自己这个对象传给了父类,可谓父子情深。最后返回包含变量points_给自己。

最后设置变量valid_ ,如果# self.points_ > 0 则就是true.

(完)

1.2Path:getPoint(index)

1.3Path:getPointsCount()

1.4Path:appendPoint(x,y)

1.5Path:insertPointAfterIndex

1.6Path:movePoint(index,y)

1.7Path:removePoint(index)

1.8Path:checkPointAtPoint(x,checkdist)

1.9Path:checkPointAtSegment(x,checkdist)

1.10Path:vardump()

1.11Path:dump(label)

12.StaticObject

创建StaticObject类也基于ObjectBase类。

13.Range

创建range类也基于ObjectBase类。

14.ObjectBase

创建一个ObjectBase类。

创建3个变量

ObjectBase.CLASS_INDEX_PATH= 1

ObjectBase.CLASS_INDEX_RANGE= 2

ObjectBase.CLASS_INDEX_STATIC = 3

有3个儿子类么。

ObjectBase:ctor(id,map)

构造函数先判断state是否是table,如果不是则报错。

将state的索引类似path:1或者state:3或者range:3和points表重新赋值给

self[kn]=v( k是points,v是点集合)如下

for k,v in pairs(state) do

local kn = k .. "_"

self[kn] = v

end

同时设置其他的变量值如下

local classId,index = unpack(string.split(id,":"))

self.map_ = map

self.id_ = id

self.classId_ = classId

self.classIndex_ = ObjectBase.CLASS_INDEX[classId]

self.index_ = checkint(index)

self.x_ = checkint(self.x_)

self.y_ = checkint(self.y_)

self.offsetX_ = checkint(self.offsetX_)

self.offsetY_ = checkint(self.offsetY_)

self.state_ = state

self.valid_ = false

self.play_ = false

self.tag_ = 0

self.sprite_ = nil

self.debug_ = false

self.debugViewEnabled_ = false

if type(self.viewZOrdered_) ~= "boolean" then

self.viewZOrdered_ = true

end

返回给子类(完)

ObjectBase:init()

该函数在ObjectFactory.newObject函数中被调用,

判断self.behaviors_变量,如果为false就直接退出。

处理类似

local object = {

behaviors = {

"CampBehavior",

"CollisionBehavior",

"DecorateBehavior",

"DestroyedBehavior",

"FireBehavior",

"TowerBehavior",

},

campId = 1,

collisionEnabled = true,

decorationsMore = {

},

defineId = "PlayerTower01",

flipSprite = false,

tag = 0,

towerId = "PlayerTower01L01",

x = 454,

y = 465,

}

objects["static:1"] = object的对象

如果没有behaviors则就退出。不过static:1这种的就肯定会执行了。

判断是一个string还是其他(table),赋值给函数中的局部变量。

然后循环执行self:bindBehavior(behaviorName)

(完)

ObjectBase:isDebug()

ObjectBase:setDebug(isDebugEnabled)

ObjectBase:isDebugViewEnabled()

ObjectBase:setDebugViewEnabled(isDebugViewEnabled)

ObjectBase:getId()

ObjectBase:getClassId()

ObjectBase:getIndex()

ObjectBase:validate()

ObjectBase:isValid()

ObjectBase:getTag()

ObjectBase:setTag(tag)

ObjectBase:getPosition()

ObjectBase:setPosition(x,y)

ObjectBase:isViewCreated()

ObjectBase:isViewZOrdered()

ObjectBase:getView()

ObjectBase:createView(batch,marksLayer,debugLayer)

ObjectBase:removeView()

ObjectBase:updateView()

ObjectBase:preparePlay()

ObjectBase:startPlay()

ObjectBase:stopPlay()

ObjectBase:isPlay()

ObjectBase:hasBehavior(behaviorName)

ObjectBase:bindBehavior(behaviorName)

该函数被init()函数调用。

该函数的参数是"CampBehavior", "CollisionBehavior","DecorateBehavior",

"DestroyedBehavior","FireBehavior","TowerBehavior"等等中的一个字符串。

判断self.behaviorObjects_,如果没有值则设置为{}。(第一次调用时候会使用)

判断self.behaviorObjects_[behaviorName]如果不为空,说明已经设置了,就直接退出。

然后调用BehaviorFactory.createBehavior(behaviorName)返回给behavior。

获取behavior实例中的getDepends参数,例如:

local depends = {

"DestroyedBehavior",

}在BuildingBehavior.lua文件中。

然后递归调用self:bindBehavior(dependBehaviorName)

创建self.behaviorDepends_变量,首次为空。创建

self.behaviorDepends_[dependBehaviorName] ={},首次为空,然后将这插入到表中。

table.insert(self.behaviorDepends_[dependBehaviorName],behaviorName)

。(将behaviorName依赖的behavior存到self.behaviorDepends_中。)

然后调用behavior:bind(self)

设置self.behaviorObjects_[behaviorName]= behavior,接着将behavior加入到变量behaviorObjects_中。

最后调用ObjectBase:resetAllBehaviors()

(完)

ObjectBase:unbindBehavior(behaviorName)

ObjectBase:resetAllBehaviors()

被函数ObjectBase:bindBehavior(behaviorName)调用。

解析变量self.behaviorObjects_中的behavior,复制给behaviors数组。

根据优先级进行排序。最后调用behavior:reset(self)。

ObjectBase:bindMethod(behavior,methodName,method,callOriginMethodLast)

ObjectBase:unbindMethod(behavior,methodName)

ObjectBase:vardump()

ObjectBase:dump(label)

Behaviors文件夹文件

BehaviorBase.lua

该类是其他各种Behavior的基类。

l Ctor (behaviorName,depends,priority,conflictions)

self.name_ = behaviorName

self.depends_ =checktable(depends)

self.priority_ =checkint(priority) -- 行为集合初始化时的优先级,越大越先初始化

self.conflictions_ = checktable(conflictions)

l BehaviorBase:getName()

返回 self.priority_

l BehaviorBase:getDepends()

返回self.depends_变量。

l BehaviorBase:getPriority()

返回优先级

return self.priority_

l BehaviorBase:getConflictions()

返回变量self.conflictions_

return self.conflictions_

l BehaviorBase:bind(object)

父类中为实现,需要子类根据需要去实现。

l BehaviorBase:unbind(object)

父类中为实现,需要子类根据需要去实现。

l BehaviorBase:reset(object)

父类中为实现,需要子类根据需要去实现。

BehaviorFactory

这个文件中定义了behaviorsClass表。定义了所有的behavior.

local behaviorsClass = {

CollisionBehavior = require("app.map.behaviors.CollisionBehavior"),

CampBehavior = require("app.map.behaviors.CampBehavior"),

DecorateBehavior = require("app.map.behaviors.DecorateBehavior"),

BuildingBehavior = require("app.map.behaviors.BuildingBehavior"),

FireBehavior = require("app.map.behaviors.FireBehavior"),

MovableBehavior = require("app.map.behaviors.MovableBehavior"),

DestroyedBehavior = require("app.map.behaviors.DestroyedBehavior"),

TowerBehavior = require("app.map.behaviors.TowerBehavior"),

NPCBehavior = require("app.map.behaviors.NPCBehavior"),

PathEditorBehavior = require("app.map.behaviors.PathEditorBehavior"),

RangeEditorBehavior = require("app.map.behaviors.RangeEditorBehavior"),

StaticObjectEditorBehavior = require("app.map.behaviors.StaticObjectEditorBehavior"),

}

BehaviorFactory.createBehavior(behaviorName)

在文件objectBase.lua的文件中被函数

local behavior = BehaviorFactory.createBehavior(behaviorName)调用。

通过参数获得class.

local class = behaviorsClass[behaviorName]

assert(class ~= nil,string.format("BehaviorFactory.createBehavior() - Invalid behavior name\"%s\"",tostring(behaviorName)))

class.new()

返回相应的类实例。

BehaviorFactory.getAllStaticObjectBehaviorsName()

获取所有静态物体的behaviors行为名字。.

BehaviorFactory.isstaticObjectBehavior(behaviorName)

获取静态行为是否开启。

BuildingBehavior

创建BuildingBehavior,继承于BehaviorBase。

l ctor

有局部变量depends

local depends = {

"DestroyedBehavior",

}

调用父节点的ctor函数。

BuildingBehavior.super.ctor(self,"BuildingBehavior",100)

设置

self.name_ = behaviorName

self.depends_ = checktable(depends)

self.priority_ = checkint(priority) -- 行为集合初始化时的优先级,越大越先初始化

self.conflictions_ = checktable(conflictions)

最后返回一个类实例。

l BuildingBehavior:bind(object)

获取对象的buildingId_

object.buildingId_ = object.state_.buildingId

包括对该变量的判断,如果不是字符串则赋值为空。

函数中定义了4个函数getBuildingId,setBuildingId,showDestroyedStatus,vardump

通过调用object:bindMethod函数都绑定到object上。

getBuildingId函数,调用return object.buildingId_。

setBuildingId函数,设置object.buildingId_,通过BuildingProperties获得object.buildingId_的定义,如果没有得到该值则判断object.campId_是否等于1,如果成立则object.buildingId_ = "BuildingP001",否则object.buildingId_ = "BuildingN001"。(这个主要两个方向,是否需要护甲)

最后设置define中的表,较索引都下一个下划线_。

showDestroyedStatus函数,视图不可见,显示装饰。

object:getView():setVisible(false)

object:getdecoration(object.defineId_ .. "Destroyed"):getView():setVisible(true)

vardump函数,如下。

state.buildingId = object.buildingId_

return state

l BuildingBehavior:unbind(object)

调用object:unbindMethod,移除

4个函数getBuildingId,setBuildingId,showDestroyedStatus,vardump

l BuildingBehavior:reset(object)

调用如下函数:

object:setBuildingId(object:getBuildingId())

CampBehavior.lua

创建CampBehavior,继承于BehaviorBase。

l CampBehavior:ctor()

调用父类的构造函数。

l CampBehavior:bind(object)

绑定2个函数,getCampId,vardump。

getCampId函数,返回object.campId_

vardump函数

state.campId = object.campId_

return state

l CampBehavior:unbind(object)

解除2个函数的绑定。

CollisionBehavior

创建CollisionBehavior,继承于BehaviorBase。

l CollisionBehavior:ctor()

调用父类的构造函数。

l CollisionBehavior:bind(object)

绑定5个函数isCollisionEnabled,setCollisionEnabled,addCollisionLock。removeCollisionLock,vardump。

isCollisionEnabled函数

return object.collisionEnabled_

setCollisionEnabled函数

object.collisionEnabled_ = enabled

addCollisionLock函数

object.collisionLock_ = object.collisionLock_+ 1

removeCollisionLock函数

object.collisionLock_ = object.collisionLock_ - 1

assert(object.collisionLock_ >= 0,

"CollisionBehavior.removeCollisionLock()- object.collisionLock_ must >= 0")

vardump函数,如下

state.collisionEnabled = object.collisionEnabled_

return state

l CollisionBehavior:unbind(object)

解除5个函数的绑定。

DecorateBehavior

创建DecorateBehavior,继承于BehaviorBase

l DecorateBehavior:ctor()

调用父类。

l DecorateBehavior:bind(object)

绑定8个函数给object.

起先设置

for i,k in ipairs(checktable(object.state_.decorations)) do

object.decorations_[k] = false

end

再设置:

for i,k in ipairs(checktable(object.state_.decorationsMore)) do

object.decorationsMore_[k] = false

end

isdecorationExists函数

return object.decorations_[decorationName]~= nil

getdecoration函数

return object.decorations_[decorationName]

updateView函数

其中定义了局部函数local function updateView_(source)。

该函数更新视图。

fastUpdateView函数

removeView函数

定义了一个局部函数local function removeView_(source)

if not source then return end

for decorationName,decoration in pairs(source) do

if decoration then decoration:removeView() end

source[decorationName] = false

end

end

再调用removeView_(object.decorations_)

removeView_(object.decorationsMore_)

setVisible函数

for decorationName,decoration in pairs(object.decorations_) do

if decoration then

local view = decoration:getView()

view:setVisible(decoration.visible_ and visible)

end

end

fadeto函数

local function fadeto(object,opacity,time)

transition.fadeto(object:getView(),{opacity = opacity,time = time})

for decorationName,decoration in pairs(object.decorations_) do

if decoration then

local view = decoration:getView()

if view:isVisible() then

transition.fadeto(view,time = time})

end

end

end

end

vardump函数

l DecorateBehavior:unbind(object)

解除绑定的8个函数。

DestroyedBehavior

创建DestroyedBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

FireBehavior

创建FireBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

MovableBehavior

创建MovableBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

NPCBehavior

创建NPCBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

PathEditorBehavior

创建PathEditorBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

RangeEditorBehavior

创建RangeEditorBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

StaticObjectEditorBehavior

创建StaticObjectEditorBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

TowerBehavior

创建TowerBehavior,继承于BehaviorBase

基本同其他behavior,存在细节差异。

Bullet文件夹文件

ArrowBullet.lua

继承与BulletBase类

l ArrowBullet:ctor(source,target,delay)

设置参数params

调用父节点的构造函数。

l ArrowBullet:fireBegan()

调用父节点的fireBegin().

l ArrowBullet:hit()

击中目标后调用。

创建破坏的箭头精灵。设置旋转角度。

获取目标视图,获取飞行距离。

最后子弹精灵fadeout,删除自身。

BulletBase

该类是其他3个子弹类的基类。其他类都基于此类。

l BulletBase:ctor(source,sprite,delay)

构造函数中定义了基类的变量,如下,四个变量时来自构造函数的,需要注意的是self_delay_这个变量设置的时候需要checknumber操作。Self_damage_变量操作的时候,随机一个最小伤害到最大伤害的值(这个是游戏中常用的手段)。此外定义了起始的位置。

self.source_ = source

self.target_ = target

self.sprite_ = sprite

self.delay_ = checknumber(delay)

self.flag_ = 0

self.damage_ = math.random(source.mindamage_,source.maxdamage_)

self.damageScale_ = 1

self.hit_ = math.random(100) <= source.hitrate_

self.critical_ = math.random(100) <= source.critical_

self.startX_ = source.x_ + source.radiusOffsetX_ + source.fireOffsetX_

self.startY_ = source.y_ + source.radiusOffsetY_ + source.fireOffsetY_

self.prevX_ = self.startX_

self.prevY_ = self.startY_

self.time_ = 0

self.over_ = false

self.isBegan_ = false

l BulletBase:setFlag(flag)

设置变量 self.flag_= flag,为其他动作判断准备。

l BulletBase:getView()

返回子弹图片如下:

return self.sprite_

l BulletBase:removeView()

移除子弹

self.sprite_:removeSelf()

l BulletBase:tick(dt)

判断子弹是否已经begin,那么设置时间self.time_ = self.time_ + dt,然后调用self:tickBullet(dt)。

如果没有发射,则判断self.delay_ <= 0,满足则调用firebegin(),否则让该值减掉时间片,实现延时发射的效果。

这个tick实现了子弹发射,保证了延时发送。

l BulletBase:fireBegan()

判断是否已经摧毁,如果摧毁,则设置变量后返回

self.time_ = 0

self.over_= true

self.isBegan_ = false

return

如果没有摧毁,则设置位置,并设置self.isBegan_ = true

l BulletBase:tickBullet(dt)

子类可以覆盖之。

l BulletBase:checkHit()

判断是否击中(通过一个随机值来产生数值判断是否击中在ctor中实现)

未击中直接调用miss()退出。

如果击中则判断目标是否存在,因为也可能击中了但是对象已经不存在,多个攻击时候很容易出现这种情况,而且子弹还需要飞行,那么也调用miss()退出。

否则调用计算目标和子弹的举例是否小于子弹直径,如果小于直径则调用hit()退出。

其他情况下调用miss() 退出。

l BulletBase:hit()

子类可以覆盖之

l BulletBase:miss()

l 子类可以覆盖之

l BulletBase:isOver()

返回变量self.over_,用于其他判断。

CannonBullet

继承与BulletBase类。

l CannonBullet:ctor(source,delay,spriteName,params)

判断params参数是否存在,如果不存在则设置params的值如下:

params = {

flyTime = math.random(70,85) / 100,

g = -1000,

delay= delay or 0.2,

}

如果没有输入spriteName,则使用CannonBall01.png图片。

最后调用父类的构造函数,见BulletBase的构造函数。

l CannonBullet:fireBegan()

调用父节点的fireBegan(),然后设置子弹可见。

l CannonBullet:hit()

击中对象后调用,该函数在父节点没有实现,通过子类覆盖。

获取帧图片,图片长度,播放间隔,然后创建动画。最后在子弹的父类中播放。

local parent = self.sprite_:getParent()

parent:addChild(boom,self.sprite_:getLocalZOrder())

CurvedBulletBase

继承与BulletBase类。

l CurvedBulletBase:ctor(source,params

调用父节点的构造函数。

l CurvedBulletBase:fireBegan()

调用父节点的firebegin().

如果目标正在移动,那么目标的坐标需要变成子弹飞行时间后目标移动后的位置。

通过目标的直径计算导弹落到目标的随机位置偏移。然后根据飞行时间计算X和Y方向的距离除以时间。最后设置子弹位置。

l CurvedBulletBase:tickBullet(dt)

覆盖父类,父类也没有实现该函数。

计算运行的事件,计算实时的X,Y坐标,并设置子弹位置。判断是否旋转,如果是则计算角度,然后设置子弹的角度。

最后判断运行时间是否结束,如果结束则返回self.over_=true,表示结束,用于其他判断调用。

Map文件夹

该文件中定义的是2个地图的数据信息。

1.MapA0001Data.lua

地图的长、宽,imagename,路径1和路径2的定义,范围,定义多个对象的特性,

最后返回这些数据信息。

2.MapA0001Events.lua

继承于类MapEventHandler,该类在app.map.MapEventHandler文件中定义。

--重写父类preparePlay函数,time,objectEnterRange函数。

function MyMapEventHandler:preparePlay()

MyMapEventHandler.super.preparePlay(self)

self.createNextEnemyDelay_= 0.1 -- 等待多少时间创建下一个敌人

self.createNextEnemyInterval_ = 3.0 -- 创建下一个敌人前的间隔时间

self.createNextEnemyOnPathIndex_ = 2 -- 下一个敌人在哪一条路径

end

3.MapA0002Data.lua

逻辑上同MapA0001Data.lua。

具体实现存在个体差异。

4.MapA0002Events.lua

逻辑上同MapA0001Events.lua。

具体实现存在个体差异。

1.代码执行流程

先从main函数中之下如下

display.replaceScene(require("editor.EditorScene").new())

进入到场景editor .EditorScene

包含地图的整个视图,用于接收触摸事件,显示编辑的UI,创建地图对象。

创建工具栏,创建工具栏的视图,创建对象信息面板,创建地图名称文字标签,注册工具栏事件,创建运行地图时的工具栏,最后根据不同的平台调用editMap或者playMap。

2.相关函数

2.1Pcall函数

Calls function f with thegiven arguments in protected mode.

This means that any error inside f is notpropagated; instead, pcallcatches the error and returns a status code. Its first result is the statuscode (a boolean),which is true if the call succeeds without errors. In suchcase,pcallalso returns all results from the call,after this first result. In case of anyerror,pcallreturns false plus the error message.

Parameters

·f : functionto be call in protected mode.

·... : functionarguments.

Return values

1.#boolean: true plusthe result of ffunction if its call succeeds without errors.

2.#boolean,#string:false plus the error message in case of any error.

2.2Unpack

Returns theelements from the given table.

This function is equivalent to

return list[i],list[i+1],...,list[j]

except that the above code can bewritten only for a fixed number of elements. By default,i is 1 and j is thelength of the list,as defined by the length operator.

Parameters

·#table list : a tableby index

·i : index offirst value.

· j :index of last value.

2.3LUA string使用

·--string.len(s)
--返回字符串s的长度

·--string.rep(s,n)
--返回重复n次字符串s的串,你使用string.rep("a",2^20)可以创建一个1M bytes的字符串(比如,为了测试需要);

·--string.lower(s)
--将s中的大写字母转换成小写(string.upper将小写转换成大写).如果你想不关心大小写对一个数组进行排序的话,你可以这样:

·--string.upper(s)
--将s中的小写字母转换成大写

·--string.sub(s,i,j)
--函数截取字符串s的从第i个字符到第j个字符之间的串.Lua中,字符串的第一个字符索引从1开始.你也可以使用负索引,负索引从字符串的结尾向前计数:-1指向最后一个字符,-2指向倒数第二个,以此类推.

·-string.char函数和string.byte函数用来将字符在字符和数字之间转换.

·--string.byte(s,i)将字符串s的第i个字符的转换成整数;第二个参数是可选的,缺省情况下i=1.

·--string.format()函数来生成具有特定格式的字符串,

·--string.gsub(s,pattern,reps[,limitNumber]) 将s中所有符合pattern的字串替换为reps,返回结果串+匹配数

·--string.gfind(s,pattern)
--返回一个迭代器,迭代器每执行一次,返回下一个匹配串;

·--string.match(s,d) --与string.find类似 但是返回匹配的子串 --s 源字符串 --d 目标字符串或者模式

quick-cocos2d-x 学习系列之十六 塔防完结的更多相关文章

  1. ios – 仅在异步函数完成执行后运行代码

    所以,例如:如果问题是你不知道要调用什么函数,你可以配置你周围的函数/对象,这样有人可以给你一个函数,然后你在我上面说“调用函数”的地方调用你的函数.例如:

  2. ios – 如何使用Objective C类中的多个参数调用Swift函数?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  3. ios – 如何使用string中的参数创建Selector

    我正在使用Swift3.1和Xcode8.3.3编写程序.我想创建一个类,负责在键盘出现和消失时移动整个视图.但是我在使用字符串参数创建自定义选择器时遇到了困难.要显示或隐藏键盘我们需要功能:我正在尝试创建一个这样的选择器:它正在编译,但是当键盘出现时,它会崩溃.因为它是独立的类我不能使用这种结构:因为它将Swift函数转换为Objective-C函数.所以问题是:如何用参数字符串创建一个Selector表单?

  4. iOS 7,用于断开调用的私有API CTCallDisconnect不起作用

    谢谢!

  5. ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数

    除非属性本身被声明为nonnull:

  6. ios – 监控CBPeripheral状态变化

    我在CoreBluetooth库中找不到任何暴露的东西,我想在CBperipheralstate发生变化时调用一个函数.现在我只有一个switch语句来检查外设状态,但它总是只返回连接或断开连接.我如何进入连接/断开连接的情况?

  7. ios – 如何为NSNotification编写单元测试

    我在swift工作,我想刷新一个页面,所以我使用通知发送它,我在一个ViewController中发布通知并在另一个中添加观察者,它工作正常.我想要做的是在swift中添加单元测试.我查了很多网站但是没能做到.我是新手,不知道从哪里开始.基本上工作是,当我点击按钮通知被发布时,并且当加载下一个视图控制器时,添加通知观察者.我该怎么做单元测试提前致谢编辑:码并添加观察者解决方法一般的解决方案是:使用

  8. iOS 6 javascript与object.defineProperty的间歇性问题

    当访问使用较新的Object.defineProperty语法定义属性的对象的属性时,有没有其他人注意到新iOS6javascript引擎中的间歇性错误/问题?https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty我正在看到javascript失败的情况,说

  9. ios – NSNotificationCenter多次呼叫

    我在我的应用程序中实现了NSNotificationCenter.我在完成图像解码时发送通知.第一次图像解码将完成8次.所以通知假设发送8次.但它调用64次(8*8).这是我的代码我是如何实现的–>//初始化//调用方法//解除分配//发布通知有人可以建议我做错了.提前致谢.//调用方法是这样的(调用8次)解决方法解:我重新检查了我的代码,initWithFrame:(CGRect)框架调用了8次

  10. ios – Xcode游乐场不执行功能

    我创建了一个新的游乐场,我添加了简单的功能,但该功能从未被调用过:你们中的任何人都知道为什么函数没有被调用?我真的很感谢你的帮助解决方法因为你没有调用该函数.只需称呼它:

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部