Cómo controlar el orden de propiedades o categorías en un PropertyGrid

El control PropertyGrid es fantástico para crear herramientas de prototipado rápido, donde podamos cambiar propiedades de objetos de forma rápida y visual. Como ya sabrás, el espacio de nombres System.ComponentModel contiene multitud de atributos y herramientas para personalizar el modo en que las propiedades se agrupan y configuran dentro de un PropertyGrid.

De forma automática, las propiedades se ordenan alfabéticamente según su DisplayName, o se agrupan por categorías (y se aplica el mismo criterio alfabético dentro de éstas) si así lo selecciona el usuario. Lamentablemente, no existe una forma sencilla de poder controlar manualmente el orden de las propiedades o de las categorías.

Existen muchas formas distintas de lograrlo, pero casi todas implican escribir código. Un workaround sencillo, efectivo, y que no implica utilizar código adicional es el siguiente:

1.- Dentro del atributo DisplayName de cada propiedad, o dentro del nombre de cada categoría (atributo Category),  añadiremos por delante tantos caracteres especiales de tipo \u200B como posiciones queramos “subir” dicha propiedad o categoría hacia arriba. Dicho carácter identifica un espacio vacío de longitud 0, por lo que en la práctica no modificará el texto que se muestra en la propiedad, pero sí afectará al algoritmo de ordenación.

En el siguiente ejemplo, se muestra un objeto con dos propiedades Width y Height. De forma natural (por orden alfabético), Height aparecería antes que Width. Para modificar ese comportamiento y lograr el orden inverso, mucho más natural, solo tendremos que modificar los atributos como sigue:

        [Category("Layout")]
        [DisplayName("\u200B\u200BWidth")]
        public float Width
        {
            get { return mWidth; }
            set { mWidth = value; }
        }
        [Category("Layout")]
        [DisplayName("\u200BHeight")]
        public float Height
        {
            get { return mHeight; }
            set { mHeight = value; }
        }

Así, logramos un PropertyGrid correctamente ordenado, como el de la siguiente ilustración:

image

2.- Debemos asegurarnos de que el PropertyGrid utiliza una fuente que soporte dicho carácter, ya que no todas lo hacen. Por ejemplo, la fuente por defecto Microsoft Sans Serif 8.25 lo soporta perfectamente. No obstante, si queréis aseguraros de forma programática de que la fuente es correcta, podéis utilizar este código:

        public UIEditor()
        {
            InitializeComponent();

            this.propertyGrid1.Font = new Font("Microsoft Sans Serif", 8.25f, FontStyle.Regular);
        }

La importancia de la codificación binaria de Shaders en DirectX o Silverlight

Si alguna vez te has topado con un Vertex o Pixel Shader que al menos en apariencia es correcto, pero que sin embargo produce errores al compilar, ten en cuenta que la codificación utilizada para salvar el texto afecta.

Como ya sabrás, por mucho que un archivo contenga texto, en el disco duro de tu ordenador se almacena como datos binarios. Y para ello, es necesario escoger uno de los muchos métodos existentes para transformar el texto a binario, y vice-versa.

Si abrimos un archivo de texto con una herramienta de análisis Hexadecimal, como HxD, podremos observar que los primeros bytes del mismo determinan su codificación. Por ejemplo, la siguiente ilustración muestra un fichero con la cabecera EF BB BF, que determina que el fichero utiliza codificación UTF-8 (la codificación por defecto en Visual Studio).

image

Podéis encontrar más información sobre cabeceras de archivos de texto aqui.

Lamentablemente, el compilador de Shaders de DirectX solo admite determinados tipos de codificación, y UTF-8 no está entre ellos. Por eso, por mucho que el código de ese shader sea correcto, si tratamos de compilarlo recibiremos el siguiente error (u otros, dependiendo del entorno en el que nos encontremos):

“X3000: Illegal character in shader file“

Si esto sucede, solo tenemos que cambiar la codificación con la que se salva el archivo a disco, utilizando una sencilla opción de Visual Studio (Archivo->Opciones avanzadas de Salvado):

