Use the SceneLoader class to display in the XNA in the loading screen (ten)

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Square has developed some Windows Phone some of the game, not what technology. Share your experiences here, only in order to exchange experiences and friends. Square will gradually will write the class uploaded to the hosting project, no good name, called WPXNA, finally, please master detour, so as not to waste time. (in order to focus and reduce space, some sample code may not strict enough. )

SceneLoader

SceneLoader is used to load the resources needed, and to inform the outside world.

Event Loaded is used to inform the outside world all scenes are already included in the resources. Field scenes indicates the need to load resources scene, field afterSceneTypes is used to determine the position sequence scene.

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 ( ); }

}

You can remove the LoadResource method, the loadContent method is modified to internal, so you can directly call the loadContent method to load the resource. In the method of loadContent, we will call the LoadContent method of all the scenes, and then trigger the Loaded event, so that it can obtain has already been loaded resource scenarios and their sequence information.

LoadingScene

Square defines the LoadingScene class as a base class, LoadingScene will use the SceneLoader class to load resources.

Below is the field of the LoadingScene class constructor, events and. Event Loaded will inform the outside world of LoadingScene has completed his task. Loader is used to load the resource fields, field isLoading indicates that the resource is loading, field loadingLabel is used to display the relevant information.

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;
    }
    
    // ...
}

We will not load the resource in the LoadContent method of the LoadingScene, but set the position of loadingLabel, and the tag in the drawing method.

public override void LoadContent ( )
{
    base.LoadContent ( );

    if ( null != this.loadingLabel )
    {
        Label.InitSize ( this.loadingLabel );

        if ( this.loadingLabel.Rotation == 0 )
            this.loadingLabel.Location = new Vector2 ( 50, 50 );
        else
            this.loadingLabel.Location = new Vector2 ( 50, 430 );

    }

}

protected override void drawing ( GameTime time, SpriteBatch batch )
{

    if ( null != this.loadingLabel )
    {
        this.world.GraphicsDevice.Clear ( this.world.BackgroundColor );

        Label.Draw ( this.loadingLabel, batch );
    }

}

In the updating method, LoadResource method, we call SceneLoader to load resources, and before a SceneLoader Loaded event. In order to prevent this code is called again, we set the isLoading field to true.

After the resource loading is completed, the loaded method will be invoked, we will close the scene and trigger his Loaded events.

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 ( );
}

Add the code for the World class

Below, we have for the World class to increase the number of fields and methods, so that we can use the above SceneLoader and LoadingScene.

Field currentSceneLoader is used to realize the load needed resources, field isVertical is used to determine the LoadingScene label direction.

The method used by sceneContentLoaded LoadingScene Loaded event, in the sceneContentLoaded method, we will get the already loaded resource scene, and add them to the World by appendScene method.

private SceneLoader currentSceneLoader = null;

private readonly bool isVertical;

private void sceneContentLoaded ( object sender, SceneLoaderEventArgs e )
{
    ( sender as LoadingScene ).Loaded -= this.sceneContentLoaded;

    for ( int index = 0; 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 ? -90 : 0 ) : null );
loadingScene.Loaded += this.sceneContentLoaded;
this.appendScene ( loadingScene, null, false );
}

We also define several appendScene methods, pay attention to the first of these methods and the appendScene method before we define different. These methods do not add scene directly, but through the creation of SceneLoader and LoadingScene to complete the add task.

Example

Scene SceneT11 is a simple class, contains a font resources and a sound resource, and define a label. SceneT11 will print labels and playing music.

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 );
    }

}

In the OnNavigatedTo method of World, we will call the appendScene method to add the scene SceneT11.

protected override void OnNavigatedTo ( NavigationEventArgs e )
{
    // ...

    this.appendScene ( new Scene[] { new mygame.test.SceneT11 ( ) } );

    base.OnNavigatedTo ( e );
}

If we do not use the SceneLoader and LoadingScene, then the background music in the scene may throw an exception.

This video

Project address
More about WPXNA

Square game QQ group 213685539

Welcome to visit the same article I published in other locations

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Don at November 19, 2013 - 1:27 AM