探索小游戏(二):英雄骨骼动画和基本操作

有了地图之后,就可以添加英雄。设定英雄基本体力为100点,每走一步扣除5点,有上下左右四个方向,有障碍物的地方不能通过,有其他英雄的地方不能通过。

英雄的json数据:

{
    "data":[ { "id":1, "r":5, "c":6 }, { "id":2, "r":1, "c":1 }, { "id":3, "r":6, "c":1 } ] }

数据中id为英雄id,r表示英雄所在的地图行,c表示英雄所在的地图列。

英雄类:

local Hero = class('Hero',function () return cc.Node:create() 
end)

function Hero:ctor(id)
    self.id = id

    self.sp = ccs.Armature:create('qishi')
    self.sp:getAnimation():play('stand')
    self:addChild(self.sp)
    self.sp:setAnchorPoint(0.5,-0.2)

    if id == 1 then
        self.sp:getBone('pifeng'):changeDisplayWithName('qishi_pifeng (2).png',true)
    elseif id == 2 then
        self.sp:getBone('pifeng'):changeDisplayWithName('qishi_pifeng (5).png',true)
        self.sp:getBone('qizhi'):changeDisplayWithName('qishi_qizhi (3).png',true)
        self.sp:getBone('shengti'):changeDisplayWithName('qishi_dunpai2.png',true)
    elseif id == 3 then
        self.sp:getBone('pifeng'):changeDisplayWithName('qishi_pifeng (8).png',true)
        self.sp:getBone('qizhi'):changeDisplayWithName('qishi_qizhi (1).png',true)
        self.sp:getBone('shengti'):changeDisplayWithName('qishi_dunpai1.png',true)
    end

    self:setNodeSize(cc.size(96,96))
end

function Hero:playAnimation(name)
    self.sp:getAnimation():play(name)
end

function Hero:setDir(dir)
    if dir=='left' then
        self.sp:setScaleX(-1)
    else
        self.sp:setScaleX(1)
    end
end

function Hero:setNodeSize(_size)
    self.size = _size
end

function Hero:getNodeSize()
    return self.size
end

function Hero:setR(r)
    self.r = r 
end

function Hero:setC(c)
    self.c = c
end

function Hero:getR()
    return self.r
end

function Hero:getC()
    return self.c 
end

function Hero:setMyTl(val)
    self.tl = val
end

function Hero:getMyTl()
    return self.tl
end

function Hero:getMyId()
    return self.id
end

return Hero 

基本操作为,点击英雄身上的四个方向按钮,使英雄朝相应方向前进一步。

操作使用的箭头类:

local Arrow = class('Arrow',function () return cc.Node:create()
end)

function Arrow:ctor(width)
    self.btn1 = ccui.Button:create('arrow.png')
    self.btn2 = self.btn1:clone()
    self.btn3 = self.btn1:clone()
    self.btn4 = self.btn1:clone()
    -- left
    self:addChild(self.btn1)
    self.btn1:setAnchorPoint(1,0.5)
    self.btn1:setPosition(-width/2.5-3,0)
    -- up
    self.btn2:setRotation(90)
    self:addChild(self.btn2)
    self.btn2:setAnchorPoint(0.5,0.5)
    self.btn2:setPosition(0,width+6)
    -- right
    self.btn3:setFlippedX(true)
    self.btn3:setAnchorPoint(1,0.5)
    self.btn3:setPosition(width/2.5+3,0)
    self:addChild(self.btn3)
    -- down
    self.btn4:setRotation(-90)
    self.btn4:setAnchorPoint(0.5,0.5)
    self.btn4:setPosition(0,-width)
    self:addChild(self.btn4)

    local t1m1 = cc.MoveBy:create(0.8,cc.p(12,0))
    local t1m2 = cc.MoveBy:create(0.8,cc.p(-12,0))
    local se1=cc.Sequence:create(t1m1,t1m2)
    local re1 = cc.RepeatForever:create(se1)

    local t3m1 = t1m2:clone()
    local t3m2 = t1m1:clone()
    local se3 = cc.Sequence:create(t3m1,t3m2)
    local re3 = cc.RepeatForever:create(se3)

    local t2m1 = cc.MoveBy:create(0.8,cc.p(0,-12))
    local t2m2 = cc.MoveBy:create(0.8,cc.p(0,12))
    local se2 = cc.Sequence:create(t2m1,t2m2)
    local re2 = cc.RepeatForever:create(se2)

    local t4m1 = t2m2:clone()
    local t4m2 = t2m1:clone()
    local se4 = cc.Sequence:create(t4m1,t4m2)
    local re4 = cc.RepeatForever:create(se4)

    self.btn1:runAction(re1)
    self.btn2:runAction(re2)
    self.btn3:runAction(re3)
    self.btn4:runAction(re4)

    self.btn1:setName('left')
    self.btn2:setName('up')
    self.btn3:setName('right')
    self.btn4:setName('down')
