[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier
红孩儿Cocos2d-X学习园地QQ群:249941957
另:本章所用Cocos2d-x版本为:
Cocos2d-html5-v2.1.1
http://cn.cocos2d-x.org/download
html5的时代正在来临,其可以方便的运行在多平台上并调用OPENGL 进行图形渲染,大量使用html5开发的2D和3D游戏正在涌现,Cocos2d-x也顺应形势推出了相应的版本,今天我们来学习一下Cocos2d-x在Html5上怎么运行和开发及调试。
打开HelloHTML5World,可以看到以下文件和目录:
res:资源图片目录:
src:当前程序的js文件目录:
main.js:主逻辑js代码文件
index.html:html5网页文件
cocos2d.js:加载Cocos2d-x库的文件
build.xml:编译cocos2d-x的html5平台版本生成的文件清单报告。
.DS_Store:系统目录显示属性存储文件,可以删除。
我们用浏览器直接打开index.html,可以看到:
其源码为:
Cocos2d-html5 Hello World test
可以看到,这里面关键的要点是两个地方:
1.
在html5中创建了一个画布(canvas),设定了名称和大小
2.
在网页中加载了cocos2d.js
打开cocos2d.js后,可以看到下面的代码:
(function () {
//定义变量d为当前网页的文档对象
var d = document;
//定义变量c为一个结构,存储了一些配置属性和值。
var c = {
COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
box2d:false,//不使用box2d
chipmunk:false,//不使用chipmunk
showFPS:true,//显示FPS
frameRate:60,//设定每秒60帧
loadExtension:false,不载入扩展库
tag:'gameCanvas', //运行cocos2d-x的画布
engineDir:'../cocos2d/',//引擎的目录,这里指定为当前上级目录下的cocos2d目录中
//SingleEngineFile:'',//这里注释掉了。
appFiles:[//应用程序要使用到的两个js文件。
'src/resource.js',//资源定义文件
'src/myApp.js'//逻辑处理文件
]
};
//当前窗口加载一个事件响应处理,在DOM被加载时调用。
window.addEventListener('DOMContentLoaded', function () {
//当前文档创建一个脚本
var s = d.createElement('script');
//如果c结构中有SingleEngineFile变量并肯engineDir为空,则s中的脚本引用为SingleEngineFile指示的文件,当然,本例中这个变量注释掉了,这一段不成立。
if (c.SingleEngineFile && !c.engineDir) {
s.src = c.SingleEngineFile;
}
//如果engineDir有效,则s中的脚本引用为engineDir指定目录下的相应文件,本例中为“../cocos2d/platform/jsloader.js”。
else if (c.engineDir && !c.SingleEngineFile) {
s.src = c.engineDir + 'platform/jsloader.js';
}
else {
//如果都不是,弹出对话框提示c结构成员变量设置错误。
alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
}
//将结构c做为一个成员变量存入到当前文档。
document.ccConfig = c;
//上面创建的‘script’的id设置为’cocos2d-html5’.
s.id = 'cocos2d-html5';
//将这个script加入到当前HTML文档的结尾。
d.body.appendChild(s);
//else if single file specified, load singlefile
});
})();
“
下面我们来打开cocos2d目录下的’platform/jsloader.js’:
//脚本执行函数。
(function () {
//定义变量engine为一个字符串数组,元素为运行当前版本cocos2d-x要加载的所有代码文件。
var engine = [
'platform/CCClass.js',
'platform/miniFramework.js',
'platform/CCCommon.js',
'platform/ZipUtils.js',
'platform/base64.js',
'platform/gzip.js',
'platform/CCMacro.js',
'platform/CCFileUtils.js',
'platform/CCTypes.js',
'platform/zlib.min.js',
'cocoa/CCGeometry.js',
'platform/Sys.js',
'platform/CCConfig.js',
'cocoa/CCSet.js',
'cocoa/CCNS.js',
'cocoa/CCAffineTransform.js',
'support/CCPointExtension.js',
'support/CCUserDefault.js',
'base_nodes/CCNode.js',
'base_nodes/CCAtlasNode.js',
'textures/CCTexture2D.js',
'textures/CCTextureCache.js',
'textures/CCTextureAtlas.js',
'misc_nodes/CCRenderTexture.js',
'misc_nodes/CCProgressTimer.js',
'effects/CCGrid.js',
'effects/CCGrabber.js',
'actions/CCAction.js',
'actions/CCActionInterval.js',
'actions/CCActionInstant.js',
'actions/CCActionManager.js',
'actions/CCActionProgressTimer.js',
'actions/CCActionCamera.js',
'actions/CCActionEase.js',
'actions/CCActionGrid.js',
'actions/CCActionTiledGrid.js',
'actions/CCActionCatmullRom.js',
'layers_scenes_transitions_nodes/CCScene.js',
'layers_scenes_transitions_nodes/CCLayer.js',
'layers_scenes_transitions_nodes/CCTransition.js',
'layers_scenes_transitions_nodes/CCTransitionProgress.js',
'layers_scenes_transitions_nodes/CCTransitionPageTurn.js',
'sprite_nodes/CCSprite.js',
'sprite_nodes/CCAnimation.js',
'sprite_nodes/CCAnimationCache.js',
'sprite_nodes/CCSpriteFrame.js',
'sprite_nodes/CCSpriteFrameCache.js',
'sprite_nodes/CCSpriteBatchNode.js',
'label_nodes/CCLabelAtlas.js',
'label_nodes/CCLabelTTF.js',
'label_nodes/CCLabelBMFont.js',
'particle_nodes/CCParticleSystem.js',
'particle_nodes/CCParticleSystemQuad.js',
'particle_nodes/CCParticleExamples.js',
'particle_nodes/CCParticleBatchNode.js',
'touch_dispatcher/CCTouchDelegateProtocol.js',
'touch_dispatcher/CCTouchHandler.js',
'touch_dispatcher/CCTouchDispatcher.js',
'touch_dispatcher/CCMouseDispatcher.js',
'keyboard_dispatcher/CCKeyboardDelegate.js',
'keyboard_dispatcher/CCKeyboardDispatcher.js',
'text_input_node/CCIMEDispatcher.js',
'text_input_node/CCTextFieldTTF.js',
'CCDirector.js',
'CCCamera.js',
'CCScheduler.js',
'CCLoader.js',
'CCDrawingPrimitives.js',
'platform/CCApplication.js',
'platform/CCSAXParser.js',
'platform/AppControl.js',
'menu_nodes/CCMenuItem.js',
'menu_nodes/CCMenu.js',
'tileMap_parallax_nodes/CCTMXTiledMap.js',
'tileMap_parallax_nodes/CCTMXXMLParser.js',
'tileMap_parallax_nodes/CCTMXObjectGroup.js',
'tileMap_parallax_nodes/CCTMXLayer.js',
'tileMap_parallax_nodes/CCParallaxNode.js',
'menu_nodes/CCMenuItem.js',
'menu_nodes/CCMenu.js',
'base_nodes/CCdomNode.js',
'../CocosDenshion/SimpleAudioEngine.js'
];
//取得当前文档存入d,取得上一节中创建的当前d的成员变量ccCofing存入c.
var d = document;
var c = d.ccConfig;
//如果c的结构变量loadExtension有效,即当前程序需要加载扩展库,则在上面的变量engine所对应的字符串数组尾部添加cocos2d-x扩展库所涉及的代码文件。
if (c.loadExtension != null && c.loadExtension == true) {
engine = engine.concat([
'../extensions/GUI/CCControlExtension/CCControl.js',
'../extensions/GUI/CCControlExtension/CCControlButton.js',
'../extensions/GUI/CCControlExtension/CCControlUtils.js',
'../extensions/GUI/CCControlExtension/CCInvocation.js',
'../extensions/GUI/CCControlExtension/CCScale9Sprite.js',
'../extensions/GUI/CCControlExtension/CCMenuPassive.js',
'../extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js',
'../extensions/GUI/CCControlExtension/CCControlHuePicker.js',
'../extensions/GUI/CCControlExtension/CCControlColourPicker.js',
'../extensions/GUI/CCControlExtension/CCControlSlider.js',
'../extensions/GUI/CCControlExtension/CCControlSwitch.js',
'../extensions/GUI/CCScrollView/CCScrollView.js',
'../extensions/GUI/CCScrollView/CCSorting.js',
'../extensions/GUI/CCScrollView/CCTableView.js',
'../extensions/CCBReader/CCNodeLoader.js',
'../extensions/CCBReader/CCBReaderUtil.js',
'../extensions/CCBReader/CCControlLoader.js',
'../extensions/CCBReader/CCSpriteLoader.js',
'../extensions/CCBReader/CCNodeLoaderLibrary.js',
'../extensions/CCBReader/CCBReader.js',
'../extensions/CCBReader/CCBValue.js',
'../extensions/CCBReader/CCBKeyframe.js',
'../extensions/CCBReader/CCBSequence.js',
'../extensions/CCBReader/CCBRelativePositioning.js',
'../extensions/CCBReader/CCBAnimationManager.js',
'../extensions/CCControlEditBox.js'
]);
}
//如果c中的engineDir设置无效,清空engine。
if (!c.engineDir) {
engine = [];
}
else {
//如果c中的engineDir设置有效
//如果c的结构中有结构变量box2d和chipmunk,则在变量engine所对应的字符串数组尾部添加cocos2d-x物理引擎库所涉及的代码文件。
if(c.box2d || c.chipmunk){
engine.push('Draw_Nodes/CCDrawNode.js');
engine.push('physics_nodes/CCPhysicsSprite.js');
engine.push('physics_nodes/CCPhysicsDebugNode.js');
if (c.box2d)
engine.push('../box2d/box2d.js');
if (c.chipmunk)
engine.push('../chipmunk/chipmunk.js');
}
//遍历engine中的所有元素,将各元素的文件相对目录转变为绝对目录。
engine.forEach(function (e, i) {
engine[i] = c.engineDir + e;
});
}
//定义量时变量
var loaded = 0;
//在engine最尾部加上c的结构变量appFiles (即当前程序资源和逻辑所对应的js),将新数组保存到que。
var que = engine.concat(c.appFiles);
//再加上当前程序的主逻辑js文件。
que.push('main.js');
//判断浏览器是否是IE9
if (navigator.userAgent.indexOf("Trident/5") > -1) {
//如果是IE9
//创建一个局部变量serial,存值-1
this.serial = -1;
//定义一个函数loadNext
var loadNext = function () {
//定义临时变量s为serial+1
var s = this.serial + 1;
//如果s所指定的索引小于que的数组数量.
if (s < que.length) {
//当前文档创建一个脚本标记,保存为变量f
var f = d.createElement('script');
//设置script的src为索引s指定的que数组元素。
f.src = que[s];
//将索引s存入f成员变量serial。
f.serial = s;
//设定scrip在被加载时调用函数loadNext。
f.onload = loadNext;
//将scrip放入到当前HTML文档的结尾.
d.body.appendChild(f);
//将数组的加载进度保存到临时变量p,在当前位置你可以处理你的加载进度条。
p = s / (que.length - 1);
}
};
//调用一下刚创建的函数,执行第一次后,就会不断的在html文档结尾加入:‘’。
loadNext();
}
else {
//如果不是IE9,则遍历que数组的每个元素。
que.forEach(function (f, i) {
//当前文档创建一个脚本标记,保存为变量s
var s = d.createElement('script');
//设置scrip的async变量为false. 目前firefox和chrome都是实现了script标签的async属性.这个新的属性能让我们以一种更 简单的方式防止浏览器阻塞
s.async = false;
//设置script的src变量值为遍历元素。
s.src = f;
//设定加载时调用函数更新进度计算。
s.onload = function () {
loaded++;
p = loaded / que.length;
//TODO: code for updating progress bar
};
//将scrip放入到当前HTML文档的结尾.
d.body.appendChild(s);
//将s保存到que数组的第i个数组元素中。
que[i] = s;
});
}
})();//最后的()代表当前函数被调用。
可见jsloader.js的作用是加载cocos2d-x所要用到的所有js文件以及‘resource.js’,‘myApp.js’,‘main.js’。
打开’resource.js’:
//定义一些资源文件字符串变量。
var s_HelloWorld = "res/HelloWorld.png";
var s_CloseNormal = "res/CloseNormal.png";
var s_CloseSelected = "res/CloseSelected.png";
//创建一个结构数组,标记文件类型和对应的文件名称字符串。
var g_ressources = [
//image
{type:"image", src:s_HelloWorld},
{type:"image", src:s_CloseNormal},
{type:"image", src:s_CloseSelected}
//plist
//fnt
//tmx
//bgm
//effect
];
上面的文件主要是就是定义程序所要用到的资源信息。
打开myApp.js:
//创建一个cocos2d-x精灵的派生类存入CircleSprite用于计时.初始化成员变量_radians为0,即不旋转。
var CircleSprite = cc.Sprite.extend({
_radians:0,
//重载父类(精灵) 构造函数ctor,调用其父类的相应函数。
ctor:function () {
this._super();
},
//重载父类(精灵)成员函数draw。增加绘制代码。
draw:function () {
//设置要绘制时的设置信息
//填充色为白色
cc.renderContext.fillStyle = "rgba(255,255,255,1)";
//画笔色为白色
cc.renderContext.strokeStyle = "rgba(255,255,255,1)";
//如果当前精灵的_radians小于0,则重置为360。
if (this._radians < 0)
this._radians = 360;
//调用cocos2d-x的绘制圆的函数,这个函数是在CCDrawingPrimitives.js中定义的,drawCircle:function (center, radius, angle, segments, drawLineToCenter),参一为中心位置,参二为半径,参三为绘制的起始角度当然也是中心连线的起始角度,参四为圆的段数,参五为是否与中心连线。
cc.drawingUtil.drawCircle(cc.PointZero(), 30, cc.DEGREES_TO_RADIANS(this._radians), 60, true);
},
//定义成员函数myUpdate,用于每次调用时成员变量_raduans自减6。等于每次调用顺时针旋转6度,因为设定FPS为60,所以一秒转一圈正好360度嘛。
myUpdate:function (dt) {
this._radians -= 6;
//this._addDirtyRegionToDirector(this.getBoundingBoxToWorld());
}
});
//由Cocos2d-x的层派生出一个类HelloWorld.
var Helloworld = cc.Layer.extend({
//初始化其成员变量
isMouseDown:false,
helloImg:null,
helloLabel:null,
circle:null,
sprite:null,
//初始化函数。
init:function () {
//定义临时变量保存当前实例指针。
var selfPointer = this;
//首先调用父类精灵的初始化函数。
this._super();
//取得窗口的大小
var size = cc.Director.getInstance().getWinSize();
//增加一个菜单按钮,设置点击后响应函数退回前一步。
var closeItem = cc.MenuItemImage.create(
"res/CloseNormal.png",
"res/CloseSelected.png",
function () {
history.go(-1);
},this);
//设置菜单按钮精灵的锚点。
closeItem.setAnchorPoint(cc.p(0.5, 0.5));
//由菜单按钮创建一个菜单,设置菜单位置并放入当前层下。
var menu = cc.Menu.create(closeItem);
menu.setPosition(cc.PointZero());
this.addChild(menu, 1);
//设置菜单按钮的位置。
closeItem.setPosition(cc.p(size.width - 20, 20));
//创建一个文字标签,显示字符串“HelloWorld”。
this.helloLabel = cc.LabelTTF.create("Hello World", "Arial", 38);
//设置横向居中显示。
this.helloLabel.setPosition(cc.p(size.width / 2, 0));
//将文字标签加入到当前层下。
this.addChild(this.helloLabel, 5);
//创建一个新层lazyLayer并放入当前层
var lazyLayer = new cc.LazyLayer();
this.addChild(lazyLayer);
// 创建当前类成员精灵,设置位置,缩放,旋转。
this.sprite = cc.Sprite.create("res/HelloWorld.png");
this.sprite.setPosition(cc.p(size.width / 2, size.height / 2));
this.sprite.setScale(0.5);
this.sprite.setRotation(180);
//将新建的精灵放入到层lazyLayer.
lazyLayer.addChild(this.sprite, 0);
//创建两个动画。
var rotateToA = cc.RotateTo.create(2, 0);
var scaleToA = cc.ScaleTo.create(2, 1, 1);
//让精灵运行一个动画序列,动画序列为这两个新建的动画。
this.sprite.runAction(cc.Sequence.create(rotateToA, scaleToA));
//创建一个计时精灵类,设置位置并放入到当前层中。
this.circle = new CircleSprite();
this.circle.setPosition(cc.p(40, size.height - 60));
this.addChild(this.circle, 2);
//这句很重要,每1/60秒响应一次它的MyUpdate函数更新。
this.circle.schedule(this.circle.myUpdate, 1 / 60);
//当前文字标签到运行一个移动动画。
this.helloLabel.runAction(cc.MoveBy.create(2.5, cc.p(0, size.height - 40)));
//开启当前视窗的触屏响应处理。
this.setTouchEnabled(true);
//这一句调用是让屏幕的分辩率按窗口大小来自适应避免拉伸。
this.adjustSizeForWindow();
//lazyLayer层的分辩率按所在画布的大小来自适应避免拉伸。
lazyLayer.adjustSizeForCanvas();
//设置当前窗口在改变大小时要调用函数adjustSizeForWindow
window.addEventListener("resize", function (event) {
selfPointer.adjustSizeForWindow();
});
return true;
},
//如果窗口在改变大小时要调用的函数,现实等比调整Cocos2d-x画布大小以适应填充网页客户区。
adjustSizeForWindow:function () {
//窗口客户端宽度减去body区域宽度,得到一个差值保存到新创建变量margin。
var margin = document.documentElement.clientWidth - document.body.clientWidth;
//如果客户端宽度小于html5中画布宽度800,设置cocos2d-x画布的宽度按照html5中画布宽度800设置,这里是限制了显示cocos2d-x画面的最小宽度。
if (document.documentElement.clientWidth < cc.originalCanvasSize.width) {
cc.canvas.width = cc.originalCanvasSize.width;
} else {
//否则,设置cocos2d-x画布的宽度按照html5中body宽度设置。
cc.canvas.width = document.documentElement.clientWidth - margin;
}
//如果可见区域高度小于html5中画布高度450,设置cocos2d-x画布的高度按照html5中画布高度450设置。
if (document.documentElement.clientHeight < cc.originalCanvasSize.height) {
cc.canvas.height = cc.originalCanvasSize.height;
} else {
//否则,设置cocos2d-x画布的高度按照html5中body高度设置。
cc.canvas.height = document.documentElement.clientHeight - margin;
}
//计算出cocos2d-x的画布与HTML5上的画布的缩放比例
var xScale = cc.canvas.width / cc.originalCanvasSize.width;
var yScale = cc.canvas.height / cc.originalCanvasSize.height;
//因为一般窗口都是宽大于高,所以这里做个处理,使画面保持等比缩放。
if (xScale > yScale) {
xScale = yScale;
}
//根据等比缩放重新计算出Cocos2d-x中画布的宽高。
cc.canvas.width = cc.originalCanvasSize.width * xScale;
cc.canvas.height = cc.originalCanvasSize.height * xScale;
//取得网页中id为Cocos2dGameContainer的文档div元素。
var parentDiv = document.getElementById("Cocos2dGameContainer");
if (parentDiv) {
//如果找到了设置其style中的宽和高按画布的像素大小
parentDiv.style.width = cc.canvas.width + "px";
parentDiv.style.height = cc.canvas.height + "px";
}
//设置cocos2d-x中渲染区域向上移动相应距离及设置相应缩放。
cc.renderContext.translate(0, cc.canvas.height);
cc.renderContext.scale(xScale, xScale);
//设置cocos2d-x的像素与点的缩放比例。
cc.Director.getInstance().setContentScaleFactor(xScale);
},
// 菜单按扭(关闭按钮)按下时的响应处理。
menuCloseCallback:function (sender) {
//终止cocos2d-x设备运行。
cc.Director.getInstance().end();
},
//当触屏按下事件被响应时的处理。
onTouchesBegan:function (touches, event) {
//设置当前层的成员变量isMouseDown为ture
this.isMouseDown = true;
},
//当触屏按下并移动事件被响应时的处理。
onTouchesMoved:function (touches, event) {
//判断如果isMouseDown为ture。
if (this.isMouseDown) {
//如果触点有效.
if (touches) {
//这里本来是显示触点的,但屏蔽了。
//this.circle.setPosition(cc.p(touches[0].getLocation().x, touches[0].getLocation().y));
}
}
},
//当触屏松开事件响应时的处理
onTouchesEnded:function (touches, event) {
//设置当前层的成员变量isMouseDown为false
this.isMouseDown = false;
},
//当触摸被取消(比如触摸过程中被来电打断),就会调用touchesCancelled方法。
onTouchesCancelled:function (touches, event) {
//控制台输出日志
console.log("onTouchesCancelled");
}
});
//创建一个cocos2d-x的场景的派生类HelloWorldScene。
var HelloWorldScene = cc.Scene.extend({
//重载onEnter函数指定在场景被加载时要做的处理。
onEnter:function () {
//先调用基类cc.Scene的相应处理。
this._super();
//创建一个Helloworld层的实例并初始化。
var layer = new Helloworld();
layer.init();
//将这个层加入到当前场景。
this.addChild(layer);
}
});
可以看出myApp.js实现了程序所用到的层和场景,它是本程序的核心逻辑,如果你有看过本博对WIN32版本所写的”Cocos2d-x HelloWorld深入分析”,关于层和场景的这些处理还是比较容易理解的。不过adjustSizeForWindow 这个函数对于画布的大小重置也让我很火大,在这里介绍一下修改成让网页窗口大小改变时画布大小自动设置为网页大小的方法。在修改之前先看下这个:
好,现在开始动刀:
在Helloworld层中加入变量
sizeLabel:null,
然后我们在HelloWorld文字标签之后加入:
//显示大小
this.sizeLabel =cc.LabelTTF.create("ClientSize:CanvasSize","Arial",16);
this.sizeLabel.setPosition(cc.p(size.width / 2, 100));
this.addChild(this.sizeLabel, 4);
最后我们在adjustSizeForWindow函数尾部加入:
//字符串变量
var sizeString= "ClientSize:[Width:"+document.documentElement.clientWidth+",Height:"+document.documentElement.clientHeight+"]- bodySize:[Width:" +document.body.clientWidth+",Height:"+document.body.clientHeight+"]-CanvasSize:[Width:"+cc.canvas.width+",Height:"+cc.canvas.height+"]";
this.sizeLabel.setString(sizeString);
运行一下:这样就可以很方便的观察各个大小了。
然后我们来继续修改代码。首先将创建lazyLayer代码屏蔽 :
// var lazyLayer =new cc.LazyLayer();
// this.addChild(lazyLayer);
并将lazyLayer加入当前层的代码
//lazyLayer.addChild(this.sprite, 0);
换成:
this.addChild(this.sprite);
lazyLayer设置大小自适应代码屏蔽:
//lazyLayer.adjustSizeForCanvas();
之后修改adjustSizeForWindow:
adjustSizeForWindow:function () {
/*屏蔽原来的代码。
var margin = document.documentElement.clientWidth - document.body.clientWidth;
if (document.documentElement.clientWidth < cc.originalCanvasSize.width) {
cc.canvas.width = cc.originalCanvasSize.width;
} else {
cc.canvas.width = document.documentElement.clientWidth - margin;
}
if (document.documentElement.clientHeight < cc.originalCanvasSize.height) {
cc.canvas.height = cc.originalCanvasSize.height;
} else {
cc.canvas.height = document.documentElement.clientHeight - margin;
}
*/
//直接将画布大小设为窗口页面大小
cc.canvas.width = document.documentElement.clientWidth;
cc.canvas.height = document.documentElement.clientHeight;
//计算X方向和Y方向的缩放
var xScale = cc.canvas.width / cc.originalCanvasSize.width;
var yScale = cc.canvas.height / cc.originalCanvasSize.height;
/*
if (xScale > yScale) {
// xScale = yScale;
}
cc.canvas.width = cc.originalCanvasSize.width * xScale;
cc.canvas.height = cc.originalCanvasSize.height * yScale;
*/
var parentDiv = document.getElementById("Cocos2dGameContainer");
if (parentDiv) {
parentDiv.style.width = cc.canvas.width + "px";
parentDiv.style.height = cc.canvas.height + "px";
}
//设置渲染缓冲区位置和缩放。
cc.renderContext.translate(0, cc.canvas.height);
cc.renderContext.scale(xScale, yScale);
cc.Director.getInstance().setContentScaleFactor(xScale);
//字符串变量
var size = cc.Director.getInstance().getWinSize()
var sizeString = "ClientSize:[Width:"+document.documentElement.clientWidth+",Height:"+document.documentElement.clientHeight+"] - bodySize:[Width:" + document.body.clientWidth+",Height:"+document.body.clientHeight+"]- CanvasSize:[Width:"+cc.canvas.width+",Height:"+cc.canvas.height+"]";
this.sizeLabel.setString(sizeString);
},
这样当我们拖放窗口时,画布大小就按窗口大小了。
最后我们看main.js:代码,打开main.js:
//由cc.Application派生出本程序所用的cocos2d-x的程序类。
var cocos2dApp = cc.Application.extend({
//创建一个变量config,初始化其值为之前创建的网页文档的成员结构变量ccConfig.
config:document['ccConfig'],
//重载构造函数ctor。
ctor:function (scene) {
//调用父类的相应函数。
this._super();
//将参数场景scene保存到成员变量startScene做为要启动的场景。
this.startScene = scene;
//设置Cocos2d-x的一些配置。
//使用DEBUG标记
cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
//初始化Debug的一些设置。
cc.initDebugSetting();
//取得config中tag结构变量值,即字符串’gameCanvas'做为参数调用cc.setup函数。
cc.setup(this.config['tag']);
//在Cocos2d-x正被加载时的响应函数。
cc.Loader.getInstance().onloading = function () {
//设置调用程序加载场景的draw函数,这里是为了显示进度条。
cc.LoaderScene.getInstance().draw();
};
//在Cocos2d-x被加载完时的响应函数。
cc.Loader.getInstance().onload = function () {
//加载完调用程序控制管理器的didFinishLaunchingWithOptions函数。
cc.AppController.shareAppController().didFinishLaunchingWithOptions();
};
//设置是否要预加载一些相关文件。
cc.Loader.getInstance().preload(g_ressources);
},
//重载程序的applicationDidFinishLaunching函数。
applicationDidFinishLaunching:function () {
// 初始化Cocos2d-x的设备。
var director = cc.Director.getInstance();
// 设置使用高清屏显示模式
// director->enableRetinaDisplay(true);
// 从config中的showFPS变量取得设置是否显示FPS
director.setDisplayStats(this.config['showFPS']);
// 设置FPS
director.setAnimationInterval(1.0 / this.config['frameRate']);
//运行当前要启动的场景。
director.runWithScene(new this.startScene());
return true;
}
});
//这里创建一个程序的实例,运行场景HelloWorldScene。
var myApp = new cocos2dApp(HelloWorldScene);
main.js还是很容易理解的,创建场景运行场景。但这里有一个重要的函数cc.setup。它必须讲一下:
打开coco2d/platform下的CCApplication.js我们来看一下:
//定义cc.setup函数,参数有三个,
cc.setup = function (el, width, height) {
//取得cc中id为el的值或者id为 ’#’+el的值。
var element = cc.$(el) || cc.$('#' + el);
//如果元素的tgaName变量值为’CANVAS’,判断参数有效,保存宽度和高度。
if (element.tagName == "CANVAS") {
width = width || element.width;
height = height || element.height;
//新建一个HTML5中的DIV标记给cc.container做为存放画布的区域层。
cc.container = cc.$new("DIV");
//保存画布
cc.canvas = element;
//将画布放入到DIV中。
cc.canvas.parentNode.insertBefore(cc.container, cc.canvas);
cc.canvas.appendTo(cc.container);
//判断参数有效,如果有效,取参数宽高,如果无效,取480,320。
cc.container.style.width = (width || 480) + "px";
cc.container.style.height = (height || 320) + "px";
//设置DIV的id为’Cocos2dGameContainer’,在myApp.js中有取得网页中id为Cocos2dGameContainer的文档div元素,自然就是指这个DIV了。
cc.container.setAttribute('id', 'Cocos2dGameContainer');
//设置DIV的画布的大小与DIV一致。
cc.canvas.setAttribute("width", width || 480);
cc.canvas.setAttribute("height", height || 320);
} else {//如果元素的tgaName变量值为’DIV’。
if (element.tagName != "DIV") {
cc.log("Warning: target element is not a DIV or CANVAS");
}
//判断参数有效,如果有效,取参数宽高,如果无效,取DIV的宽高。
width = width || parseInt(element.style.width);
height = height || parseInt(element.style.height);
//新建一个HTML5中的Canvas标记返回给cc.canvas
cc.canvas = cc.$new("CANVAS");
//在cc.canvas下增加一个子类名称为gameCanvas
cc.canvas.addClass("gameCanvas");
//设置DIV的画布的大小与DIV一致。
cc.canvas.setAttribute("width", width || 480);
cc.canvas.setAttribute("height", height || 320);
//保存DIV到cc.container并将画布放入到这个DIV之中。
cc.container = element;
element.appendChild(cc.canvas);
//判断参数有效,如果有效,取参数宽高,如果无效,取480,320。
cc.container.style.width = (width || 480) + "px";
cc.container.style.height = (height || 320) + "px";
}
//设置DIV使用相对布局方式和style属性。
cc.container.style.position = 'relative';
cc.container.style.overflow = 'hidden';
cc.container.top = '100%';
//这里取出cc.canvas的Context给cc.renderContext,即设置渲染目标缓冲区为上面创建的DIV的显示设备上下文。
cc.renderContext = cc.canvas.getContext("2d");
//这里设置渲染目标缓冲区类型为画布类型
cc.renderContextType = cc.CANVAS;
//如果渲染目标缓冲区类型为画布类型
if (cc.renderContextType == cc.CANVAS) {
//因为cocos2d-x的坐标系是左下角为0,0点,而html的坐标系为左上角0,0点,为了在html上显示正确的图像,将渲染目标缓冲区设置到画布的左下角位置。
cc.renderContext.translate(0, cc.canvas.height);
//创建一个可以绘制到标缓冲区的cc.drawingUtil实例对象。
cc.drawingUtil = new cc.DrawingPrimitiveCanvas(cc.renderContext);
}
//设置Cocos2dx中的画布大小。
cc.originalCanvasSize = cc.size(cc.canvas.width, cc.canvas.height);
//设置DIV。
cc.gameDiv = cc.container;
//输出引擎版本到日志
cc.log(cc.ENGINE_VERSION);
//设置关闭响应菜单
cc.setContextMenuEnable(false);
//是否是移动游览器,如果是,增加对于用户输入控制的处理。
if(cc.Browser.isMobile)
cc._addUserSelectStatus();
//下面是一些显示属性的设置和响应。
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
function handleVisibilityChange() {
if (!document[hidden])
cc.Director.getInstance()._resetLastUpdate();
}
if (typeof document.addEventListener === "undefined" ||
typeof hidden === "undefined") {
cc.isAddedHiddenEvent = false;
} else {
cc.isAddedHiddenEvent = true;
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
};
好了,所有的js代码基本讲完了,现在为了更好的显示整个程序的流程,现在我们用安装FireBug的Firefox浏览器来进行调试。请先安装一下Firefox,然后在组件管理器里安装FireBug.
FireBug可以很方便的调试js并监控变量和堆栈。
用Firefox打开index.html。之后我们在画布上右键“使用FireBug查看元素”:
可以看到相应语句对应的元素在网页上反蓝显示。
我们在FireBug里开启脚本进入cocos2d.js,我们在其中的尾部加入断点后重新载入页面,我们会看到中断的代码以及右边的监控:
我们可以看到d.body.appendChild的参数s的属性表为
src=”../cocos2d/platform/jsloader.js”,id=”cocos2d-html5”.
所以执行完这一句之后会调用执行jsloader.js,我们在其增加本实例所用的js处加入断点。
可以看到.在右边que的数组元素尾部增加了“resource.js”,”myApp.js”,”main.js”。
我们在main.js里可以增加断点看一下cc.setup的函数执行情况:按F11进入:
进入函数内部我们可以在右边看到参数值并跟踪执行:
通过FireBug的跟踪,我们可以深入的理解js脚本的整个执行情况。在main.js中我们可以加断点观察当前网页上的显示状态,如果没有断点,你是否有看到过这个进度显示的页面呢?好了,下课!