coco2d Javascript跨平台游戏开发:入门指南

翻译:有二

校对:glory, 子龙山人

原文:How To Make a Cross-Platform Game with Cocos2D Javascript Tutorial: Getting Started

这不是一张图片这是个游戏!用鼠标点击

你是否知道你可以做个COCO2D游戏,让这个游戏可以同时运行在IPhone, Mac, Andriod和Web中,并且它们都共享同一份代码吗? 不相信我吗?你试着点击右边上的截图,实际上这就是一个Coco2d游戏!

你可以做到的,你只需要采用一种新的神奇的Coco2D技术----Cocos2D Javascript。 它允许你写一次游戏代码,并能够以完全本地化app的速度在任何地方运行它。现在新技术的唯一问题就是文档不足,但是我们绝不会投降,我们可以弥补它。

在本教程中,你将采用cocos2d-javascript来移植raywenderlich.com的经典游戏Ninjas Going Pew-Pew. 当我学习新框架时,我就会想去实现这款游戏。因为这个游戏不仅简单,而且涵盖了游戏开发中的大部分重要思想。

这个教程适合以下2类人,一种是完全不懂Cocos2D, 还有一种是已经熟悉了Cocos2DIOS,并想学习Cocos2D Javascript。 但是,这个教程还是假设你是有一些Javascript基础的一类人。如果你没有接触过 Javascript,我推荐一本《Javascript:The Definitive Guide》,我就是通过阅读该书来学习这门语言的。

继续阅读并学习本教程,成为Cocos2D-Javascript大神吧!

关于Cocos2D Javascript

在你开始Coding 之前,先了解Cocos2D Javascript 是什么, 它是怎么工作的,这对你很重要。目前有三种Cocos2D变体(cocos2d-iphone, cocos2d-x, 和 coco2d-html5),它们一起共享了一套Javascript API。它的基本思想是,你只需要使用Javascript编写核心游戏玩法。

  • Cocos2d-iphone和cocos2d-x引用了一个叫做SpiderMonkey的库来运行你写的Javascript代码,但在幕后,所有的核心Cocos2D框架代码本身仍然是用OpenGL / objective - C / C + +编写,所以它还是跑得很快。
  • cocos2d-html 直接在浏览器中跑Javascript,正如你预想的那样。另外,CocosBuilder 场景编辑器完全兼容Javascript API。想要看一个完整的采用cocos2d Javascript编写的游戏例子,可以check out我在一月份的 One Game A Month 中提到的游戏: :Confinement.,这个游戏就是利用Javascript 绑定,能够在web ,ios, mac等等平台上运行。Cocos2D Javascript 绑定是一项很时髦的新技术,新技术出来都会有些问题。但它是未来,所以这绝对是值得学习和关注的!

先有JavaScript代码,还是先有框架?

总的来说,你编写一次Javascript代码,就能够采用上述任何游戏框架来运行它。但你必须先从某一个框架开始学习,在初学者中我发现最简单的是使用cocos2d-html5。

这是因为cocos2d-html5他本身就是用Javascript编写的,所以当你调试的时候,可以进入框架内部查看代码。查看框架代码是很有必要的,这能让我们更好地了解错误原因。你将要在本教程中学习的内容,就是用cocos2d-html5先做出一个游戏(web版)并把这代码放到上述其他框架中运行(使之能够同时运行在Android,ios上面)。

入门指南:

首先:在这里下载starter project,解压zip文件, 你将会看到下面目录结构:

im1

Starter project包含以下文件夹:

  • Art: 制作SimpleGame游戏时所需要的图片目录-一个怪物,一个忍者,和他的忍者飞镖。
  • Platform: 存放每种框架代码的四个空目录,在教程后面将会填充这些空目录。现在我给你列出这些空目录,只是为了目录结构的完整。
  • Sounds: 背景音乐 和“pew-pew”声音效果,这些文件的作者是 truly。
  • 注意,Starter project 没有包含任何的代码,因为那是你的工作。

Hello ,Cocos2D-Javascript!

