DCSIMG
October 2010 - Posts - Alex Golesh's Blog About Silverlight Development

October 2010 - Posts

PDC10–thoughts a minute after it finished

PDC10 is over. Now it is a time to think about how it was and summarize the experience.

For me it was very special PDC. It was very special because of two things:

First – I delivered a session during the PDC Workshop! My session was about XNA Game Development for Windows Phone 7. Thanks for all participants – it was a great honor to present for you. The sample I’ve presented during the demo hosted here. The samples I’ve presented from the phone are the part of XNA Creators Club Education Content. They could be found here.

 

Second – I’m kinda upset from the change of the direction Microsoft takes. I did expected to hear something about the futures of Silverlight or at least some commitment about it. Sadly for me I heard a lot about HTML5 and how great it to be especially in cross-platforms scenarios but not a word about Silverlight. It seemed to me, like Silverlight turns to be a solution for Windows Phone 7 development only... I had a chance to talk to Microsoft representatives during the breaks (hey, that’s what PDC is for) and they clarified that Silverlight will continue to be a No. 1 choice for LOB, rich media and mobile applications development.

 

To sum it up – it definitely was a special PDC.

Let’s hope next event I plan to visit (MIX11) will brig better news about my favorite technology!

 

Enjoy,

Alex

Thoughts about application packaging, Resources, MVVM and others

I thought a lot before decided to write this post…

First - I’d like to thanks Ariel Ben Horesh for “inspiring” me to write this post and for dedicating so much time to write his post!

After reading his post I thought a lot and my thoughts about the post are the follows:

1. First, I thought about the applications and the way to provide user with best experience while loading those applications… The users shouldn’t wait minutes for application to download… While authoring large Silverlight applications (MVVM or not) the author should consider to split package (XAP file) into multiple packages to improve loading time, memory footprint, etc. This will enable your application to only use what it needs, when it needs it but also provide an experience to the user and improve overall download times for your application. It is wrong to assume, that all applications are being used in company intranet on 100Mbps-1Gbps bandwidth like connection between developers workstation and internal test webserver. The best practice is very clear about it; for more information I suggest learn about it here; the specific lab named “Partitioning Your Silverlight Application for Deployment” and could be downloaded from here.
Generally, the practice when developer have to re-build the whole application package (let’s say 20+ projects) every time single DLL changes is not optimal for real LOB applications and to the real projects. Much easier to recreate a specific XAP package. I think Microsoft was very clear on this while introduced MEF and added it to Silverlight as well.

2. My second thought was about a resources… I realize, that many of developers uses a resources, but never thought about them in-depth.
To load resource from assembly in the same XAP package, the assembly should be loaded first and then get manifested resource stream from it (and load/add it to merged dictionaries).
To load an embedded resource from assembly packaged into external XAP (according to the technique described in my first point) the application should use a ResourceManager. The external XAP file need to be downloaded to the client machine first. Once downloaded, the assemblies from this package should be loaded and only then embedded resources could be used.
Last thing is about referenced assemblies in same XAP package. The referenced assemblies are not loaded if the types manifested in them are not used. In such case assembly should be loaded first (like in my first example) and the could be used. 
I created a small, but very self-explaining sample (not prism-based Smile) which introduces how to use resources from external assemblies. It could be found at the following location.

3. My last thought was about MVVM and Prism… As a consultant I see too many confusion between those two...

To put is very simple - Prism is not MVVM and MVVM is not Prism.

MVVM pattern is an adaptation of the MVC and MVP patterns in which the view model provides a data model and behavior to the view but allows the view to declaratively bind to the view model. The view becomes a mix of XAML and C#, the model represents the data available to the application, and the view model prepares the model in order to bind it to the view.
Prism is designed to help building modular WPF and Silverlight client applications. These types of applications typically feature multiple screens, rich, flexible user interaction and data visualization, and role-determined behavior.

Prism enable/supports MVVM, but MVVM itself is an architecture that much bigger than Prism. To learn more about Prism and MVVM please refer to the following links:

http://msdn.microsoft.com/en-us/magazine/dd943055.aspx
http://msdn.microsoft.com/en-us/magazine/dd458800.aspx

 

That’s it for now… I’d love to hear professional opinions about my thoughts – the professional discussion is always good!

Alex

PDC10 Workshop Session

Tomorrow I’m flying to Redmond, WA to take a part at PDC10. I believe it will be very special PDC and not only because of its location.

 

PDC10 Workshop taking place on October 30th, the day after PDC10. During this day I’ll present at “Beginning XNA Development for Windows Phone 7” session. My session slot is from 14:00-15:00, right after the lunch :)

 

If you lucky to be at PDC10, staying a day after it ends and want to learn how to start XNA development, when use XNA and when Silverlight on Windows Phone 7 join my session! A lot of fun and cool samples are “on the house”!

 

See you at PDC10!

Alex

TechEd Israel 2010 – “XNA Game Studio 4.0: Code Once, Play Everywhere” Session announcement

Next month, 28-30 November, I’m going to TechEd Israel 2010.

At the conference I have a session dedicated to games! During the session I will show how to build the real world computer game running on such various platforms as Windows Phone 7, Xbox 360 and PC. A lot of fun and cool sample are “on the house” :)

For additional details about the development tools and technologies track (which hosts my session) follow the  link: http://www.microsoft.com/israel/TechEd2010/Tracks/DEV.aspx

 

See you at TechEd!

Alex

Windows Phone 7 Quick Tip: How to use Bing Maps in XNA games

A few days ago, a colleague of mine pointed out to this site which shows a Bing Maps usage within XNA game.

I was intrigued how to achieve it… I know that Silverlight applications for Windows Phone 7 could use Bing Maps control (see great usage tutorial here), but XNA games cannot render Silverlight controls…

To solve it, I decided to use a different approach for XNA – download image tiles and present them in XNA game.

Let’s get started. First, in order to use Bing Maps API you need a Bing Maps Account and Application Private Key.
The Bing Maps Account Center allows you to create keys to use the Bing Maps Control, Bing Maps SOAP Services, Bing Maps REST (representational state transfer) Services and Bing Spatial Data Services.

If you already have a key for using Bing, you may skip next few linesSmile.

Without a valid key, you won’t be able to see retrieve Bing Maps content from the web. To create the account use the following steps (shamelessly taken from here)

  1. Open your web browser and go to the following address: http://www.bingmapsportal.com.
  2. Click Create to create a new Bing Maps account using your Windows Live ID.

    alt

  3. On the next page, fill in your details.

    alt

  4. Once you’ve agreed the terms and registered and/or signed in, you may choose to create a new key for your application. Click the “Create or view keys” link on the left.

    alt

  5. On the next page fill in your application details and click Create Key.

    alt

  6. Below, you’ll see your new private key. Save this key, you will use it later.

    alt

Now let’s do some coding! I decided to create very simple XNA game, which uses Windows Phone 7 location services (on the device) or hardcoded location (on emulator). The game will query Bing maps services and display the received map on screen.

In addition I added my XboxXBOX Live avatar to the center of the map – this will simulate a game process.

Lastly I decided to add simple Zoom In/Out controls too.

Disclaimer: this sample is not an XNA tutorial. To learn about 2D game development with XNA game studio 4.0 for Windows Phone 7 please refer to great tutorial (which I had a great honor to be an author Winking smile) at new MSDN Apps Hub site (http://create.msdn.com/en-US/education/catalog/lab/catapult_wars).

My game will start with loading some assets at LoadContent function – it will load a font to draw text on screen, default background (to fill the screen while first map tile still downloading) and ZoomIn/ZoomOut images.

First – the references I will need in order to make whole thing work – please make sure all of the selected assemblies referenced in the project (some of them automatically referenced with new Windows Phone 7 Game project, some of them need to be referenced manually):

image

Make sure or add the following using statements at the top of the class:

using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using System.Device.Location;
using System.Net;
using Microsoft.Devices;

Let’s see the LoadContent function:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    // TODO: use this.Content to load your game content here
    font = Content.Load<SpriteFont>("Font");
    mapImage = Content.Load<Texture2D>("Nowhere");
    zoominImage = Content.Load<Texture2D>("zoomin");
    zoomoutImage = Content.Load<Texture2D>("zoomout");

}

