cocos2dx-html5 實現網頁版flappy bird遊戲

我也是第一次使用cocos2d_html5,對js和html5也不熟,看引擎自帶的例子和引擎源碼,邊學邊作,若是使用過cocos2d-x的話,完成這個遊戲仍是十分簡單的。遊戲體驗地址:
 
1. 首先去cocos2d-x官網下載Cocos2d-html5-v2.2.2(目前最新版本)壓縮包
 
2. 下載安裝WampServer( http://www.wampserver.com/en/),後期在瀏覽器運行程序的時候,須要用到wampserver。WampServer是一款由法國人開發的Apache Web服務器、PHP解釋器以及MySQL數據庫的整合軟件包,自己也不大,才30多M。我這裏安裝到e盤,安裝到最後會出現選擇explorer的提示,定位到WINDOWS目錄下explorer.exe或者其餘本身安裝的瀏覽器目錄下的explorer.exe文件。安裝好後啓動,在桌面的右下角會有一個綠色圖標。
 
3. 解壓Cocos2d-html5-v2.2.2到E:\wamp\www目錄下,此時打開瀏覽器,輸入localhost,就能夠看到下面的界面了,點擊cocos2d_html5,就能夠看到項目列表了:
 
4. 複製cocos2d_html5目錄下的HelloHTML5World例子,命名爲flappybird,這是引擎自帶的Hello World demo。在引擎目錄下建立projects目錄,而後把flappybird放到projects目錄下。修改引擎根目錄下的index.html文件,在MoonWarriors下添加
1
< li >< a href = "projects/flappybird/index.html" >flappybird </ a > < span > - Game</ span ></ li >
刷新瀏覽器,會看到剛添加的flappybird了:
 
flappybird目錄結構以下:
res目錄存放的是圖片等資源文件,src存放自定義的js源碼,build.xml是打包文件,使用ant打包。cocos2d.js文件是配置一些屬性,好比:是否顯示fps,是否使用物理引擎,指定引擎目錄,指定自定義的js文件等,相似於android的Android.mk文件。index.html是遊戲顯示的界面,在這裏指定canvas尺寸。main.js裏定義了Application,加載遊戲的入口Scene,相似於c++的AppDelegate.cpp。
 
5. 開始編寫遊戲
src目錄下有兩個文件,myApp.js(遊戲主要代碼在這個文件裏)和resource.js(定義遊戲所使用的資源),因爲這個遊戲代碼量比較少,就直接在這兩個文件添加代碼。
遊戲有三個狀態:READY、START、OVER。
READY表示遊戲剛開始時顯示logo,而後提示玩家點擊開始遊戲;
START表示遊戲進行中;
OVER表示遊戲結束,顯示遊戲結算界面。
遊戲中出現的精靈有:小鳥、底部不停滾動的地面、背景圖片、一直向左滾動的水管。其實小鳥在水平方向是一直不動的,只有水管和地面在滾動。
遊戲中須要完成的主要功能點:小鳥自身的動畫、點擊屏幕時小鳥上升和降低的動畫、小鳥死亡動畫、地面滾動動畫、水管滾動動畫、添加水管、小鳥和地面及小鳥和水管的碰撞檢測、遊戲分數存儲。
 

首先加載資源和添加遊戲背景:html

1
2
3
4
5
this .winSize = cc.Director.getInstance().getWinSize();
cc.SpriteFrameCache.getInstance().addSpriteFrames(res.flappy_packer);
this .bgSprite = cc.Sprite.create(res.bg);
this .bgSprite.setPosition( this .winSize.width / 2, this .winSize.height / 2);
this .addChild( this .bgSprite, 0);

遊戲資源使用TexturePacker打包在flappy_packer.plist文件中,函數名跟cocos2d-x c++版本是同樣的。 初始化地面:html5

1
2
3
4
5
6
7
8
9
10
11
12
13
Helloworld.prototype.initGround = function () {
     //cc.log("initGround");
     this .groundSprite = cc.Sprite.create(res.ground);
     var halfGroundW = this .groundSprite.getContentSize().width;
     var halfGroundH = this .groundSprite.getContentSize().height;
     this .groundSprite.setAnchorPoint(0.5, 0.5);
     this .groundSprite.setPosition(halfGroundW / 2, halfGroundH / 2);
     this .addChild( this .groundSprite, GROUND_Z);
     var action1 = cc.MoveTo.create(0.5, cc.p(halfGroundW / 2 - 120, this .groundSprite.getPositionY()));
     var action2 = cc.MoveTo.create(0, cc.p(halfGroundW / 2, this .groundSprite.getPositionY()));
     var action = cc.Sequence.create(action1, action2);
     this .groundSprite.runAction(cc.RepeatForever.create(action));
};

js能夠使用proptotype來爲類型添加行爲,不理解的能夠google一下。固然也能夠跟init函數同樣寫在裏面,像這樣:android

1
2
3
4
5
6
7
var Helloworld = cc.Layer.extend({
init: function () {
},
  
initGround:: function () {
}
);

這裏爲地面定義兩個動做,由於地面圖片寬度是840px,而遊戲屏幕分辨率指定是720×1280,因此先讓地面向左移動120px,再迅速回到原位置。c++

初始化小鳥動畫:git

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Helloworld.prototype.initBird = function () {
     //cc.log("initBird");
     var animation = cc.AnimationCache.getInstance().getAnimation( "FlyBirdAnimation" )
     if (!animation) {
         var animFrames = [];
         var str = "" ;
         var birdFrameCount = 4;
         for ( var i = 1; i < birdFrameCount; ++ i) {
             str = "bird" + i + ".png" ;
             var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(str);
             animFrames.push(frame);
         }
         var animation = cc.Animation.create(animFrames, 0.05);
         cc.AnimationCache.getInstance().addAnimation(animation, "FlyBirdAnimation" );
     }
  
     this .flyBird = cc.Sprite.createWithSpriteFrameName(res.fly_bird);
     this .flyBird.setAnchorPoint(cc.p(0.5, 0.5));
     this .flyBird.setPosition( this .winSize.width / 2, this .winSize.height / 2);
     this .addChild( this .flyBird, BIRD_Z);
     var actionFrame = cc.Animate.create(animation);
     var flyAction = cc.RepeatForever.create(actionFrame);
     this .flyBird.runAction(cc.RepeatForever.create(flyAction));
};

小鳥自身動畫是一個幀動畫,建立成功後添加到緩存中。github

初始化ready界面,就是遊戲開始的時候提示用戶點擊的畫面:web

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Helloworld.prototype.initReady = function () {
     this .readyLayer = cc.Layer.create();
     var logo = cc.Sprite.createWithSpriteFrameName(res.logo);
     logo.setAnchorPoint(cc.p(0.5, 0.5));
     logo.setPosition( this .winSize.width / 2, this .winSize.height - logo.getContentSize().height - 50);
     this .readyLayer.addChild(logo);
  
     var getReady = cc.Sprite.createWithSpriteFrameName(res.getReady);
     getReady.setAnchorPoint(cc.p(0.5, 0.5));
     getReady.setPosition( this .winSize.width / 2, this .winSize.height / 2 + getReady.getContentSize().height);
     this .readyLayer.addChild(getReady);
  
     var click = cc.Sprite.createWithSpriteFrameName(res.click);
     click.setAnchorPoint(cc.p(0.5, 0.5));
     click.setPosition( this .winSize.width / 2, getReady.getPositionY() - getReady.getContentSize().height / 2 - click.getContentSize().height / 2);
     this .readyLayer.addChild(click);
  
     this .addChild( this .readyLayer);
};

效果以下:數據庫

添加點擊屏幕時小鳥上升和降低自由落體的動畫:canvas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Helloworld.prototype.runBirdAction = function () {
     var riseHeight = 50;
     var birdX = this .flyBird.getPositionX();
     var birdY = this .flyBird.getPositionY();
     var bottomY = this .groundSprite.getContentSize().height - this .flyBird.getContentSize().height / 2;
  
     var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation( "FlyBirdAnimation" ));
     var flyAction = cc.RepeatForever.create(actionFrame);
//上升動畫
     var riseMoveAction = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight));
     var riseRotateAction = cc.RotateTo.create(0, -30);
     var riseAction = cc.Spawn.create(riseMoveAction, riseRotateAction);
//下落動畫
//模擬自由落體運動
     var fallMoveAction = FreeFall.create(birdY - bottomY);
     var fallRotateAction =cc.RotateTo.create(0, 30);
     var fallAction = cc.Spawn.create(fallMoveAction, fallRotateAction);
     this .flyBird.stopAllActions();
     this .flyBird.runAction(flyAction);
     this .flyBird.runAction(cc.Spawn.create(
         cc.Sequence.create(riseAction, fallAction) )
     );
};

這裏自定義了一個自由落體的Action:FreeFall:數組

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
var FreeFall = cc.ActionInterval.extend( {
      timeElasped:0,
      m_positionDeltaY: null ,
      m_startPosition: null ,
      m_targetPosition: null ,
  
     ctor: function () {
         cc.ActionInterval.prototype.ctor.call( this );
         this .yOffsetElasped = 0;
         this .timeElasped = 0;
         this .m_positionDeltaY = 0;
         this .m_startPosition = cc.p(0, 0);
         this .m_targetPosition = cc.p(0, 0);
      },
  
     initWithDuration: function (duration) {
         if (cc.ActionInterval.prototype.initWithDuration.call( this , duration)) {
             return true ;
         }
         return false ;
     },
  
     initWithOffset: function (deltaPosition) {
         var dropTime = Math.sqrt(2.0*Math.abs(deltaPosition)/k_Acceleration) * 0.1;
         //cc.log("dropTime=" + dropTime);
         if ( this .initWithDuration(dropTime))
         {
             this .m_positionDeltaY = deltaPosition;
             return true ;
         }
          //cc.log("dropTime =" + dropTime + "; deltaPosition=" + deltaPosition);
         return false ;
     },
  
     isDone: function () {
         if ( this .m_targetPosition.y >= this ._target.getPositionY()) {
             return true ;
         }
         return false ;
     },
  
     //Node的runAction函數會調用ActionManager的addAction函數,在ActionManager的addAction函數中會調用Action的startWithTarget,而後在Action類的startWithTarget函數中設置_target的值。
     startWithTarget: function (target) {
         //cc.log("startWithTarget target=" + target);
         cc.ActionInterval.prototype.startWithTarget.call( this , target);
         this .m_startPosition = target.getPosition();
         this .m_targetPosition = cc.p( this .m_startPosition.x, this .m_startPosition.y - this .m_positionDeltaY);
     },
  
     update: function (dt) {
         this .timeElasped += dt;
         //cc.log("isdone=" + this.timeElasped);
         if ( this ._target && !( this .m_targetPosition.y >= this ._target.getPositionY())) {
             var yMoveOffset = 0.5 * k_Acceleration * this .timeElasped * this .timeElasped * 0.3;
             if (cc.ENABLE_STACKABLE_ACTIONS) {
                 var newPos = cc.p( this .m_startPosition.x, this .m_startPosition.y - yMoveOffset);
                 if ( this .m_targetPosition.y > newPos.y) {
                     newPos.y = this .m_targetPosition.y;
                     this ._target.stopAction( this );
                 }
  
                 this ._target.setPosition(newPos);
  
             } else {
                 this ._target.setPosition(cc.p( this .m_startPosition.x, this .m_startPosition.y + this .m_positionDeltaY * dt));
             }
         }
     }
  
});
  