image

Aqui, podremos escoger qué codificación utilizar para guardar el archivo. Por ejemplo, podemos escoger “Western European (Windows) – Codepage 1252”, que es una codificación ASCII simple, para que el compilador de shaders funcione correctamente:

image

Mas info:

http://blog.pixelingene.com/2008/07/file-encodings-matter-when-writing-pixel-shaders/

http://www.cplotts.com/2008/08/22/encodings-matter-with-fx-files/

Conduce un simulador Simax Bentley Continental GT V8

Como parte de la promoción del Campeonato del Mundo FIA GT1 que tendrá lugar la semana que viene en el Circuito de Navarra, estos días tenéis la oportunidad de rodar virtualmente con un Bentley Continental GT V8 a los mandos de un simulador Simax. En el Parque Comercial Galaria (c.c. La Morea) - Pamplona -

WP_000252

Bentley Continental GT V8 Simulator, by Simax

Ayer lanzamos un video sobre el último producto Simax: el simulador del nuevo Bentley Continental GT V8, utilizado por la marca en la premiere mundial para prensa especializada este año. Tuvo gran aceptación entre gente como Tiff Needell (Fifth Gear), Frank Marcus (MotorTrend USA) o Guy Smith (ganador de LeMans 2003). Este último estuvo casi 2 horas conduciendo en el simulador, bajando tiempos vuelta tras vuelta. Más info en: www.simaxvirt.com

--

Yesterdary, we released a video about the latest Simax product: the Bentley Continental GT V8 simulator, which was used by the brand in the world press premiere last February. People like Tiff Needell (Fifth Gear), Frank Marcus (MotorTrend USA) or Guy Smith (2003 LeMans winner) had the chance to try it. Mr. Smith was driving for almost 2 hours in the sim, getting better and better times each lap. More info at: www.simaxvirt.com

Developing a MatrixStack in pure managed C# code (ready for XNA)

Some time ago, we already talked about the possibility of creating your own Math library directly in C#, with no native code. If you take enough care, it can be as fast as performing interop with a native one.
Today, we are showing an additional example on this matter, and we are going to develop our own fast MatrixStack class, all in safe C# code, with no COM interop.

Why?

I never understood well why the MatrixStack class remains to be an iDisposable COM object. Don´t know what kind of optimizations it has internally that justify having disposable resources, but it’s annoying to have the iDisposable overhead with no need for it.
Besides that, MatrixStacks are used in most cases as simple matrix helpers, to traverse object hierarchies. So, replacing the API MatrixStack with your own one should be a piece of cake, and will definitely help you if trying to port your code to some other platform.
Last, but not least, XNA does not have a MatrixStack class. So this C# implementation fits perfectly on it for all that want to use it.
I this example, I will be comparing my own class with the SlimDX MatrixStack, which is nothing more than a wrapper over the D3DX Matrix Stack.

The interface

In order to make the SlimDX stack replacement painless, I will keep the exact same interface in my class (except the COM-related stuff, which is no longer necessary). So, it will have to be something like this:
image

How it works

A MatrixStack, basically supplies a mechanism to enable matrices to be pushed onto and popped off of a matrix stack. Implementing a matrix stack is an efficient way to track matrices while traversing a transform hierarchy.
So, we can clear the stack to the Identity or to any other matrix, we can operate with the top of the stack, and we can add (push) or remove (pop) nodes (or levels, if you want) to the stack.
Example: for a robot arm hierarchy, we would go like this:

1.- Initialize the stack, and load the matrix of the first node in the hierarchy (the upper arm, for example). Now you can use the Top matrix to draw the upper arm.
2.- Create another level on the stack (Push) for the lower arm, and multiply the lower arm matrix. Use the Top matrix to draw the lower arm.
3.- Create another level on the stack (Push) for the hand, and multiply the hand matrix. Use the Top matrix to draw the hand.
The stack itself does nothing you cannot do with regular Matrix multiplications, except that it keeps track of the previous levels you have been creating. So you can go back to the upper node whenever you want. After the previous operations, for instance, if we perform a Pop, we would remove the top node of the stack, and go back to the previous. This way, the new Top node would represent the lower arm matrix, instead of the hand matrix.

The code

Here is my implementation of the MatrixStack. Please keep in mind that it has not been intensively tested, and might contain errors. Use it at your own risk:
    public class MatrixStack
    {
        /// <summary>
        /// Retrieves the Top node matrix of the stack
        /// </summary>
        public Matrix Top = Matrix.Identity;        
        public object Tag = null;
        private List<Matrix> mStack = new List<Matrix>();
        
        /// <summary>
        ///
        /// </summary>
        public MatrixStack()
        {
            LoadIdentity();
        }
        /// <summary>
        /// Clears the stack and loads the Identity Matrix in the top of the stack
        /// </summary>
        public void LoadIdentity()
        {
            mStack.Clear();
            Top = Matrix.Identity;
        }
        /// <summary>
        /// Clears the Stack, and loads the matrix in the top of the stack
        /// </summary>
        /// <param name="pMat"></param>
        public void LoadMatrix(Matrix pMat)
        {
            mStack.Clear();
            Top = pMat;
        }
        /// <summary>
        /// Adds a new level to the stack, cloning the current TOP matrix of the stack
        /// </summary>
        public void Push()
        {
            mStack.Add(Top);
        }
        /// <summary>
        /// Removes the current TOP matrix of the stacks, returning back to the previous one
        /// </summary>
        public void Pop()
        {
            if (mStack.Count > 0)
            {
                Top = mStack[mStack.Count - 1];
                mStack.RemoveAt(mStack.Count - 1);                
            }
        }
        /// <summary>
        /// This method right-multiplies the given matrix to the current matrix (transformation is about the current world origin).
        /// This method does not add an item to the stack, it replaces the current matrix with the product of the current matrix and the given matrix.
        /// </summary>
        /// <param name="pMat"></param>
        public void MultiplyMatrix(Matrix pMat)
        {
            Matrix.Multiply(ref Top, ref pMat, out Top);
        }
        /// <summary>
        /// This method left-multiplies the given matrix to the current matrix (transformation is about the local origin of the object).
        /// This method does not add an item to the stack, it replaces the current matrix with the product of the given matrix and the current matrix.
        /// </summary>
        /// <param name="pMat"></param>
        public void MultiplyMatrixLocal(Matrix pMat)
        {
            Matrix.Multiply(ref pMat, ref Top, out Top);            
        }      
        /// <summary>
        /// Rotates (relative to world coordinate space) around an arbitrary axis.
        /// </summary>
        public void RotateAxis(Vector3 pAxis, float pAngle)
        {
            Matrix tmp;
            Matrix.RotationAxisAngle(ref pAxis, pAngle, out tmp);
            Matrix.Multiply(ref Top, ref tmp, out Top);           
        }
        /// <summary>
        /// Rotates (relative to world coordinate space) around an arbitrary axis.
        /// </summary>
        public void RotateAxisLocal(Vector3 pAxis, float pAngle)
        {
            Matrix tmp;
            Matrix.RotationAxisAngle(ref pAxis, pAngle, out tmp);
            Matrix.Multiply(ref tmp, ref Top, out Top);           
        }
        /// <summary>
        /// Rotates (relative to world coordinate space) the specified Euler Angles
        /// </summary>
        public void RotateYawPitchRoll(float pYaw, float pPitch, float pRoll)
        {
            Matrix tmp;
            Matrix.CreateFromYawPitchRoll(pYaw, pPitch, pRoll, out tmp);
            Matrix.Multiply(ref Top, ref tmp, out Top);            
        }
        /// <summary>
        /// Rotates (relative to world coordinate space) the specified Euler Angles
        /// </summary>
        public void RotateYawPitchRollLocal(float pYaw, float pPitch, float pRoll)
        {
            Matrix tmp;
            Matrix.CreateFromYawPitchRoll(pYaw, pPitch, pRoll, out tmp);
            Matrix.Multiply(ref tmp, ref Top, out Top);           
        }
        /// <summary>
        /// Scale the current matrix about the world coordinate origin
        /// </summary>
        public void Scale(float pX, float pY, float pZ)
        {
            Matrix tmp;
            Matrix.CreateScale(pX, pY, pZ, out tmp);
            Matrix.Multiply(ref Top, ref tmp, out Top);
        }
        /// <summary>
        /// Scale the current matrix about the world coordinate origin
        /// </summary>
        public void ScaleLocal(float pX, float pY, float pZ)
        {
            Matrix tmp;
            Matrix.CreateScale(pX, pY, pZ, out tmp);
            Matrix.Multiply(ref tmp, ref Top, out Top);           
        }
        /// <summary>
        /// Determines the product of the current matrix and the computed translation matrix determined by the given factors (x, y, and z).
        /// </summary>
        public void Translate(float pX, float pY, float pZ)
        {
            Matrix tmp;
            Matrix.CreateTranslation(pX, pY, pZ, out tmp);
            Matrix.Multiply(ref Top, ref tmp, out Top);           
        }
        /// <summary>
        /// Determines the product of the current matrix and the computed translation matrix determined by the given factors (x, y, and z).
        /// </summary>
        public void TranslateLocal(float pX, float pY, float pZ)
        {
            Matrix tmp;
            Matrix.CreateTranslation(pX, pY, pZ, out tmp);
            Matrix.Multiply(ref tmp, ref Top, out Top);
        }
    }

