Monthly Archives: November 2014

Console Games – Snake – Part 3 (Introducing a game timer)

The console snake game is progressing well. Based on where we got to on the last post, we had a game where the snake itself was behaving more or less as expected. The next task is to plant some food. In order to plant the food, we’re going to need a game timer.

What is a game timer?

It’s important to remember here that we’re using this as a teaching device, so trying to introduce something like a System.Threading timer is not going to work because it’s complicated to explain; additionally, one thing that I’ve learned from the small amount of game development that I’ve done is that the more control you have over your threads, the better. Since we already have a game loop, let’s just use that. We currently have a function to accept user input and a function to update the screen; this time we need a function to update the game variables:

        private static DateTime nextUpdate = DateTime.MinValue;
        private static bool UpdateGame()
        {
            if (DateTime.Now < nextUpdate) return false;

            nextUpdate = DateTime.Now.AddMilliseconds(500);
            return true;
        }

Notice that we have an update variable to store the next update, and return a flag where we do update. The Main function would handle this like so:

        static void Main(string[] args)
        {
            Console.CursorVisible = false;
            DrawScreen();
            while (true)
            {
                if (AcceptInput() || UpdateGame())
                    DrawScreen();                
            }
        }

So far, nothing concrete has changed. Let’s use our new function to add some `food`. This is actually quite involved, because we need to translate Position to use a class, rather than a struct; here’s why:

        private static DateTime nextUpdate = DateTime.MinValue;
        private static Position _foodPosition = null;
        private static Random _rnd = new Random();
        private static bool UpdateGame()
        {
            if (DateTime.Now < nextUpdate) return false;

            if (_foodPosition == null)
            {
                _foodPosition = new Position()
                {
                    left = _rnd.Next(Console.WindowWidth),
                    top = _rnd.Next(Console.WindowHeight)
                };
            }

            nextUpdate = DateTime.Now.AddMilliseconds(500);
            return true;
        }

We need to be able to signify that the food is nowhere (at the start, and after it’s eaten). I tried to avoid bringing in classes at this stage, because they add complexity to an already complicated change; however, this seemed the cleanest and easiest solution at this stage.

There’s some other changes to allow for the change to a class from a struct:

        private static bool AcceptInput()
        {
            if (!Console.KeyAvailable)
                return false;

            ConsoleKeyInfo key = Console.ReadKey();

            Position currentPos;
            if (points.Count != 0)
                currentPos = new Position() { left = points.Last().left, top = points.Last().top };
            else
                currentPos = GetStartPosition();

            switch (key.Key)
            {
                case ConsoleKey.LeftArrow:
                    currentPos.left--;
                    break;
                case ConsoleKey.RightArrow:
                    currentPos.left++;
                    break;
                case ConsoleKey.UpArrow:
                    currentPos.top--;
                    break;
                case ConsoleKey.DownArrow:
                    currentPos.top++;
                    break;

            }

            points.Add(currentPos);
            CleanUp();

            return true;
        }

This is because structs are immutable; meaning that we can take one, change it and add it to a collection without issue; but do that with a class and it changes the copied class.

We need to change the DrawScreen method to display the `food`:

        private static void DrawScreen()
        {
            Console.Clear();
            foreach (var point in points)
            {
                Console.SetCursorPosition(point.left, point.top);
                Console.Write('*');
            }

            if (_foodPosition != null)
            {
                Console.SetCursorPosition(_foodPosition.left, _foodPosition.top);
                Console.Write('X');
            }
        }

Finally, the snake now needs to move based on the game timer. First, refactor the section of `AcceptInput` that actually moves the snake:

        private static bool AcceptInput()
        {
            if (!Console.KeyAvailable)
                return false;

            ConsoleKeyInfo key = Console.ReadKey();

            Move(key);

            return true;
        }

        private static void Move(ConsoleKeyInfo key)
        {
            Position currentPos;
            if (points.Count != 0)
                currentPos = new Position() { left = points.Last().left, top = points.Last().top };
            else
                currentPos = GetStartPosition();

            switch (key.Key)
            {
                case ConsoleKey.LeftArrow:
                    currentPos.left--;
                    break;
                case ConsoleKey.RightArrow:
                    currentPos.left++;
                    break;
                case ConsoleKey.UpArrow:
                    currentPos.top--;
                    break;
                case ConsoleKey.DownArrow:
                    currentPos.top++;
                    break;

            }

            points.Add(currentPos);
            CleanUp();
        }

