Compartir a través de


Este artículo proviene de un motor de traducción automática.

Continuar coloca

Juegos de la clave de Zune

Mike Calligaro

Contenido

Hombre, que C está cerrada
Anatomía de un juego
Los objetos Sprite en polvo Pixie
Los nombres de los activos y claves de color
Hasta que mover A reproducir
Objeto Sprite en un cuadro
Bing signo de exclamación pluma
Avanzado de dibujo
El resto es hacia arriba para

Mi hijo, que se está reproduciendo Xbox ya que tres, ha iniciado muestra interés en la programación, en concreto escribe juegos. Esto pide me descargar XNA Game Studio y profundizar en él yo mismo, ya sabe, para que puede enseñar con él. Que ha siempre deseaba escribir Mis propia juegos tenía nada que hacer con él. Realmente.

XNA Game Studio 3.0 agrega la posibilidad de escribir juegos para Zune, lo que significa que el Zune ahora es una plataforma de desarrollo para dispositivos móviles. Por lo que es importante, er, juegos de un artículo continuar lugares. Si ya es un desarrollador XNA, es posible que se revisar algunos conceptos que ya conoce. Pero, si es como yo, un programador que es bastante experiencia en desarrollo de juegos, pero entusiastas sobre leer en.

Hombre, que C está cerrada

Para la mayoría de mi carrera año quince en Microsoft, ha sido un desarrollador de sistemas y los controladores. Mi idioma de opción y la necesidad de ha sido un básica de bare bastante C++. Rara vez aparece Utilice runtimes como MFC y Microsoft .NET Framework. Hasta hace poco tiempo, no se pudo ha incluso escrito STL mucho menos hace uso de la.

Eso es mi trabajo del día. Pero en mi tiempo fuera me encanta reproducción alrededor con C#. Principalmente escribir aplicaciones poco para los dispositivos Windows Mobile y en ocasiones para mi PC. C++ no trate me incorrectamente como lo hace muchos programadores nativos, pero que aún aparece un poco giddy cuando escribo en C#. Se puede obtener un lote que ha realizado con muy pocas líneas de código. Jurar, C# es divertido tanto debe hacen un contenido controlled.

En la diversión categoría, XNA Game Studio es como C# en steroids. El equipo a través de ella ha realizado un trabajo de desarrollo de juegos fácil sorprendente. El marco de trabajo es sencillo, en gran parte se controla el material de disco duro para usted y se ha emitido una gran cantidad de muestras dirigidas a impartir los diversos aspectos del desarrollo de juego.

Iniciar en creators.xna.com. Desde allí, puede descargar libre XNA Game Studio 3.0. Si ya utiliza una de las diversas versiones de Visual Studio 2008, XNA Game Studio se integrarán con él. Si no tiene Visual Studio 2008, no se preocupe. XNA Game Studio también funciona con la libre Visual C# Express Edition. (En otras palabras, aunque Mencione Visual Studio, puede emplear Visual C# Express Edition si eso es lo que estás utilizando.)

El sitio de Web creators.xna.com también está lleno de información excelente para pasar. Haga clic en el vínculo de aprendizaje en la parte superior de la página para encontrar las guías de principiantes, ejemplos y cómo - a de. La "principiantes guía para juegos en 2D" es especialmente bien, como la documentación que se instala con XNA Game Studio. En algunos casos, la documentación de instalación dispone de información que no está en el Web. En Visual studio, puede llegar a esa documentación seleccionando ayuda | contenido y la configuración del filtro en XNA Game Studio 3.0.

XNA Game Studio le permite escribir un código base y implementar en Xbox, equipo y Zune. Todo lo que aquí funcionará en todas las plataformas de tres. Las descargas libres son todo lo que necesita para desarrollar para PC o Zune, pero el desarrollo de Xbox requiere una suscripción a Premium que los costos de una cuota anual.

Anatomía de un juego

Una vez que tiene XNA Game Studio 3.0 instalado, puede crear un juego Hello World para Zune seleccionando archivo | nuevo | proyectos. A continuación, seleccione Visual C# | XNA Game Studio 3.0 y haga clic en el juego de Zune (3.0). Mientras el programa que esto genera en realidad no dice Hello World, realiza inspeccionar los datos proporcionados, dibujar el fondo azul y salir a petición.

