cocos2d-XNA遊戲開發之山寨《Flapy Bird》(一)

  最近在看cocos2d開發,想找個遊戲練練手,礙於沒有策劃能力,只能從山寨作起。目前最火的遊戲,莫過因而這個像素鳥《Flapy Bird》了,下面就開始山寨它吧。php

開發環境

系統:Windows8node

IDE:Visual Studio 2012算法

資源文件

隨便那個網站下載一個flapybird的apk(下載地址:http://app.suning.com/d.php?pack=com.dotgears.flappybird),改後綴名爲.rar,解壓以後就能找到遊戲引用的資源。app

打開assets\gfx,會找到一張atlas.png,包含了全部的圖片資源,sound中是聲音資源。框架

 

項目搭建

由於是學習項目,就本身搭建cocos框架,不使用cocos模版。新建項目,選擇XNAGame->WindowsPhone遊戲。dom

添加AppDelegate.cs類,繼承 CCApplication,添加構造函數,重寫applicationDidFinishLaunching方法;ide

public class AppDelegate : CCApplication
    {
        public AppDelegate(Game game, GraphicsDeviceManager graphics)
            : base(game, graphics)
        {
            CCApplication.sm_pSharedApplication = this;
        }


        public override bool applicationDidFinishLaunching()
        {
            CCDirector pDirector = CCDirector.sharedDirector();
            pDirector.setOpenGLView();

            pDirector.DisplayFPS = true;
            pDirector.deviceOrientation = ccDeviceOrientation.CCDeviceOrientationPortrait; ;
            pDirector.animationInterval = 1.0 / 60;

            CCScene pScene = new CCScene();
            pDirector.runWithScene(pScene);
            return base.applicationDidFinishLaunching();
        }
    }

修改Game1.cs構造函數,添加代碼:函數

public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            this.graphics.IsFullScreen = true;
            // Windows Phone 的默認幀速率爲 30 fps。
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // 延長鎖定時的電池壽命。
            InactiveSleepTime = TimeSpan.FromSeconds(1);

            CCApplication application = new AppDelegate(this, graphics);
            this.Components.Add(application);
        }

  

添加場景(CCScene)

咱們仔細觀察遊戲能夠把遊戲分爲2個場景:學習

1.菜單場景動畫

2.遊戲場景

因爲咱們在AppDelegate建立了一個CCScene,能夠用它來做爲菜單場景,再新建一個GamePlayScene做爲遊戲場景(也能夠本身新建一個MenuScene做爲菜單場景)。

添加層(CCLayer)

遊戲能夠大體分爲如下個層:

1.背景層(BackgroundLayer)

2.移動的道路層(RoadLayer)

3.遊戲層(GamePlayLayer)

4.菜單層(MainLayer)

 

在菜單場景中,咱們須要用到BackgroundLayer,RoadLayer和MainLayer。修改AppDelegate.cs代碼:

public override bool applicationDidFinishLaunching()
        {
            CCDirector pDirector = CCDirector.sharedDirector();
            pDirector.setOpenGLView();

            pDirector.DisplayFPS = true;
            pDirector.deviceOrientation = ccDeviceOrientation.CCDeviceOrientationPortrait; ;
            pDirector.animationInterval = 1.0 / 60;

            CCScene pScene = new CCScene();
            pScene.addChild(BackgroundLayer.node(), (int)LayerTags.Background, (int)LayerTags.Background);
            pScene.addChild(RoadLayer.node(), (int)LayerTags.Road, (int)LayerTags.Road);
            pScene.addChild(MainLayer.node(), (int)LayerTags.Game, (int)LayerTags.Game);
            pDirector.runWithScene(pScene);
            return base.applicationDidFinishLaunching();
        }

  

public enum LayerTags
    {
        Background = 0,
        Game = 1,
        Road = 2
    }

  

背景層(BackgroundLayer)

 BackgroundLayer繼承自CCLayer,重寫靜態方法node;

public static new CCLayer node()
        {
            BackgroundLayer ret = new BackgroundLayer();
            if (ret.init())
            {
                return ret;
            }

            return null;
        }

