神刀安全网

Cocos2d-JS连载之打飞机游戏学习基础概念

  打飞机这个游戏并不是我原创,只是拿来学习使用。望原作者见谅。刚刚开始是强烈建议简书可以上传源代码的,但是后来一想,已经有了github了可以直接链接过去,都不用简书浪费资源了。哈哈哈哈。我讲要分析的项目上传到了我的github仓库:github AirBarons

游戏玩耍地址:http://112.126.90.18/airbarons/
  先看一下AirBarons目录结构。

Cocos2d-JS连载之打飞机游戏学习基础概念
AirBarons目录结构

  • project.json 项目的一些配置信息

    "project_type": "javascript",   "debugMode" : 1,   "showFPS" : true,   "frameRate" : 60,   "id" : "gameCanvas",   "renderMode" : 0,   "engineDir":"frameworks/cocos2d-html5",   "modules" : ["cocos2d"],

    这些前一篇已经说过了。
    看下AirBarons项目用到了哪些js文件

    "jsList" : [       "src/resource.js",        "src/config/GameConfig.js",       "src/config/EnemyType.js",       "src/config/Level.js",        "src/mainMenu/scene/MainMenu.js",       "src/mainMenu/layer/MMBackgroundLayer.js",       "src/mainMenu/layer/MMMainMenuLayer.js",       "src/mainMenu/layer/MMTouchLayer.js",        "src/setting/scene/Setting.js",       "src/setting/layer/STBackgroundLayer.js",       "src/setting/layer/STTouchLayer.js",        "src/about/scene/About.js",       "src/about/layer/ABBackgroundLayer.js",       "src/about/layer/ABTouchLayer.js",        "src/gamePlay/classes/LevelManager.js",       "src/gamePlay/scene/GamePlay.js",       "src/gamePlay/layer/GPBackgroundLayer.js",       "src/gamePlay/layer/GPTouchLayer.js",       "src/gamePlay/sprite/ShipSprite.js",       "src/gamePlay/sprite/BulletSprite.js",       "src/gamePlay/sprite/EnemySprite.js",       "src/gamePlay/sprite/ExplosionSprite.js",       "src/gamePlay/sprite/SparkEffectSprite.js",        "src/gameOver/scene/GameOver.js",       "src/gameOver/layer/GOBackgroundLayer.js",       "src/gameOver/layer/GOTouchLayer.js"    ]

    基本概念之resource
    看到加载的第一个文件就是 “src/resource.js”,典型的js文件。定义了res对象,里面存储的是图片和声音的地址对象,最后将res对象的属性都放到了全局g_resources数组中了

