平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛。在这里分享一下经验,仅为了和各位朋友交流经验。平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXNA 吧,最后请高手绕道而行吧,以免浪费时间。(为了突出重点和减少篇幅,有些示例代码可能不够严谨。)

SceneLoader

类 SceneLoader 用来载入场景所需要的资源,并通知外界。

事件 Loaded 用来通知外界所有场景都已经载入了资源。字段 scenes 表示需要载入资源的场景,字段 afterSceneTypes 则用来确定场景的位置顺序。

internal sealed class SceneLoader
: IDisposable
{
internal event EventHandler<SceneLoaderEventArgs> Loaded; private readonly List<Scene> scenes = new List<Scene> ( );
private readonly Type[] afterSceneTypes; internal SceneLoader ( World world, Scene[] scenes, Type[] afterSceneTypes )
{ if ( null == world )
throw new ArgumentNullException ( "world", "world can't be null" ); if ( null != scenes )
foreach ( Scene scene in scenes )
if ( null != scene )
{
scene.World = world;
scene.IsClosed = false; this.scenes.Add ( scene );
} this.afterSceneTypes = afterSceneTypes;
} internal void LoadResource ( )
{ this.loadContent ( ); } private void loadContent ( )
{ foreach ( Scene scene in this.scenes )
scene.LoadContent ( ); if ( null != this.Loaded )
{
SceneLoaderEventArgs loadedArg = new SceneLoaderEventArgs ( this.scenes, this.afterSceneTypes ); this.Loaded ( this, loadedArg );
loadedArg.Dispose ( );
} } public void Dispose ( )
{ this.scenes.Clear ( ); } }

你可以去掉 LoadResource 方法,而将 loadContent 方法修改为 internal,这样你可以直接调用 loadContent 方法来载入资源。在方法 loadContent 中,我们将调用所有场景的 LoadContent 方法,然后触发 Loaded 事件,这样外界就可以获得已经载入资源的场景和他们的顺序信息。

LoadingScene

平方定义了 LoadingScene 类作为基类,LoadingScene 将使用 SceneLoader 类来载入场景的资源。

下面是 LoadingScene 类的字段,事件和构造函数。事件 Loaded 将通知外界 LoadingScene 已经完成了自己的任务。字段 loader 用来载入资源,字段 isLoading 表示资源是否正在载入中,字段 loadingLabel 用来显示相关信息。

internal sealed class LoadingScene
: Scene
{
internal event EventHandler<SceneLoaderEventArgs> Loaded; private readonly SceneLoader loader;
private bool isLoading = false;
private readonly Label loadingLabel; internal LoadingScene ( SceneLoader loader )
: this ( loader, null
)
{ }
internal LoadingScene ( SceneLoader loader, Label loadingLabel )
: base ( Vector2.Zero, GestureType.None,
new Resource[] {
new Resource ( "peg", ResourceType.Font, @"font\peg" )
},
new Making[] {
loadingLabel
}
)
{ if ( null == loader )
throw new ArgumentNullException ( "loader", "loader can't be null" ); this.loader = loader;
this.loadingLabel = loadingLabel;
} // ...
}

我们并不会在 LoadingScene 的 LoadContent 方法中载入资源,而是设置了 loadingLabel 的位置,并在 drawing 方法中绘制了标签。

public override void LoadContent ( )
{
base.LoadContent ( ); if ( null != this.loadingLabel )
{
Label.InitSize ( this.loadingLabel ); if ( this.loadingLabel.Rotation == )
this.loadingLabel.Location = new Vector2 ( , );
else
this.loadingLabel.Location = new Vector2 ( , ); } } protected override void drawing ( GameTime time, SpriteBatch batch )
{ if ( null != this.loadingLabel )
{
this.world.GraphicsDevice.Clear ( this.world.BackgroundColor ); Label.Draw ( this.loadingLabel, batch );
} }

在 updating 方法中,我们调用 SceneLoader 的 LoadResource 方法来载入场景的资源,并在此之前设置了 SceneLoader 的 Loaded 事件。为了防止这段代码被再次调用,我们设置 isLoading 字段为 true。

在资源载入完毕之后,loaded 方法将被调用,我们将关闭场景并触发他的 Loaded 事件。