end

function Arrow:setBtnFunc(func)  -- 回调
    self.btn1:addTouchEventListener(func)
    self.btn2:addTouchEventListener(func)
    self.btn3:addTouchEventListener(func)
    self.btn4:addTouchEventListener(func)
end

function Arrow:showSomeone(name,isShow)
    if self.btn1:getName()==name then
        self.btn1:setVisible(isShow)
    elseif self.btn2:getName()==name then
        self.btn2:setVisible(isShow)
    elseif self.btn3:getName()==name then
        self.btn3:setVisible(isShow)
    elseif self.btn4:getName()==name then
        self.btn4:setVisible(isShow)
    else
        self.btn1:setVisible(isShow)
        self.btn2:setVisible(isShow)
        self.btn3:setVisible(isShow)
        self.btn4:setVisible(isShow)
    end
end

return Arrow

往地图上添加英雄:

local MainScene = class("MainScene", cc.load("mvc").ViewBase)

function MainScene:ctor()
    self.heros = {}

    self:addMap()
    self:addHero()
end

function MainScene:addMap()
    local mapDataStr = cc.FileUtils:getInstance():getStringFromFile('res/MapData.json')
    local mapData = json.decode(mapDataStr)

    local mapStr = mapData['map']
    local mapInfo = self.split(mapStr,'#')

    self.mapLayer = require('app/views/MapEditor').new(mapInfo)
    self:addChild(self.mapLayer)
    self.range = self.mapLayer:getRange()

    local winSize = cc.Director:getInstance():getWinSize()
    self.mapLayer:setPosition(winSize.width/2-self.mapLayer:getMapWidth()/2,winSize.height/2-self.mapLayer:getMapHeight()/2)
end

function MainScene:addHero()
    local heroDataStr = cc.FileUtils:getInstance():getStringFromFile('HeroData.json')
    local heroData = json.decode(heroDataStr)
    local data = heroData['data']

    ccs.ArmatureDataManager:getInstance():addArmatureFileInfo('qishi.ExportJson')
    for i=1,#data do
        local hero = require('app/views/Hero').new(data[i]['id'])
        hero:setR(data[i]['r'])
        hero:setC(data[i]['c'])
        -- 设定初始体力为100
        hero:setMyTl(100)
        self.mapLayer:addChild(hero)
        local tile = self.mapLayer:getTileByPos(data[i]['r'],data[i]['c'])
        hero:setPosition(tile:getPosition())
        table.insert(self.heros,hero)
        local isShow = false
        if i == 1 then
            isShow = true
        end
        self:addArrow(hero,isShow)
    end
end

function MainScene:addArrow(hero,isShow)
    local arrow = require('app/views/Arrow').new(hero:getNodeSize().width)
    hero:addChild(arrow)
    arrow:setPositionY(hero:getNodeSize().height/2)
    arrow:setName('Arrow')
    -- 检查箭头该不该显示
    if isShow then
        self:showArrow(hero)
    else
        arrow:showSomeone('all',false)
    end
    arrow:setBtnFunc(function(sender,_type)
        if _type == ccui.TouchEventType.ended then
            self:heroAction(hero,sender:getName())                               
        end
    end)
end

function MainScene:showArrow(hero)
    local arr = hero:getChildByName('Arrow')

    local id = hero:getMyId()
    local heroR = hero:getR()
    local heroC = hero:getC()

    local mapC = self.mapLayer:getC()
    local mapR = self.mapLayer:getR()

    if heroC==1 then
        arr:showSomeone('left',false)
    elseif heroC==mapC then
        arr:showSomeone('right',false)
    end

    if heroC-1>0 then
        arr:showSomeone('left',self:checkArrowShow(heroR,heroC-1,id))
    end

    if heroC+1<=mapC then
        arr:showSomeone('right',self:checkArrowShow(heroR,heroC+1,id))
    end

    if heroR==1 then
        arr:showSomeone('up',false)
    elseif heroR==mapR then
        arr:showSomeone('down',false)
    end

    if heroR-1>0 then
        arr:showSomeone('up',self:checkArrowShow(heroR-1,heroC,id))
    end

    if heroR+1<=mapR then
        arr:showSomeone('down',self:checkArrowShow(heroR+1,heroC,id))
    end
end

function MainScene:checkArrowShow(r,c,id)
    local tile  = self.mapLayer:getTileByPos(r,c)
    local have = false
    if tonumber(tile:getId()) >= 3 and tonumber(tile:getId()) <= 5 then  -- 障碍不可站 
        return false
    else
        for i=1,#self.heros do
            local hero = self.heros[i]
            if hero:getMyId() ~= id then
                local _r = hero:getR()
                local _c = hero:getC()
                if _r == r and _c == c then
                    have = true
                    break
                end
            end
        end
        if have then
            return false
        else
            return true
        end
    end
