A simple State based level manager in XNA

This post is to explain a simple level manager that will handle the transition between levels of a simple sprite based game based on simple state management of a sequence of levels. It assumes linear progression from one level to the next

A level consists of a set of items (Sprite based items in this case) that you want to interact with or get them to interact independently, during game play. The key to level management is to have a parent class for each level that you want in your game and that will contain references to collections that you may have in each level of your game.

The level manager manages the transition between the levels based on the outcome of a particular level. Failure and re-doing a level is not dealt with here but could be easily accommodated by extending the state model for the Level Class and coding the Level Manager accordingly.

To keep it simple here and concentrate on the Level class and the Level Manager class I will create two levels of a game that will just transit through states based on a Timer. These two classes will be level1 and level2 respectively. I will also only have static (non-animated and non interactive) content in the Level class which can then be filled in the two sub classes (level1 and level2).

The level Manager is created, updated and drawn in the Game1 class. The Draw is implemented just to call the Draw methods of the level1 and level2 classes which in turn pass the draw message on to the components that they contain.

All the classes here only implement or override  a common Update or Draw method, which are most fundamental in Game programming.

So the Game creates the Game Manager.

image

The Level manager creates the Game Levels.

image

The Levels create instances of the level contents Sprites, sound, textures.

There are a couple of Key issues about the structure and control of the levels.

  1. As Level1 and Level2 inherit from Level they can be treated as being the general Level class in some instances. Such as iteration over the collection of Level Objects.
  2. The Sate of a level is kept in the parent class Level and is chosen from the enumerated type LEVELSTATE

image

 

So to the actual State Management and transition of the individual levels. The Level Manager maintains a collection of levels that are created and assigned in the constructor.

class LevelManager
{
    // Indicate the last level is complete
    bool gameOver = false;

    public bool GameOver
    {
        get { return gameOver; }
        set { gameOver = value; }
    }
    // Counter for the current level
    int CurrentLevel = 0;
    // Maximum amount of levels

    const int MAXLEVEL = 2;

    // Collection of levels which are created as subclasses of Level
    Level[] Levels;
    

    public LevelManager(Game g)
    {
        Levels = new Level[MAXLEVEL];
        Levels[0] = new Level1(g);
        Levels[1] = new Level2(g);

        Levels[0].LevelState = LEVELSTATE.PLAYING;
        
    }

Level1 is put into playing mode. It is up to Level1 to transit itself into Finished Mode when it’s end condition is met. In this case a timer is used to time down the fairly static levels. The levels here just show a collection of Chasing Sprites in a location and a player in Level1 that the Chasing sprites will chase.

The transition from playing for a Level is monitored in the Update method of the Level Manager class

 

public void Update(GameTime t)
        {
            if (!gameOver)
            {
                foreach (Level l in Levels)
                {
                    if (l != null && l.LevelState == LEVELSTATE.PLAYING)
                    {   // Update the current playing level
                        l.Update(t);
                        // if the current level has finished
                        if (l.LevelState == LEVELSTATE.FINISHED)
                        {   // Get rid of the level should 
                            Levels[CurrentLevel] = null;
                            // and if the not the last level finished
                            if (++CurrentLevel < MAXLEVEL)
                                // then play the next level
                                Levels[CurrentLevel].LevelState = LEVELSTATE.PLAYING;   
                                //Or else we are finished
                            else gameOver = true;
                        }
                    }
                }
            }

        }

The key thing here is that although level1 and level2 are objects in their own right they have a LevelState variable that can be monitored. The Level class definition is shown below

class Level
{

    private LEVELSTATE levelState;
    public LEVELSTATE LevelState
    {
        get { return levelState; }
        set { levelState = value; }
    }
    protected ChasingEnemy[] enemies;
    protected Sprite[] collectables;
    protected Sprite BackGround;
    protected Player player;

    public virtual void Update(GameTime t)
    {

    }

    public virtual void Draw(SpriteBatch sp)
    {

    }


The virtual methods are provided in case the methods need to be overridden in the future. Any collections of object that you want to have in levels are added as class variables here and can be populated in the constructor for the sub class for example here is the constructor for the Level1 class

class Level1 : Level
    {
        float Timer = 5000; // milliseconds