下面咱們就須要畫背景圖片了,重寫init方法

首先咱們須要算出資源圖片與屏幕大小的縮放比例:

//288,511是背景圖的大小
sX = CCDirector.sharedDirector().getWinSize().width / 288f; 
sY = CCDirector.sharedDirector().getWinSize().height / 512f;

因爲此遊戲的資源圖片是一整張大圖,因此咱們須要根據區域進行讀取,觀察資源圖片咱們能夠發現,存在2個背景圖片,看來須要隨機出現一個背景圖片,完整init代碼:

public override bool init()
        {
            sX = CCDirector.sharedDirector().getWinSize().width / 288f;
            sY = CCDirector.sharedDirector().getWinSize().height / 512f;
            Random random = new Random();
            int number = random.Next(0, 2);
            CCRect ccRect;
            if (number == 0)
            {
                ccRect = new CCRect(0, 0, 288, 512);
            }
            else
            {
                ccRect = new CCRect(292, 0, 288, 512);
            }
            CCSprite backgroundCcSprite = CCSprite.spriteWithFile("Images/background", ccRect);
            backgroundCcSprite.position = new CCPoint(240, 400);
            backgroundCcSprite.scaleY = sY;
            backgroundCcSprite.scaleX = sX;
            addChild(backgroundCcSprite);

            
            return base.init();

        }

效果以下:

 道路層(RoadLayer)

與背景層相似,繼承自CCLayer並重寫方法node()、init();

public static new CCLayer node()
        {
            RoadLayer ret = new RoadLayer();
            if (ret.init())
            {
                return ret;
            }

            return null;
        }

        public override bool init()
        {
            sX = CCDirector.sharedDirector().getWinSize().width / 288f;
            sY = CCDirector.sharedDirector().getWinSize().height / 512f;

            CCSprite downRoadCcSprite1 = CCSprite.spriteWithFile("Images/background", new CCRect(584, 0, 336, 112));
            downRoadCcSprite1.position = new CCPoint(240, 72);
            downRoadCcSprite1.scaleX = sX;
            downRoadCcSprite1.scaleY = sY;
            addChild(downRoadCcSprite1, 1, (int)SpriteTags.Road);

            return base.init();
        }

讓道路動起來

此處我採用的是添加2個道路CCSprite,像小火車同樣跟着,每動一幀,2個道路的座標減小4,當第一個的x座標等於0以後,將其放到第二個的後面,也就是x座標等480(屏幕寬度)。

添加一個schedule定時器執行更新道路座標方法,代碼以下:

public override bool init()
        {
            sX = CCDirector.sharedDirector().getWinSize().width / 288f;
            sY = CCDirector.sharedDirector().getWinSize().height / 512f;

            downRoadCcSprite1 = CCSprite.spriteWithFile("Images/background", new CCRect(584, 0, 336, 112));
            downRoadCcSprite1.position = new CCPoint(240, 72);
            downRoadCcSprite1.scaleX = sX;
            downRoadCcSprite1.scaleY = sY;
            addChild(downRoadCcSprite1, 1, (int)SpriteTags.Road);

            downRoadCcSprite2 = CCSprite.spriteWithFile("Images/background", new CCRect(584, 0, 336, 112));
            downRoadCcSprite2.position = new CCPoint(480, 72);
            downRoadCcSprite2.scaleX = sX;
            downRoadCcSprite2.scaleY = sY;
            addChild(downRoadCcSprite2, 1, (int)SpriteTags.Road);

            this.schedule(updateDownRoad, 0.01f);
            return base.init();
        }
        private void updateDownRoad(float dt)
        {
            downRoadCcSprite1.position = new CCPoint(downRoadCcSprite1.position.x - 4, downRoadCcSprite1.position.y);
            if (downRoadCcSprite1.position.x == 0)
            {
                downRoadCcSprite1.position = new CCPoint(480, downRoadCcSprite1.position.y);
            }
            downRoadCcSprite2.position = new CCPoint(downRoadCcSprite2.position.x - 4, downRoadCcSprite2.position.y);
            if (downRoadCcSprite2.position.x == 0)
            {
                downRoadCcSprite2.position = new CCPoint(480, downRoadCcSprite2.position.y);
            }
        }