你准备好最后看到这个神奇的跨平台的Javascript代码了吗?让我们试一试,并创建一个简单的Cocos2D场景显示Hero精灵。当你引用art目录中的images 及Cocos2D-Javascript中的其他资源,你必须用特殊的数组包含他们,数组取名为g_ressources(是的,这命名是有意义的),以致框架能加载他们,所以第一步是添加英雄精灵到特殊的数组中。用你喜欢的编辑器创建一个新文件,文件名为Cocos2DSimpleGame\Src\resource.js(最近我使用的的Sublime Text2),并用以下内容修改文件中的内容。

var dirArt = "Art/";
var s_player = dirArt + "player.png";
 
var g_ressources = [
 
    {type:"image", src:s_player}
 
];

这仅仅只是添加了一张图片到你的资源列表中(你的玩家图片)。稍后你将要添加Art目录和Sounds目录下的资源到这个资源列表中。但是,现在我们只要这一张图片就行。

接下来,你讲创建一个简单的Cocos2D 层来放置这种图片。创建一个新文件名为Cocos2DSimpleGame\Src\MainLayer.js并用以下内容替换之:

// 1
var MainLayer = cc.LayerColor.extend({
 
    // 2
    ctor:function() {
        this._super();
 
        // 3
        cc.associateWithNative( this, cc.LayerColor );
    },
 
    // 4
    onEnter:function () {
        this._super();
 
        // 5
        var player = cc.Sprite.create(s_player);
 
        // 6
        player.setPosition(player.getContentSize().width / 2, winSize.height / 2);
 
        // 7
        this.addChild(player);
    }
 
});

让我们一行一行的阅读下这段代码:

1. 创建一个MainLayer类,该类继承了Cocos2D的LayerColor类,注意,在Cocos2DJavascript bindings中,所有的Cocs2D类都有个cc前缀。

2. 创建一个构造函数,该构造函数会调用基类的构造函数。

3. 在Cocos2D Javascript 绑定中, 无论什么时候,只要你继承了Cocos2D类,你就必须要调用这个方面来保证你的类与cocos2D类能更好的合作。

4. 当这个节点第一次添加到场景中,Cocos2D将会调用这个方法,所以这是把layer初始化代码替换的好地方。

5. 这行将创建一个精灵并用变量player保存,注意:是通过参数(该参数为一个已经创建了的常量精灵)传递给该变量

6. 设置精灵在屏幕中间,其中winSize是一个常量,之后我们将会定义它。

7. 最后把精灵添加到图层中。

然后,在文件的后面添加下面的方法。

// 1
MainLayer.create = function () {
    var sg = new MainLayer();
    if (sg && sg.init(cc.c4b(255, 255, 255, 255))) {
        return sg;
    }
    return null;
};
 
// 2
MainLayer.scene = function () {
    var scene = cc.Scene.create();
    var layer = MainLayer.create();
    scene.addChild(layer);
    return scene;
};

这是创建对象的2个辅助方法

1. 第一个方法是,创建一个MainLayer实例

2. 第二个方法是,创建一个新的场景并把创建MainLayer的对象以孩子形式添加到场景中。

现在这只是创建一个MainLayer.js文件,最好代码是你能写出跨平台的代码,并能工作在ios,Android等等平台中。

Hello, Cocos2D-HTML5!

由于之前我提到过,你首先需要制作一个cocos2d-HTML5版本的游戏。然后把它移植到你想要的平台上去。

下载最新的版本latest version of Coos2D-HTML5,,这是我写教程时用到的最新的版本V2.1,并解压到你硬盘中的任何目录下,只要这个目录是安全的。

然后,把Cocos2D-HTML5目录下的cocos2d, CocosDenshion, 和extensions 目录拷贝到
Cocos2DSimpleGame\Platform\HTML5目录下。

im2

把Cocos2D-HTML5所有代码拷贝到你工程的目录下,以便你更好的引用他。注意:你不能这样就直接发布游戏,在第二部分你将会学习到更多关于这方面的内容。目前这样做会有利于提高你的调试及开发能力。