Si está esperando algo realmente complicado, estará en para una sorpresa agradable. Las cantidades de toda la infraestructura juego a unos 20 líneas de código extienden más seis funciones. Esto es una descripción de estas funciones.

El constructor es simplemente un estándar, jardinería diversas C# objeto constructor. Tratarlo igual como lo haría alguna otra.

Se llama al inicializar después de que finalice el constructor. Le permite hacer más inicialización, especialmente para acciones relacionadas con el sistema de gráficos.

LoadContent se denomina después de inicializar y es donde se carga la imágenes y sonidos.

UnloadContent se llama al salir del juego y le permite descargar su contenido. Pero, puesto que la descarga de la mayoría de las imágenes y sonidos se controla para usted, por lo general no necesita hacer nada aquí.

Actualización es probablemente el lugar en desarrollo de juegos difiere más el desarrollo de aplicaciones normales. En lugar de un bucle de mensajes, juegos con regularidad sondear su entrada, calcular qué hacer con él y, a continuación, dibuje el resultado de dichos cálculos. La mayor parte de la sucede en actualizar, por lo que esto es donde se live la mayor parte de su código.

Dibujar se denomina después de cada actualización y es dibujar las imágenes.

Eso es todo. Aunque el programa es muy breve, inicia, pinta la pantalla azul, lee la entrada y termina cuando se presione el botón espera. ¿Cuál es? ¿Cree que desarrollo de juegos podría ser difícil? No con XNA Game Studio.

Los objetos Sprite en polvo Pixie

Eso fue sencillo, pero no realizar un fondo azul que sale para un juego atractivo. Deberá imágenes reales si se va a tiene una partida. Por suerte, es difícil poner imágenes en la pantalla.

En un minuto voy a mostrar el código, pero primero necesitará cargar una imagen en el proyecto. En Visual Studio, debe tener una ventana denominada Explorador de soluciones (si no lo hace, puede buscar, en el menú Ver). Haga clic con el botón en el Explorador de soluciones, secundario en contenido y seleccione Agregar | elemento existente. Desde aquí puede señalar en cualquier archivo de imagen .bmp, .jpg, .png, .tga o .DDS.

Supongamos que tiene una imagen de una persona denominado player.jpg y que acaba de agregar se a contenido. Figura 1 muestra el código para mostrar esa imagen en la pantalla.

Figura 1 mostrar una imagen

// Add these member variables
Texture2D texture;
Vector2 position;

// Add this line to the constructor
position = new Vector2(100, 100);

// Add this line to LoadContent()
texture = Content.Load<Texture2D>("player");

// And add these lines to Draw();
spriteBatch.Begin();
spriteBatch.Draw(texture, position, Color.White);
// (Draw the rest of your sprites)
spriteBatch.End();

Antes de explique esas líneas, vamos a hablar jerga. XNA Game Studio iniciado como un sistema de desarrollo para la Xbox. Como tal, todos los basado en gráficos 3D. Juegos en 2D (y, dado que la Zune no tiene un representador 3D, sólo tiene que juegos en 2D) son realmente 3D juegos donde todo lo que es muy fino. Por lo que podrá ver términos 3D sprinkled alrededor de su código. Por ejemplo, aunque sprite es el término normal de una imagen en un juego 2D, la textura de palabra procede de juegos en 3D. Como lo como XNA Game Studio está relacionada, los objetos Sprite son muy fina rectángulos 3D con texturas asignadas a ellos.

La función Content.Load toma un nombre de activos, que de forma predeterminada es el nombre de archivo sin la extensión. Desde que cargó una imagen denominada player.jpg, pasa la cadena "jugador" al Content.Load. En la función LoadContent, encontrará que ya hay una línea que asigna un SpriteBatch. Todos los dibujos se realiza con este SpriteBatch. En la función de dibujo, para indicar el SpriteBatch que estás va a comenzar, dibujar todos los objetos Sprite y después indicamos a que termine.

La variable de miembro de posición es un vector de estructura que contiene la x y una ubicación y donde desee que se va a dibujar el sprite. En el ejemplo, utiliza la ubicación del píxel (100, 100). El color es una tinta que se pueden agregar a los objetos Sprite. Uso del producto deja la imagen sin modificar.