It has to be fast

When you start coding your own MatrixStack, you will soon realize that .Net includes a Generic Collection called Stack. You can use it, although I didn’t. Why?
Because I have separated the management of the Top Matrix of the stack to a member variable, and for the rest I just preferred to use a simple list to keep track of the previous nodes.
The Top Matrix is stored as a member variable to be able to pass it By Reference to the Matrix Multiplication methods. The speed increase avoiding to pass a whole matrix by value is significant. In the example below, it was around a 40% faster.

Test 1 – Reliability

I just made several random operations with the matrix stack, trying to test some of its features by comparing the end Top Matrix, both with a SlimDX MatrixStack and my own. The test operations are:
matrixStack.LoadIdentity();
matrixStack.MultiplyMatrix(Matrix.PerspectiveFovLH(0.8f, 1.6f, 0.1f, 999f));
matrixStack.Translate(10, 10, 10);
matrixStack.Scale(2, 2, 2);
matrixStack.RotateYawPitchRoll(1f, 0f, 0f);
matrixStack.RotateAxis(Vector3.UnitY, 0.75f);
matrixStack.Push();
matrixStack.TranslateLocal(-5, -5, -5);
matrixStack.ScaleLocal(0.1f, 0.1f, 0.1f);
matrixStack.Pop();
matrixStack.MultiplyMatrixLocal(Matrix.RotationZ(1.45f));
The resulting top matrix is:
SlimDX MatrixStack:
  1. [M11:-0.06350367 M12:4.695973 M13:-0.3505643 M14:0]
  2. [M21:0.5231493 M22:0.5700315 M23:2.887983 M24:0]
  3. [M31:18.08297 M32:20 M33:-23.60117 M34:1]
  4. [M41:-0.1968169 M42:0 M43:0.03565279 M44:0]
MyMatrixStack:
  1. {M11:-0.06350368 M12:4.695973 M13:-0.3505643 M14:0}
  2. {M21:0.5231493 M22:0.5700315 M23:2.887982 M24:0}
  3. {M31:18.08297 M32:20 M33:-23.60117 M34:1}
  4. {M41:-0.1968169 M42:0 M43:0.0356528 M44:0}
As you can see, the result is exactly the same.

Test 2 - Speed

