wp7使用Cocos2d-X for XNA制作一个塔防类游戏 (一)游戏基础场景搭建
游戏基础场景搭建
Loading,进入主菜单然后再进入选关界面最后进入游戏,红色箭头的流程。
退出,Back键完成蓝色箭头的流程,最后完成退出。Demo源代码下载
有LoadingScreen.cs,MainMenuScreen.cs,ChooseScreen.cs,GameScreen.cs四个场景类构成,他们都继承于CCScene。
游戏开始进入LoadingScreen在等待3秒后载入MainMenuScreen,点击开始游戏进入选单场景ChooseScreen,关卡图片可以滑动,点击关卡图标进入游戏主界面GameScreen.红色箭头流程。
响应物理键back完成游戏的退出,当在LoadingScreen和MainMenuScreen的时候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在显示3秒Loading.jpg后跳转到MainMenuScreen。
LoadingScreen只在每次游戏开始时出现一次Back键无法回到改场景。
添加单例代码如下:
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
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的位置,按钮的坐标就相对的发生了改变。
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方法
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的逻辑,把背景填充为黑色。
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赋值位置一样。
语文不好小学开始就不及格,有看不懂的地方加群:190784175