Por lo tanto, para obtener una imagen en la pantalla, sólo necesarios para cargar la textura y saber el lote de sprite para dibujar. La primera imagen básicamente toma cuatro líneas de código y cada uno de los siguientes tarda más de dos.

Los nombres de los activos y claves de color

Con suerte, en este momento se está examinando la imagen del Reproductor en la pantalla y pensar que esto no es tan difícil. Pero quizá no esté totalmente satisfecho. ¿Qué ocurre si no desea que el código necesita usar el nombre de archivo de la imagen? Y, por lo que es más importante, ¿qué ocurre si la imagen carga es rectangular, pero el Reproductor no? ¿Cómo puede dibuja sólo el Reproductor y no el fondo?

Para responder de estas preguntas, deberá examinar las propiedades de la imagen que carga. Vuelva al Explorador de soluciones y haga clic con el botón secundario en el archivo (en mi ejemplo, player.jpg). Seleccione Propiedades. Un panel de propiedades aparecerá debajo el Explorador de soluciones, que ofrece una gran cantidad de información útil. Examine primero nombre del activo. Éste es el nombre que se pasado a Content.Load. Si desea que sea algo que no sea el nombre de archivo, cambiarlo por aquí.

Expandir ahora el contenido del procesador si hace clic en el poco + a la izquierda del nombre. La propiedad que interesa aquí es el color de clave de color. Los píxeles cuyo color coincida con la clave de color será transparente. La forma de tomar una imagen rectangular y eliminar el fondo. Por lo tanto, para deshacerse de fondo de los objetos sprite, cambiar su color o cambiar el color clave configuración para que se ajusten. Establece el valor predeterminado a valores de rojo, verde, azul y alfa de 255, 0, 255, 255, que es color fucsia.

Hasta que mover A reproducir

Ciertamente, un sprite único en un fondo azul no se va a ser lo siguiente grande de juegos. Como mínimo, necesita el usuario sea capaz de mover ese objeto sprite alrededor de alguna manera. Y, para ello, deberá saber lo que el usuario desea realizar. Si ha examinó la función de actualización en el programa, probablemente ya tiene una idea cómo hacerlo. El código predeterminado lee la entrada y sale si se presiona la tecla de espera. Por desgracia, del tipo monopolized la entrada no existe. Vamos a cambiar cosas alrededor de un bit que le permiten utilizar como la entrada.

Esto es lo que ve actualmente:

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == 
    ButtonState.Pressed)
    this.Exit();

Sugiero cambiarlo para que sea similar a esto:

GamePadState input = 
    GamePad.GetState(PlayerIndex.One);
if (input.Buttons.Back == ButtonState.Pressed)
    this.Exit();

Ahora puede usar la variable de entrada para ver datos proporcionados por el usuario.Tenga en cuenta que entrada es un GamePadState.Considere entrada la Zune como un controlador de juegos de XBOX es que faltan algunos de los botones.Figura 2 ofrece la lista completa de asignaciones para botones el Zune.

La Figura 2 botón Zune asignaciones
Botón Asignación
Realizar una seguridad GamePadState.Buttons.Back
Reproducir/pausa GamePadState.Buttons.B
Centro de DPad GamePadState.Buttons.A
DPad bordes GamePadState.DPad
Deslizante en la ZunePad GamePadState.Thumbsticks.Left
Hacer clic en el ZunePad GamePadState.Buttons.LeftShoulder

De acuerdo, por lo que vamos a convertir el Reproductor de mover.El código de la figura 3 trata tanto DPad ZunePad entrada, por lo que funcionarán los Zune.(El Zunes original no tener la funcionalidad de ZunePad.)

La figura 3 soporte técnico de movimiento

// add these lines to Update()
const int c_speedScalar = 100;
Vector2 speed = Vector2.Zero;

speed.X = input.ThumbSticks.Left.X * c_speedScalar;
speed.Y = input.ThumbSticks.Left.Y * c_speedScalar * -1;

if (input.DPad.Left == ButtonState.Pressed)
    speed.X -= c_speedScalar;
else if (input.DPad.Right == ButtonState.Pressed)
    speed.Y += c_speedScalar;