Speed is important, so I decided to run the above mentioned operation 10 million times, to se how long it takes to complete both using SlimDX and my own code.
Obviously, if we run in Debug mode (disabling optimizations), there will be a huge performance difference, as the SlimDX dll is already compiled with optimizations. But what happens if we turn all optimizations on when compiling our code?
Here is the result of a small test application:
image
As you can see, the .Net Framework alone is faster than SlimDX, thanks to its optimizations and to the absence of the interop layer.
What happens if we increase the number of iterations to 60 million? The difference is obviously bigger (1.36 seconds faster):
image
Note: This test has been done on an intel i7 CPU at 3.8 Ghz, running on Windows 7 x64 with .Net Framework 4.0.
Note2: SlimDX MatrixStack uses its own Matrix class and operations. My implementation uses my own Matrix implementation, also written in pure C# code.
Conclusion: .Net Rocks. A purely native C++ code would be even faster of course, but if you put in the equation the huge amount of benefits .Net will give you, I really think it’s worth it. Don’t you think?
Cheers !

New XNA 4.0 book by Packt Publishing

Packt has released a new book on XNA 4.0 development: XNA 4.0 Game Development by Example: Beginner's Guide – Visual Basic Edition.

2403EXP_XNA%204_0%20Game%20Developement%20by%20Example

I think I will have the chance to review the book, so I’ll tell you more when I’ve read it, but it looks promising. Seems to be a must for anyone that is facing XNA 4.0 development in Visual Basic.

Cheers !

Simax to develop the Bentley Continental GT V8 Simulator

During the last month, Bentley has been presenting the new Continental GT V8 at the Circuit of Navarra.

SimaxBentley_DiarioDeNavarra_Low

Simax was there, testing the car and working in the development of an accurate simulation, to be introduced in the Simax driving simulators permanently installed at the circuit, so journalists could test the car both virtually and in the real track.

After several days working with Bentley experts to tune up the simulated car, the result has been pretty impressive. Now, journalists from all around the globe, like Tiff Needell, from Fifth Gear (in the picture, driving one of our simulators) are coming to the event.

P1010404_Low

There were also some professional drivers there, like the LeMans 2003 Winner Guy Smith, who was driving in our simulator for almost one hour and a half. It was a pleasure to hear his impressions, and I must say, he really liked the sim.

P1010372_Low

Make some cash developing for Windows Phone

imageIn this post I’ll try to share my thoughts and experience developing applications for the Windows Phone Marketplace. I’ll share with you why I think it’s a great platform for an indie or pro developer, and I’ll also try tell you what did work in this last years, what didn’t, and a couple of hints that could help you improve a bit your revenue.
First things first: I’m not a professional developer for mobile devices. I am indeed a software developer in other fields, but as I always was interested in this kind of devices, I decided to give them a try. All my interest was to test the investment and resources needed for a development like that, and the return profit one can expect from it.
Although not everything I tried really worked, my applications has been downloaded almost 22.000 times since published (today is January 17th, 2012), with a full version conversion rate of almost a 16%. This is my total and daily download chart since October 2010:
image

A bit of history