添加菜單

開始我作菜單的方法和上面同樣從大圖中截取圖片生成CCMenuItemSprite,可是加入後發現菜單並不是是一直顯示的,不知道哪裏設置出了問題:

CCSprite testCcSprite = CCSprite.spriteWithFile("Images/background", new CCRect(705, 235, 107, 58));
            testCcSprite.scaleX = sX;
            testCcSprite.scaleY = sY;
            CCMenuItemSprite testMenuItemSprite = CCMenuItemSprite.itemFromNormalSprite(testCcSprite, testCcSprite);
            CCMenu testmenuOperate = CCMenu.menuWithItems(testMenuItemSprite);
            testmenuOperate.position = new CCPoint(240, 205);
            this.addChild(testmenuOperate);

效果:

沒辦法了,只能切成單個圖片,而後用另一種方式試試,發現竟然可行,求解!!!

CCMenuItemImage rateCcMenuItemSprite = CCMenuItemImage.itemFromNormalImage("Images/rate", "Images/rate_pressed", this, rateCallback);
            rateCcMenuItemSprite.scaleX = sX;
            rateCcMenuItemSprite.scaleY = sY;

            CCMenu menuRate = CCMenu.menuWithItems(rateCcMenuItemSprite);
            menuRate.position = new CCPoint(240, 350);
            this.addChild(menuRate);

            CCMenuItemImage startCcMenuItemSprite = CCMenuItemImage.itemFromNormalImage("Images/play", "Images/play_pressed", this, playCallback);
            startCcMenuItemSprite.scaleX = sX;
            startCcMenuItemSprite.scaleY = sY;

            CCMenuItemImage scoreCcMenuItemSprite = CCMenuItemImage.itemFromNormalImage("Images/rank", "Images/rank_pressed", this, rankCallback);
            scoreCcMenuItemSprite.scaleX = sX;
            scoreCcMenuItemSprite.scaleY = sY;

            CCMenu menuOperate = CCMenu.menuWithItems(startCcMenuItemSprite, scoreCcMenuItemSprite);
            menuOperate.alignItemsHorizontallyWithPadding(30);
            menuOperate.position = new CCPoint(240, 205);
            this.addChild(menuOperate);

CCMenuItemImage startCcMenuItemSprite = CCMenuItemImage.itemFromNormalImage("Images/play", "Images/play_pressed", this, playCallback);第一個參數爲默認圖片,第二個爲按下時候圖片,playCallback爲按下的處理事件

  

而後添加Logo

CCSprite logoCcSprite = CCSprite.spriteWithFile("Images/background", new CCRect(700, 177, 185, 55));
            logoCcSprite.position = new CCPoint(240, 550);
            logoCcSprite.scaleX = sX;
            logoCcSprite.scaleY = sY;
            addChild(logoCcSprite);

添加會動的小鳥

此處採用CCAnimation進行繪製小鳥的動畫,在init中調用initActiveBird()