In addition I created a number of class level variables which will be used during the game:

GeoCoordinateWatcher watcher;
Texture2D mapImage;
Texture2D playerImage;
Texture2D zoominImage;
Texture2D zoomoutImage;
SpriteFont font;
GeoCoordinate co;
bool mapLoaded = false;
bool mapUpdated = false;

float baseScale = 0.04545454545454545454545454545455f;
float scale = 1f;
Vector2 zoomInPosition = new Vector2(20, 20);
Vector2 zoomOutPosition = new Vector2(20, 100);
const string bingAppKey = "MY_BING_MAPS_KEY";

The GeoCoordinateWatcher will be used to observe location changes on the device; once location changes it will be retrieved to the GeoCoordinate variable.

Since Bing Maps uses scale between 1 and 22, I have to scale my textures accordingly.

baseScale variable is 1/22 in order to enable easy scale calculation.

bingAppKey is a private key received at step 6 during registration process.

Now game will draw a mapImage on screen and will display status text according to boolean variables introduced above:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    // TODO: Add your drawing code here
    spriteBatch.Begin();

    spriteBatch.Draw(mapImage, Vector2.Zero, Color.White);

    if (mapLoaded)
        DrawZoomControls();

    if (null != playerImage)
    {
        Vector2 position = 
            new Vector2(GraphicsDevice.Viewport.Width / 2 - 
                        (playerImage.Width * baseScale * scale) / 2,
                        GraphicsDevice.Viewport.Height / 2 - 
                        (playerImage.Height * baseScale * scale) / 2);

        spriteBatch.Draw(playerImage, position, null, Color.White, 0f, 
            Vector2.Zero, baseScale * scale, SpriteEffects.None, 0);
    }

    if (!mapLoaded || mapUpdated)
    {
        string text = !mapLoaded ? "Locating position..." : "Refining map...";
        Color color = !mapLoaded ? Color.White : Color.Red;
        Vector2 size = font.MeasureString(text);
        Vector2 position = new Vector2(10, GraphicsDevice.Viewport.Height - size.Y  - 10);
        spriteBatch.DrawString(font, text, position, color);
    }

    spriteBatch.End();
    base.Draw(gameTime);
}
private void DrawZoomControls()
{
    spriteBatch.Draw(zoominImage, zoomInPosition, Color.White);
    spriteBatch.Draw(zoomoutImage, zoomOutPosition, Color.White);
}

The code snippet is pretty simple, yet requires some explanations. In XNA the on-screen object location and its Z-Index depends on draw order during the Draw function. In order to start drawing the function should Begin a sprite batch rendering process and End it after all objects are drawn. First, the function above draws a background texture which currently will be a “Nowhere” image and will be replaced by the map once it arrives from server. Next, if map already downloaded it will call to helper method to draw zoom controls at known fixed positions. This assures, that zoom texture will be paced above the background (Z-Index is higher). After then, if the player’s image (remember  - it will be my XBOX Live Avatar) arrived, it will display it at the center of the screen scaled accordingly to the map scale. Lastly, it will display “Loading” text if the map is not loaded yet or zoom level changed and map image being updated.

Running application at this stage produces the following result (both at emulator and the device):

image

To get map images I will use a WebClient class (same one which used also in Silverlight applications on Windows Phone 7).

