CococCreator跨域訪問資源服務器


需求與思路

項目上線前有一個需求

游戲資源需要存放在cdn上

而游戲入口一般是通過運營渠道的服務器進入(服務器A)

玩家需要通過服務器A的游戲頁面請求資源服務器B的游戲資源

這樣就產生了跨域問題

(版本ccc1.3.3)轉載請注明原文地址http://www.cnblogs.com/billyrun/articles/7029221.html

 

具體來說問題可能有以下兩個

1.瀏覽器跨域(本文解決)

2.WebGL模式禁止跨域(沒有遇到,可能是引擎避開了這個問題)

 

網頁技術處理跨域問題有多種解決方案

這里通過修改服務端響應頭header

eg:

//任意ip均不受跨域限制

header('Access-Control-Allow-Origin:*');

//指定IP如服務器A不受跨域限制

header('Access-Control-Allow-Origin: http(s)://yourdomain(or IP):port');

原理和思路大概就這么多

實現起來要小費一番周折

一方面要搭建服務器模擬資源服務器

另一方面要修改Creator引擎js源碼

 

NodeJS搭建資源服務器

下載NodeJS並安裝express

編寫服務端程序代碼如下

var express = require('express');
var app = express();
app.use(express.static('public'));
 
// 設置跨域頭部
app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

//  主頁輸出 "Hello World"
app.get('/', function (req, res) {
   console.log("主頁 GET 請求");
   res.send('Hello GET');
})

// 返回圖片
app.get('/image', function(req, res) {   
   res.sendfile(__dirname + '/runoob-logo.png');
})
 
// 啟動服務
var server = app.listen(3000, function () {
 
  var host = server.address().address
  var port = server.address().port
  console.log("應用實例,訪問地址為 ", (new Date()).toLocaleString(), port)
 
})

命令行中鍵入node [路...徑]app.js 啟動服務程序

打開瀏覽器后,即如上圖所示

 

修改圖片下載模塊

首先找到下載模塊

engine/cocos2d/core/load-pipeline/downloader.js

function downloadImage(item, callback, isCrossOrigin, img) {
            void 0 === isCrossOrigin && (isCrossOrigin = true);
            var url = urlAppendTimestamp(item.url);
            img = img || new Image();
            isCrossOrigin && "file:" !== window.location.protocol ? img.crossOrigin = "anonymous" : img.crossOrigin = null;
            if (img.complete && img.naturalWidth > 0 && img.src === url) {
                callback(null, img);
            } else {
                function loadCallback() {
                    img.removeEventListener("load", loadCallback);
                    img.removeEventListener("error", errorCallback);
                    callback(null, img);
                }
                function errorCallback() {
                    img.removeEventListener("load", loadCallback);
                    img.removeEventListener("error", errorCallback);
                    "https:" !== window.location.protocol && img.crossOrigin && "anonymous" === img.crossOrigin.toLowerCase() ? downloadImage(item, callback, false, img) : callback("Load image (" + url + ") failed");
                }
                img.addEventListener("load", loadCallback);
                img.addEventListener("error", errorCallback);
                //img.src = url;
                if(url.indexOf("testSprite") >= 0)
                    url = "http://localhost:3000/image"
                img.src = url;
                cc.log("test3 downloadImage" , url)
            }
        }

if(url.indexOf("testSprite") >= 0)
  url = "http://localhost:3000/image"

這兩行是我自己加的,等下加載testSprite時,我們強行加載跨域的另一個資源(用以測試跨域加載圖片)

原本的url形如res/raw-assets/Texture/HelloWorld.png

上線cdn時只需要拼接完整url即可,如http://xx.xx.xx.xx/ + url

 

生成修改后的js引擎

這里需要參考官方文檔http://www.cocos.com/docs/creator/advanced-topics/engine-customization.html

然而目前我還沒弄好!

js引擎文件改寫之后,需要重新生成cocos2d-js.js文件

網頁中完全依靠該文件而非engine目錄下的零散文件提供引擎支持

若環境尚未配置不能自動生成cocos2d-js.js文件

也可以手動修改!

首先打包發布webmobile

在打包的路徑下找到build\web-mobile\cocos2d-js.js

並修改其中的downloadImage方法

注意:先發布運行,再修改,再刷新

 

測試跨域加載效果

測試場景放置一個按鈕

點擊回調加載testSprite,就像downloadImage方法里修改的那樣

會去加載跨域資源

var node = new cc.Node(),sprite = node.addComponent(cc.Sprite)
cc.loader.loadRes("testSprite.png" , cc.SpriteFrame , function(err , sp){
    sprite.spriteFrame = sp
})
node.parent = this.node

測試成功!

可以看到圖片正常顯示

ResponseHeader里面可以看到添加的頭部信息

 

若將app.js其中跨域的部分注釋掉

可以看到原本跨域帶來的問題

/*app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});*/

Access to Image at 'http://localhost:3000/image' from origin 'http://localhost:7456' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:7456' is therefore not allowed access.
CCTexture2D.js:858

Uncaught DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at http://localhost:3000/image may not be loaded.
at cc_Texture2D.handleLoadedTexture (http://localhost:7456/build/cocos2d-js.js:43009:28)
at Loader.loadImage (http://localhost:7456/build/cocos2d-js.js:35660:17)
at Loader.handle (http://localhost:7456/build/cocos2d-js.js:35702:26)
at Loader.asyncFlow [as flowIn] (http://localhost:7456/build/cocos2d-js.js:36171:22)
at http://localhost:7456/build/cocos2d-js.js:36179:37
at http://localhost:7456/build/cocos2d-js.js:35580:37
at HTMLImageElement.loadCallback (http://localhost:7456/build/cocos2d-js.js:35415:21)

 

最后說一句,真心不得不學一點服務端的東西~

 

參考文獻

跨域相關

http://blog.csdn.net/flower46273736/article/details/62889077

http://forum.cocos.com/t/url/42848/4

http://forum.cocos.com/t/h5/42703  [經驗分享] h5游戲緩存根據版本去更新

nodejs相關

http://www.runoob.com/nodejs/nodejs-express-framework.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM