经过了前面3节的教程,现在我们已经拥有了一个不错的游戏,但是,有没发现,其实还有一些问题的。比如,背景音乐,即使回到了菜单,那背景音乐依然在播放。这个体验不友好,应该算是BUG了。
那么来修改一下吧。打开GamePlayScene类。在里面重装父类的两个方法,OnEnter和OnExit。把原来在GamePlayLayer的Init里面的播放背景音乐移到OnEnter里面播放背景音乐,并且设置为重复播放。在OnExit里面停止背景音乐的播放。具体代码如下:
public override void onExit() { base.onExit(); SimpleAudioEngine.sharedEngine().stopBackgroundMusic(); } public override void onEnter() { base.onEnter(); SimpleAudioEngine.sharedEngine().playBackgroundMusic(@"resource/backgroundmusic",true); }
这样,我们一旦不在游戏场景,背景音乐就自然停止了。回到游戏场景,背景音乐也能开始播放了。
现在游戏还有一个问题。就是按开始菜单,回到桌面后,按返回键无法返回到游戏中。细心的朋友就会发现,Debug窗口里面显示有异常,并且线程退出了。线程退出了,我们自然无法回到游戏中去了。
那么是什么原因呢,因为我们把一个场景的引用---GamePlayScene的引用放在了PhoneApplicationService里面。这个又黄又暴力的行为微软是认定为不安全的。所以有一个安全异常。这个异常导致线程直接退出了。那么怎么解决呢,我又舍不得不用这个引用。。虽然认为是不安全的。那么就来曲线救国一把。
打开Game1.cs,往Game1这个类里面添加一个声明
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
然后在Game1的构造函数里面增加程序的Deactived和Actived的注册。
PhoneApplicationService.Current.Deactivated += new EventHandler<DeactivatedEventArgs>(Current_Deactivated); PhoneApplicationService.Current.Activated += new EventHandler<ActivatedEventArgs>(Current_Activated);
然后在Deactived时候把GamePlayScene存到IsolatedStorage里面。并且在PhoneApplicationService里面删除,在Actived的时候再把他取出来。其实把这东西存到IsolatedStorage里面也是引发安全异常的。但是经过测试能用。。
void Current_Activated(object sender, ActivatedEventArgs e) { Debug.WriteLine("Activated"); GamePlayScene temp; if (settings.TryGetValue("PlayScene", out temp)) { PhoneApplicationService.Current.State["PlayScene"] = temp; settings.Remove("PlayScene"); } } void Current_Deactivated(object sender, DeactivatedEventArgs e) { CCScene currentScene = CCDirector.sharedDirector().runningScene; string currentSceneName = currentScene.GetType().ToString(); if (currentSceneName == "cocos2dSimpleGame.Classes.GamePlayScene" || currentSceneName == "cocos2dSimpleGame.Classes.GameOverScene") { if (PhoneApplicationService.Current.State.ContainsKey("PlayScene")) { GamePlayScene pScene = (GamePlayScene)PhoneApplicationService.Current.State["PlayScene"]; settings["PlayScene"] = pScene; PhoneApplicationService.Current.State.Remove("PlayScene"); } } else { if (PhoneApplicationService.Current.State.ContainsKey("PlayScene")) PhoneApplicationService.Current.State.Remove("PlayScene"); } Debug.WriteLine("Deactived"); }
测试成功,能用返回键返回程序了。
关于这两个事件我就不多说了。不懂的去了解程序的生命周期的相关资料。
现在说下墓碑机制的问题。现在我用的是7.1的SDK,不是最新的SDK。最新的是7.11,现在我这里的问题就是XNA程序如果重新部署的话,IsolatedStorage就会清空,但是XAML程序就不会。经过多次折腾,还是无法折腾出在程序后台运行后,从启动器启动能返回到以前运行的界面。经过我多次尝试,发现的问题是在Deactived中保存到IsolatedStorage里面的值,在Actived里面能够取到,但是在Launching里面就取不到了。显示特征为压根IsolatedStorage里面压根就没有这个值。由于重新部署IsolatedStorage会清空,所以无法调试。(奇怪的是我用小程序测试还是可以存储的。)。所以进入后台后从启动器恢复程序没有完成。这个很具有WP7的特点的东西,没做好。
现在就这样吧,原来设想是用暴力点的方法直接把场景保存,如果是进入后台从启动器进入,直接暴力转到保存的这个场景。其实也有没那么暴力的方法,就是把游戏场景的游戏层里面增加两个方法,用来设置和获取需要存储的相关变量以便保存和恢复。不过这个相对麻烦多了。
现在想想,我手机上的游戏程序基本没有能进入后台后从启动器能够恢复的。或许也是XNA的局限性吧。毕竟那么多的精灵需要恢复很麻烦不说。还很慢。
到这里,不管怎么说,我们有一个非常不错的游戏了----一个旋转的炮塔,成千上万的不同类型的敌人,多个关卡,win/lose场景,菜单界面,about的声明,当然,还有很棒的音效!