Now it is a time to look at Bing Maps API; from MSDN documentation (http://msdn.microsoft.com/en-us/library/ff701716.aspx, http://msdn.microsoft.com/en-us/library/ff701724.aspx) I see, that the request URI should be build as follows:

http://dev.virtualearth.net/REST/version/Imagery/Metadata/imagerySet?key=BingMapsKey

For more info about version, Imagery, Metadata, etc. please refer to the Bing Maps APIs documentation.

In my sample I will use static image search by query on the emulator:

http://dev.virtualearth.net/REST/V1/Imagery/Map/AerialWithLabels/eiffel tower?zoomLevel=SCALE&mapSize=800,480&key=MY_BING_MAPS_KEY
and location centers at specified geographical coordinate (longitude and latitude) on the device:
http://dev.virtualearth.net/REST/V1/Imagery/Map/Aerial/LATITUDE,LONGTITUDE/SCALE?mapSize=800,480&key=MY_BING_MAPS_KEY

SCALE will be replaced by current scale and MY_BING_MAPS_KEY by my private key. On the device also LATITUDE and LONGTITUDE will be replaced by values reported by Windows Phone 7 location services.

In this quick-and-dirty sample I put the initialization code in Initialize function of XNA game class:

protected override void Initialize()
{
    string requestUri = "";
    WebClient wc = null;

    float currentScale = baseScale * scale * 22;

    // TODO: Add your initialization logic here
    if (Microsoft.Devices.Environment.DeviceType == DeviceType.Device)
    {
        watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // Use high accuracy.
        watcher.MovementThreshold = 20; // Use MovementThreshold to ignore noise in the signal.
        watcher.StatusChanged += (sender, e) =>
        {
            if (e.Status == GeoPositionStatus.Ready)
            {
                mapUpdated = true;
                co = watcher.Position.Location;
                //watcher.Stop(); //Stop to conserve the battery - will disable the movement updates

                requestUri = string.Format("http://dev.virtualearth.net/REST/V1/Imagery/Map/Aerial/{0},{1}/{3}?mapSize=800,480&key={2}", 
                    co.Latitude, co.Longitude, 
                    bingAppKey, currentScale);
                wc = new WebClient();
                wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
                wc.OpenReadAsync(new Uri(requestUri, UriKind.Absolute), "MAP");
            }
        };
        watcher.Start();
    }
    else
    {
        //Get static location (also by lat/long) on emu
        requestUri = "http://dev.virtualearth.net/REST/V1/Imagery/Map/AerialWithLabels/eiffel tower?zoomLevel=" 
            + currentScale.ToString() + "&mapSize=800,480&key=" + bingAppKey;
        wc = new WebClient();
        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
        wc.OpenReadAsync(new Uri(requestUri, UriKind.Absolute), "MAP");
    }

    //Download avatar anyway
    requestUri = "http://avatar.xboxlive.com/avatar/Dark%20Virus%20ISR/avatar-body.png";
    wc = new WebClient();
    wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
    wc.OpenReadAsync(new Uri(requestUri, UriKind.Absolute), "IMG");

    base.Initialize();
}

The code snippet above check the Environment variable in order to understand where it is being executed.

Note: this is not System.Environment available for all .NET applications, but Microsoft.Device.Environment specific to Windows Phone apps.

If the device is actual device (Windows Phone 7 hardware) the code snippet initializes GeoCoordinateWatcher and subscribes to StatusChanged events. Once the status turns to “Ready”, the code snippet gets current reported location and requests a map image using WebClient. It uses reported Longitude, Latitude and current zoom level; in addition it provides Bing Maps private key.

If the device is emulator (and GeoCoordinateWatcher will never return meaningful value), the code snippet uses WebClient to request a map centered at some landmark – in my case Eiffel Tower.

In both request WebClient passes desired image size 800x480 to match Windows Phone 7 landscape resolution.

Lastly, it uses another instance of WebClient to download my XBOX Live avatar.

Last parameter in all OpenReadAsync calls is a state object I’m using to identify which image is arrived.

Let’s see the wc_OpenReadCompleted method:

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    if (e.Error == null)
    {
        if (e.UserState.ToString() == "MAP")
        {
            mapImage = Texture2D.FromStream(graphics.GraphicsDevice, e.Result);
            mapLoaded = true;
            mapUpdated = false;
        }
        else
            playerImage = Texture2D.FromStream(graphics.GraphicsDevice, e.Result);
    }
}