Windows BlocksMy first application for the phone, published in October 23rd 2010, was Windows Blocks. It was a very simple Arkanoid-like game, that was first developed as a C# game developing tutorial for a webcast. The title of the webcast was: “Developing a full Windows Phone game in less than 2 hours”. Once it was done for the webcast, I decided to finish the few details still remaining, and to publish it in the marketplace, just to learn how it worked. Of course, it was not a hit, and the reviews weren’t excellent (remember it was done in a few hours), but it was a good first try.
In those days (a couple of weeks after the Marketplace was launched), the publication process was a bit of a pain, I must say. But it has been improved a lot since then, and now it is far easier.
Gravitards
Then, I decided to make something more serious, investing more resources and effort, what lead to my second Windows Phone game: Gravitards. It was a beautiful skill game in which the player had to move a ball through several levels with progressive difficulty. This time, reviews were much better, and sales were better too, but honestly not enough to cover the hours invested in the game.
In the first case, it was not surprising that things didn’t work. After all, I didn’t invested too much efforts in the game, so that was predictable. The second one though was much more detailed and I put much more care into it, so I expected more. However it was, it had a couple of drawbacks users complained about that kept sales down I guess.
Silver NavigatorBut then came my third attempt: Silver Navigator. It was not a game, but a GPS-like application.
One day, I had to drive to Madrid. My ex-wife kept my old GPS, and it was a holiday here, so I couldn’t buy a newer one. I decided to check in the Marketplace if there was something like that in there, but there wasn’t yet. Then, I remembered that I saw once a Silverlight Bing Maps control over there, that had pretty decent features. So I took Visual Studio, created a new Silverlight project, and put one of those controls in there. I found a couple of web services that could calculate routes, and added several features like route painting over the Bing Maps control. In three hours, I had a very primitive version of Silver Navigator, that allowed me to drive through Madrid without a problem.
As there was not anything like that in the marketplace yet, I decided to invest some hours on it, and after two or three weeks adding more features, a User Interface, and some other stuff, I published the first version of Silver Navigator on April, 2011. It wasn’t a full-featured GPS device, as maps and route calculation required an internet connection, but it did a pretty decent job inside cities, where signal always works, and in fact that’s where I most use GPS devices, instead of open roads.
The impact was remarkable. Downloads started to grow, and it stayed above 100 downloads per day for several months. I opened a Facebook page for it, where users could write their opinions, and that was a win with no doubt. People started to ask for new features, like voice guidance and automatic map rotation. As things were doing well, I decided to go further, and to implement those features, releasing a couple of new versions which had a great acceptance by the users.
Now, Silver Navigator has been downloaded almost 18.300 times, with a full version conversion rate of almost a 18%.

The numbers

Up to date (January 17th, 2012), the statistics of my applications are:
  • Windows Blocks: Total Downloads: 620           Conversion Rate: 10.1 %
  • Gravitards:         Total Downloads: 2512         Conversion Rate:  5.6 %
  • Silver Navigator: Total Downloads: 18269        Conversion Rate: 17.5 %
Note: What these numbers mean? All my applications in the Windows Phone Marketplace had a free/demo mode, that users can try first, and then decide to buy them or not. The conversion rate is the percentage of the total downloads that truly became sales.
So, as you can see, it’s been a great result for an indie developer, and even more if you think of the amount of hours and resources invested in the development of these applications. The effort/reward balance has been really positive:
  • Windows Blocks: Aprox. hours invested: 5      Total units sold up to date:  63
  • Gravitards:         Aprox. hours invested: 280   Total units sold up to date:  141
  • Silver Navigator: Aprox. hours invested: 240   Total units sold up to date:  3202

Hints to keep in mind when publishing an application

First, you should care about maximizing the visibility of your application in the Marketplace. This is influenced by many factors, like the number of total applications in there, how attractive it results for the users, etc. There are some things you cannot do anything about, like the number of apps in the marketplace, but you can help out in many others. In general, keep the following things in mind:
  • Try to think of a good name for your application. I failed in that with “Gravitards” (some people talked about the name, saying it reminded of “retard” or “retarded”, haha… :-).
  • Publish it in the appropriate category, as people uses categories to filter searches.
  • Put a lot of attention and detail to graphics and presentation of your application. Icons, pictures, and all media material should be well designed. It should be concise and clear, but also beautiful and attractive when possible. This is more important than you think…
  • Promote your application as much as you can. If you can afford it, pay for ads at Facebook or wherever you want. If you think you have a really good idea, contact your local Microsoft representative and ask for support. They are amazing, and will really help you if they can.
  • Give your users the chance to talk to you. Create a Facebook page for your application, and include a link on your app that takes you directly there.
  • Send the details of your application to most common mobile websites our there, like WMPowerUser, XDA Devs, etc etc. They do a great job reviewing apps.
  • Put a free/demo mode on your app. Give the users the chance to try it for free. Many people won’t pay without trying first.