private void initActiveBird()
        {
            CCTexture2D texture = CCTextureCache.sharedTextureCache().addImage("Images/background");//2D紋理

            CCSpriteFrame birFrame6 = CCSpriteFrame.frameWithTexture(texture, new CCRect(117, 976, 40, 50));
            CCSpriteFrame birFrame7 = CCSpriteFrame.frameWithTexture(texture, new CCRect(117, 975, 40, 50));
            CCSpriteFrame birFrame8 = CCSpriteFrame.frameWithTexture(texture, new CCRect(117, 974, 40, 50));
            CCSpriteFrame birFrame9 = CCSpriteFrame.frameWithTexture(texture, new CCRect(117, 975, 40, 50));
            CCSpriteFrame birFrame10 = CCSpriteFrame.frameWithTexture(texture, new CCRect(117, 976, 40, 50));
            CCSpriteFrame birFrame0 = CCSpriteFrame.frameWithTexture(texture, new CCRect(61, 982, 40, 50));
            CCSpriteFrame birFrame1 = CCSpriteFrame.frameWithTexture(texture, new CCRect(61, 981, 40, 50));
            CCSpriteFrame birFrame2 = CCSpriteFrame.frameWithTexture(texture, new CCRect(61, 980, 40, 50));
            CCSpriteFrame birFrame3 = CCSpriteFrame.frameWithTexture(texture, new CCRect(61, 979, 40, 50));
            CCSpriteFrame birFrame4 = CCSpriteFrame.frameWithTexture(texture, new CCRect(61, 978, 40, 50));
            CCSpriteFrame birFrame5 = CCSpriteFrame.frameWithTexture(texture, new CCRect(61, 977, 40, 50));
            CCSpriteFrame birFrame11 = CCSpriteFrame.frameWithTexture(texture, new CCRect(5, 977, 40, 50));
            CCSpriteFrame birFrame12 = CCSpriteFrame.frameWithTexture(texture, new CCRect(5, 978, 40, 50));
            CCSpriteFrame birFrame13 = CCSpriteFrame.frameWithTexture(texture, new CCRect(5, 979, 40, 50));
            CCSpriteFrame birFrame14 = CCSpriteFrame.frameWithTexture(texture, new CCRect(5, 980, 40, 50));
            CCSpriteFrame birFrame15 = CCSpriteFrame.frameWithTexture(texture, new CCRect(5, 981, 40, 50));
            CCSpriteFrame birFrame16 = CCSpriteFrame.frameWithTexture(texture, new CCRect(5, 982, 40, 50));
            CCSprite birdCcSprite = CCSprite.spriteWithSpriteFrame(birFrame0);
            birdCcSprite.position = new CCPoint(240, 430);
            birdCcSprite.scaleX = sX;
            birdCcSprite.scaleY = sY;
            addChild(birdCcSprite);

            List<CCSpriteFrame> animFrames = new List<CCSpriteFrame>();
            animFrames.Add(birFrame0);
            animFrames.Add(birFrame1);
            animFrames.Add(birFrame2);
            animFrames.Add(birFrame3);
            animFrames.Add(birFrame4);
            animFrames.Add(birFrame5);
            animFrames.Add(birFrame6);
            animFrames.Add(birFrame7);
            animFrames.Add(birFrame8);
            animFrames.Add(birFrame9);
            animFrames.Add(birFrame10);
            animFrames.Add(birFrame11);
            animFrames.Add(birFrame12);
            animFrames.Add(birFrame13);
            animFrames.Add(birFrame14);
            animFrames.Add(birFrame15);
            animFrames.Add(birFrame16);
            CCAnimation animation = CCAnimation.animationWithFrames(animFrames, 0.03f);
            CCAnimate animate = CCAnimate.actionWithAnimation(animation, true);
            CCActionInterval seq = (CCActionInterval)(CCSequence.actions(animate));
            birdCcSprite.runAction(CCRepeatForever.actionWithAction(seq));
        }

 

場景切換

在點擊開始按鈕時候,咱們須要進行場景切換,跳到遊戲場景,爲playCallback添加實現

 private void playCallback(CCObject sender)
        {
            GamePlayScene gamePlayScene = new GamePlayScene();
            gamePlayScene.addChild(BackgroundLayer.node(), (int)LayerTags.Background, (int)LayerTags.Background);
            gamePlayScene.addChild(RoadLayer.node(), (int)LayerTags.Road, (int)LayerTags.Road);
            gamePlayScene.addChild(GamePlayLayer.node(), (int)LayerTags.Game, (int)LayerTags.Game);
            float t = 0.8f;
            CCTransitionScene reScene = CCTransitionFade.transitionWithDuration(t, gamePlayScene);
            CCDirector.sharedDirector().replaceScene(reScene);
        }

 

*******************************************

至此,第一屏已經山寨完畢,樓主去寫第二屏算法去了。

相關文章
相關標籤/搜索