        public Level1(Game g)
        {
            player = new Player(g, g.Content.Load<Texture2D>("FullTank"), new Vector2(400, 600), 1);
            enemies = new ChasingEnemy[3];
            enemies[0] = new ChasingEnemy(g, g.Content.Load<Texture2D>("EnemyDot"), new Vector2(100, 200), 1);
            enemies[1] = new ChasingEnemy(g, g.Content.Load<Texture2D>("EnemyDot"), new Vector2(300, 200), 1);
            enemies[2] = new ChasingEnemy(g, g.Content.Load<Texture2D>("EnemyDot"), new Vector2(300, 400), 1);
            LevelState = LEVELSTATE.CREATED;
        }

NOTE the sub-classing of the Level class is Key as it contains the exposed LevelState and allows all levels to iterated over using for each and treating them all as Level objects for the purposes of this iteration

Here is the state transition in the Level1 update method

public override void Update(GameTime t)
        {
            if (Timer > 0)
                Timer -= t.ElapsedGameTime.Milliseconds;
            else
                LevelState = LEVELSTATE.FINISHED;

            player.Update(t);

            foreach (ChasingEnemy c in enemies)
                c.follow(player);

            foreach (ChasingEnemy c in enemies)
                c.Update(t);

        }

the full code listing can be found here

Posted in Uncategorized | Leave a comment

Incomplete Federation of Live accounts

I have four Windows Live accounts linked together. But a word of warning. If you want to access files in folders you must give permission on the folder to the linked live accounts. You can edit in the browser from Linked account that you have switched to when initially logged in as another account which would seem to suggest that federation across the accounts works to a certain extent. Sometimes you get an HTTP access error 403 when accessing locations belonging to another Live account that is linked but not directly logged in. This I think is due to improper federation between the Live accounts.

If you are using the office live plug in locally on your PC to download and open a Live sky drive hosted office document for editing, then the account that Office live plug in is setup for needs to have edit permission on the folder and hence the file to be downloaded and opened so all the Live accounts need to have access to folders owned by the other in order for navigation to run smoothly.

Also worth a NOTE: Folder access is inherited from the parent, so if you give access to the account at the top most level then it will be granted for sub folders always.

Posted in Uncategorized | Leave a comment

Jeff Prosise’s Blog : Silverlight 4’s New Local File System Support and Problems with My Documents in Windows 7

While looking at the new restricted capabilities of Silverlight to deal with Files I came across this post Jeff Prosise’s Blog : Silverlight 4’s New Local File System Support. I downloaded the sample code an went to run it. It worked impressively in fact for the My Picture example. But I need to access folders in My Documents. So I tried that and oops it broke. The problem is that

string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

in windows 7 maps onto “C:\\Users\\name\\Documents” and the sub folders of that location have My Music, My Pictures and My Videos contained within and you cannot chain through these folders as you do not have permission to do so. So you have to skip over these thus

string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

foreach (string dir in Directory.EnumerateDirectories(path))
{
if (!dir.Contains(“My Music”) && !dir.Contains(“My Pictures”) && !dir.Contains(“My Videos”))
etc

Another Gotcha in Windows 7 and file permissions is that if you download a zip file from the web is that certain files will be blocked and you have to unblock each one before you can process the files programmatically.

Posted in Silverlight 4 | Tagged , | Leave a comment

Managing Complex Groups in Windows Live – Group Work for students

The Windows Live Group feature allows you to easily manage Group work for students. I have a group of about 70 students from 4 different courses in First year. These Groups are further split into groups for a game that they are designing and developing in Game Maker. I got them to set up groups with one person hosting the Group on their Sky Drive. I set up a new Windows Live ID to manage the group from my side. The Group owner invites the other members to the newly created group along with myself.

I manage the group by setting up Hotmail folders for each Course and then place the invites from each Game Group into these folders.

Games_Groups

This enables me to keep track of the groups within groups via the Email Invite which has a

Group_Invite

Everyone in the Group has read write privileges on the folders in the group. This gives them a means to share content that they are developing for the game. It also allows me to keep an eye on the Progress of the group and comment or advice on the on going work.

Group_Page

There is a One Note web file that the group can use to document the sources of content and keep a group and individual schedule of tasks to be done and completed.

The group can contact me and each other using Instant messenger or by Emailing the group.

Video Link

http://cid-b4f98d68def2bb83.photos.live.com/embedicon.aspx/Video/ScreenCapture_06-04-2011%2016.21.03.wmv

Posted in Windows Live | Leave a comment

Navigating between members through Membership of Groups in Windows Live

If you look at the membership on the right of the Group Window. You will notice that some of the Profile links probably do not have links on them.

shared_membership

That is because you are not friends with those people or they do not have their profile marked as public. Hence you cannot view directly folders of that person in this way if they share them with you. There are other ways to share folders, you can get or send a link in an email. But the best and safest way is to request a friendship link with person and then you can navigate to their space form the membership link. In the screen shot above taken from the ITS Windows Live Educators group. Paul and John are friends and hence they can navigate using the Hyperlink below the pictures. You are brought to profile page of the member in question. if you click on their Documents link, you can see the documents that the member has shared with you and others.

johns_profile

later

Paul.

Posted in Windows Live | Leave a comment

Good Post on Multiple Drawable Game Components – App Hub Forums
via Multiple Drawable Game Components – App Hub Forums.

Posted on by Paul | Leave a comment

XNA Game Components – How Far do they go

Ok. The idea of game components is that they allow you to take logic that would normally be in the game loop out of the game loop. This promotes a certain amount of independence in a class. As an example say we have a image that must move in a game. We’ll make it nice and simple and we’ll create an image that uses Vector2.Lerp to move to a target vector within the screen co-ordinates. Firstly we’ll look at the logic of doing this in the Game loop and then we’ll look at a class that is of type DrawableGameComponent. It’s quite strange that you can only choose a GameComponent Template when you add a new component to a game. This is an oversight by Microsoft in Visual studio.

ContentDir

First we need some class variables.

 

   1: SpriteBatch spriteBatch;

   2: Texture2D movingCircle;

   3: Vector2 movingCirclePosition;

   4: Vector2 Target;

So lets set up our Image first which is in the Project Content folder and load it into the Texture2D Class Variable and Randomise the initial position

   1: protected override void LoadContent()

   2:         {

   3:             Random r = new Random();

   4:             spriteBatch = new SpriteBatch(GraphicsDevice);

   5:             movingCircle = this.Content.Load<Texture2D>("MovingCircle");

   6:             movingCirclePosition = new Vector2(r.Next(600), r.Next(400));

   7:             Target = new Vector2(r.Next(600), r.Next(400));        }

Now we need a Randomised Vector2 for our Target. We can do this in the LoadContent or the or the initialise section.

Next its on to the update method to move things along so to speak.

   1: protected override void Update(GameTime gameTime)

   2: {

   3:     movingCirclePosition = Vector2.Lerp(movingCirclePosition, Target, 0.01f);

   4:     if (Vector2.Distance(movingCirclePosition, Target) < 0.1)

   5:     {

   6:         Random r = new Random();

   7:         movingCirclePosition = Target;

   8:         Target = new Vector2(r.Next(600), r.Next(400));

   9:     }

  10:     base.Update(gameTime);

  11: }

 

Then we draw the moving cricle

   1: protected override void Draw(GameTime gameTime)

   2:         {

   3:             GraphicsDevice.Clear(Color.Black);

   4:             spriteBatch.Begin();

   5:             spriteBatch.Draw(movingCircle,movingCirclePosition,Color.White);

   6:             spriteBatch.End();

   7:             base.Draw(gameTime);

   8:         }

and that’s it. One moving circle.

So lets look at the component version. Firstly a component is usually implemented as a class which is a sub-class of the component class. Once again the only component available in the new class template is a game component which does not override the Draw and LoadContent Class.

 

   1: public class MovingCircle : Microsoft.Xna.Framework.GameComponent

   2:     {

   3:         public MovingCircle(Game game)

   4:             : base(game)

   5:         {

   6:             // TODO: Construct any child components here

   7:         }

 

So we change GameComponent to DrawableGameComponent and then override the Draw and LoadContent Methods. We can then transfer the variables for moving the circle, keeping positions, drawing the circle sprite into the MovingCircle Class and the code transfers into the override methods such as the LoadContent Method shown in the code Snippet below. NOTE the LoadContent method has to have the same visibility as the DrawableGameComponent LoadContent Method. The other methods have a public visibility. The override for Draw must be public.

image

 

   1: protected override void LoadContent()

   2:         {

   3:             Random r = new Random();

   4:             spriteBatch = new SpriteBatch(Game.GraphicsDevice);

   5:             movingCircle = Game.Content.Load<Texture2D>("MovingCircle");

   6:             movingCirclePosition = new Vector2(r.Next(600), r.Next(400));

   7:             Target = new Vector2(r.Next(600), r.Next(400));

   8:         }

   9: public override void Update(GameTime gameTime)

  10:         {

  11:             // TODO: Add your update code here

  12:             movingCirclePosition = Vector2.Lerp(movingCirclePosition, Target, 0.1f);

  13:             if (Vector2.Distance(movingCirclePosition, Target) < 0.2)

  14:             {

  15:                 Random r = new Random();

  16:                 movingCirclePosition = Target;

  17:                 Target = new Vector2(r.Next(600), r.Next(400));

  18:             }

  19:             base.Update(gameTime);

  20:         }

  21:  

  22:         public override void Draw(GameTime gameTime)

  23:         {

  24:             Game.GraphicsDevice.Clear(Color.Black);

  25:             spriteBatch.Begin();

  26:             spriteBatch.Draw(movingCircle, movingCirclePosition, Color.Red);

  27:             spriteBatch.End();

  28:             base.Draw(gameTime);

  29:         }

 

Notice that the code changes so that you use Game.GraphicsDevice isntead of the GraphicsDevice variable that was use in the LoadContent function in the Game class presiously

All that remains to do then is to wire up a MovingCircle instance to the Game Loop by adding it as a component to the game class. This is best done in the Initialise class so that the DrawableGameComponent’s LoadConentFunction is called after the DrawableGameComponent is created. The total code for the Game class now looks like this

   1: public class Game1 : Microsoft.Xna.Framework.Game

   2: {

   3:     MovingCircle myMovingCircle;

   4:     GraphicsDeviceManager graphics;

   5:     public Game1()

   6:     {

   7:         graphics = new GraphicsDeviceManager(this);

   8:         Content.RootDirectory = "Content";

   9:     }

  10:     protected override void Initialize()

  11:     {

  12:         myMovingCircle = new MovingCircle(this);

  13:         this.Components.Add(myMovingCircle);

  14:         base.Initialize();

  15:     }

  16:     protected override void LoadContent()

  17:     {         }

  18:  

  19:     protected override void UnloadContent()

  20:     {

  21:     }

  22:     protected override void Update(GameTime gameTime)

  23:     { base.Update(gameTime);         }

  24:  

  25:     protected override void Draw(GameTime gameTime)

  26:     {          base.Draw(gameTime);         }

  27: }

When we add the DrawableGameComponent to the Component collection of the Game and this plugs it into game loop.

Posted in XNA Games | Leave a comment

Windows Live and EDU@LIVE Joining a group and sharing a document with the group and the owner of the group

At IT Sligo when a student joins a group they are accepted by the co-owner / owner of the group. The student will then get an Email appearing in their in box in the outlook live app

Group Joined Email

I have test student accounts to see what the students see. I also have other accounts that are owners/co-owners of the various groups for my courses.

I can Visit the group or immediately share document, pictures and folders out with the group or individuals based on the group email address or individual Email addresses or so it would appear. (By the way the Office/your documents link at the top of the page does not work. But the Office Recent documents does)

When I clicked on the Share Documents with the group and attempted to share a newly created document with the group but I did not have any success. The the first reason I thought might be that the test profile is private. I have blogged on this fault previously

So I made the profile public but it still didn’t share via the group that the two Live ids are members of!!

I Have to say. In all my years in computing I have never seen something that has been as confusingly put together as windows live and groups. There are more holes than a colander in the functionality and there is over complication at every turn. I’m afraid I have wasted so much time testing this service that I’ll have to give it a 2/10 and go back to the ugly but functional Moodle! Maybe the January new features promised will solve this, but my faith has been broken. Microsoft seem to have shipped (well deployed) a product and waited for the users to test it. It’s very frustrating to be a Microsoft user. Windows Live with Groups is a visually attractive product that shows promise but fails to deliver. It does not bode well for their relatively late and recent incursion into the world of web.

While I do accept that Sharepoint is probably more suited to this functionality, Sharepoint is a complicated business oriented documentation and sharing system. Its too much in all aspects for an educational delivery system

Office Live made it to Beta, but seems to be shelved, with functionality cut back in being moved to the sky drive.

Anyway enough time wasted.

Posted in Windows Live | Leave a comment

Windows Live calendar unavailable

One of the things with web services is that they need to be 100% reliable, otherwise they will not get used.

I tried to load a group calendar and got….

calendar_not_available

Gee I hope not!!

I tried to invite a group to an event and got this

loading_contacts_windows_live_appointment_invite

 

Starting to equate these two!!.

Posted in Uncategorized | Leave a comment

Signing up for XBOX Live on Dream spark

The procedure to redeem a code for membership XBOX creators club.

Firstly you have to go to www.dreamspark.com .

You have to sign in using your Live id.

In the case of students at IT Sligo its sXXXXXXXX@mail.itsligo.ie which is the student EDU@LIVE enabled id’s. Then they have to get verified even though they have been activated on Live already.

Get_Verified_with_Dreamspark

You then choose your Educational institute and then if your id matches the template you are validated. Then student is challenged.

 dreamspark_registered

So now you have to register (again where is windows live?).

Dreamspark_user_create

but here is the snag. It is looking for our old email format which is sXXXXXX@itsligo.ie but the new format is sXXXXXXX@mail.itsligo.ie . So now you get a dispatched email to an address that does not exist anymore. Dreamspark needs an update I think.

Posted in Uncategorized | Leave a comment