FreeFall.create = function (deltaPosition) {
         var ff = new FreeFall();
         ff.initWithOffset(deltaPosition);
         return ff;
     };

模仿了CCActionInterval.js中的其餘內置的Action,如MoveBy,主要重寫了initWithDuration,startWithTarget,update,isDone函數。 initWithDuration是設置該action運行的時間,時間的長短決定降低的速度。 startWithTarget函數由ActionManager調用,設置_target的值。 update函數在ActionInterval的step函數中會調用,在這個函數中不斷更新精靈的座標,使用了自由落體計算位移的公式。 isDone函數設置了動做是否運行結束。 重力加速度和action運行的時間須要不斷調試。

添加水管:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function getRandom(maxSize) {
     return Math.floor(Math.random() * maxSize) % maxSize;
}
  
Helloworld.prototype.addPipe = function () { 
     cc.log( "addPipe" );
     var ccSpriteDown = cc.Sprite.createWithSpriteFrameName(res.holdback1);
     var pipeHeight = ccSpriteDown.getContentSize().height;
     var pipeWidth = ccSpriteDown.getContentSize().width;
     var groundHeight = this .groundSprite.getContentSize().height;
         //小鳥飛行區間高度
     var acrossHeight = 300;
     var downPipeHeight = 100 + getRandom(400);
    // cc.log("downPipeHeight=" + downPipeHeight);
  
     var upPipeHeight = this .winSize.height - downPipeHeight - acrossHeight - groundHeight;
     var PipeX = this .winSize.width + pipeWidth / 2;
     ccSpriteDown.setZOrder(1);
     ccSpriteDown.setAnchorPoint(cc.p(0.5, 0.5));
     ccSpriteDown.setPosition(cc.p(PipeX + pipeWidth / 2, groundHeight + pipeHeight / 2 - (pipeHeight - downPipeHeight)));
  
var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(res.holdback2);
     ccSpriteUp.setZOrder(1);
     ccSpriteUp.setAnchorPoint(cc.p(0.5, 0.5));
     ccSpriteUp.setPosition(cc.p(PipeX + pipeWidth / 2, this .winSize.height + (pipeHeight- upPipeHeight) - pipeHeight / 2));
  
  this .addChild(ccSpriteDown, PIPE_Z);
     this .addChild(ccSpriteUp, PIPE_Z);
  
   this .PipeSpriteList.push(ccSpriteDown);
     this .PipeSpriteList.push(ccSpriteUp);
  
  this .score += 1;
};