var res = {     HelloWorld_png : "res/HelloWorld.png",     CloseNormal_png : "res/CloseNormal.png",     CloseSelected_png : "res/CloseSelected.png",   //    shared     sh_arial_14_fnt : 'res/shared/arial-14.fnt',     sh_arial_14_png : 'res/shared/arial-14.png',  //    mainMenu     TextureTransparentPack_plist : "res/mainMenu/textureTransparentPack.plist",     TextureTransparentPack_png : "res/mainMenu/textureTransparentPack.png",     mm_bg_png   : "res/mainMenu/bg.png",     mm_logo_png : "res/mainMenu/logo.png",     mm_mune_png : "res/mainMenu/menu.png",     mm_flare_jpg : "res/mainMenu/flare.jpg",     mm_btnEffect : "res/sound/effect/buttonEffect.mp3",     mm_bgMusic_mp3 : "res/sound/music/mainMainMusic.mp3",  //    gamePlay     gp_TextureOpaquePack_plist : "res/gamePlay/textureOpaquePack.plist",     gp_TextureOpaquePack_png : "res/gamePlay/textureOpaquePack.png",     gp_b01_plist : "res/gamePlay/b01.plist",     gp_b01_png : "res/gamePlay/b01.png",     gp_Explosion_plist : "res/gamePlay/explosion.plist",     gp_Explosion_png : "res/gamePlay/explosion.png",     gp_explodeEffect_mp3 : 'res/sound/effect/explodeEffect.mp3',     gp_bgMusic_mp3 : "res/sound/music/bgMusic.mp3",     gp_shipDestroyEffect_mp3 : 'res/sound/effect/shipDestroyEffect.mp3',  //    setting     st_menuTitle_png : "res/setting/menuTitle.png",  //    gameOver     go_gameOver_png : "res/gameOver/gameOver.png",     go_cocos2d_html5_png : "res/gameOver/cocos2d-html5.png"  };  var g_resources = []; for (var i in res) {     g_resources.push(res[i]); }
  • 接着是游戏js中用到的配置相关参数js的引入
    "src/config/GameConfig.js", "src/config/EnemyType.js", "src/config/Level.js",
  • 接着是到了游戏各个分类的相关js文件的引入,该游戏有 设置关于游戏游戏结束后四个模块。下面看看这四个模块都用到了Cocos2d 的哪些基础概念。

首先说一下js的地址是:api-ref/js/V3.12/
看main.js

cc.game.onStart = function(){     cc.view.adjustViewPort(true);     cc.view.setDesignResolutionSize(320, 480,                 cc.ResolutionPolicy.SHOW_ALL);     cc.view.resizeWithBrowserSize(true);     cc.LoaderScene.preload(g_resources, function () {         cc.director.runScene(new MainMenuScene());     }, this); }; cc.game.run();
  1. cc.game
    这个是An object to boot the game.(启动游戏的对象)其中有 end(游戏停止)、isPaused(检查游戏是否停止)、pause(停止游戏)、prepare(游戏前准备)、restart(游戏重新启动)
    resume(继续游戏)、run(启动游戏) setFrameRate(设置帧率)、step(一帧一帧运行游戏)这些方法。还有很多属性onStart就是其中的一个属性,这里将onStart定义成了一个function,在scripts引擎加载完毕后就会回调。
  2. cc.view
    在onStart回调的方法中设置了cc.view的相关属性,cc.view是个代表了游戏窗口的单例的对象
    这里使用setDesignResolutionSize(width, height, resolutionPolicy)设置了游戏窗口的大小和屏幕适配的策略。屏幕大小自适应的涉及到cc.ResolutionPolicy,其中有六种方式

    EXACT_FIT会拉伸游戏,充满整个屏幕,最简单最粗暴
    SHOW_ALL保持游戏原比例,让一边占满屏幕,另外一侧黑边
    NO_BORDER跟SHOW_ALL类似,但让短边占满屏幕,另外一侧超出屏幕,不显示黑边,一部分画面在屏幕外,无法显示
    FIXED_HEIGHTFIXED_WIDTH都是NO_BORDER的升级版,指定那一侧充满屏幕,另外一侧超出屏幕,
    UNKNOWN 六种方案。该游戏选择的是SHOW_ALL
    接着使用resizeWithBrowserSize(enabled)
    这个方法只在web中起作用,canvas 跟着浏览器得大小变动而自适应。

  3. cc.LoaderScenecc.director
Cocos2d-JS连载之打飞机游戏学习基础概念
Node子类的结构图

这里涉及到Node、Scence、Director。即节点、导演和场景 ,其实还有Layer(层)、Sprite(精灵)。节点是Node是上层的对象。在Cocos2d-x-3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点(即对象,游戏中基本上所有的类都派生于节点类Node)。可以执行Action来修改游戏节点的属性,使其移动、旋转、放大、缩小等等。
看下官网给出的图即可明白

Cocos2d-JS连载之打飞机游戏学习基础概念
官网给出的关系图

到眼控制着场景,层属于场景中的一个场景。然后精灵有事属于场景中的一个东东。精灵的移动,旋转,缩放,执行动画,并接受其他转换构成层的东西,各个层之间顺序执行然后构成一个场景。场景之间的切换最终构成了一个游戏,执行者就是导演。
cc.LoaderScene.preload了g_resources后传入回调函数
function () {
cc.director.runScene(new MainMenuScene());
}回调函数是导演执行了第一个场景。
再传入当前的对象 this);
好了看new出的第一个场景 MainMenuScene 看一下场景定义的规范