private void loaded ( object sender, SceneLoaderEventArgs e )
{
this.Close ( ); if ( null != this.Loaded )
this.Loaded ( this, e ); } protected override void updating ( GameTime time )
{ if ( this.isLoading )
return; this.isLoading = true; if ( null != this.Loaded )
this.loader.Loaded += this.loaded; this.loader.LoadResource ( );
} public override void Dispose ( )
{
this.loader.Loaded -= this.loaded;
this.loader.Dispose ( ); base.Dispose ( );
}

为 World 类增加代码

下面,我们还要为 World 类增加一些字段和方法,这样就可以使用上面的 SceneLoader 和 LoadingScene。

字段 currentSceneLoader 用来实现载入场景所需要的资源,字段 isVertical 用来决定 LoadingScene 中标签的方向。

方法 sceneContentLoaded 用来处理 LoadingScene 的 Loaded 事件,在 sceneContentLoaded 方法中,我们将得到已经载入资源的场景,并通过 appendScene 方法将他们添加到 World 中。

private SceneLoader currentSceneLoader = null;

private readonly bool isVertical;

private void sceneContentLoaded ( object sender, SceneLoaderEventArgs e )
{
( sender as LoadingScene ).Loaded -= this.sceneContentLoaded; for ( int index = ; index < e.Scenes.Count; index++ )
{
Type afterSceneType; if ( null != e.AfterSceneTypes && index < e.AfterSceneTypes.Length )
afterSceneType = e.AfterSceneTypes[ index ];
else
afterSceneType = null; this.appendScene ( e.Scenes[ index ], afterSceneType, true );
} if ( null != this.currentSceneLoader )
this.currentSceneLoader.Dispose ( ); this.currentSceneLoader = null;
} private void appendScene ( Scene[] scenes )
{ this.appendScene ( scenes, null, true ); }
private void appendScene ( Scene[] scenes, bool isVisible )
{ this.appendScene ( scenes, null, isVisible ); }
private void appendScene ( Scene[] scenes, Type[] afterSceneTypes, bool isVisible )
{ this.appendScene ( new SceneLoader ( this, scenes, afterSceneTypes ), isVisible ); }
private void appendScene ( SceneLoader loader )
{ this.appendScene ( loader, true ); }
private void appendScene ( SceneLoader loader, bool isVisible )
{ if ( null == loader || null != this.currentSceneLoader )
return; this.currentSceneLoader = loader; LoadingScene loadingScene = new LoadingScene ( loader, isVisible ? new Label ( "peg.f", "Loading...", 1.5f, this.isVertical ? - : ) : null );
loadingScene.Loaded += this.sceneContentLoaded;
this.appendScene ( loadingScene, null, false );
}

我们还定义了数个 appendScene 方法,注意这些方法与之前我们定义的第一个 appendScene 方法不同。这些方法并不会直接添加场景,而是通过创建 SceneLoader 和 LoadingScene 来完成添加任务。

示例

场景 SceneT11 是一个简单的类,包含了一个字体资源和一个声音资源,并定义了一个标签。SceneT11 将打印标签并播放音乐。

internal sealed class SceneT11
: Scene
{
private readonly Label l1; internal SceneT11 ( )
: base ( Vector2.Zero, GestureType.None,
new Resource[] {
new Resource ( "peg", ResourceType.Font, @"font\myfont" ),
new Resource ( "scene.sound", ResourceType.Music, @"sound\music1" ),
},
new Making[] {
new Label ( "l1", "I'm SceneT11!!!!!!", 2f, Color.White, 0f )
}
)
{
this.l1 = this.makings[ "l1" ] as Label;
} protected override void drawing ( GameTime time, SpriteBatch batch )
{
base.drawing ( time, batch ); Label.Draw ( this.l1, batch );
} }

在 World 的 OnNavigatedTo 方法中,我们将调用 appendScene 方法添加场景 SceneT11。

protected override void OnNavigatedTo ( NavigationEventArgs e )
{
// ... this.appendScene ( new Scene[] { new mygame.test.SceneT11 ( ) } ); base.OnNavigatedTo ( e );
}

如果我们没有使用 SceneLoader 和 LoadingScene,那么在场景中播放背景音乐可能将引发异常。

本期视频 http://v.youku.com/v_show/id_XNTc3MTAyMjYw.html