分爲上下兩根水管,隨機設置上下水管的高度,固定小鳥飛行區間的高度爲300。而後把建立的水管放到數組中,同時每添加一排水管就增長一分。

添加碰撞檢測函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Helloworld.prototype.getRect = function (a) {
      var pos = a.getPosition();
      var content = a.getContentSize();
      return cc.rect(pos.x - content.width / 2, pos.y - content.height / 2, content.width, content.height);
};
  
Helloworld.prototype.collide = function (a, b) {
     var aRect = this .getRect(a);
     var bRect = this .getRect(b);
     return cc.rectIntersectsRect(aRect, bRect);
};
  
Helloworld.prototype.checkCollision = function () {
     if ( this .collide( this .flyBird, this .groundSprite)) {
         //cc.log("hit floor");
         this .birdFallAction();
         return ;
     }
     for ( var i = 0; i < this .PipeSpriteList.length; i++) {
         var pipe = this .PipeSpriteList[i];
         if ( this .collide( this .flyBird, pipe)) {
             cc.log( "hit pipe i=" + i);
             this .birdFallAction();
             break ;
         }
     }
}

採用最簡單的方式:判斷矩形是否相交。把小鳥分別跟地面和數組中的水管進行檢測,若是發生碰撞,則執行小鳥死亡動畫:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Helloworld.prototype.birdFallAction = function () {
     this .gameMode = OVER;
     this .flyBird.stopAllActions();
     this .groundSprite.stopAllActions();
     var birdX = this .flyBird.getPositionX();
     var birdY = this .flyBird.getPositionY();
  
     var bottomY = this .groundSprite.getContentSize().height + this .flyBird.getContentSize().width / 2;
     var fallMoveAction = FreeFall.create(birdY - bottomY);
     var fallRotateAction =cc.RotateTo.create(0, 90);
     var fallAction = cc.Spawn.create(fallMoveAction, fallRotateAction);
     this .flyBird.runAction(cc.Sequence.create(cc.DelayTime.create(0.1),
         fallAction)
     );
  
     this .runAction(cc.Sequence.create(cc.DelayTime.create(1.0),
         cc.CallFunc.create( this .showGameOver, this ))
     );
}