end

function MainScene:heroAction(hero,arr_dir)
    local heroR = hero:getR()
    local heroC = hero:getC()
    local arrow = hero:getChildByName('Arrow')
    local heroTl = hero:getMyTl()
    local heroX,heroY = hero:getPosition()

    if heroTl <= 0 then
        print("--体力不足--")
        return false
    end

    if arr_dir == 'left' then
        heroX = heroX - self.range
        heroC = heroC - 1 
    elseif arr_dir == 'up' then
        heroY = heroY + self.range
        heroR = heroR - 1
    elseif arr_dir == 'right' then
        heroX = heroX + self.range
        heroC = heroC + 1
    else  -- down
        heroY = heroY - self.range
        heroR = heroR + 1 
    end

    if heroTl >= 5 then
        if arr_dir == 'left' or arr_dir == 'right' then
            hero:setDir(arr_dir)
        end

        local move = cc.MoveTo:create(0.7,cc.p(heroX,heroY))
        local function playA()
            arrow:showSomeone('all',false)
            hero:playAnimation('move')
        end
        local spawn = cc.Spawn:create(move,cc.CallFunc:create(playA))

        local function playB()
            hero:playAnimation('stand')

            hero:setR(heroR)
            hero:setC(heroC)

            self:showArrow(hero)

            hero:setMyTl(heroTl - 5)
        end
        hero:runAction(cc.Sequence:create(spawn,cc.CallFunc:create(playB)))
        return true
    end
end

function MainScene.split(str,reps)
    local resultStrList = {}
    string.gsub(str,'[^'..reps..']+',function (w)
        table.insert(resultStrList,w)
    end)
    return resultStrList
end

return MainScene

地图类和瓦片类增加了相应方法:

local MapEditor = class('MapEditor',function () 
    return cc.Layer:create() 
end)

function MapEditor:ctor(mapInfo)
    -- 行数
    self.R = #mapInfo

    local tileDataStr = cc.FileUtils:getInstance():getStringFromFile('res/TileData.json')
    local tileData = json.decode(tileDataStr)

    for i=1,#mapInfo do
        local c = self.split(mapInfo[i],',')
        for j=1,#c do
            local img = tileData[c[j]]
            local tile = require('app/views/TileNode').new(c[j],img)

            if i==1 and j==1 then
                -- 列数
                self.C = #c
                self:setMapWidth(tile:getNodeSize().width * #c)
                self:setMapHeight(tile:getNodeSize().height * #mapInfo)
                self:setRange(tile:getNodeSize().width)
            end

            self:addChild(tile)

            local _x = (j*2-1) * (tile:getNodeSize().width/2)
            local _y = (#mapInfo-i) * (tile:getNodeSize().height)

            tile:setPosition(_x,_y)
            tile:setMyTag(i,j)
            tile:setName('Tile')
        end
    end
end

function MapEditor.split(str,reps)
    local resultStrList = {}
    string.gsub(str,'[^'..reps..']+',function (w)
        table.insert(resultStrList,w)
    end)
    return resultStrList
end

function MapEditor:setMapWidth(_w)
    self.mapWidth = _w
end

function MapEditor:setMapHeight(_h)
    self.mapHeight = _h 
end

function MapEditor:getMapWidth()
    return self.mapWidth
end

function MapEditor:getMapHeight()
    return self.mapHeight
end

function MapEditor:getR()
    return self.R
end

function MapEditor:getC()
    return self.C
end

function MapEditor:setRange(_range)
    self.range = _range
end

function MapEditor:getRange()
    return self.range
end

function MapEditor:getTileByPos(_x,_y)
    local chs = self:getChildren()
    for i=1,#chs do
        local t = chs[i]
        if t:getName()=='Tile' then
            local r,c = t:getMyTag()
            if r==_x and c==_y then
                return t
            end
        end
    end
end

return MapEditor
local TileNode = class('TileNode',function ()
    return cc.Node:create()
end)

function TileNode:ctor(id,img)
    self.id = id
    local sp = cc.Sprite:create('res/dipi.png')

    if id ~= 0 then
        local sp1 = cc.Sprite:create('res/'..img..'.png')
        sp:addChild(sp1,2)
        sp1:setPosition(sp:getContentSize().width/2,sp:getContentSize().height/2)
    end

    sp:setAnchorPoint(0.5,0)
    self:addChild(sp)
    self:setNodeSize(sp:getContentSize())
end

function TileNode:setNodeSize(_size)
    self.nodeSize = _size
end

function TileNode:getNodeSize()
    return self.nodeSize
end

function TileNode:getId()
    return self.id
end

function TileNode:setMyTag(_x,_y)
    self.x = _x
    self.y = _y 
end

function TileNode:getMyTag()
    return self.x , self.y
end

return TileNode

效果:

你可能感兴趣的:(探索小游戏(二):英雄骨骼动画和基本操作)