接下来,创建一个新文件,命令为Cocos2DSimpleGame\index.html并用以下内容修改文件内容。




    
    Cocos2D-JS Simple Game Demo | raywenderlich.com



 

这是一些简单的HTML语言,目的是让cocos2D出现在页面的中间。如果你对HTML语言比较陌生,不要担心,你可以用这部分代码为一个模板,基本能满足你的需求。

有2处比较重要的地方我要指出:


这是设置了HTML5层,就是Cocos2D画面要出现的地方,并给这个层的ID为“gameCanvas”,框架则根据ID来识别层。如果你想改变层的大小,则你可以修改上面的数字。


这代码告诉浏览器去寻找一个名为cocosd.js的Javascript文件,这个文件你现在还没有写。

所以现在让我们来添加这个文件,创建一个文件,命名为Cocos2DSimpleGame\cocos2d.js并添加以下内容:

(function () {
    var d = document;
    var c = {
 
        // 1
        menuType:'canvas',
        COCOS2D_DEBUG:2,
        box2d:false,
        chipmunk:false,
        showFPS:true,
        frameRate:60,
        loadExtension:true,
        tag:'gameCanvas', 
 
        // 2
        engineDir:'./Platform/HTML5/cocos2d/',
        appFiles:[
            './Src/resource.js',
            './Src/MainLayer.js',
            './Src/main.js'
        ]
    };
 
    // 3
    window.addEventListener('DOMContentLoaded', function () {
        var s = d.createElement('script');
 
        if (c.SingleEngineFile && !c.engineDir) {
            s.src = c.SingleEngineFile;
        }
        else if (c.engineDir && !c.SingleEngineFile) {
            s.src = c.engineDir + 'platform/jsloader.js';
        }
        else {
            alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
        }        
 
        document.ccConfig = c;
        s.id = 'cocos2d-html5';
        d.body.appendChild(s);
    });
})();

这个文件基本可以作为模板来用,但有一部分你可能想自己改改,所以让我们一起看看这些代码吧。

1. 有各种各样的Cocos2D配置, 如激活框架调试功能,是否引用库文件(Box2D库)等等。

2. 这里你应该指定源文件的目录及文件名,你还记得你是怎么拷贝Platform/HTML5/cocos2d目录的吗?你也要指定你游戏中的Javascript文件。

3. 这仅仅是一些Cocos2D框架运行的入口模板。

你也许发现了2中的main.js文件了,但是你现在还没有写这个文件。这是你运行游戏不得不写的最后一个文件了。

创建一个新文件,命名为Cocos2DSimpleGame\Src\main.js并添加如下代码:

var cocos2dApp = cc.Application.extend({
    config:document['ccConfig'],
    ctor:function (scene) {
        this._super();
        this.startScene = scene;
        cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
        cc.initDebugSetting();
        cc.setup(this.config['tag']);
        cc.Loader.getInstance().onloading = function () {
            cc.LoaderScene.getInstance().draw();
        };
        cc.Loader.getInstance().onload = function () {
            cc.AppController.shareAppController().didFinishLaunchingWithOptions();
        };
        cc.Loader.getInstance().preload(g_ressources);
    },
    applicationDidFinishLaunching:function () {
        var director = cc.Director.getInstance();
        director.setDisplayStats(this.config['showFPS']);
        director.setAnimationInterval(1.0 / this.config['frameRate']);
        // 1
        director = cc.Director.getInstance();
        winSize = director.getWinSize();
        centerPos = cc.p( winSize.width/2, winSize.height/2 );
        director.runWithScene(new this.startScene());
        return true;
    }
});
 
// 2
var director;
var winSize;
var centerPos;
var myApp = new cocos2dApp(MainLayer.scene);

为了运行游戏,你需要创建一个类,该类继承cc.Application,实际做事是在这里。它有个applicationDidFinishLaunching方法,该方法很像ios。除了我标出的2部分,其他部分都是程序的通用方式。

1. 初始化全局变量,我之间就提过的。