讓小鳥旋轉90度,而後垂直下落,而後顯示game over畫面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Helloworld.prototype.showGameOver = function () {
     var userDefault = cc.UserDefault.getInstance();
     var oldScore = userDefault.getIntegerForKey( "score" );
     var maxScore = 0;
     if ( this .score > oldScore) {
         maxScore = this .score;
         userDefault.setIntegerForKey( "score" , maxScore);
     } else {
         maxScore = oldScore;
     }
  
     var gameOverLayer = cc.Layer.create();
     cc.log( "gameover=" + res.gameover);
     var gameOver = cc.Sprite.createWithSpriteFrameName(res.gameover);
     gameOver.setAnchorPoint(cc.p(0.5, 0.5));
     gameOver.setPosition( this .winSize.width / 2, this .winSize.height - gameOver.getContentSize().height / 2 - 150);
     gameOverLayer.addChild(gameOver);
  
     var scorePanel = cc.Sprite.createWithSpriteFrameName(res.scorePanel);
     scorePanel.setAnchorPoint(cc.p(0.5, 0.5));
     scorePanel.setPosition(gameOver.getPositionX(), gameOver.getPositionY() - gameOver.getContentSize().height / 2 - scorePanel.getContentSize().height / 2 - 60);
     gameOverLayer.addChild(scorePanel);
  
     if ( this .score > oldScore) {
         var gold = cc.Sprite.createWithSpriteFrameName(res.gold);
         gold.setAnchorPoint(cc.p(0.5, 0.5));
         gold.setPosition(68 + gold.getContentSize().width / 2, 72 + gold.getContentSize().height / 2);
         scorePanel.addChild(gold);
     } else {
         var gray = cc.Sprite.createWithSpriteFrameName(res.gray);
         gray.setAnchorPoint(cc.p(0.5, 0.5));
         gray.setPosition(68 + gray.getContentSize().width / 2, 72 + gray.getContentSize().height / 2);
         scorePanel.addChild(gray);
     }
  
     var newScoreLabel = cc.LabelAtlas.create( this .score, res.number, 22, 28, '0' );
     newScoreLabel.setAnchorPoint(cc.p(0.5, 0.5));
     newScoreLabel.setScale(1.2);
     newScoreLabel.setPosition(scorePanel.getContentSize().width - newScoreLabel.getContentSize().width - 90, newScoreLabel.getContentSize().height / 2 + 180);
     scorePanel.addChild(newScoreLabel);
  
     var maxScoreLabel = cc.LabelAtlas.create(maxScore, res.number, 22, 28, '0' );
     maxScoreLabel.setAnchorPoint(cc.p(0.5, 0.5));
     maxScoreLabel.setScale(1.2);
     maxScoreLabel.setPosition(newScoreLabel.getPositionX(), maxScoreLabel.getContentSize().height / 2 + 75);
     scorePanel.addChild(maxScoreLabel);
  
     var start = cc.Sprite.createWithSpriteFrameName(res.start);
     var startMenuItem = cc.MenuItemSprite.create(start, null , null , this .restartGame, this );
     var startMenu = cc.Menu.create(startMenuItem);
     startMenu.setAnchorPoint(cc.p(0.5, 0.5));
     startMenu.setPosition( this .winSize.width / 2 , scorePanel.getPositionY() - scorePanel.getContentSize().height / 2 - start.getContentSize().height / 2 - 60);
     gameOverLayer.addChild(startMenu);
  
     this .addChild(gameOverLayer, GAMEOVER_Z);
};

顯示game over時保存遊戲數據,顯示這局遊戲的分數和歷史最高分。

點擊開始遊戲按鈕,就能夠從新開始遊戲:

1
2
3
4
5
Helloworld.prototype.restartGame = function () {
     var scene = cc.Scene.create();
     scene.addChild(Helloworld.create());
     cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
};

記得在init函數中清空水管數組:

1
this .PipeSpriteList = [];