if (input.DPad.Up == ButtonState.Pressed)
    speed.Y -= c_speedScalar;
else if (input.DPad.Down == ButtonState.Pressed)
    speed.Y += c_speedScalar;

position += speed * (float)gameTime.ElapsedGameTime.TotalSeconds;

Recuerde que la rutina de dibujo está dibujando el Reproductor en la ubicación especificada por la variable de miembro de posición. Por lo tanto, para mover el objeto sprite, todo lo que necesita para realizar es actualizar esa ubicación.

La parte realmente elegante aquí es la línea última donde que cambiar la posición. La consola Xbox tiene más seguras capacidades de gráficos que el Zune, por lo que su rutina de actualización se llama con más frecuencia. En otras palabras, tiene un framerate superior. Esto significa que es necesario realizar el movimiento de ser independiente de la framerate. Para ello, utilice la entrada para calcular una velocidad, no una posición. A continuación, convertir la velocidad en una posición al multiplicar por la cantidad de tiempo que ha transcurrido desde la última llamada a Update.

Objeto Sprite en un cuadro

Cualquier usuario puede mover. El truco es saber cuándo se debe detener.

Si el juego se va a ser interesante, a continuación, deberá saber cuando un sprite entra en conflicto con otro. Término del desarrollador juego elegante para esto es la detección de colisiones y la forma más sencilla para realizar la detección de colisiones en XNA Game Studio es utilizar un objeto denominado un BoundingBox. Básicamente, ajuste cuadros invisibles alrededor de los objetos y a continuación, compruebe si cualquiera de estos cuadros se intersecan unos con otros.

Aparte el juego actual se menos interesante, el problema mayor es que el sprite puede mover fuera de la pantalla. Vamos a corregir. Siempre que el sprite llega a un borde, se le facilitan saltar volver a la ubicación (100, 100).

En primer lugar, necesitará un cuadro de límite para la pantalla:

// Add this member variable
BoundingBox bbScreen;

// Add these lines to Initialize() 
Vector3 min = new Vector3(0, 0, 0);
Vector3 max = new Vector3(graphics.GraphicsDevice.Viewport.Width,
    graphics.GraphicsDevice.Viewport.Height, 0);
bbScreen = new BoundingBox(min, max);

Hay algo de magia aquí, pero no muy complicado truco de magia. El marco de Hello World le proporcionó una variable miembro denominada gráficos que contiene el ancho y alto de la pantalla de juego. Puede establecer la esquina superior izquierda del cuadro de límite a la esquina superior izquierda de la pantalla y la esquina inferior derecha del cuadro de límite a la esquina inferior derecha de la pantalla. BoundingBoxes necesitan vectores 3D, por lo que las coordenadas de z a 0.

Ahora vamos a crear un cuadro para el objeto sprite, así:

// Add these lines to Update() after 
// the position has been calculated.
Vector3 min = 
    new Vector3((int)position.X, (int)position.Y, 0);
Vector3 max = 
    new Vector3((int)position.X + texture.Width - 1,
    (int)position.Y + texture.Height - 1, 0);
BoundingBox bb = new BoundingBox(min, max);

Por último, veamos si el objeto sprite está contenido totalmente en la pantalla. Si no, debe ha presionar un borde. Agregar estas líneas directamente debajo de los que agregado anteriormente:

ContainmentType ct = bbScreen.Contains(bb);
if (ct != ContainmentType.Contains)
    position = new Vector2(100, 100);

Ahora el sprite saltará al (100, 100) cada vez que llega al borde de la pantalla. Debes, por supuesto, probablemente hacer algo más inteligentes, como detener o arrugar al otro lado.

Colliding con el borde de la pantalla es un poco diferente de colliding con otro objeto. La situación normal es que está dentro de la pantalla, pero está fuera de otros objetos. Por lo tanto, para comprobar si hay un conflicto con el borde de la pantalla, desea ver si el cuadro de la pantalla contiene. Pero si desea comprobar si hay un conflicto con otro objeto, desea ver si el cuadro de ese objeto cruza con usted. Con ese fin, el objeto BoundingBox tiene una función de miembro Intersects. Intersección con devuelve un booleano que es true cuando se cruzan los dos cuadros. Utilice Intersects si desea comprobar si dos objetos Sprite aciertos entre sí.

