使用 Cosos2dX-Lua 制作一个横版过关游戏 (2)

之前已经实现了在场景上添加英雄,并使英雄播放待机动作,接下来让英雄在场景动起来

本游戏的代码已开源,包含游戏资源
git地址
https://github.com/dreamfairy/PrompaLua

首先我们创建用户控制层 HudLayer.lua 包位置为 scenes.layers.HudLayer.lua

HudLayer.lua 的内容为

local HudLayer  = class("HudLayer", function()
    return display.newLayer()
end)

local DPad
function HudLayer:ctor()

end

function HudLayer:getDPad()
    return DPad
end

return HudLayer

可以看到我们实现了一个 getDPad()方法,但是DPad目前还是nil, 接下来开始创建 DPad 用户操控面板
创建 SimpleDPad.lua 包位置为 scenes.Controller.SimpleDPad.lua


SimpleDPad 内容:

local SimpleDPad  = class("SimpleDPad", function()
    return display.newSprite("pd_dpad.png")
end)

local Radius
local Direction
local IsHeld
local Delegate

function SimpleDPad:ctor()
    local updateFunc = function(dt) self:onUpdate(dt) end
    IsHeld = false
    Direction = CCPointZero
    self:scheduleUpdate(updateFunc)
    self:setNodeEventEnabled(true)
   
    self.touchLayer = display.newLayer()
    self:addChild(self.touchLayer)
end

function SimpleDPad:updateDirectionForTouchLocation(location)
    local radians = ccpToAngle(ccpSub(location,ccp(self:getPositionX(),self:getPositionY())))
    local degrees = -1 * math.deg(radians)
   
    if degrees <= 22.5 and degrees >= -22.5 then
        --right
        Direction = ccp(1.0,0.0)
    elseif degrees > 22.5 and degrees < 67.5 then
        --bottom right
        Direction = ccp(1.0,-1.0)
     elseif degrees >= 67.5 and degrees <= 112.5 then
        --bottom
        Direction = ccp(0.0,-1.0)
    elseif degrees  > 112.5 and degrees < 157.5 then
        --bottom left
        Direction = ccp(-1.0,-1.0)
    elseif degrees >= 157.5 or degrees <= -157.5 then
        --left
        Direction = ccp(-1.0,0.0)
    elseif degrees < -22.5 and degrees > -67.5 then
        --top right
        Direction = ccp(1.0,1.0)
    elseif degrees <= -67.5 and degrees >= -112.5 then
        --top
        Direction = ccp(0.0,1.0)
    elseif degrees < -112.5 and  degrees > -157.5 then
        --top left
        Direction = ccp(-1.0,1.0)
    end
   
    Delegate:didChangeDirectionTo(self,Direction)
end

function SimpleDPad:onEnter()
    self.touchLayer:addTouchEventListener(function(event,x,y)
    return self:onTouch(event,x,y)
    end)
    self.touchLayer:setTouchEnabled(true)
end

function SimpleDPad:onExit()
    self.touchLayer:removeTouchEventListener()
    self:setTouchEnabled(false)
end

function SimpleDPad:onUpdate(dt)
    --CCLuaLog(dt)
    if IsHeld == true then
        Delegate:isHoldingDirection(self,Direction)
        end
end

function SimpleDPad:setRadius(value)
    Radius = value;
end

function SimpleDPad:setDelegate(value)
    Delegate = value
end

function SimpleDPad:onTouch(event,x,y)
    local location = ccp(x,y)
    if event == "began" then
        local distanceSQ = ccpDistanceSQ(location, ccp(self:getPositionX(),self:getPositionY()))
        if distanceSQ <= Radius * Radius then
            self:updateDirectionForTouchLocation(location)
            IsHeld = true
            return true
            end
        return false
    end
   
    if event == "moved" then
        self:updateDirectionForTouchLocation(location)
    end
   
    if event == "ended" then
        location = CCPointZero
        IsHeld = false
        Delegate:simpleDPadTouchEnded(self)
    end
end

return SimpleDPad

使用 display.newSprite(“pd_dpad.png”) 8方向键作为用户的操作面板
self:setNodeEventEnabled(true) 开启节点事件,只有开启该事件 onEnter 和 onExit函数才会被调用,我们需要在 onEnter 函数中添加触摸事件监听,并在 onExit中移除它
self.touchLayer = display.newLayer() 建立一个 touch 层,用来接收触摸事件
self:addChild(self.touchLayer)

在编写的时候,Delegate 是在 setDelegate 函数调用后初始化的,Delegate 实际上市一个 接口,任何实现该接口的类都可以被set进来
现在来编写 Delegate 接口,一共有3个函数和1个继承方法

创建 SimpleDPadDelegate.lua 包位置 scenes.Controller.SimpleDPadDelegate.lua
SimpleDPadDelegate 的内容如下

local SimleDpadDelegate = {}

function SimleDpadDelegate:extend()
    local o = {}
    setmetatable(o,self)
    self.__index = self
    return o
end

function SimleDpadDelegate:didChangeDirectionTo(SimpleDPad,Direction)
    CCLuaLog("This function muse be written")
end

function SimleDpadDelegate:isHoldingDirection(SimpleDPad,Direction)
    CCLuaLog("This function muse be written")
end

function SimleDpadDelegate:simpleDPadTouchEnded(SimpleDPad, Direction)
    CCLuaLog("This function muse be written")
end

return SimleDpadDelegate

好了,现在有Delegate 接口了,我们让 GameLayer 来实现它,并在GameLayer上实现操控英雄的逻辑

GamLayer.lua 中添加一个变量

local Delegate = require("scenes.Controller.SimpleDPadDelegate"):extend()

Delegate 继承了 SimpleDPadDelegate中的方法,之后要在GameLayer中具体实现
继续实现3个方法

function Delegate:didChangeDirectionTo(SimpleDPad,Direction)
    Hero:walkWithDirection(Direction)
end

function Delegate:isHoldingDirection(SimpleDPad,Direction)
    Hero:walkWithDirection(Direction)
end

function Delegate:simpleDPadTouchEnded(SimpleDPad, Direction)
    if Hero:getActionState() == ACTION_STATE_WALK then
        Hero:idle()
    end
end

操作的逻辑部分基本完成,现在将它们组装起来
在HudLayer.lua 的ctor()中添加下列代码

function HudLayer:ctor()
    DPad = require("scenes.Controller.SimpleDPad").new()
    DPad:setRadius(64)
    DPad:setPosition(64,64)
    DPad:setOpacity(100)
    self:addChild(DPad)
end

在 GameScene 中添加HudLayer,并将 GameLayer 设置为Delegate

GameScene.lua 现在完整代码如下

require("config")

local GameScene  = class("GameScene", function()
    return display.newScene("GameScene")
end)

local GameLayer = require("scenes.layers.GameLayer").new()
local HudLayer = require("scenes.layers.HudLayer").new()

function GameScene:ctor()
    self:addChild(GameLayer)
    self:addChild(HudLayer)
   
    local DPad =  HudLayer:getDPad()
    DPad:setDelegate(GameLayer:getClass())
end

到此为止,你已经可以使用你的控制器,控制英雄行走了
<img src="http://www.dreamfairy.cn/blog/wp-content/uploads/2013/10/p3.jpg" alt="p3" width="486" height="368" class="aligncenter size-full wp-image-1576" />
return GameScene

下一节将添加上怪物们,以及让它们可以被攻击

发表评论

电子邮件地址不会被公开。 必填项已用*标注