Secondly, you will probably care about having the highest conversion rate possible. It’s nice to see that your application is being downloaded thousands of times, but it’s even nicer to see that becoming sales :)  !!!. So, to improve your conversion rate, keep in mind:
  • Your free/demo mode should be long enough to allow users trying the application well. But more importantly, it should be long and featured enough to make them want the full version. And this is important. If it’s too short, there might be not enough time for them to appreciate the app, and to get into it. If it’s too long, they might get the feeling that they had enough with the demo. In a game, for example, give them the chance to be playing for 10 or 15 minutes with the demo. I made this mistake with Gravitards, where the demo was only one level long (only 2-3 minutes playing), and people found that way too short.
  • Easy of use: this is crucial. Keep an eye on professional apps or games, and study how they are done. Why options are laid out that way, why menus have that shape. Everything is studied. Try to copy from the people that knows how to do it. Users should find easily what they want to do, with as few clicks as possible.
  • If it’s a game, keep an eye on difficulty level. This is very important, and very difficult to properly tune. If the game is too easy, people will get bored soon, may be even with the demo only, and will not buy the full version. If it’s too hard, it could be frustrating for users, and stop playing. However, if you are about to make this mistake, it’s better to make it a hard game than an easy game (there’s always people out there that takes that as a challenge).
  • Responsiveness of your application. Nowadays, people don’t tolerate slow or unresponsive applications. Easy as that. Everything should be fluid.
  • Localize your app to as many languages as possible, and of course include English as a minimum. Your app will be sold worldwide !!!
  • Consider including publicity in the free/demo version of your application. It’s a great way to make some cash with the free downloads.
  • Think of a reasonable price. It’s sometimes better to sell a lot of copies at a low price, than selling a few, more expensive copies.

Why do I think that Windows Phone is a GREAT platform to develop for?

There are many reasons, but some of them are:
  • Microsoft’s support to developers is great, with direct contact that really helps, continuous contests and prizes for developers, app promotion as “App of the week”, etc.
  • The number of Windows Phone devices in the market is raising amazingly. Specially since the Nokia Lumia came out, Windows Phone is now the hit. Everybody is talking about the Lumia.
  • Technically, there are very few hardware differences between WP7 devices, so you can be pretty sure that your application will work well on every device. This is a BIG problem in other platforms, like Android, were the phones are frustratingly segmented.
  • Microsoft offers development tools for free, like Visual Studio Expresss, XNA Game Studio, etc. The investment needed to start earning money from your developments is almost ZERO. And that doesn’t happen in any other platform.
  • You can re-use your WP developments for the XBox too, what is really great. Very soon, you will also have a Marketplace for Windows, what is going to be an awesome milestone in software development.
  • The technology behind your developments (.Net Framework, XNA Game Studio, Silverlight, etc), has a very affordable learning curve. In fact, it’s the easiest and most efficient platform in the market. And for free !!!
  • The development tools are, simply, the best. And this deserves an specific chapter.

Development tools

Microsoft is not a clear software leader in all fields. But in Development Tools, it is. I think that every software developer opinion is the same. Microsoft Visual Studio has no rival.

And this is no exception. The set of tools that you will use to develop for the Windows Phone is truly amazing (and free). The Windows Phone emulator is a masterpiece, with a mindblowing debugging speed. Those of you that have tried developing for Android, for example, know what I´m talking about.
If you plan to develop a game, the XNA Game Studio is simply awesome. It provides you with a full featured framework for game creation that allows you to develop last-gen games, again with a learning curve like no other.
If you plan to develop and application, Silverlight is again very cool. Last-gen user interfaces, beautifully animated and fluid, all with a .Net Framework basement, with thousands of classes ready for you, that will make your developments a piece of cake.
I have developed for Android for some time now, and believe me, it’s a frustrating experience compared to all of this.

My conclusion

If you are planning a new development for a mobile platform, Windows Phone has become THE way to go. When it first came out, it was soon positioned as a clear candidate and a tough competitor for iOS and Android. But now, in my modest opinion, it has no rival.
No matter if you are a pro developer or an indie one, the design and development period of your life-cycle will be much easier and shorter. Of course, if you have the resources to make a cross-platform development, and you can make your app to work in all iOS, Android and Windows Phone, go for it.
But if you’re a indie developer, or simply don’t need that level of compatibility, your best bet is WP. Currently, it is clearly the platform which requires the lowest initial investment (almost zero), the most efficient and easy (and therefore the one that requires less effort and work), and step by step it’s becoming the one with the highest return rates. You just need to check this blog post.
Cheers !!