Next, we’ll just cache the key input instead of actually moving on keypress:

        static ConsoleKeyInfo _lastKey;
        private static bool AcceptInput()
        {
            if (!Console.KeyAvailable)
                return false;

            _lastKey = Console.ReadKey();

            return true;
        }

And then handle it in the UpdateGame() method:

        private static bool UpdateGame()
        {
            if (DateTime.Now < nextUpdate) return false;

            if (_foodPosition == null)
            {
                _foodPosition = new Position()
                {
                    left = _rnd.Next(Console.WindowWidth),
                    top = _rnd.Next(Console.WindowHeight)
                };
            }

            Move(_lastKey);

            nextUpdate = DateTime.Now.AddMilliseconds(500);
            return true;
        }

Next time, we’ll manage eating the food and collision detection.

GitHub

For anyone following these posts, I’ve uploaded the code so far to GitHub:

Git Hub Repository

Console Games – Snake – Part 2

Following on from this post, we were creating a snake game for the purpose of teaching a 9 year old to program. This post will not make sense without its predecessors.

Clean up the tail

The next part of this game is to get the snake game to tidy up after itself (to remove the last part of its own tail). This was done (for us) in two parts.


private static int _length = 3;        

private static void CleanUp()
{
    while (points.Count() > _length)
    {
        points.Remove(points.First());
    }
}

This is called from AcceptInput:

private static bool AcceptInput()
{
    …
    points.Add(currentPos);
    CleanUp();

    return true;
}

If you run that now, it simply does what it did before; the final part is to re-introduce the clear:


private static void DrawScreen()
{
    Console.Clear();
    foreach (var point in points)
    …

So now we have a 3 star snake game; try extending the length manually to play with it. It is strangely addictive, even in this immature state.

Console Games – Snake – Part 1

Based on this earlier post, we had a working console game. Admittedly it doesn’t do much, apart from allow you to move a star around the screen. In order to turn this into a snake game, the first thing to do is to no longer clear the screen:

        private static void DrawScreen()
        {
            //Console.Clear();
            Console.SetCursorPosition(_left, _top);
            Console.Write('*');            
        }

That gives us a snake – but you might notice that when you move left, it doesn’t ‘trail’. There is a possible workaround (albeit, not massively efficient – although remember that this is a game with the purpose of teaching programming).

First, create a struct to hold the position:

        private struct Position
        {
            public int left;
            public int top;
        }

This obviously could be a class. Next, create a list of these:

        private static List<Position> points = new List<Position>();

Here’s what the `AcceptInput` function looks like with the changes:

        private static bool AcceptInput()
        {
            if (!Console.KeyAvailable)
                return false;

            ConsoleKeyInfo key = Console.ReadKey();

            Position currentPos;
            if (points.Count != 0)
                currentPos = points.Last();
            else
                currentPos = GetStartPosition();

            switch (key.Key)
            {
                case ConsoleKey.LeftArrow:
                    currentPos.left--;
                    break;
                case ConsoleKey.RightArrow:
                    currentPos.left++;
                    break;
                case ConsoleKey.UpArrow:
                    currentPos.top--;
                    break;
                case ConsoleKey.DownArrow:
                    currentPos.top++;
                    break;

            }

            points.Add(currentPos);

            return true;
        }

        private static Position GetStartPosition()
        {
            return new Position()
            {
                left = 0,
                top = 0
            };
        }

But what about the tail

In traditional snake, the last element is removed each iteration, unless you `eat` something. Doing it the above way lends itself to this more easily. I’ll tackle that for the next post.

Service has zero application (non-infrastructure) endpoints

The Error

Service ‘Namespace.ServiceName’ has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Service ‘Namespace.ServiceName’ has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:

[InvalidOperationException: Service ‘Namespace.ServiceName’ has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.]
System.ServiceModel.Description.DispatcherBuilder.EnsureThereAreApplicationEndpoints(ServiceDescription description) +345
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +292
System.ServiceModel.ServiceHostBase.InitializeRuntime() +90
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +175
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +740
System.ServiceModel.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity) +125
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +901
[ServiceActivationException: The service ‘/ServiceDirectory/ServiceName.svc’ cannot be activated due to an exception during compilation. The exception message is: Service ‘Namespace.ServiceName’ has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element..]
System.Runtime.AsyncResult.End(IAsyncResult result) +624522
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +196075
System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +166

When are you likely to get this

This appears frequently when setting up new WCF services, or changing namespace or service names of existing ones. Unless, you’re a machine and never mistype anything, that is.

The cause

This is caused by a configuration error in the web.config. In my experience, it’s always caused by this; even if you’re sure that you’ve got it configured right – you haven’t.

Resolution