2. 声明全局变量,并指出在特定的环境中运行(MainLayer.scene 是你之前创建的一个场景)

最后你可以运行了, 用你喜欢的浏览器打开index.html,就测试了,注意:我很幸运我使用的是Firefox浏览器,Safari浏览器可能有时运行不起来(因为safari的file协议限制,不过可以采用web server的方式来运行))。

如果运行正常,你将会在你的屏幕出现忍者:

im3

移动怪兽

下面你应该想添加一些怪兽到你的屏幕去跟忍者战斗,为了更有趣,你想让怪兽移动。另外不要有太多的怀疑,让我们创建怪兽从屏幕的右边轻飘出来,并设置一个向左运动的行为。

首先,打开Cocos2DSimpleGame\Src\resource.js修改资源文件,并包含以下2个图片文件:

var dirArt = "Art/";
var s_player = dirArt + "player.png";
var s_monster = dirArt + "monster.png";
var s_projectile = dirArt + "projectile.png";
 
var g_ressources = [
 
    {type:"image", src:s_player},
    {type:"image", src:s_monster},
    {type:"image", src:s_projectile}
 
];

然后打开Cocos2DSimpleGame\Src\MainLayer.js并用以下内容替换文件开头部分:

var MainLayer = cc.LayerColor.extend({
 
    _monsters:[],
 
    ctor:function() {
 
        // Rest of file...

这在场景中创建了怪物实例变量,并初始化为空数组,在onEnter方法后添加一个停顿,以及添加一个新方法:

addMonster:function() {
 
    var monster = cc.Sprite.create(s_monster);
 
    // Determine where to spawn the monster along the Y axis
    var minY = monster.getContentSize().height / 2;
    var maxY = winSize.height - monster.getContentSize().height / 2;
    var rangeY = maxY - minY;
    var actualY = (Math.random() * rangeY) + minY; // 1
 
    // Create the monster slightly off-screen along the right edge,
    // and along a random position along the Y axis as calculated above
    monster.setPosition(winSize.width + monster.getContentSize().width/2, actualY);
    this.addChild(monster); // 2
 
    // Determine speed of the monster
    var minDuration = 2.0;
    var maxDuration = 4.0;
    var rangeDuration = maxDuration - minDuration;
    var actualDuration = (Math.random() % rangeDuration) + minDuration;
 
    // Create the actions
    var actionMove = cc.MoveTo.create(actualDuration, cc.p(-monster.getContentSize().width/2, actualY)); // 3
    var actionMoveDone = cc.CallFunc.create(function(node) { // 4
        cc.ArrayRemoveObject(this._monsters, node); // 5
        node.removeFromParent();
    }, this); 
    monster.runAction(cc.Sequence.create(actionMove, actionMoveDone));
 
    // Add to array
    monster.setTag(1);
    this._monsters.push(monster); // 6
 
}

在这里我将以一种啰嗦的方式讲解,以便尽可能的理解。首要的还是我们尽量讨论一些有意义的问题:你简单的计算一下在什么时候创建对象,该对象放置在什么的位置,并添加它到场景中。这跟你创建英雄精灵是一样的。

我将以2种不同的方法解释剩下的代码,以你是否已经熟悉了Cocos2D ios API为准。如果你熟悉cocos2d-ios,你就看情况一。如果不熟悉,则看情况二。你不需要同时看这两种情况的内容。

情况一:我熟悉Cocos2D-IOS

对于从Cocos2D-IOS转Cocos2D-Javascript这里给出了一写参考:

1. Javascript有很方便的参考手册,如Math.random(). 你能在Javascript book I recommended.找到相关的资料。

2. 在objective - c中你会使用monster.postion这样的dot语法,但是在javascript bindings中都是采用monster.setPosition这样的setters语法。

3. cc.p等于cpp宏。

4. 你能通过方法名进入cc.CallFunc.create, 或者你能进入匿名函数,像你在这看到的一样(很像Objective-C中using CCCallBlock)

5. Cocos2D 有一个方法从Javascript数组中移除元素:cc.ArrayRemoveObject.

6. 在Javascript中运用this,而不是self,我很多时候都忘了这个规则,结果导致代码经常出现问题。

情况二:我是个Cocos2D新手

在这里添加动作元素,Cocos2D提供了一些非常方便的生成Action的方法,你能运用这个使你的精灵更灵活,如添加一个移动动作,跳的动作,淡化的动作,动画动作等等,在怪物中我们运用3个动作:

1. ccMoveTo: 你用cc.MoveTo动作物体直接移出屏幕左边,注意:你应该指定运行动作需要的时间,这里你还可以随机给出一个2s~4s的速度。

2. cc.CallFunc:这cc.CallFunc动作允许你指定一个回调函数去运行,当这个动作被调用时。你或者能进入函数名(像这样:怪物移动)或者你能用一个无名的函数显示他

们。在这个游戏中,在怪物移动到屏幕左边时,你应添加一些代码来实现怪物从游戏(或者是怪物数组)中移除,这代码是很重要的,不然就会出现内存泄露。注意:有其他(或更好的)方法去解决这个问题,如可以重复使用精灵数组,但是作为初学者,你还是用移除的这种简单的方法。

3. cc.Sequence: 这cc.Sequence动作允许你一序列动作按顺序执行,一次一个的。这种方法,你可以首先执行cc.MoveTo动作,然后完成cc.CallFun动作。

回到刚才问题:

现在让我们确定你addMonster函数能被定期的调用,这是一种方法。要做这事,添加addMonster, 这个新方法。

gameLogic:function(dt) {
    this.addMonster();
}

并在onEnter方法最后一行添加如下代码:

this.schedule(this.gameLogic, 3);

这会每隔3秒定时的运行你的gameLogic方法去产生一个怪物。保存你的文件,并重启你的浏览器,现在应该有怪物从你的屏幕中飞出来。

im4

射击炮弹

在这节,忍者想要一些技能,所以让我们添加射击技能。有很多的方法你能实现射击功能,但是这个游戏你将这样做,当用户点击屏幕时, 忍者则朝着点击的方向发射炮弹。

我想用cc.MoveTo动作来实现这种发射子弹的动作,这样初学者也能看懂,但是想要灵活运用,你不得不具备一些数学知识。这是因为这个cc.MoveTo需要你给定飞镖前进的目的地,但是你又不能使用这个touch点,因为touch点只是代表了飞镖飞出去的方向。实际上你想保持子弹移动穿过你点击的位置直到子弹移除屏幕。

下图表示的就是这种情况:

im5

正如你所看到的,来自相对于原点及点击点的x,y坐标构成的一个小三角形。你还需要构建一个大的三角形,放大一些比例,你知道了你离开屏幕时的终点位置了。好的,现在进入代码,首先,在文件头添加一个存放炮弹的数组。

_projectiles:[],

然后你必须能响应点击事件在你的层中,但是怎样处理这样依据你的额运行环境,如手机,桌面,或者浏览器。所以在onEnter函数开始的地方添加如下代码,正确的还要调用
this._super():

if( 'touches' in sys.capabilities ) {
    this.setTouchEnabled(true);
}
if( 'mouse' in sys.capabilities ) {
    this.setMouseEnabled(true);
}

这onMouse被回调,如果这里有鼠标输入,或者onTouch被回调如果有触屏输入。

gameLogic方法后,添加如下代码:

locationTapped:function(location) {
    // Set up initial location of the projectile
    var projectile = cc.Sprite.create(s_projectile);
    projectile.setPosition(20, winSize.height/2);
 
    // Determine offset of location to projectile
    var offset = cc.pSub(location, projectile.getPosition()); // 1
 
    // Bail out if you are shooting down or backwards
    if (offset.x <= 0) return;
 
    // Ok to add now - we've double checked position
    this.addChild(projectile);
 
    // Figure out final destination of projectile
    var realX = winSize.width + (projectile.getContentSize().width / 2);
    var ratio = offset.y / offset.x;
    var realY = (realX * ratio) + projectile.getPosition().y;
    var realDest = cc.p(realX, realY);
 
    // Determine the length of how far you're shooting
    var offset = cc.pSub(realDest, projectile.getPosition());
    var length = cc.pLength(offset);
    var velocity = 480.0;
    var realMoveDuration = length / velocity;
 
    // Move projectile to actual endpoint
    projectile.runAction(cc.Sequence.create( // 2
        cc.MoveTo.create(realMoveDuration, realDest),
        cc.CallFunc.create(function(node) {
            cc.ArrayRemoveObject(this._projectiles, node);
            node.removeFromParent();
        }, this)
    ));
 
    // Add to array
    projectile.setTag(2);
    this._projectiles.push(projectile);
},
 
onMouseUp:function (event) {
    var location = event.getLocation();
    this.locationTapped(location);
},
 
onTouchesEnded:function (touches, event) {
    if (touches.length <= 0)
        return;
    var touch = touches[0];
    var location = touch.getLocation();
    this.locationTapped(location);
}

我要再一次依据你是否已经熟悉Cocos2D-IOS来做不同的解释:

解释一:假设你熟悉Cocos2D-IOS

这里提出几点建议给Cocos2D-IOS转Cocos2D-Javascript的程序员

1.这方法用点演示数学,你知道你喜欢的ccpAdd,ccpSub在这仍然存在。他们仅仅是改变了以下名字,例如:cc.pSub就等同于ccpSub。

2.你能创建一序列的动作就像你在Cocos2D-IOS一样。

解释二:你完全是个Cocos2D新手

onMouseUp和onTounchesEnded方法会获取鼠标或触摸位置,并把这个值通过locationTapped函数分发出去。

这方法开始就载入一个炮弹精灵,并和往常一样初始化了放置子弹的位置。这时你决定你需要炮弹移动到哪里,可以使用忍者与触摸点之间的向量为参考,根据之前描述的逻辑算法去计算子弹最终移动的位置。

注意,这个算法并不是完美的。假设你让子弹一直运动到屏幕之外的X位置,此时,子弹的y坐标可能早就超过屏幕之外了。你可以使用一些其它的最短距离算法,判断到底是x方向先出屏幕还是y方向先出屏幕。 作为一个新手入门教程,我们就不在这里再作讨论了。

最后一件事,你计算子弹移动的时间。为了让子弹在任何方向上都是以恒定的速度运行,你不得不再用一些数学来处理了。你能通过cc.pLength函数计算出运动的速度。

一旦你有了这个距离,你仅仅通过除以速度就能获取时间了。这是因为速度=距离除以时间,或者是时间=距离除以速度。

其他部分的设置动作就想你朝着目标设置一样。保存文件,刷新你的浏览器,现在你的忍者应该能发射子弹来迎接面朝你扑过来的敌人了。

im6

碰撞检测

所以现在你的忍者可以朝任何方向发射子弹了,但是你的忍者真的想去做的是打到怪物,所以让我们添加一些代码来检测你的子弹与怪物什么时候碰撞。

有很多方法去解决这个问题。采用Cocos2D,可以运用一个物理引擎库:Box2D 或者Chipmunk,但是为了保持简单,我们自己将实现一个简单的碰撞检测。

你已经把怪物,炮弹存放在数组中了。现在你要做的是定期的检查是否发生了碰撞。

为了做到这些,我们添加如下方法在onTouchesEnded函数中:

update:function (dt) {
    for (var i = 0; i < this._projectiles.length; i++) {
        var projectile = this._projectiles[i];
        for (var j = 0; j < this._monsters.length; j++) {
            var monster = this._monsters[j];
            var projectileRect = projectile.getBoundingBox();
            var monsterRect = monster.getBoundingBox();
            if (cc.rectIntersectsRect(projectileRect, monsterRect)) {
                cc.log("collision!");
                cc.ArrayRemoveObject(this._projectiles, projectile);
                projectile.removeFromParent();
                cc.ArrayRemoveObject(this._monsters, monster);
                monster.removeFromParent();                
            }
        }
    }
}

以上代码相当于做了一个清除。你不停的通过你的子弹跟怪物,生成的矩形边框,并用CGRectIntersectsRect去检查重叠。如果有重叠,你把他们从场景和数组中移除。

注意:你不要像Objective-C一样创建分离“toDelete”数组,因为通过迭代器从一个数组中移除元素在Javascript中是安全的。

在你开始射子弹前你还需要在做一件事,通过在你的onEnter方法中加入以下代码让这个方法总是被调用:

this.scheduleUpdate();

保存文件并刷新你的浏览器,现在当你的弹丸碰到目标的时候他们都会消失!

音乐和音效

现在你相当于完全了能跑的游戏了,你还需要添加一些声音效果(你还么有的声音效果)和一些简单的游戏逻辑。

首先更新Cocos2DSimpleGame\Src\resource.js添加声音效果:

var dirArt = "Art/";
var dirSounds = "Sounds/";
 
var s_player = dirArt + "player.png";
var s_monster = dirArt + "monster.png";
var s_projectile = dirArt + "projectile.png";
 
var s_bgMusic = dirSounds + "background-music.mp3";
var s_bgMusicOgg = dirSounds + "background-music.ogg";
var s_bgMusicCaf = dirSounds + "background-music.caf";
 
var s_shootEffect = dirSounds + "pew-pew-lei.mp3";
var s_shootEffectOgg = dirSounds + "pew-pew-lei.ogg";
var s_shootEffectWav = dirSounds + "pew-pew-lei.wav";
 
var g_ressources = [
 
    {type:"image", src:s_player},
    {type:"image", src:s_monster},
    {type:"image", src:s_projectile},
 
    {type:"sound", src:s_bgMusic},
    {type:"sound", src:s_bgMusicOgg},
    {type:"sound", src:s_bgMusicCaf},
 
    {type:"sound", src:s_shootEffect},
    {type:"sound", src:s_shootEffectOgg},
    {type:"sound", src:s_shootEffectWav}
 
];

注意:背景音乐和声音效果应该保存三种格式:mp3, ogg, and wav. 这是因为不是所有浏览器,都支持所有的格式,所有通过添加三种格式,我们要尽可能的让玩家能听到声音。Cocos2D将判断浏览器支持的格式,我们将添加相应的格式文件。只要他们是相同的文件名。

注意:如果你想知道如何对这些格式进行相互转换,这是我做的:

1. 我通常用一个WAV文件。

2.我然后运用iTunes去转换为一个MP3.为了做这事,去iTunes Preferences\General\Import Settings and change Import Using to MP3 Encoder。然后在iTunes工具导入一个WAV文

件,并点击右键,选择Create MP3 Version将创建一个MP3格式文件。

3. 我用oggenc工具将MP3格式转换为一个OGG,我有一个手册介绍怎么安装它。

现在,是时候添加声音效果了,回到Cocos2DSimpleGame\Src\MainLayer.js,在文件头添加如下代码:

var audioEngine = cc.AudioEngine.getInstance();

这获取一个全局引用一个声音引擎,之后你将会用到它,然后添加这行到你的onEnter函数末尾:

audioEngine.playMusic(s_bgMusic, true);

添加以下代码到locationTapped的结尾

audioEngine.playEffect(s_shootEffect);

保存文件并重新刷新浏览器,现在你应该有些音乐了。

输和赢

最后,让我们创建一个新的场景和层,该层将为你胜利或者失败提供说明。创建一个新文件Cocos2DSimpleGame\Src\GameOver.js并添加如下内容:

var GameOver = cc.LayerColor.extend({
 
    _won:false,
 
    ctor:function() {
        this._super();
        cc.associateWithNative( this, cc.LayerColor );
    },
 
    onEnter:function () {
 
        this._super();
 
        var director = cc.Director.getInstance();
        var winSize = director.getWinSize();
        var centerPos = cc.p( winSize.width/2, winSize.height/2 );
 
        var message;
        if (this._won) {
            message = "You Won!";
        } else {
            message = "You Lose :[";
        }
 
        var label = cc.LabelTTF.create(message, "Arial", 32);
        label.setColor(cc.c3b(0, 0, 0));
        label.setPosition(winSize.width/2, winSize.height/2);
        this.addChild(label);
 
        this.runAction(cc.Sequence.create(
            cc.DelayTime.create(3),
            cc.CallFunc.create(function(node) {
                var scene = MainLayer.scene();
                cc.Director.getInstance().replaceScene(scene);
            }, this)
        ));
 
    }
});
 
GameOver.create = function (won) {
    var sg = new GameOver();
    sg.won = won;
    if (sg && sg.init(cc.c4b(255, 255, 255, 255))) {
        return sg;
    }
    return null;
};
 
GameOver.scene = function (won) {
    var scene = cc.Scene.create();
    var layer = GameOver.create(won);
    scene.addChild(layer);
    return scene;
};

这是一个层包含一个标签在你的屏幕中间(cc.LabelTTF),该标签包含一些信息。创建一个动作等待三秒回到主界面。

为了使用这个新场景,回到Cocos2DSimpleGame\Src\MainLayer.js并修改一些代码:

// Add this new instance variable to the top of the file
_monstersDestroyed:0,
 
// Add inside update, right after monster.removeFromParent():
this._monstersDestroyed++;
if (this._monstersDestroyed >= 2) {
    var scene = GameOver.scene(true);
    cc.Director.getInstance().replaceScene(scene);
}
 
// Add inside addMonster, right after node.removeFromParent():
var scene = GameOver.scene(false);
cc.Director.getInstance().replaceScene(scene);

最后,当你添加了一个新文件,你需要在cocos2d.js引用它。所以打开Cocos2DSimpleGame\cocos2d.js修改如下appFiles数组:

appFiles:[
    './Src/resource.js',
    './Src/MainLayer.js',
    './Src/GameOver.js',
    './Src/main.js'
]

就是这样,保存文件,重新刷新浏览器,现在你的Cocos2D Javascript游戏完成了。

im7

还有一件事情

Cocos2D-Javascript不是一直强调跨平台吗,对么?

让我展示你看,最多5秒钟让你相同的代码怎么运行在iPhone。

好的,假设你有了最新的Coscos2D-iOS版本已经安装了,如果没有,下载最新的不稳定版 2.X version (2.1-rc0a)然后安装模板。

注意:下载最新你能安装的Cocos2D版本,在终端中运行如下命令cd~/Downloads/

cocos2d-iphone-2.1-rc0

./install-templates.sh -f -u

然后在XCode创建一个iOS\cocos2d v2.x\cocos2d iOS with JavaScript新工程模板,命名为Cocos2DSimpleGame并保存到Cocos2DSimpleGame\Platform\iOS目录下。

然后找到你的Cocos2DSimpleGame文件夹,选中Art, SoundsSrc文件夹,把他们拖到你的XCode工程中。注意:你弹出框出现时,选择Create folder references for any added folders并像如下图一样设置一些属性:

im8

如果你没有错误,你的文件夹应该是蓝色的在XCode像如下截图一样,如果你的是黄色的,你选中groups”替换,移除他们重新试一次。

im9

接下来,打开Resources\main.js并用以下内容替换:

require("jsb.js");
require("Src/resource.js");
require("Src/MainLayer.js");
require("Src/GameOver.js");
 
director = cc.Director.getInstance();
winSize = director.getWinSize();
centerPos = cc.p( winSize.width/2, winSize.height/2 );
 
function run()
{
    director.runWithScene( MainLayer.scene() );
}
 
run();

这里你加载你的游戏文件,设置全局变量,并运行主场景。

像这样,编译,运行,现在你可以相同的代码运行在你的iPhone了,但使用本机Cocso2DiPhone !

im10

注意:如果你Javascript代码是错误的,有时你会看到一个错误在Xcode console,但是大多数默认的Xcode会给你一些没有用的错误提示。

这也是其中一个我为什么选择Cocos2D-HTML5作为初学者开发的理由。

标签: none

?>