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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2012-04-14 02:28  XNAGAME  阅读(3562)  评论(11编辑  收藏  举报