美文网首页
CocosLua3.10 塔防类(提供思路)

CocosLua3.10 塔防类(提供思路)

作者: 叫我29就好啦 | 来源:发表于2019-11-27 17:34 被阅读0次

    参考文章:https://www.cnblogs.com/hll2008/p/4235714.html
    参考文章:https://blog.csdn.net/oShunz '王国保卫战'相关内容

    注:没有ui,纯用layout写,比较劣质。只提供思路和写法。

    思路:


    Mind.png

    #怪物
    1.怪物沿着创建好的地图路径前进。

    #塔
    1.塔创建子弹,并且检测所有怪物,当遇到某个怪物在自己的检测,攻击范围内,则执行攻击子弹操作。
    2.当子弹创建完毕并发射的时候,执行检测子弹周边。当遇到怪物的话,执行怪物掉血等操作(这里就只做了掉血)。
    3.移除子弹

    #道路
    1.默认地图创建,建立起始点,然后根据上下左右(1像素)与偏移值进行添加道路。
    2.建立可点击的区块。并且当选择要创建的塔时,广播创建塔操作。

    目前完善功能:

    (塔):可攻击,可点击创建
    (怪物):可移动,只可代码内创建
    (地图):只有一张地图,直接就执行。地图路径在代码里面写入。

    概括:
    [[由一个大层(控制层),去加载次类层。由控制层去转发内容等操作。然后次类层在自己执行自己需要的操作。]]
    #1 控制层:用于转发各层内容,数据,加载各层内容等。
    #2 地图层:道路的总集合。创建地图,创建怪物行走路径,创建可点击的创建塔的区域。
    #2 建筑层:塔的总集合。创建塔。
    #2 怪物层: 怪物的总集合。创建怪物。

    代码:(文件路径我用的本地的,注意更改):

     -- 全局
    -- Interval = 70  -- 间隔
    -- Road_Size = cc.size(60, 60)  -- 区域大小
    
    Event_Create_Protecter = 'Event_Create_Protecter'
    
    -- 控制层
    require('app.testFile.event.Key_3_Event_File.Global.GlobalData')
    local MapRoadLayer = require('app.testFile.event.Key_3_Event_File.Layer.MapRoadLayer')  -- 地图道路层
    local MonsterLayer = require('app.testFile.event.Key_3_Event_File.Layer.MonsterLayer')
    local ProtecterLayer = require('app.testFile.event.Key_3_Event_File.Layer.ProtecterLayer')
    
    local event = class('event', cc.Node)
    
    function event:ctor()
        self:initValue()
        self:initNode()
        self:bindEvent()
    end
    
    function event:initValue()
        -- 层
        self._Layer_MapRoad = nil  -- 地图道路层
        self._Layer_Monster = nil  -- 怪物层
        self._Layer_Protecter = nil  -- 塔防层
    end
    
    function event:initNode()
        self:initLayer()
        self:initLayerRoad()
        self:initMonster()
    
        self:initProtecter()
    end
    
    -- 添加背景点击区域
    function event:initLayer()
        local layout = ccui.Layout:create()
        layout:setContentSize(cc.size(display.width,display.height))
        self:addChild(layout)
    
        local function onTouchBegan(touch, event)
            return true
        end
    
        local function onTouchEnded(touch, event)
            local pos = touch:getLocation()
            self:clickEvent(pos)
        end
    
        -- 注册两个回调监听方法
        local listener = cc.EventListenerTouchOneByOne:create()
        listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
        listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )
        local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
        -- 绑定触摸事件到层当中
        eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layout)
    end
    
    function event:initLayerRoad()
        self._Layer_MapRoad = MapRoadLayer:create(self)
        self:addChild(self._Layer_MapRoad)
        self._Layer_MapRoad:createRoads()
    end
    
    function event:initMonster()
        self._Layer_Monster = MonsterLayer:create(self)
        self:addChild(self._Layer_Monster)
        self._Layer_Monster:createMonsters()
    end
    
    function event:initProtecter()
        self._Layer_Protecter = ProtecterLayer:create(self)
        self:addChild(self._Layer_Protecter)
        self._Layer_Protecter:createProtecters()    
    end
    
    function event:clickEvent(pos)
        self._Layer_Protecter:resetAllProtecterScopeCircle()
    
        self._Layer_MapRoad:createClickNode(pos)
    end
    
    function event:getProtecter()
        return self._Layer_Protecter
    end
    
    function event:getMonster()
        return self._Layer_Monster
    end
    
    function event:getRoads()
        return self._Layer_MapRoad
    end
    
    function event:getAllProtecter()
        return self._Layer_Protecter:getAllProtecter()
    end
    
    function event:getAllMonster()
        return self._Layer_Monster:getAllMonster()
    end
    
    function event:getAllRoads()
        return self._Layer_MapRoad:getAllRoads()
    end
    
    function event:bindEvent()
        -- enter exit事件
        local function onNodeEvent(event)
            if event == "enter" then
                self:onEnter()
            elseif event == "exit" then
                self:onExit()
            end
        end
        self:registerScriptHandler(onNodeEvent)
    end
    
    function event:onEnter()
    
    end
    
    function event:onExit()
        
    end
    
    return event
    
    -- 地图层
    --[[
        第一个方块是0,0
    ]]
    
    local Start_Pos = cc.p(100, 100)  --起始坐标
    local _A = cc.p(-1, 0)
    local _D = cc.p(1, 0)
    local _W = cc.p(0, 1)
    local _S = cc.p(0, -1)
    
    -- 道路
    local Map = {
        _D,_D,_D,_D,
        _W,_W,_W,
        _D,_D,
        _S,_S,
        _D,
        _S,
        _D,_D,
        _W,_W,_W,_W,_W,
        _A,_A,_A,_A,_A,_A,_A,
        _S,_S,
        _A,_A,
        _W,_W,_W,_W,
        _D,_D,_D,_D,_D,_D,_D,_D,_D,_D,_D,
    }
    
    local Interval = 70  -- 形块间隔
    local Road_Size = cc.size(60, 60)  -- 形块大小
    
    local Road = require('app.testFile.event.Key_3_Event_File.Node.Road')
    
    local MapRoad = class('MapRoad', cc.Node)
    function MapRoad:ctor(data, pos)
        self:initValue()
    end
    
    function MapRoad:initValue()
        self._roads = {}
        self._roadsTable = {}
        self._clickRoads = nil
    end
    
    function MapRoad:createRoads()
        if #Map > 0 then
            self:createRoadNode(0, 0)
    
            -- 先转换一下
            local tempMap = {}
            local x, y = 0, 0
            for i, v in ipairs(Map) do
                x = x + v.x
                y = y + v.y
                tempMap[i] = cc.p(x, y)
            end
    
            for i, v in ipairs(tempMap) do
                self:createRoadNode(v.x, v.y)
            end
        end
    end
    
    -- 创建道路方块
    function MapRoad:createRoadNode(x, y)
        local data = {
            Color = cc.c3b(50, 50, 50),
            Pos = cc.p(x, y),
        }
    
        local node = Road:create(data)
        self:addChild(node)
        node:createRoadNode()
        table.insert(self._roads, node)
        self:setRoadTable(x, y)
    end
    
    -- 创建可点击方块
    function MapRoad:createClickNode(pos)
        local x = math.floor(pos.x / Interval) - 1
        local y = math.floor(pos.y / Interval) - 1
    
        if self:getIsUseInRoadTable(x, y) then
            if self._clickRoads then
                self._clickRoads:setVisible(false)
                self:removeInRoadTable(x, y)
            end
    
            return
        end
    
        if not self._clickRoads then
            local data = {
                Color = cc.c3b(255, 255, 255),
                Pos = cc.p(x, y),
            }
    
            self._clickRoads = Road:create(data)
            self:addChild(self._clickRoads)
            self._clickRoads:createClickNode()
            self._clickRoads:setVisible(false)
        end
    
        self._clickRoads:setVisible(true)
        self._clickRoads:resetPosition(x, y)
        self._clickRoads:doShowChoose()
        self:setRoadTable(x, y)
    end
    
    -- 将当前xy保存到表内(标记这里已被占用)
    function MapRoad:setRoadTable(x, y)
        local str = string.format('%s_%s', x, y)
        self._roadsTable[str] = true
    end
    
    function MapRoad:getIsUseInRoadTable(x, y)
        local str = string.format('%s_%s', x, y)
        return self._roadsTable[str] or false
    end
    
    function MapRoad:removeInRoadTable(x, y)
        local str = string.format('%s_%s', x, y)
        self._roadsTable[str] = nil
    end
    
    function MapRoad:getAllRoads()
        return self._roads
    end
    
    function MapRoad:getStartPos()
        return Start_Pos
    end
    
    return MapRoad
    
    -- 怪物层
    --[[
        data = {Blood = (血量), Speed = (移动速度), CircleRadius = (偏移值,半径圆,怪物的宽高一半)}
    ]]
    
    local MonsterNode = require('app.testFile.event.Key_3_Event_File.Node.Monster')
    local Start_Pos = cc.p(100, 100)
    
    local MonsterTable = {
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},
        {Blood = 200, Speed = 1, CircleRadius = 20},    
        {Blood = 200, Speed = 1, CircleRadius = 40},            
    }
    
    local Free_Time = 0
    local Monster_Create_Interval = 1  -- 间隔几秒创建小怪兽
    
    local Monster = class('Monster', cc.Node)
    
    function Monster:ctor(_Main)
        self._Main = _Main
        self:initValue()
    end
    
    function Monster:initValue()
        self._monster = {}
        self._createMonsterSchedule = nil
    end
    
    function Monster:createMonsters()
        local idx = 0
    
        local function callfunc()
            idx = idx + 1
            if MonsterTable[idx] then
                local monster = MonsterNode:create(MonsterTable[idx])
                self:addChild(monster)
                table.insert(self._monster, monster)
                monster:resetPosition(Start_Pos)
                monster:runMove()
            else
                if self._createMonsterSchedule then
                    self:stopAction(self._createMonsterSchedule)
                    self._createMonsterSchedule = nil
                end
            end
        end
    
        local delayFree_Time = cc.DelayTime:create(Free_Time)
        local function afterFree_Time()
            self._createMonsterSchedule = schedule(self, callfunc, Monster_Create_Interval)
        end
    
        local seq = cc.Sequence:create(delayFree_Time, cc.CallFunc:create(afterFree_Time))
        self:runAction(seq)
    end
    
    function Monster:getAllMonster()
        return self._monster
    end
    
    function Monster:getDelegate()
        return self._Main
    end
    
    function Monster:getMonsterStartPos()
        return Start_Pos
    end
    
    return Monster
    
    -- 塔(保卫层)
    local Interval = 70
    
    local Time_Check_Monster = 0.2
    local Start_Pos = cc.p(100, 100)
    
    local testProtecter1 = {Blood = 1, Speed = 1, CircleRadius = 30, Scope = 3}
    local testProtecter2 = {Blood = 1, Speed = 1, CircleRadius = 30, Scope = 3}
    local testProtecter3 = {Blood = 1, Speed = 1, CircleRadius = 30, Scope = 3}
    
    local ProtecterNode = require('app.testFile.event.Key_3_Event_File.Node.Protecter')
    local Bullet = require('app.testFile.event.Key_3_Event_File.Node.Bullet')
    
    local Protecter = class('Protecter', cc.Node)
    
    --[[
        data = {Blood = (血量), Speed = (射击速度), CircleRadius = (偏移值,半径圆,塔的宽高一半), Scope = 1(以自己为中心,半径为Scopr画圆)}
    ]]
    function Protecter:ctor(_Main, data)
        self._Main = _Main
        self._ProtecterData = data
        self:initValue()
        self:bindEvent()
    end
    
    function Protecter:initValue()
        self._protecter = {}
    end
    
    function Protecter:createProtecters()
        self:createProtecterNode(testProtecter1, 6, 0)
        self:createProtecterNode(testProtecter2, 4, 6)
        self:createProtecterNode(testProtecter3, 8, 4)
    end
    
    function Protecter:createProtecterNode(data, x, y)
        local protecter = ProtecterNode:create(data)
        self:addChild(protecter)
        protecter:resetPosition(x, y)
        table.insert(self._protecter, protecter)
        protecter:startCheckMonster(self:getDelegate():getAllMonster())
    end
    
    function Protecter:resetAllProtecterScopeCircle()
        if not self._protecter or #self._protecter <= 0 then
            return
        end
    
        for i, v in ipairs(self._protecter) do
            if v.setScopeCircle then
                v:setScopeCircle(true)
            end
        end
    end
    
    function Protecter:getDelegate()
        return self._Main
    end
    
    function Protecter:getAllProtecter()
        return self._protecter
    end
    
    function Protecter:bindEvent()
        self:bindCreateProtecter()
    end
    
    function Protecter:bindCreateProtecter()
        local function fun(event)
            if not event or not event.data then
                return
            end
    
            self:createProtecterNode(event.data, event.data.Pos.x, event.data.Pos.y)
        end
    
        local listener = cc.EventListenerCustom:create(Event_Create_Protecter, fun)
        cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)
    end
    
    function Protecter:getProtecterStartPos()
        return Start_Pos
    end
    
    return Protecter
    
    -- 单个道路
    --[[
        data:
            Color = (颜色),
            Pos = (位置),
    ]]
    
    local Interval = 70  -- 形块间隔
    local Road_Size = cc.size(60, 60)  -- 形块大小
    local Road_Size_Mid = cc.size(54, 54)
    
    local Road = class('Road', cc.Node)
    function Road:ctor(data)
        self._data = data
        self:initValue()
    end
    
    function Road:initValue()
        self._Color = self._data.Color or cc.c3b(250, 250, 250)
        self._Pos = self._data.Pos or cc.p(1, 1)
    
        self._clickTable = {}
    end
    
    -- 创建道路Node
    function Road:createRoadNode()
        self:createNode()
    end
    
    -- 创建可点击Node(可选择建筑的)
    function Road:createClickNode()
        self:createNode()
        self:createNode(true)
        self:showClickEvent()
    end
    
    function Road:createNode(isMid)
        local x, y = self._Pos.x, self._Pos.y
        local layout = ccui.Layout:create()
        layout:setAnchorPoint(cc.p(0.5, 0.5))
        layout:setContentSize(isMid and Road_Size_Mid or Road_Size)
        layout:setBackGroundColorType(ccui.LayoutBackGroundColorType.solid) --设置颜色
        layout:setBackGroundColor(isMid and cc.c3b(0, 0, 0) or self._Color)
        self:addChild(layout)
        self:resetPosition(x, y)
    end
    
    function Road:resetPosition(x, y)
        self._Pos = cc.p(x, y)
        local startPos = self:getStartPos()
        self:setPositionX(Interval * self._Pos.x + startPos.x)
        self:setPositionY(Interval * self._Pos.y + startPos.y)
    end
    
    function Road:showClickEvent()
        local temp = {
            {Color = cc.c3b(255, 0, 0)},
            {Color = cc.c3b(0, 255, 0)},
            {Color = cc.c3b(0, 0, 255)},
        }
    
        for i, v in ipairs(temp) do
            local layout = ccui.Layout:create()
            layout:setAnchorPoint(cc.p(0.5, 0))
            layout:setContentSize(cc.size(20, 20))
            layout:setPosition(cc.p((i - (#temp+1)/2) * Road_Size.width/2, Road_Size.height/2 + 5))
            layout:setBackGroundColorType(ccui.LayoutBackGroundColorType.solid) --设置颜色
            layout:setBackGroundColor(v.Color)
            layout:setTouchEnabled(true)
            layout:setScale(0)
            self:addChild(layout)
            table.insert(self._clickTable, layout)
    
            local function clickEvent(sender, eventType)
                if eventType == ccui.TouchEventType.ended then
                    local data = {Color = layout:getBackGroundColor(), }
                    self:dispatchCreateProtecter(data)
                end
            end
            
            layout:addTouchEventListener(clickEvent)  
        end
    
        self:doShowChoose()
    end
    
    function Road:doShowChoose()
        for i, v in ipairs(self._clickTable) do
            v:setScale(0)
            local scale1 = cc.ScaleTo:create(0.1, 1.2)
            local scale2 = cc.ScaleTo:create(0.05, 1)
            local seq = cc.Sequence:create(scale1, scale2)
            v:runAction(seq)
        end
    end
    
    function Road:getStartPos()
        return self:getParent():getStartPos()
    end
    
    function Road:dispatchCreateProtecter(_data)
        local event = cc.EventCustom:new(Event_Create_Protecter)
        local data = {Blood = 1, Speed = 1, CircleRadius = 30, Scope = 3, Pos = self._Pos, Color = _data.Color, }
        event.data = data
    
        cc.Director:getInstance():getEventDispatcher():dispatchEvent(event)
        self:setVisible(false)
    end
    
    return Road
    
    -- 单个怪物
    --[[
        data = {Blood = (血量), Speed = (移动速度), CircleRadius = (偏移值,半径圆,怪物的宽高一半)}
    ]]
    
    local Monster = class('Monster', cc.Node)
    
    function Monster:ctor(data)
        self._MonsterData = data
        self:initValue()
        self:createMonster()
        self:createBlood()
    end
    
    function Monster:initValue()
        self._monsterNode = nil
        self._bloodBg = nil
        self._Blood = self._MonsterData.Blood or 1  -- 总血量
        self._Speed = self._MonsterData.Speed or 1
        self._CircleRadius = self._MonsterData.CircleRadius or 20
        self._currentBlood = self._MonsterData.Blood or 1  -- 当前血量
    end
    
    function Monster:createMonster()
        local color = cc.c3b(math.random(1, 255), math.random(1, 255), math.random(1, 255))
        self._monsterNode = ccui.Layout:create()
        self._monsterNode:setAnchorPoint(cc.p(0.5, 0.5))
        self._monsterNode:setContentSize(cc.size(self._CircleRadius * 2, self._CircleRadius * 2))
        self._monsterNode:setBackGroundColorType(ccui.LayoutBackGroundColorType.solid) --设置颜色
        self._monsterNode:setBackGroundColor(color)
        self:addChild(self._monsterNode)
    end
    
    function Monster:createBlood()
        self._bloodBg = ccui.Layout:create()
        self._bloodBg:setAnchorPoint(cc.p(0.5, 0))
        self._bloodBg:setContentSize(cc.size(self._CircleRadius * 2, 8))
        self._bloodBg:setBackGroundColorType(ccui.LayoutBackGroundColorType.solid) --设置颜色
        self._bloodBg:setBackGroundColor(cc.c3b(255, 255, 255))
        self._bloodBg:setBackGroundColorOpacity(150)
        self._bloodBg:setPosition(cc.p(0, self._monsterNode:getContentSize().height / 2 + 5))
        self:addChild(self._bloodBg)
    
        self._bloodNode = ccui.Layout:create()
        self._bloodNode:setAnchorPoint(cc.p(0, 0.5))
        self._bloodNode:setContentSize(cc.size(self._CircleRadius * 2, 8))
        self._bloodNode:setBackGroundColorType(ccui.LayoutBackGroundColorType.solid) --设置颜色
        self._bloodNode:setBackGroundColor(cc.c3b(255, 0, 0))
        self._bloodNode:setPosition(cc.p(0, self._bloodBg:getContentSize().height / 2))
        self._bloodBg:addChild(self._bloodNode)
    end
    
    function Monster:runMove()
        local roadTable = self:getParent():getDelegate():getAllRoads()
        local idx = 1
    
        local function run()
            idx = idx + 1
    
            local roadPos = cc.p(roadTable[idx]:getPositionX(), roadTable[idx]:getPositionY())
            local move = cc.MoveTo:create(self:getMoveSpeed(), roadPos)
            local callfunc = cc.CallFunc:create(function()
                if idx == #roadTable then
                    self:showEnd()
                else
                    run()
                end
            end)
    
            local seq = cc.Sequence:create(move, callfunc)
            self:runAction(seq)
        end
    
        if #roadTable > 0 then
            run()
        end
    end
    
    function Monster:showEnd()
        print('end...')
    end
    
    function Monster:getSpeed()
        return self._Speed
    end
    
    function Monster:getMoveSpeed()
        return 1 - self._Speed * 0.1
    end
    
    function Monster:dropBlood(_damage)
        self._currentBlood = self._currentBlood - _damage
        if self._currentBlood <= 0 then
            self:removeFromParent()
        else
            self:setBlood()     
        end
    end
    
    -- 偏移值
    function Monster:getCircleRadius()
        return self._CircleRadius
    end
    
    function Monster:setBlood()
        self._bloodNode:setContentSize(cc.size((self._CircleRadius * 2) * (self._currentBlood / self._Blood), 8))
    end
    
    function Monster:resetPosition()
        self:setPosition(self:getParent():getMonsterStartPos())
    end
    
    return Monster
    
    -- 单个塔
    local Interval = 70
    
    local ZOrder_Protexter = 5
    local ZOrder_Circle = 1
    local Zorder_Bullet = 6
    
    local Time_Check_Monster = 0.2
    
    local Protecter = class('Protecter', cc.Node)
    local Bullet = require('app.testFile.event.Key_3_Event_File.Node.Bullet')
    
    --[[
        data = {Blood = (血量), 
        Speed = (射击速度), 
        CircleRadius = (偏移值,半径圆,塔的宽高一半), 
        Scope = 1(以自己为中心,半径为Scopr画圆), 
        Pos = (位置),可不传,暂时没用,
        Color = (颜色,不传则为默认颜色(随机色))
    ]]
    
    function Protecter:ctor(data, pos)
        self._ProtecterData = data
        self:initValue()
        self:createProtecter()
        self:createScopeCircle()
        self:bindEvent()
    
        -- 测试,打开检测区域
        -- self:setScopeCircle()
    end
    
    function Protecter:initValue()
        self.ui = nil
        self._scopeCircle = nil
        self._isShowScopeCircle = false
    
        self._Blood = self._ProtecterData.Blood or 1
        self._Speed = self._ProtecterData.Speed or 1
        self._CircleRadius = self._ProtecterData.CircleRadius or 30
        self._Scope = self._ProtecterData.Scope or 1
        self._Pos = self._ProtecterData.Pos
        self._Color = self._ProtecterData.Color
    end
    
    function Protecter:createProtecter()
        local color = self._Color or cc.c3b(math.random(1, 255), math.random(1, 255), math.random(1, 255))
        local layout = ccui.Layout:create()
        layout:setAnchorPoint(cc.p(0.5, 0.5))
        layout:setContentSize(cc.size(self._CircleRadius * 2, self._CircleRadius * 2))
        layout:setBackGroundColorType(ccui.LayoutBackGroundColorType.solid) --设置颜色
        layout:setBackGroundColor(color)
        layout:setTouchEnabled(true)
        layout:setLocalZOrder(ZOrder_Protexter)
        self:addChild(layout)
    
        self.ui = layout
    end
    
    function Protecter:createScopeCircle()
        self._scopeCircle = cc.DrawNode:create()
        self._scopeCircle:drawDot(cc.p(0, 0), self:getScope() * Interval, cc.c4b(150, 150, 150, 0.5))
        self._scopeCircle:setLocalZOrder(ZOrder_Circle)
        self:addChild( self._scopeCircle)
        self._scopeCircle:setScale(0)
        self._scopeCircle:setOpacity(0)
        -- self._scopeCircle:setVisible(false)
    end
    
    -- 如果没传isHide,则由当前的self._isShowScopeCircle来做决定
    function Protecter:setScopeCircle(isHide)
        local fade = cc.FadeTo:create(0.15, (isHide or self._isShowScopeCircle) and 0 or 1)
        local scale = cc.ScaleTo:create(0.15, (isHide or self._isShowScopeCircle) and 0 or 1)
        local spawn = cc.Spawn:create(fade, scale)
        self._scopeCircle:runAction(scale)
    
        if isHide then
            self._isShowScopeCircle = false
        else
            self._isShowScopeCircle = not self._isShowScopeCircle
        end
    end
    
    function Protecter:bindEvent()
        local function clickEvent(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                if self._scopeCircle then
                    self:setScopeCircle()
                end
            end
        end
            
        self.ui:addTouchEventListener(clickEvent)   
    end
    
    function Protecter:getNode()
        return self.ui
    end
    
    function Protecter:getScopeCircle()
        return self._scopeCircle
    end
    
    function Protecter:getScope()
        return self._Scope
    end
    
    function Protecter:startCheckMonster(_monsterData)
        local function callback()
            local isShould, monster = self:checkMonster(_monsterData)
            if isShould then
                self:shoot(monster, _monsterData)
            end
        end
    
        schedule(self, callback, Time_Check_Monster)
    end
    
    function Protecter:checkMonster(_monsterData)
        for i, v in ipairs(_monsterData) do
            if v and not tolua.isnull(v) then
                local monsterWorldPos = v:convertToWorldSpace(cc.p(0, 0))
                local protecterWorldPos = self:convertToWorldSpace(cc.p(0, 0))
                local distance = cc.pGetDistance(protecterWorldPos, monsterWorldPos) - v:getCircleRadius()
                if distance <= self._Scope * Interval then
                    return true, v
                end
            end
        end
    end
    
    function Protecter:shoot(_monster, _targetTable)
        if not _monster then
            return
        end
    
        if tolua.isnull(_monster) then
            return
        end
    
        local monsterWorldPos = _monster:convertToWorldSpace(cc.p(0, 0))
        local protecterWorldPos = self:getWorldPos()
        local distance = cc.pGetDistance(protecterWorldPos, monsterWorldPos)
    
        local bulletData = {
            Speed = self._Speed, 
            Damage = 1, 
            StartPos = protecterWorldPos, 
            EndPos = monsterWorldPos, 
            Distance = distance,
        }
    
        local bullet = Bullet:create(bulletData)
        bullet:setLocalZOrder(Zorder_Bullet)
        self:addChild(bullet)
        bullet:startShoot(_targetTable)
    end
    
    function Protecter:getWorldPos()
        return self:convertToWorldSpace(cc.p(0, 0))
    end
    
    -- 偏移值
    function Protecter:getCircleRadius()
        return self._CircleRadius
    end
    
    function Protecter:resetPosition(x, y)
        self:setPosition(self:getParent():getProtecterStartPos().x + x * Interval, self:getParent():getProtecterStartPos().y + y * Interval)
    end
    
    return Protecter
    
    -- 单个子弹
    --[[
        Speed(速度)
        Damage(伤害)
        StartPos(起始位置,世界坐标)
        EndPos(终点位置,世界坐标,这个只用于得到角度和移动方向)
        Distance(距离)
    ]]
    
    local Bullet_Radius = 10
    local Bullet_Color = cc.c4b(1, 0, 0, 1)
    local Time_Check_Is_Hit_The_Target = 1 / 60
    
    local Bullet = class('Bullet', cc.Node)
    
    function Bullet:ctor(data)
        self._data = data
        self:initValue()
        self:initNode()
    end
    
    function Bullet:initValue()
        self._bullet = nil
        self._Speed = self._data.Speed or 1
        self._Damage = self._data.Damage or 1
        self._StartPos = self._data.StartPos or cc.p(0, 0)
        self._EndPos = self._data.EndPos or cc.p(0, 0)
        self._Distance = self._data.Distance or 1
    end
    
    function Bullet:initNode()
        self._bullet = cc.DrawNode:create()
        self._bullet:drawDot(cc.p(0, 0), Bullet_Radius, Bullet_Color)
        self:addChild(self._bullet)
    end
    
    function Bullet:getMoveSpeed()
        return 1 - self._Speed * 0.1
    end
    
    function Bullet:startShoot(_targetTable)
        local localPos = self:convertToNodeSpace(cc.p(self._EndPos.x, self._EndPos.y))
        -- localPos = cc.p(localPos.x * 3, localPos.y * 3)  -- 沿线继续做处理
    
        local move = cc.MoveTo:create(self:getMoveSpeed() * self._Distance * 0.002, localPos)
        local callfunc = cc.CallFunc:create(function()
            self:removeFromParent()
        end)
    
        local seq = cc.Sequence:create(move, callfunc)
        self:runAction(seq)
    
        self:startCheckIsHitTheTarget(_targetTable)
    end
    
    function Bullet:startCheckIsHitTheTarget(_targetTable)
        local function callback()
            local targetTable = _targetTable or {}
            for i, v in ipairs(targetTable) do
                if v and not tolua.isnull(v) then
                    local targetWorldPos = v:convertToWorldSpace(cc.p(0, 0))
    
                    -- 检测目标与子弹碰撞,决定使用圆与圆(考虑之后可能改为小怪物,避免是长方形)
                    local flag = true
                    if v.getCircleRadius then
                        local targetRadius = v:getCircleRadius()
                        local bulletRadius = Bullet_Radius
                        local distance = cc.pGetDistance(self:getWorldPos(), targetWorldPos)
                        if distance <= targetRadius + bulletRadius then
                            v:dropBlood(self._Damage)
                            self:removeFromParent()
                        end
                    else
                        print('当前子弹检测的目标,没有配置getCircleRadius方法喔!!请注意')
                    end
    
                    -- 在判断点到框的位置
                end
            end
        end
    
        schedule(self, callback, Time_Check_Is_Hit_The_Target)
    end
    
    function Bullet:getWorldPos()
        return self:convertToWorldSpace(cc.p(0, 0))
    end
    
    return Bullet
    
    塔防类.png

    ε≡٩(๑>₃<)۶ 请大家多多评论一起讨论讨论

    相关文章

      网友评论

          本文标题:CocosLua3.10 塔防类(提供思路)

          本文链接:https://www.haomeiwen.com/subject/puxmwctx.html