1. Check that the web.config has an endpoint defined:


      <service behaviorConfiguration="commonBehavior" name="Namespace.ServiceName">
        <endpoint binding="..." contract="Interface.IServiceName"/>
      </service>

2. Check the spelling. Compare the namespace against the service.svc file:


<%@ ServiceHost Service="Namespace.ServiceName" %>

3. Make sure you have the namespace specified in the web.config. The easiest way to determine why a WCF service is not working is navigating to the service.svc in internet explorer.

4. Don’t forget to do an IISReset if you change the web.config.

MVVM Cross MvxStorePage Missing for 3.2.1

Recently I upgraded from MVVMCross 3.1.1 to 3.2.1 and everything broke. The reason was that suddenly, the MvxStorePage was unavailable.

After downloading the latest MVVMCross source, I found it safe and well:

namespace Cirrious.MvvmCross.WindowsStore.Views
{
    public abstract class MvxStorePage
        : Page
          , IMvxStoreView
    {

So – the page was still there in Cirrious.MvvmCross.WindowsStore.Views, but NuGet was no longer referencing its assembly:

Cirrious.MvvmCross.WindowsStore.dll

I posted this question.

And prompted by Stuart’s comments, I revisited the MVVMCross source. The confusing thing here is that the MvxStorePage has not been moved; it’s just been ignored and replaced by the MvxWindowsPage; here’s the new version:


namespace Cirrious.MvvmCross.WindowsCommon.Views
{
    public abstract class MvxWindowsPage
        : Page
          , IMvxWindowsView
    {

I’m sure many people knew this; but I wasn’t one of them.

Cannot modify members of ‘myVar’ because it is a ‘foreach iteration variable’

This can occur in a situation such as the following:

        private struct Position
        {
            public int left;
            public int top;
        }

        private static List<Position> _points = new List<Position>();

        private static void MyFunc()
        {
            foreach (Position pnt in _points)
            {
                pnt.top++;
            }
        }

This will fail to compile with the error message:

Cannot modify members of ‘pnt’ because it is a ‘foreach iteration variable’

Why?

The reason for this is simply that you cannot modify the collection that you iterate through, as you iterate through it. From the above statement, I can see that modifying the variable `top` would make no difference, but imagine this:

            foreach (Position pnt in _points.OrderBy(p => p.top))
            {
                pnt.top++;
            }

How to fix?

There’s two easy ways around this; the first is to switch a struct for a class:

    internal class Position
    {
        public int left;
        public int top;
    }

That would now work. The reason for this is the way that the two types are stored. Classes are reference types; which means that what is actually stored in the collection is a list of pointers to classes, and not the classes themselves; consequently, changing them does not affect the actual collection. You can even use orderby on the collection because it caches the order at the start of the loop (I’m certainly not advocating actually doing this).

What if you need to use a struct

Structs are immutable; which means you cannot change them. You can do something like this; although I personally can’t see why it’s easier that using a class:

            for (int i = 0; i <= _points.Count() - 1; i++)
            {
                _points[i] = new Position() { left = _points[i].left, top = _points[i].top + 1 };
            }

Writing a Game in a Console Application – Teaching Programming

Recently I began trying to teach my children some basics of programming. I’d previously tried teaching them using tools like Scratch, but they seemed to get distracted by the graphics whizzing around, and they forgot about the actual coding.

This time, I started up a Visual Basic Console Application, and took them through a couple of basic programs: guess the number, guess the favourite food and calculate prime numbers.

They quickly started to ask about games (by which they meant arcade games), but I didn’t want to jump into a game framework like XNA, as I felt that this time, they were actually understanding some of the constructs. My idea was that we could write a game using a console application.

In order to introduce this, I simply got them to swap the code they had been writing (for example):

        Dim name As String

        Console.WriteLine("hello, what is your name?")
        name = Console.ReadLine() ' Remember name here

For something like this:

        While True
            Dim test As ConsoleKeyInfo = Console.ReadKey()

            Console.Clear()

            If test.Key = ConsoleKey.LeftArrow Then
                Console.WriteLine("You have pressed the left arrow")

Which was going well – I had definitely piqued their interest. The subsequent conversation went something like this:

9 Year Old: So, how do we use this to move something around the screen?

Me: Err, well – we’ll do that next time!

The truth is I had no idea… but I do now, so I thought I’d write at least one post describing it. This is the it. Note that the code that follows in C#, and the preceding code is VB. That’s because I thought that a 9-year-old child would relate better to Visual Basic than C# initially, but I personally think in C# (I learnt to program using Spectrum Basic – and I think we’d have more children programming if you had to wait five minutes for a game to load).

Translation between the two is straight-foward, but you can always use this.

The hardest part

The hardest part in getting a console game working is displaying a character outside of the next position on the console; the trick here is:

Console.SetCursorPosition(left, top);

Extending this, here a function to position a character on the screen:

        private static void DrawScreen()
        {
            Console.Clear();
            Console.SetCursorPosition(_left, _top);
            Console.Write('*');
        }

And the function to read the input would be:

        private static void AcceptInput()
        {
            ConsoleKeyInfo key = Console.ReadKey();

            switch (key.Key)
            {
                case ConsoleKey.LeftArrow:
                    _left--;
                    break;
                case ConsoleKey.RightArrow:
                    _left++;
                    break;
                case ConsoleKey.UpArrow:
                    _top--;
                    break;
                case ConsoleKey.DownArrow:
                    _top++;
                    break;

            }

Finally, the main function and variables:

        private static int _left;
        private static int _top;

        static void Main(string[] args)
        {
            Console.CursorVisible = false;
            while (true)
            {
                DrawScreen();
                AcceptInput();
            }
        }

Is this efficient?

No – it’s not. You can improve this by using:

            if (Console.KeyAvailable)

I’m not planning to write Call Of Duty, but I will try and get them to optimize it slightly, just to get the idea across that the less code executed, the better.

Not much of a game?

No, it’s not. But it is the basis of every arcade game. We had a talk, and have a snake game, and a catch the falling characters game planned; both seem eminently doable based on this starting point.

Creating a Shared Project in WPF

The new thing for VS 2013 is Universal Apps. They allow you to create a Win 8 and Phone app with shared code. But what if you’re writing LOB apps in WPF, maybe using MVVM? You may have a Winforms app and a XAML app, and want to share code; or have two WPF apps that share a core code base, and some screens.

This post walks through creating a sample shared app.

Create WPF App

I’ll just cover WPF in this post. Start by creating a new application:

sharedcode1

Okay, so we have a WPF application (as you might already have). How to create a shared project? Well, the bad news is: you can’t; at least as far as I’m aware (please, please, please let me know in the comments if you know this to be false!).

So, if you can’t create a shared application without a universal one then create a universal one in the same solution:

sharedcode2

This creates a shared app with a reference from Windows 8.1 and Windows Phone 8.1:

sharedcode3

Now, what comes next might feel like a hack… and there’s a good reason for that!

Have a look in the Win 8 app csproj:

sharedcode4

Copy this into the csproj file of the WPF project (remember the path may be different – although in this case, are not):

sharedcode6

The important thing here is the `Label`. However, you’re most likely to get the path wrong. If you do then when you update the project in VS it will fail to load and give you an error message telling you where it’s trying to find the shared project. Having done this a couple of times, my advice is have this error message up, and try to navigate to the path in Windows Explorer: you should see where you went wrong quickly enough.

Adding stuff to the shared project

Start by adding a page to the shared project so that we can see that it works:

sharedcode7

Make it obvious so that you can recognise it:

sharedcode8

Okay, so you’ve now created a shared project, added some shared content, and referenced it from your main project. Next, tidy up by removing Windows 8 and Phone 8 apps and add a second WPF app:

sharedcode9

To make sure that this is, in fact, a shared project, create and make the same change to the second project and then modify each to call the shared page; e.g.:

    private void Button_Click(object sender, RoutedEventArgs e)
        {
            TestPage test = new TestPage();
            Window w = new Window();
            w.Content = test;
            w.Show();

        }

Then run both projects:

sharedcode10

Notes, and using this in an MVVM architecture

Okay – some things that are worth noting here. The main thing is this: the shared code is just that – shared. If you call something like:

typeof(TestPage).Assembly

You will get the assembly of the running application. Effectively, you’ve created a kind of link between the projects, without the messiness of actually creating a link. The consequences of this are that you must ensure that code in the shared project only has dependencies that can be resolved in ALL the projects that include the shared project.

MVVMCross

I’ve tried this on MVVM Cross using two projects and sharing XAML files; and it works. MVVM Cross looks in the current assembly for a `MyView`, when you navigate to a `MyViewModel`. It will find it providing all your projects reference the shared project and you do not try to re-implement the view.

To clarify:

– Creating a shared project between Winforms and WPF that shares a XAML file will most probably not work (admittedly I haven’t tried it).

– Creating a shared project for two WPF projects and copying MyView.xaml into the shared project, leaving the original intact will cause MVVM Cross to fail to resolve the page (because it doesn’t know which one you want).