wp7使用Cocos2d-X for XNA制作一個塔防類游戲 (一)游戲基礎場景搭建


 

游戲基礎場景搭建

 

Loading,進入主菜單然后再進入選關界面最后進入游戲,紅色箭頭的流程。

退出,Back鍵完成藍色箭頭的流程,最后完成退出。Demo源代碼下載

LoadingScreen.cs,MainMenuScreen.cs,ChooseScreen.cs,GameScreen.cs四個場景類構成,他們都繼承於CCScene

游戲開始進入LoadingScreen在等待3秒后載入MainMenuScreen,點擊開始游戲進入選單場景ChooseScreen,關卡圖片可以滑動,點擊關卡圖標進入游戲主界面GameScreen.紅色箭頭流程。

響應物理鍵back完成游戲的退出,當在LoadingScreenMainMenuScreen的時候Back鍵直接退出游戲,GameScreen場景時back有退出提示,確定則退回上一場景。藍色箭頭

流程。

 

一、下載安裝我們的模板后,新建cocos2d-xna項目

1.打開cocos2d-xna項目新建cocos2d-x工程。

2.清理沒有用的HelloCocos2D項目和Classes文件夾里的HelloWorldScene.cs,刪掉AATDDemoContent下所有的文件,讓整個項目干凈一點。

3.Screen文件夾里添加LoadingScreen.cs,MainMenuScreen.cs,ChooseScreen.cs,GameScreen.cs,他們都繼承與CCScene

二、實現LoadingScreen

LoadingScreen在顯示3Loading.jpg后跳轉到MainMenuScreen

LoadingScreen只在每次游戲開始時出現一次Back鍵無法回到改場景。

添加單例代碼如下:

View Code
        private static LoadingScreen _current;
        public static LoadingScreen Current
        {
            get
            {
                GameMain.CurrentScreen = -1;
                if (_current == null)
                {
                    _current = new LoadingScreen();
                }
                return _current;
            }
        }
        CCDelayTime delayTime;
        private LoadingScreen()
        {
        }

 

在構造函數LoadingScreen()中加入圖片Loading.jpg

View Code
   CCSprite loadingImage = CCSprite.spriteWithFile("Images/Loading");
   addChild(loadingImage);
   loadingImage.position = new CCPoint(400, 240);

 

現在要解決的一個問題是讓這個場景停留3秒然后跳轉到下一個場景MainMenuScreen。
方法很多這里用到了CCDelayTime這個延時action,給他設置延時時間3秒,執行這個action,在游戲更新循環中檢測它是否完成如果完成則跳轉場景。

      delayTime = CCDelayTime.actionWithDuration(3);
      loadingImage.runAction(delayTime);

      sheduleUpdate();

sheduleUpdate();注冊了該CCScene的更新邏輯是update方法,重寫update方法,處理跳轉邏輯

        public override void update(float dt)
        {
            if (delayTime.isDone())
            {
                CCDirector.sharedDirector().replaceScene(MainMenuScreen.Current);
            }
        }

MainMenuScreen也是一個單例實現方式和本類相同,恩恩ChooseScreen,GameScreen,也一樣都是單例。

三、MainMenuScreen

添加按鈕

        private MainMenuScreen()
        {

            CCTexture2D menusImage = CCTextureCache.sharedTextureCache().addImage("Images/Menus");
            CCSprite startSprite = CCSprite.spriteWithTexture(menusImage, new CCRect(0, 0, 250, 80));
            CCSprite optionSprite = CCSprite.spriteWithTexture(menusImage, new CCRect(0, 80, 250, 80));
            CCSprite aboutSprite = CCSprite.spriteWithTexture(menusImage, new CCRect(0, 160, 250, 80));

            CCMenuItem startMenuItem = CCMenuItemImage.itemFromNormalSprite(startSprite, null, this, StartCallBack);
            CCMenuItem optionMenuItem = CCMenuItemImage.itemFromNormalSprite(optionSprite, null, this, OptionCallBack);
            CCMenuItem aboutMenuItem = CCMenuItemImage.itemFromNormalSprite(aboutSprite, null, this, AboutCallBack);
            CCMenu menus = CCMenu.menuWithItems(startMenuItem, optionMenuItem, aboutMenuItem);
            menus.alignItemsVerticallyWithPadding(20);
            menus.position = new CCPoint(400, 200);
            addChild(menus);
        }

menus.png是這樣的一張圖片

 

先把它保存到了一個CCTexture2D中,截取它的一部分來創建CCSprite,CCSprite.spriteWithTexture(menusImage, new CCRect(0, 80, 250, 80));
用CCSprite創建CCMenuItem,把CCMenu中的CCMenuItem豎向排列間距為20px,並放在相應的位置。

在StartCallBack回調函數中跳轉場景到ChooseScreen

        void StartCallBack(CCObject sender)
        {
            CCDirector.sharedDirector().replaceScene(ChooseScreen.Current);
        }

四、ChooseScreen

ChooseScreen是一個可滑動的選擇菜單,而CCScene只是一個容器他是不能響應touch事件的。

添加能響應touch事件的CCLayer

        private ChooseScreen()
        {
            this.addChild(new ChooseLayer());
        }

在Screen文件夾地下再添加一個Layer文件夾來盛放所有的CCLayer。

