cocos2dx lua 열 업데이트

12422 단어 #1.1cocos2d-x
원리:
        게임 에 로그 인 할 때마다 cocos 의 assetManager 를 이용 하여 서버 에서 현재 최신 두 파일 을 끌 어 옵 니 다.하 나 는 version. mainifest, 하나의 procject. mainifest 입 니 다. 이 두 파일 은 모두 xml 설명 파일 입 니 다.하 나 는 버 전 정 보 를 포함 하고, 두 번 째 는 게임 의 모든 자원 을 포함 하 는 MD5 코드 입 니 다.먼저 version 파일 을 통 해 로 컬 버 전이 같은 지, 다른 경우 로 컬 procject 파일 과 MD5 코드 를 비교 하여 어떤 파일 을 다시 다운로드 하고 자원 을 교체 해 야 하 는 지 판단 합 니 다. 
 
단계:
1. 파일 다운로드 열 업데이트 서버 가 있 습 니 다. 최신 프로젝트 자원 (res /  src / 디 렉 터 리) 를 열 업데이트 서버 에 넣 고 버 전 정보 모 파일 (version info. json) 과 python 스 크 립 트 파일 eneate Manifest. py (procject. manifest, version. manifest 파일 생 성) 를 추가 합 니 다.
2.version_info. json 파일: 주로 정 보 를 설정 하 는 데 사 용 됩 니 다.
{
    "packageUrl" : "http://ip:port/update/MyProj/assets/",
    "remoteManifestUrl" : "http://ip:port/update/MyProj/version/project.manifest",
    "remoteVersionUrl" : "http://ip:port/update/MyProj/version/version.manifest",
    "engineVersion" : "3.3",
	"update_channel" : "Android",
	"bundle" : "2018111701",
    "version" : "1.0.0",
}

3. eneateManifest. py 파일: 이 파일 은 python 입 니 다.대응 하 는 version 과 procject 파일 을 만 드 는 것 이 목적 입 니 다.procject 파일 은 모든 자원 에 유일한 MD5 코드 를 만 들 수 있 습 니 다. 모든 자원 의 태그 에 해당 합 니 다.다음은 python 파일 의 코드 입 니 다.
#coding:utf-8

import os
import sys
import json
import hashlib
import subprocess
import getpass

username = getpass.getuser()
#         
#os.chdir('/Users/' + username + '/Documents/client/MyProj/')

assetsDir = {
    #MyProj              
    "searchDir" : ["src", "res"],
    #        
    "ignorDir" : ["cocos", "framework", ".svn"],
    #       
    "ignorFile":[".DS_Store"],
}

versionConfigFile   = "version/version_info.json"  #           
versionManifestPath = "version/version.manifest"    #       version.manifest    
projectManifestPath = "version/project.manifest"    #       project.manifest    
# projectManifestPath = "/Users/ximi/Documents/client/MyProj/res/version/project.manifest"    #       project.manifest    (mac )

class SearchFile:
    def __init__(self):
        self.fileList = []

        for k in assetsDir:
            if (k == "searchDir"):
                for searchdire in assetsDir[k]:                 
                    self.recursiveDir(searchdire)

    def recursiveDir(self, srcPath):
        '''             '''
        dirList = []    #       

        files = os.listdir(srcPath) #            ,   (     )

        for f in files:         
            #     
            if (os.path.isdir(srcPath + '/' + f)):              
                if (f[0] == '.' or (f in assetsDir["ignorDir"])):
                    #             
                    pass
                else:
                    #                                           
                    dirList.append(f)

            #     
            elif (os.path.isfile(srcPath + '/' + f)) and (f not in assetsDir["ignorFile"]):               
                self.fileList.append(srcPath + '/' + f) #    

        #       ,   
        for dire in dirList:        
            #        
            self.recursiveDir(srcPath + '/' + dire)

    def getAllFile(self):
        ''' get all file path'''
        return tuple(self.fileList)


def CalcMD5(filepath):
    """generate a md5 code by a file path"""
    with open(filepath,'rb') as f:
        md5obj = hashlib.md5()
        md5obj.update(f.read())
        return md5obj.hexdigest()


def getVersionInfo():
    '''get version config data'''
    configFile = open(versionConfigFile,"r")
    json_data = json.load(configFile)

    configFile.close()
    # json_data["version"] = json_data["version"] + '.' + str(GetSvnCurrentVersion())
    json_data["version"] = json_data["version"]
    return json_data


def GenerateVersionManifestFile():
    '''       version.manifest'''
    json_str = json.dumps(getVersionInfo(), indent = 2)
    fo = open(versionManifestPath,"w")  
    fo.write(json_str)  
    fo.close()