项目地址 http://wp-xna.googlecode.com/
更多内容 WPXNA

平方开发的游戏 http://zoyobar.lofter.com/ QQ 群 213685539

欢迎访问我在其他位置发布的同一文章:http://www.wpgame.info/post/decc4_70d2c0

使用 SceneLoader 类在 XNA 中显示载入屏幕(十)的更多相关文章

  1. 使用 Button 类在 XNA 中创建图形按钮(九)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  2. 使用 Scene 类在 XNA 中创建不同的场景(八)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  3. 使用 Spirit 类在 XNA 中创建游戏中的基本单位精灵(十三)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  4. 使用 CommandScene 类在 XNA 中创建命令场景(十二)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  5. 使用 Anime 类在 XNA 中创建小动画(十一)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  6. 使用 NPC,NPCManager 在 XNA 中创建 NPC(十九)

    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛.在这里分享一下经验,仅为了和各位朋友交流经验.平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXN ...

  7. 接收键盘输入的字符串,用FileWirter类将字符串写入文件,用FileReader类读出文件内容显示在屏幕上

    public class SY63 { public static void main(String[] args) throws Exception { System.out.print(" ...

  8. 4. 在Inspector面板中显示类中变量+ 拓展编辑器

    1. C#脚本如下: using UnityEngine; using System.Collections; public class MyTest : MonoBehaviour { ; ; [S ...

  9. XNA 中3D模型的显示

    XNA 中3D模型的显示: ModelMeshPart[] meshParts; Model start_model; Matrix[] dq_model_transforms; Matrix vie ...

随机推荐

  1. [Unity3D] 如何识别屏幕边缘

    出现的问题 Unity3D中长度单位是米 使用Screen.resolutions获取的屏幕信息单位是像素 也就是说,即使获取了屏幕相关信息及参数,也无法把信息转换成可在editor中使用的信息.当时 ...

  2. C++各大有名科学计算库(转)

    在 C++中,库的地位是非常高的.C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论.现实中,C++的库门类繁多,解决的问题也是极其广泛,库从轻量级 ...

  3. python 数据库操作 SQLite、MySQL 摘录

    转自: http://www.cnblogs.com/windlaughing/p/3157531.html 不管使用什么后台数据库,代码所遵循的过程都是一样的:连接 -> 创建游标 -> ...

  4. BZOJ 2502: 清理雪道

    BZOJ 2502: 清理雪道 标签(空格分隔): OI-BZOJ OI-最小流 OI-上下界网络流 Time Limit: 10 Sec Memory Limit: 128 MB Descripti ...

  5. elasticsearch RestHighLevelClient 使用方法及封装工具

    目录 EsClientRHL 更新日志 开发原因: 使用前你应该具有哪些技能 工具功能范围介绍 工具源码结构介绍 开始使用 未来规划 git地址:https://gitee.com/zxporz/ES ...

  6. C#的接口基础教程之三 定义接口成员

    接口可以包含一个和多个成员,这些成员可以是方法.属性.索引指示器和事件,但不能是常量.域.操作符.构造函数或析构函数,而且不能包含任何静态成员.接口定义创建新的定义空间,并且接口定义直 接包含的接口成 ...

  7. sass安装更新及卸载方法

    在 Windows 平台下安装 Ruby 需要先有 Ruby 安装包,大家可以到 Ruby 的官网(http://rubyinstaller.org/downloads)下载对应需要的 Ruby 版本 ...

  8. SQL数据库查询出一张表中重复的数据,按某个字段来查找。

    例如表名为Course 需要查询出name重复的有那些??? 解答如下: 补充: 如:查询每个姓名出现大于2次,SQL如下 SELECT COUNT(NAME) as '出现次数',  NAME FR ...

  9. 使用IP地址方法登录MySQL数据库Can't connect to MySQL server的原因。mysql -h 192.168.1.104 -P3306 -uroot -p 失败

    mysql -h 192.168.1.104 -P3306 -uroot -p 然后输入你安装时设置的MySQL密码 发现Can't connect to MySQL server 你的IP 解决方法 ...

  10. 关于小程序button控件上下边框的显示和隐藏问题

    问题: 小程序的button控件上下有一条淡灰色的边框,在空件上加上了样式 border:(none/0); 都没办法让button上下的的边框隐藏: 代码如下 <button class=&q ...