Bing signo de exclamación pluma

Es ahora una tecnología fuera de escribir sus propios juegos. Puede dibujar imágenes, muévalos en respuesta a entradas del usuario y actúan en ellos se ejecute a entre sí. Dado que esto es un juego, probablemente deseará una colisión de sprite para finalizar en una enorme expansión. Ya sabe cómo dibujar la expansión de, pero no ser muy gratificante a menos que rattle altavoces el Reproductor, demasiado. Afortunadamente, la reproducción de sonidos es incluso más fácil que dibujar objetos Sprite.

En primer lugar, deberá agregar un sonido a su proyecto. El proceso aquí es similar a agregar una imagen. Vaya para el explorador de soluciones, haga clic con el botón secundario en contenido y seleccione Agregar | elemento existente. Desde allí puede elegir un archivo .wav, WMA, MP3 o .xap. Además, como el archivo de imagen, si desea un nombre de activos diferente que el nombre de archivo, puede cambiar, en las propiedades.

Ahora vamos a reproducir que sonido. Este código supone que el archivo cargado que fue explode.wav:

// Add this member variable
SoundEffect sndBoom;

// Add these lines to LoadContent()
ContentManager contentManager = 
    new ContentManager(Services, "Content");
sndBoom = 
    contentManager.Load<SoundEffect>("explode");

// Add these lines to Update()
if (input.Buttons.B == ButtonState.Pressed)
    sndBoom.Play();

La llamada contentManager.Load es similar a la función utilizada al cargar la textura el sprite. A continuación, como ver, cuando desea oír el sonido, sólo reproducirlo. Tenga en cuenta que, que escribe, este código intentará reproducir un sonido nuevo cada marco mientras esté presionado el botón de B. Según la longitud del sonido, esto puede provocar en demasiadas copias de éste reproducción y el juego produce una excepción. Debe protegerse por reproducir sólo una vez por presionar el botón. El clásico para ello consiste en almacenar el estado anterior de la entrada y actuar sólo cuando se cambia el estado.

Avanzado de dibujo

Ahora tenemos las herramientas básicas que necesita para crear sus propios juegos. Sugiero que Dedique un rato a jugar con esas herramientas y obtener cómodo con los. Cuando esté listo para obtener más información, se puede leer en esta sección para obtener una breve introducción a ideas avanzadas. Los documentos de Ayuda de estas funciones le proporcionará todo lo que necesita saber su uso.

En primer lugar, vamos a hablar sobre el orden Z. Tal como el código actualmente esté, si se superponen dos objetos Sprite, que se dibuja última finalizará hacia arriba en la parte superior. Eso es el tipo de un dificultades. Un método mucho mejor es ofrecer cada sprite una variable que indica el orden en que se debe dibujar. Para ello, deberá utilizar versiones más complicadas de spriteBatch.Begin y spriteBatch.Draw, así:

spriteBatch.Begin(
    SpriteBlendMode.AlphaBlend, 
    SpriteSortMode.BackToFront, 
    SaveStateMode.None);
spriteBatch.Draw(texture, position, 
    null, Color.White, 0, Vector2.Zero, 
    1.0F, SpriteEffects.None, zOrder);

Dedicar algún tiempo con la documentación de SpriteBatch y experimentar. Estas funciones son un poco complicadas, pero también son muy eficaces. Por ejemplo, si desea cambiar el tamaño de los sprites, puede utilizar un rectángulo en lugar de un vector de la posición. Si los límites del rectángulo son diferentes de tamaño de la textura, XNA Game Studio escalará, que automáticamente. Si la textura tiene varias imágenes que desea desplazarse entre, puede pasar en un rectángulo de origen que especifica qué parte de la textura que se va a dibujar.

Si desea un sprite translúcido, cambie el valor alfa del color que se pasa al dibujar:

Color trans = new Color(
    Color.White.R, Color.White.G, 
    Color.White.B, 128);

Transacciones de pasar a dibujar en lugar de Color.White y el sprite sería mitad translúcido.

Por último, aquí es algún código nueva que se puede utilizar para girar la pantalla de vertical a horizontal:

// Add this member variable
Matrix matTransform;