添加5個按鈕CCMenuItem(按鈕是五個很帥的魔獸角色大法師,死亡騎士,劍聖,惡魔獵手和火法帝、他真的不是一個普通的血法師)

這五個角色(menus)被addChild到背景里了所以只要改變背景CCSprite的位置,按鈕的坐標就相對的發生了改變。

View Code
        CCSprite back;
        public ChooseLayer()
        {
            this.isTouchEnabled = true;
            CCSprite ico1 = CCSprite.spriteWithFile("images/warcraft1");
            CCSprite ico2 = CCSprite.spriteWithFile("images/warcraft2");
            CCSprite ico3 = CCSprite.spriteWithFile("images/warcraft3");
            CCSprite ico4 = CCSprite.spriteWithFile("images/warcraft4");
            CCSprite ico5 = CCSprite.spriteWithFile("images/warcraft5");

            CCMenuItem menu1 = CCMenuItemSprite.itemFromNormalSprite(ico1, null, this, CallBack);
            CCMenuItem menu2 = CCMenuItemSprite.itemFromNormalSprite(ico2, null, this, CallBack);
            CCMenuItem menu3 = CCMenuItemSprite.itemFromNormalSprite(ico3, null, this, CallBack);
            CCMenuItem menu4 = CCMenuItemSprite.itemFromNormalSprite(ico4, null, this, CallBack);
            CCMenuItem menu5 = CCMenuItemSprite.itemFromNormalSprite(ico5, null, this, CallBack);
            CCMenu menus = CCMenu.menuWithItems(menu1, menu2, menu3, menu4, menu5);


            CCTexture2D texture = new CCTexture2D();
            texture.PixelsWide = 2000;
            texture.PixelsHigh = 480;
            back = CCSprite.spriteWithTexture(texture);
            addChild(back);
            back.position = GameMath.ScreenCenter;
            back.addChild(menus);

            menus.position = new CCPoint(back.contentSize.width / 2, back.contentSize.height / 2);
            menus.alignItemsHorizontallyWithPadding(100);
        }

在Touch Moved中做位置處理,重寫ccTouchesMoved方法

 

View Code
 public override void ccTouchesMoved(List<CCTouch> touches, CCEvent event_)
        {
            if (touches.Count > 0)
            {
                var touch = touches.Single();
                CCPoint touchLocation = touch.locationInView(touch.view());
                CCPoint prevLocation = touch.previousLocationInView(touch.view());

                touchLocation = CCDirector.sharedDirector().convertToGL(touchLocation);
                prevLocation = CCDirector.sharedDirector().convertToGL(prevLocation);

                CCPoint diff = new CCPoint(touchLocation.x - prevLocation.x, touchLocation.y - prevLocation.y);
                CCPoint currentPos = back.position;

                if (currentPos.x + diff.x < 800 && currentPos.x + diff.x > 0)
                {
                    back.position = new CCPoint(currentPos.x + diff.x, 240);
                }
            }
        }

CallBack回調函數使場景跳轉到主游戲場景GameScreen。

五、GameScreen

GameScreen暫時只是打印出GameScreen而已

        private GameScreen()
        {
            CCLabelTTF lb = CCLabelTTF.labelWithString("GameScreen", "Default", 1);
            lb.position = new CCPoint(400, 240);
            addChild(lb);
        }

這里的labelWithString第三個參數字體大小沒有發揮作用,需要修改自己的大小在.spritefont文件中修改Size節點。


六、Back鍵的處理

在Game1的構造函數中可以清楚的看到Cocos2d-xna只是一個GameComponents。

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

Game1.cs還是那么重要有很多操作仍需在里面做的比如說處理Back的邏輯,把背景填充為黑色。

View Code
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                switch (GameMain.CurrentScreen)
                {
                    case -1:
                    case 0:
                        this.Exit();
                        break;
                    case 1:
                        CCDirector.sharedDirector().replaceScene(MainMenuScreen.Current);
                        break;
                    case 2:

                        string msg = "Quit Game?";
                        List<string> MBButtons = new List<string>();
                        MBButtons.Add("Yes");
                        MBButtons.Add("No");
                        Guide.BeginShowMessageBox("Game Over", msg, MBButtons, 0,
                                            MessageBoxIcon.Alert, GetMBResult, null);

                        break;
                    default:
                        this.Exit();
                        break;
                }
            }


            base.Update(gameTime);
        }

        void GetMBResult(IAsyncResult r)
        {
            int? b = Guide.EndShowMessageBox(r);
            if (b == 0)
            {
                CCDirector.sharedDirector().replaceScene(ChooseScreen.Current);
            }
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            base.Draw(gameTime);
        }

GameMain.CurrentScreen這個靜態字段是為了處理back,標記當前場景的。

LoadingScreen:-1,MainMenuScreen:0,ChooseScreen:1,GameScreen:2

        private static GameScreen _current;
        public static GameScreen Current
        {
            get
            {
                GameMain.CurrentScreen = 2;
                if (_current == null)
                {
                    _current = new GameScreen();
                }
                return _current;
            }
        }

其他類的GameMain.CurrentScreen賦值位置一樣。

Demo源代碼下載

語文不好小學開始就不及格,有看不懂的地方加群:190784175

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM