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
这个是地图相关的入口。
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
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函数
--传入字符串和分隔符,返回分割后的table,classId此处是range,path,static这3种字符串。
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
输入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)
该函数的参数是"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)
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",
}
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()退出。
否则调用计算目标和子弹的举例是否小于子弹直径,如果小于直径则调用hit()退出。
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图片。
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, pcall
catches 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,pcall
also returns all results from the call,after this first result. In case of anyerror,pcall
returns false plus the error message.
Parameters
·f : functionto be call in protected mode.
·... : functionarguments.
Return values
1.#boolean: true plusthe result of f
function 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 目标字符串或者模式