// Add these lines to the constructor
matTransform = Matrix.Identity;
matTransform *= 
    Matrix.CreateRotationZ(MathHelper.ToRadians(90));
matTransform *= 
    Matrix.CreateTranslation(240, 0, 0);

// In Draw() change spriteBatch.Begin to this
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, 
    SpriteSortMode.BackToFront, SaveStateMode.None, 
    matTransform);

El resto es hacia arriba para

El código completo para el ejemplo se muestra en la figura 4 , y debe obtener que mover. Si ejecuta aground, el sitio de Web creators.xna.com es completo de ejemplos que muestran cómo realizar todo tipo de cosas de desarrollo de juegos secretos, en por píxel límite cuadros a physics modelos.

Figura 4 un simple Zune juego

public class Game1 : Microsoft.Xna.Framework.Game {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Matrix matTransform;
    Texture2D texture;
    SoundEffect sndBoom;
    BoundingBox bbScreen;
    Vector2 position;

    public Game1() {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        position = new Vector2(100, 100);
        matTransform = Matrix.Identity;
        // Uncomment these lines to do Landscape Mode
        //matTransform *= Matrix.CreateRotationZ(          MathHelper. ToRadians(90));
        //matTransform *= Matrix.CreateTranslation(240, 0, 0);
    }

    protected override void Initialize() {
        Vector3 min = new Vector3(0, 0, 0);
        Vector3 max = 
            new Vector3(
            graphics.GraphicsDevice.Viewport.Width, 
            graphics.GraphicsDevice.Viewport.Height, 0);
        bbScreen = new BoundingBox(min, max);
        base.Initialize();
    }

    protected override void LoadContent() {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        texture = Content.Load<Texture2D>("player");
        ContentManager contentManager = 
            new ContentManager(Services, @"Content\Audio");
        sndBoom = contentManager.Load<SoundEffect>("explode");
    }

    protected override void UnloadContent() {
    }

    protected override void Update(GameTime gameTime) {
        GamePadState input = GamePad.GetState(PlayerIndex.One);
        if (input.Buttons.Back == ButtonState.Pressed)
            this.Exit();

        if (input.Buttons.B == ButtonState.Pressed)
            sndBoom.Play();

        const int c_speedScalar = 100;
        Vector2 speed = Vector2.Zero;

        speed.X = input.ThumbSticks.Left.X * c_speedScalar;
        speed.Y = input.ThumbSticks.Left.Y * c_speedScalar * -1;

        if (input.DPad.Left == ButtonState.Pressed)
            speed.X -= c_speedScalar;
        else if (input.DPad.Right == ButtonState.Pressed)
            speed.X += c_speedScalar;

        if (input.DPad.Up == ButtonState.Pressed)
            speed.Y -= c_speedScalar;
        else if (input.DPad.Down == ButtonState.Pressed)
            speed.Y += c_speedScalar;

        position += speed * (float)gameTime.ElapsedGameTime.TotalSeconds;

        Vector3 min = new Vector3((int)position.X, (int)position.Y, 0);
        Vector3 max = new Vector3((int)position.X + 
            texture.Width - 1, (int)position.Y + texture.Height - 1, 0);
        BoundingBox bb = new BoundingBox(min, max);

        ContainmentType ct = bbScreen.Contains(bb);
        if (ct != ContainmentType.Contains)
            position = new Vector2(100, 100);

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime) {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin(SpriteBlendMode.AlphaBlend, 
            SpriteSortMode.BackToFront, SaveStateMode.None, matTransform);
        spriteBatch.Draw(texture, position, null, Color.White, 
            0, Vector2.Zero, 1.0F, SpriteEffects.None, 0.5F);
        spriteBatch.End();

        base.Draw(gameTime);
    }
}

Espero que encuentre XNA desarrollo de juegos en C# que tantos divertidas como haría.Quizás algo que escribir se convertirán en lo siguiente grande de juegos...Si mi hijo no tiene en él.¡ Feliz codificación.

Envíe sus preguntas y comentarios agoplaces@Microsoft.com.

Mike Calligaroes un jefe de desarrollo jefe con el equipo de Windows Mobile en Microsoft y un colaborador en el blog de equipo de Windows Mobile, que puede ver enblogs.msdn.com/WindowsMobile.