def GenerateProjectManifestFile():
    searchfile = SearchFile()
    fileList = list(searchfile.getAllFile())
    project_str = {}
    project_str.update(getVersionInfo())
    dataDic = {}
    for f in fileList:      
        dataDic[f] = {"md5" : CalcMD5(f)}
        print f

    project_str.update({"assets":dataDic})
    json_str = json.dumps(project_str, sort_keys = True, indent = 2)

    fo = open(projectManifestPath,"w")  
    fo.write(json_str)  
    fo.close()

if __name__ == "__main__":
    GenerateVersionManifestFile()
    GenerateProjectManifestFile()
	

version. manifest 생 성 은 다음 과 같 습 니 다.
{
  "packageUrl": "http://ip:port/update/MyProj/assets/", 
  "engineVersion": "3.3", 
  "version": "1.0.0", 
  "remoteVersionUrl": "http://ip:port/update/MyProj/version/version.manifest", 
  "remoteManifestUrl": "http://ip:port/update/MyProj/version/project.manifest"
}

procject. manifest 생 성 은 다음 과 같 습 니 다.
{
    "assets": {
        "src/packages/mvc/init.lua": {
            "md5": "6b9173481a1300c5e737ad5885ebef00"
        }, 
        "src/protobuf.lua": {
            "md5": "f790fe35eb179a4341ff41d94e488a5d"
        }
        ...
    }, 
    "packageUrl": "http://ip:port/update/MyProj/assets/", 
    "engineVersion": "3.3", 
    "version": "1.0.0", 
    "remoteVersionUrl": "http://ip:port/update/MyProj/version/version.manifest", 
    "remoteManifestUrl": "http://ip:port/update/MyProj/version/project.manifest"
}

 
4. 게임 클 라 이언 트: cocos assetManager 를 이용 하여 서버 에서 파일 을 가 져 오고 자원 을 교체 합 니 다. (여기 서 바 꾸 는 것 은 실제 바 꾸 는 것 이 아니 라 Fileutils - > searchPath () 를 이용 하여 자원 파일 을 읽 는 우선 순 위 를 설정 합 니 다. 즉, 오래된 자원 과 코드 는 삭제 되 지 않 고 버 리 는 것 입 니 다.
--region *.lua
--Date

local AssetsManager = class("AssetsManager",function ()
    return cc.LayerColor:create(cc.c4b(20, 20, 20, 220))
end)

function AssetsManager:ctor()
    self:onNodeEvent("exit", handler(self, self.onExitCallback))
    self:initUI()
    self:setAssetsManage()
end

function AssetsManager:onExitCallback()
    self.assetsManagerEx:release()
end

function AssetsManager:initUI()

    local hintLabel = cc.Label:createWithTTF("    ...", CONFIG.TTF_FONT_2, 20)
        :addTo(self)
        :move(600, 80)

    local progressBg = display.newSprite("sprites/hyd_progress_bg.png")    
        :addTo(self)
        :move(600, 40)

    self.progress = cc.ProgressTimer:create(display.newSprite("sprites/hyd_progress.png"))
        :addTo(progressBg)
        :move(380, 19)
    self.progress:setType(cc.PROGRESS_TIMER_TYPE_BAR)
    self.progress:setBarChangeRate(cc.p(1, 0))
    self.progress:setMidpoint(cc.p(0.0, 0.5))
    self.progress:setPercentage(0) 

    --    
    self.listener = cc.EventListenerTouchOneByOne:create()
    self.listener:setSwallowTouches(true)
    local onTouchBegan = function (touch, event)
        return true
    end

    self.listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
    cc.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(self.listener, self)   
end

function AssetsManager:setAssetsManage()
    --             
    local storagePath = cc.FileUtils:getInstance():getWritablePath() .. "NewRes/" 
    local resPath = storagePath.. '/res/'
    local srcPath = storagePath.. '/src/'
    if not (cc.FileUtils:getInstance():isDirectoryExist(storagePath)) then         
        cc.FileUtils:getInstance():createDirectory(storagePath)
        cc.FileUtils:getInstance():createDirectory(resPath)
        cc.FileUtils:getInstance():createDirectory(srcPath)
    end
    local searchPaths = cc.FileUtils:getInstance():getSearchPaths() 
    table.insert(searchPaths, 1, storagePath)  
    table.insert(searchPaths, 2, resPath)
    table.insert(searchPaths, 3, srcPath)
    cc.FileUtils:getInstance():setSearchPaths(searchPaths)

    self.assetsManagerEx = cc.AssetsManagerEx:create("version/project.manifest", storagePath)    
    self.assetsManagerEx:retain()

    local eventListenerAssetsManagerEx = cc.EventListenerAssetsManagerEx:create(self.assetsManagerEx, 
       function (event)
           self:handleAssetsManagerEvent(event)
       end)

    local dispatcher = cc.Director:getInstance():getEventDispatcher()
    dispatcher:addEventListenerWithFixedPriority(eventListenerAssetsManagerEx, 1)

    --       
    self.assetsManagerEx:update()
end

function AssetsManager:handleAssetsManagerEvent(event)    
    local eventCodeList = cc.EventAssetsManagerEx.EventCode    

    local eventCodeHand = {

        [eventCodeList.ERROR_NO_LOCAL_MANIFEST] = function ()
            print("    :           ")
        end,

        [eventCodeList.ERROR_DOWNLOAD_MANIFEST] = function ()
            print("    :            ")  --         ,
            self:downloadManifestError()
        end,

        [eventCodeList.ERROR_PARSE_MANIFEST] = function ()
             print("    :          ")
        end,

        [eventCodeList.NEW_VERSION_FOUND] = function ()
            print("       ")
        end,

        [eventCodeList.ALREADY_UP_TO_DATE] = function ()
            print("            ")            
            self:updateFinished()
        end,

        [eventCodeList.UPDATE_PROGRESSION]= function ()
            print("         ")
            self.progress:setPercentage(event:getPercentByFile())
        end,

        [eventCodeList.ASSET_UPDATED] = function ()
            print("         ")
        end,

        [eventCodeList.ERROR_UPDATING] = function ()
            print("    :         ")
        end,

        [eventCodeList.UPDATE_FINISHED] = function ()
            print("      ")
            self:updateFinished()
        end,

        [eventCodeList.UPDATE_FAILED] = function ()
            print("      ")
        end,

        [eventCodeList.ERROR_DECOMPRESS] = function ()
            print("     ")
        end
    }
    local eventCode = event:getEventCode()    
    if eventCodeHand[eventCode] ~= nil then
        eventCodeHand[eventCode]()
    end  
end

function AssetsManager:updateFinished()
    self:setVisible(false)
    self.listener:setEnabled(false)
end

function AssetsManager:downloadManifestError()
    self:setVisible(false)
    self.listener:setEnabled(false)
end

return AssetsManager


--endregion

 
 
Android apk 가 설 치 된 후에 도 핸드폰 에 apk 가 존재 합 니 다. apk 는 기록 하고 삭제 할 수 없 기 때문에 핫 업데이트 로 다운로드 한 최신 자원 은 모두 캐 시 에 존재 하고 캐 시 디 렉 터 리 를 최고 우선 순위 검색 디 렉 터 리 로 추가 합 니 다. 자원 을 불 러 올 때 최고 우선 순위 디 렉 터 리 에서 불 러 와 업 데 이 트 를 대체 하 는 역할 을 합 니 다.
 
cocos2dx 에는 열 업데이트 클래스 Assets Manager Ex 가 있 습 니 다. 이 클래스 로 열 경 기능 을 실현 하려 면 두 개의 파일 이 필요 합 니 다. procject. manifest 와 version. manifest 입 니 다. 여 기 는 주로 procject. manifest 파일 입 니 다.
코 코스 자체 도 핫 업데이트 모듈 AssetsManager, AssetsManagerEx 을 봉 했다.AssetsManager 업그레이드 패 키 지 를 관리 하 는 방식 으로 먼저 버 전 번 호 를 비교 한 다음 에 URL 에 따라 해당 하 는 업그레이드 패 키 지 를 가 져 오고 업그레이드 패 키 지 를 압축 해제 하 며 자원 로드 경 로 를 설정 하고 로드 writepath 를 통 해디 렉 터 리 아래 의 최신 파일 방식 으로 업 데 이 트 를 실현 합 니 다. 문 제 는 버 전 업데이트 와 관련 되 거나 한 파일 만 바 뀌 었 을 때 사용 자 는 앞의 모든 업그레이드 내용 을 다운로드 해 야 합 니 다. 업그레이드 패 키 지 는 점점 커 집 니 다.AssetsManagerExAssetsManager 강화 판 으로 업그레이드 패 키 지 를 사용 하지 않 고 하나의 파일 로 끌 어 내 는 방식 이 다 릅 니 다. 먼저 로 컬 업데이트 설정 을 가 져 온 다음 서버 의 업데이트 설정 과 비교 하여 차이 파일 을 얻 은 다음 에 하나의 차이 점 을 가 져 옵 니 다. 로 컬 버 전이 서버 버 전 보다 클 때 로 컬 업데이트 캐 시 를 지 웁 니 다. AssetsManagerEx여러 업데이트 시퀀스 가 병행 되 지 않 아 순서대로 시작 할 수 밖 에 없 는 문제 도 있 습 니 다. 또한 버 전 후기 에는 프로젝트 의 방대 한 프로필 에 거의 모든 파일 정보 가 포함 되 어 있어 파일 에 비해 시간 이 오래 걸 립 니 다.
 
레 퍼 런 스
Cocos2dx Lua 열 업데이트

좋은 웹페이지 즐겨찾기