Running the application at the current state produces the following output on the emulator:

image

and the following at the device:

image

Note small red rectangle I put on both images – there is a very small scaled avatar inside Smile

Now let’s enable zoom controls. First, I enabled a Tap gesture at the Game constructor:

TouchPanel.EnabledGestures = GestureType.Tap;

Next, at the Update function of the game I checked Available gestures and if available, their positions. I limited the scale between 1 and 22 (supported by Bing Maps) and if scale change detected used WebClient to get new map at desired zoom level:

protected override void Update(GameTime gameTime)
{
    float prevScale = scale;

    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();

    // TODO: Add your update logic here
    while (TouchPanel.IsGestureAvailable && mapLoaded)
    {
        GestureSample sample = TouchPanel.ReadGesture();

        //Prepare a rectangle around touch position to allow more comfortable touch 
        Rectangle touchPosition = new Rectangle((int)sample.Position.X - 5, 
                                                (int)sample.Position.Y - 5,
                                                10, 10);

        //Prepare a rectange from ZoomIn texture and on-screen position
        Rectangle zoomInRect = new Rectangle((int)zoomInPosition.X, (int)zoomInPosition.Y,
                                                zoominImage.Width, zoominImage.Height);

        //Prepare a rectange from ZoomOut texture and on-screen position
        Rectangle zoomOutRect = new Rectangle((int)zoomOutPosition.X, (int)zoomOutPosition.Y,
                                zoomoutImage.Width, zoomoutImage.Height);

        //Check Touch and zoom rectangles intersection
        if (touchPosition.Intersects(zoomInRect))
            scale += 1;
        else if (touchPosition.Intersects(zoomOutRect))
            scale -= 1;

        //Limit the result between 1 and 22 (scale values supported by Bing Maps
        scale = MathHelper.Clamp(scale, 1, 22);
    }

    if (prevScale != scale)
    {
        string requestUri = "";
        WebClient wc = null;

        float currentScale = baseScale * scale * 22;

        if (Microsoft.Devices.Environment.DeviceType == DeviceType.Device)
            requestUri = string.Format("http://dev.virtualearth.net/REST/V1/Imagery/Map/Aerial/{0},{1}/{3}?mapSize=800,480&key={2}", 
                co.Latitude, co.Longitude, bingAppKey, currentScale);
        else
            //Get static location (also by lat/long) on emu
            requestUri = "http://dev.virtualearth.net/REST/V1/Imagery/Map/AerialWithLabels/eiffel tower?zoomLevel=" 
                + currentScale.ToString() + "&mapSize=800,480&key=" + bingAppKey;

        wc = new WebClient();
        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
        wc.OpenReadAsync(new Uri(requestUri, UriKind.Absolute), "MAP");
        mapUpdated = true;
    }

    base.Update(gameTime);
}

Now when running the application on the device touching Zoom In/Out buttons produces the following results:

image

Note: in this image the next map image is still downloading…

image

and on the emulator:

image

From here the process is simple: add some real game logic, animations, some Bing Maps pushpins (using sample Bing Maps APIs), respond to drag/pinch gestures and voila – the XNA game for Windows Phone 7 with Bing Maps integrated is ready!

Completed sample hosted here. Note: you will need a Bing Maps Application Key to run it.

To see more of XNA 4.0 with Windows Phone 7, PC and Xbox 360 visit my session “XNA Studio 4.0: Code Once, Play Everywhere! PC, Xbox, Phone” at TechEd 2010 Israel/Development Tools & Technologies track. In this session you will see how to build the real world computer games running on all platforms together!

Stay tuned for more come!

Enjoy,

Alex