Finding the external IP Address of your machine, with a timeout, in C#

If you try to find the IP Address your machine is using, you can follow two paths. The most obvious one is:
 string host = System.Net.Dns.GetHostName();
System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(host);
System.Net.IPAddress[] addr = ipEntry.AddressList;
 for (int i = 0; i < addr.Length; i++)
{
      if (addr[i].AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
          continue;
      return addr[i].ToString();
}
 
 return "";
Unfortunately, in most cases people are connected to the internet through a router, and therefore each machine is assigned with an internal IP Address of the private LAN network, assigning the external IP Address to the router only, not to each machine. Finding this external address directly is not trivial, as you would need to deal with the router itself, with different router models, etc.
The easiest way to find the external IP Address is to do a web request to one of the several websites out there specially designed to provide you with that address, like whatismyipaddress.com, www.whatismyip.com, etc. In this case, we will use the last one.
Of course, doing a web request can take time, specially if there is no internet connection available, as the default timeout can take several seconds. This function will do the job for you, and accept a custom timeout.
/// <summary>
/// This function uses a Web request to find the external IP Address your machine is using
/// </summary>
/// <param name="pTimeOutMiliSeconds">Number of miliseconds to wait for a response</param>
/// <returns></returns>
public static string GetExternalIP(int pTimeOutMiliSeconds)
{
   string whatIsMyIp = "http://automation.whatismyip.com/n09230945.asp";
   WebClient wc = new WebClient();
   UTF8Encoding utf8 = new UTF8Encoding();
   try
   {
      string ipaddr = null;
      bool done = false;
 
      wc.DownloadDataCompleted += new
      DownloadDataCompletedEventHandler((object sender, DownloadDataCompletedEventArgs e) =>
      {
         ipaddr = utf8.GetString(e.Result);
         done = true;
      });
 
      wc.DownloadDataAsync(new Uri(whatIsMyIp));
      System.DateTime startTime = System.DateTime.Now;
      while (!done)
      {
         System.TimeSpan sp = System.DateTime.Now - startTime;
 
         // We should get a response in less than timeout. If not, we cancel all and return the internal IP Address
         if (sp.TotalMilliseconds > pTimeOutMiliSeconds)
         {
            done = true;
            wc.CancelAsync();
         }
      }
      return ipaddr;
   }
   catch
   {
      return null;
   }
   finally
   {
      if (wc != null)
      {
         wc.Dispose();
         wc = null;
      }               
   }
}

It works pretty obviously. It just uses the DownloadDataAsync method, instead of the synchronous DownloadData, and waits for a certain amount of time. If no response is received in that time, cancels the async method and returns null.
Hope it helps!

FIXED: VStudio 2010 Intellisense doesn’t select a default value

From time to time, my Visual Studio Intellisense seemed to stop working properly, until VStudio was re-booted.

Apparently with no reason, Intellisense stopped selecting a default value automatically, what is pretty annoying for me, as I tend to misspell many words…

As re-booting VStudio and re-loading my entire Solutions takes several priceless seconds, many times I saw myself working without that feature, and getting more and more nervous…

Today I have realized that, in fact, nothing was going wrong with Intellisense.

It seems that there is a keyboard combination shortcut to enable/disable this feature (I probably was hitting it by mistake)…

If that happens to you… simply hit:

Ctrl + Alt + Space

And you will be enabling/disabling it… Now I feel like a dumbass…. hahahaaa…

Thank God!

Simax emergency braking practice, with and without ABS

The following video shows one of the Road Safety training exercises available in the Simax Road Safety simulator. It allows to practice emergency braking and obstacle avoidance on wet surfaces. The driver learns how to react depending on the presence of an ABS system or not.