var MainMenuScene  = cc.Scene.extend({  //this._super();重写后这个方法一定要记得写上,要不然导致后续不会执行 //这里是场景的各个函数的重写 场景是是继承自node的所以node中方法也可以被重写,其中这里有onEnter方法,这个方法是不需要主动调用的。 官方给出的解释Event callback that is invoked every time when CCNode enters the 'stage'. 可以看出 这个方法会每次都被调用 当进入到stage后. var layer = new MainMenuLayer();   this.addChild(layer);这个场景只有一个层,最后将这个层假如到这个场景,由于只有一个层所以都不需要指定执行的顺序。 })

下面看MainMenuLayer,层的规范定义是

var MainMenuLayer = cc.Layer.extend({ //    这里可以声明属性     _backgroundLayer : null,     _touchLayer      : null, ctor方法相当于是构造方法,你在new这个层的时候就会被调用。 构造方法中又可以调用其他的方法 这里是调用了addBackgroundLayer和addTouchLayer可以看出是加了两个子层到该层中,这个是按加入的顺序执行的。 })

看一下假如的MMBackgroundLayer和MMTouchLayer层,
MMBackgroundLayer是创建了一个背景层,这个和上一个所讲的层基本一致。里面涉及到了精灵的创建

 this._sptBg = new cc.Sprite(res.mm_bg_png);         this._sptBg.attr({             anchorX : 0.5,             anchorY : 0.5,             x: GC.w_2,             y: GC.h_2         });

可以看出精灵的创建方式 可以指定属性一个其中有anchorPoint 锚点坐标,默认是 (0.5, 0.5) 这就说明这个精灵位于层的中央。x,y是宽和高的概念。
这里涉及到cocos2d的坐标概念
总之openGL的坐标和UI的坐标是不一致的,按openGL坐标来就可以了

Cocos2d-JS连载之打飞机游戏学习基础概念
ui坐标

Cocos2d-JS连载之打飞机游戏学习基础概念
openGL坐标

坐标中还有模型坐标和世界坐标的概念 其实就是精灵相对的坐标概念

![Upload Paste_Image.png failed. Please try again.]
在游戏场景中有两个Node对象,其中Node1的坐标是(400, 500),大小是300 x 100像素。Node2是放置在Node1中的,它对于Node1的模型坐标是(0, 0),大小是150 x 50像素。

好了继续到MMTouchLayer了,在该层中 用到了cc.audioEngine去播放音乐。

/        播放背景音乐,true代表循环无限次播放,false表示只播放一次。         if (GC.SOUND_ON){             if (cc.audioEngine.isMusicPlaying()){                 return;             }             cc.audioEngine.playMusic(res.mm_bgMusic_mp3, true);         }

然后又去加载了cc.Menu

//        菜单。 对应三者关系:菜单里面有菜单项,菜单项中绑定要执行的方法,并且需要图片去显示。图片就是精灵         var menu = new cc.Menu(newGame, gameSettings, about);         menu.alignItemsVerticallyWithPadding(10);         menu.x = GC.w_2;         menu.y = GC.h_2 - 80;         this.addChild(menu, 1, 2);

构造方法传入的是cc.MenuItemSprite 看其中的一个MenuItemSprite 定义

var newGame = new cc.MenuItemSprite(             newGameNormal,             newGameSelected,             newGameDisabled,             function(){                 this.onButtonEffect();                 this.flareEffect(flare, this, this.onNewGame);             }.bind(this)         );

里面构造方法传入的也是各个精灵,精灵的创建中用到了cc.rect,看其中的一个。

//        根据rect区域去创建一个精灵,作为下面menuItemSprite显示的图片。 //        因为menuItem有Normal、Selected、Disabled三个状态,所以一个菜单项需要三张纹理图片         var newGameNormal = new cc.Sprite(res.mm_mune_png, cc.rect(0, 0, 126, 33));

cc.rect(0, 0, 126, 33));是指定cc.Rect(x, y, width, height)。
这样的话就渲染出来了两个层,一个背景层,一个菜单层。在菜单切换的过程中还涉及到了 动作 ,函数的回调 、按顺序执行一组动作、 同时执行一组动作

//        定义动作         var opacityAnim = cc.fadeIn(0.5, 255);         var opacDim = cc.fadeIn(1, 0);  //        为动作加上easing效果,具体参考tests里面的示例         var biggerEase = cc.scaleBy(0.7, 1.2, 1.2).easing(cc.easeSineOut());         var easeMove = cc.moveBy(0.5, cc.p(328, 0)).easing(cc.easeSineOut());         var rotateEase = cc.rotateBy(2.5, 90).easing(cc.easeExponentialOut());         var bigger = cc.scaleTo(0.5, 1);  //        函数回调动作         var onComplete = cc.callFunc(callback, target);         var killflare = cc.callFunc(function () {             this.getParent().removeChild(this,true);         }, flare);  //        按顺序执行一组动作         var seqAction = cc.sequence(opacityAnim, biggerEase, opacDim, killflare, onComplete);  //        同时执行一组动作         var action = cc.spawn(seqAction, easeMove, rotateEase, bigger);         flare.runAction(action);     }

动作比较简单的。 就是精灵的旋转放大缩小等。
cc.callFunc是去执行一个函数,这里有this.getParent().removeChild方法,其实就是去移除创建的层。
cc.sequence是按顺序执行一组动作,传给 cc.spawn 是组合一组动作,然后精灵去执行 flare.runAction(action);
主要看一下GamePlayScene 游戏玩耍这个层,这个层里面涉及到了基础概念cc.spriteFrameCache缓存

 cc.spriteFrameCache.addSpriteFrames(res.gp_TextureOpaquePack_plist);

直接这样调用就可以了。这个层假如了两个层GPTouchLayer和GPBackgroundLayer
GPBackgroundLayer比较简单就是放了一张背景图片而已。主要的碰撞动作在GPTouchLayer中
这个里面涉及到比较多和重要的几个概念。scheduleUpdate和schedule
scheduleUpdate相当于是调用层的update方法

//    游戏时时刷新     update:function (dt) {         if (this._state == STATE_PLAYING) {  //            UI在这边更新             this.updateUI();  //            敌人在这里面产生,以及界面上             this.moveActiveUnit(dt);  //            碰撞检测             this.checkIsCollide();  //            检测我们的飞船重生             this.checkIsReborn();  //            这个部分被我直接干掉了。。。因为,重复代码,没什么内容 //            this._movingBackground(dt);         }     },

schedule是一致去执行一个方法这里一直在执行分数计数方法。

//    分数在这里面加     scoreCounter:function () {         if (this._state == STATE_PLAYING) {             this._time++;             this._levelManager.loadLevelResource(this._time);         }     },

存放分数信息的是cc.LabelBMFont

this._lbScore = new cc.LabelBMFont("Score: 0", res.sh_arial_14_fnt);         this._lbScore.attr({             anchorX: 1,             anchorY: 0,             x: GC.w - 5,             y: GC.h - 30         });

这个里面还有一个比较重要的就是碰撞检测
利用坐标是否落在区域去检测
看代码

//   碰撞坚持     collide:function (a, b) {         var ax = a.x;         var ay = a.y;         var bx = b.x;         var by = b.y;         if (Math.abs(ax - bx) > MAX_CONTAINT_WIDTH || Math.abs(ay - by) > MAX_CONTAINT_HEIGHT)             return false;          var aRect = a.collideRect(ax, ay);         var bRect = b.collideRect(bx, by);         return cc.rectIntersectsRect(aRect, bRect);     },

这里面分了不同种类的精灵BulletSprite、EnemySprite、ExplosionSprite、ShipSprite、SparkEffectSprite看名字就可以看出来各个代表什么精灵,既然有碰撞检测那么坐标移动在哪里呢,其实就是在各个精灵中自己定义的action
看BulletSprite这个精灵吧,

update:function (dt) {  //        cc.log("这里。。。");         var y = this.y;         this.y = y - this.yVelocity * dt; //不断的移动坐标去达到移动的目的         if (y < 0 || y > GC.h + 10 || this.HP <= 0) {             this.destroy();         }     },

其中还有一些别的方法 死亡啊,新产生啊之类的,这个就是碰撞检测后的逻辑代码,不涉及到基础知识了,这里就过了。

真不容易写完了。这里贴出来试玩地址
http://112.126.90.18/airbarons/
算了还是放顶部吧
go home。

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Cocos2d-JS连载之打飞机游戏学习基础概念

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址