下面是Helloworld類的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
var Helloworld = cc.Layer.extend({
     gameMode: null ,
     bgSprite: null ,
     groundSprite: null ,
     flyBird: null ,
     PipeSpriteList:[],
     passTime: 0,
     winSize: 0,
     screenRect: null ,
     readyLayer: null ,
     score: 0,
     scoreLabel: null ,
  
     init: function () {
         cc.log( "helloworld init" );
         this ._super();
         this .PipeSpriteList = [];
         this .winSize = cc.Director.getInstance().getWinSize();
         cc.SpriteFrameCache.getInstance().addSpriteFrames(res.flappy_packer);
         this .bgSprite = cc.Sprite.create(res.bg);
         this .bgSprite.setPosition( this .winSize.width / 2, this .winSize.height / 2);
         this .addChild( this .bgSprite, 0);
         this .initGround();
         this .initReady();
         this .screenRect = cc.rect(0, 0, this .winSize.width, this .winSize.height);
         this .gameMode = READY;
         this .score = 0;
         this .scheduleUpdate();
         this .setTouchEnabled( true );
         return true ;
     },
  
     onTouchesBegan: function (touches, event) {
     },
  
     onTouchesMoved: function (touches, event) {
     },
  
     onTouchesEnded: function (touches, event) {
         if ( this .gameMode == OVER) {
             return ;
         }
         if ( this .gameMode == READY) {
             this .gameMode = START;
             this .readyLayer.setVisible( false );
             this .initBird();;
         }
         this .runBirdAction();
     },
  
     onTouchesCancelled: function (touches, event) {
     },
  
     update: function (dt) {
         if ( this .gameMode != START) {
             return ;
         }
         for ( var i = 0; i < this .PipeSpriteList.length; ++ i) {
             var pipe = this .PipeSpriteList[i];
             pipe.setPositionX(pipe.getPositionX() - 3);
             if (pipe.getPositionX() < -pipe.getContentSize().width / 2) {
                 this .PipeSpriteList.splice(i, 1);
                 //cc.log("delete pipe i=" + i);
             }
         }
         this .passTime += 1;
         if ( this .passTime >= this .winSize.width / 6) {
             this .addPipe();
             this .passTime = 0;
         }
         this .checkCollision();
     }
});

在update函數中更新水管的位置,若是水管出了左邊的屏幕就從數組中移除,每通過必定的時間就添加一排水管。 如今看看index.html的內容,在瀏覽器中訪問的就是它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE HTML>
< html >
< head >
     < meta charset = "utf-8" >
     < title >Flappy Bird-codingnow.cn</ title >
     < link rel = "icon" type = "image/png" href = "http://codingnow.cn/favicon.ico" >
     < meta name = "viewport" content = "user-scalable=no" />
     < meta name = "screen-orientation" content = "portrait" />
     < meta name = "apple-mobile-web-app-capable" content = "yes" />
     < meta name = "full-screen" content = "yes" />
     < meta name = "x5-fullscreen" content = "true" />
     < style >
         body, canvas, div {
             -moz-user-select: none;
             -webkit-user-select: none;
             -ms-user-select: none;
             -khtml-user-select: none;
             -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
         }
     </ style >
</ head >
< body style = "padding:0; margin: 0;text-align: center;background: #f2f6f8;" >
     < canvas id = "gameCanvas" width = "720" height = "1280" ></ canvas >
< script src = "cocos2d.js" ></ script >
< img style = "position:absolute;left:-9999px" src = "http://zhoujianghai.github.io/games/flappybird/res/icon_wechat.png" onerror = "this.parentNode.removeChild(this)" >
</ body >
</ html >

在這個文件中指定了canvas的尺寸。html的內容從cocos2d-html5自帶的例子中copy過來的,這裏在底部添加了一個img,這個圖片是分享到微信朋友圈時顯示在左邊的圖片。 當瀏覽器窗口大小改變時,爲了能自動調整顯示遊戲完整畫面,須要在main.js的applicationDidFinishLaunching函數中添加:

1
2
3
cc.EGLView.getInstance().adjustViewPort( true );
cc.EGLView.getInstance().setDesignResolutionSize(720, 1280, cc.RESOLUTION_POLICY.SHOW_ALL);
cc.EGLView.getInstance().resizeWithBrowserSize( true );

還記得那個build.xml文件麼,能夠使用ant打包工具,把src目錄下的js代碼跟引擎代碼打包成一個myApp-HelloWorld.js文件,這樣咱們只須要把res資源、cocos2d.js、index.html、myApp-HelloWorld.js放到網站上就能夠了,也就更安全了。切換到項目build.xml所在目錄,在命令符窗口執行:ant。很快就會生成myApp-HelloWorld.js文件,而後還須要修改cocos2d.js的window.addEventListener函數,修改s.src的值爲myApp-HelloWorld.js,cocos2d.js文件裏有詳細註釋的。

ok,flappy bird遊戲的主要代碼就完成了,感受cocos2d-html5仍是很是強大的,開發效率很高。 如今還只能在本地運行遊戲,爲了能在外網訪問,能夠把項目傳到github上,建立github pages,能夠參考:http://pages.github.com/

相關文章
相關標籤/搜索