4 comments

I will be writing a few posts on connecting silverlight and drupal in which I will replicate my main site. I will be doing this piece by piece as I investigate each drupal module that I am using and how I can request the appropriate data to populate my silverlight controls. I have outlined the basics needed to accomplish this in my previous post and will be focusing on the new information that is needed to complete each new piece.

Drupal's aggregator module is a core module that is used for fetching syndicated content from other sites. However, it has the ability to provide an xml syndication button for your drupal site if you decide to show the syndication block. There is much more functionality that this module can provide, but all I needed was a simple link to my sites syndication. After doing some initial research I did not find a way to call some method that returned my sites syndication. So I decided to 'cheat' a little bit and produce my sites syndication link manually (at least I did not hard code this!). Here is the php below:

$mainSiteRSS = variable_get('site_name', 'Drupal');
$mainSiteRSS .= url('rss.xml');
return array('rssLoaded', $mainSiteRSS);

I simply grab the sites name, append 'rss.xml' and return a correctly formatted url string to my silverlight application. I then tie that url to my rss button:

private void rssLoaded(object feedSite)
{
    string rssLocation = ((MethodToCall)feedSite).MethodName;
    Uri rssLink = new Uri("http://" + rssLocation, UriKind.RelativeOrAbsolute);
    HtmlPage.Window.Navigate(rssLink);            
}

Remember, I have a generic method that gets called when drupal returns its data that casts the data to a MethodToCall object as outlined in my previous post.

And that's it! This was one of the simpler controls and that is one reason that I decided to start with this one. The silverlight code was very simple as well; just a button that looks like the standard rss icon that was made using Expression Blend that has a click event that sends a request to drupal to return my sites syndication link, as outlined above in the php code. Here is the XAML for the rss icon:

<Button Click="rss_Click">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Canvas>
                <Rectangle Width="50" Height="50" Fill="Orange" RadiusX="5" RadiusY="5" />
                <Canvas>
                    <Ellipse Width="10" Height="10" Fill="White" Canvas.Left="10" Canvas.Top="30" />
                    <Path Stroke="White" StrokeThickness="5" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Data="M 15,20 a 15,15 90 0 1 15,15" />
                    <Path Stroke="White" StrokeThickness="5" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Data="M 15,10 a 25,25 90 0 1 25,25" />
                </Canvas>
            </Canvas>
        </ControlTemplate>
    </Button.Template>
</Button>

I will post my full source code when I complete this entire replication of my site to silverlight. Until then, I will post the source for each control in a separate solution. If there is a specific drupal module that you would like converted to a silverlight control let me know and I will try to help you out!

filefile size
SLDrupal – RSS.rar141.97 KB
RSSIcon.xaml939 bytes
rssmodule.txt652 bytes

1 comment
Get Microsoft Silverlight

The above silverlight application will allow you to do the following actions:

  • Login
  • Anonymous login
  • Create a new user
  • Logout

You can do multiple actions above during a silverlight session; there is no need to refresh the page for the actions to take effect within the silverlight application. But refresh the page once your account is created or when you are logged in to allow drupal to recognize the changes.

drupalLogo

Drupal is an open source content management system (CMS) that allows users to add modules to their sites for great flexibility. These modules are typically written in PHP and use drupal's API to connect themselves with the framework. Silverlight (version 2.0 and greater) is a cross-platform browser plugin that allows users to write managed .NET code for the back end and use XAML as the front end. Since silverlight is a browser application and drupal is a framework for hosting data in browsers there can be data that is shared between the two using HTTP as the transport. In this example, I have chosen to use XML-RPC as drupal uses xml-rpc natively and silverlight can easily take advantage of this.

xmlrpc

One thing to note, drupal has a module called services that is currently under development that will allow external applications (such as silverlight) to easily communicate through various interfaces, such as: XML-RPC, SOAP, REST and AMF. I am NOT using this module in my example.

Custom Module for Drupal:

As far as the drupal side of things go, I have a basic install of drupal 6.2 with a custom module that I have written to communicate with my silverlight application. I wrote the module based off of tips from Pro Drupal Development using chapters 2 and 19. There are two files that are needed to construct a drupal module: a .info file that contains information about the module and a .module file that is the actual custom module. My custom module is extremely simple in which it implements hook_xmlrpc to map xml-rpc methods to php callback functions. The xml-rpc methods are received from silverlight and then call the appropriate php function with the appropriate arguments. My php functions do various tasks, such as: checking the drupal database to see if a user exists so that user can login if the correct credentials are supplied,logging in an anonymous user, logging a user out and creating a fully authenticated user. Once the module is uploaded to the server, enable the module and your done! Well, done with the drupal side.

Silverlight application:

silverlightLogo

There are currently two methods in silverlight to communicate via a web service (in this case xml-rpc): WebClient and HttpWebRequest. HttpWebRequest contains all of the properties and methods that WebClient has and then some. But of course the extra goodies that HttpWebRequest provides come at a price; added complexity. WebClient is extremely easy to use and only requires one event and one property to be used, all though there are additional events and properties that can make life easier. Here are the events and properties that I have used in my application:

drupalDB = new WebClient();

drupalDB.UploadStringCompleted += new UploadStringCompletedEventHandler(drupalDB_UploadStringCompleted);

drupalDB.UploadProgressChanged += new UploadProgressChangedEventHandler(drupalDB_UploadProgressChanged);

drupalDB.UploadStringAsync(location, xmlData);

 

drupalDB is my WebClient and there are two events defined that will notify me when upload progress has changed (perfect for a progress bar) and completed. The property, UploadStringAsync takes in a Uri and a string as the data to upload to the web service. One thing to note here is that I am using UploadStringCompleted and not DownloadStringCompleted as WebClient does a GET for downloads and a POST for uploads and xml-rpc only accepts POSTs.

The data that I am uploading to the xml-rpc service is a string that is xml formatted that uses the standard xml-rpc definition:

string xmlData = "<?xml version=\"1.0\"?>"

              + "<methodCall>"

              + "<methodName>userlogin.logAnonIn</methodName>"

              + "<params>"

              + "<param>"

              + "<value>"

              + "</value>"

              + "</param>"

              + "</params>"

              + "</methodCall>";

 

There are two important things to note here. The tag <methodName> contains the xml-rpc method that the hook_xmlrpc function will map to a php function. The first part of that argument, userlogin is the name of my module and a standard format that drupal follows. The <param> tag contains a <value> tag where an argument can be passed to the hook_xmlrpc function. If multiple arguments are required then one needs to add additional <param><value>my data here</value></param> tags in between the <params> tag. Once the data is sent from silverlight to drupal and the appropriate mapping php function is processed, a return value is sent back to silverlight:

<methodResponse>
  <params>
    <param>
      <value>
        <string>return value</string>
      </value>
    </param>
  </params>
</methodResponse>

The UploadStringCompleted event will fire once all of the above data is received. A popular way to parse the returned data is to use LINQ. LINQ is very powerful and very easy to use once you learn a little about it. I can parse the above data with the following LINQ statement:

XDocument document = XDocument.Parse(e.Result);

List<MethodToCall> methodsToCall = (from user in document.Descendants("value").Elements("string")

                                    select new MethodToCall

                                    {

                                        MethodName = user.Value

                                    }).ToList();

 

I place the result in an XDocument and use LINQ to parse the document for any node 'value' that has a child node 'string'. This is the standard format that xml-rpc sends. If there are multiple arguments then there will be multiple 'value' nodes. I call ToList() on the LINQ statement to create a generic list for multiple arguments that may be passed back.

With my particular application, since I can control what I send to and from the xml-rpc service, I decided to use reflection and pass back a string from drupal that I have defined as a method in my silverlight application. One thing to note here is that arguments are passed back as objects. If multiple arguments are passed back they are each an object, not an object[] so your method must take multiple arguments that are each objects instead of one argument of type object[].

After my method is called via reflection I simply update my user object as appropriate. And that's it! That is the basics of how to get drupal to talk to silverlight and vice versa. Of course, one needs to add some more logic and flare to a silverlight application to take advantage of the data it receives from drupal. I have added a few items that hopefully make the user experience that much better (and easier) in my user login application.

As a side note, once silverlight is configured on your web server all you need to display the silverlight application is the following html code placed wherever you would like:

<div style="width: 325px; height: 350px;">

    <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">

        <param name="source" value="/silverlight/SLApps/DrupalGameDemo.xap" />

        <!-- Only need the below to show a link to get silverlight if it is not installed –>

        <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">

            <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none" />

        </a>

    </object>

</div>

 

The <object> tag contains a <param> tag that has the 'value' attribute of the location of your .xap file. The link in the above html code (<a> tag) is the link that will be displayed if a user does not have silverlight installed.

Feel free to try out the attached silverlight source (application is also displayed at the top of this page) and change things to your liking. Enjoy!

I have uploaded the custom module file as 'userlogin.txt'. (Rename it to .module) Remember to include a 'userlogin.info' file as well to complete your custom module. You can view the module file with notepad.

The LayoutTransformControl that I am using has been updated to the RTW bits. The latest code required additional code to update the transform at any time an animation was fired that would normally update the transform. Dave talks about why that is and one of the comments in his post points out a simple way to achieve this. Go grab this control as it's a great control to keep in your toolbox!

filefile size
UserLogin.rar448.1 KB
userloginmodule.txt3.6 KB

0 comments

After reading Kirupa's excellent blog post about filtering images in a Deep Zoom Collection, I decided to take it one step further. Deep Zoom has the potential to allow us to think way outside the box. There have already been some great examples of this, such as: Jose Fajardo's demo and Deep Earth. I'm sure there are a few other great examples out there, but those 2 really demonstrate true potential for this technology.

In Kirupa's example of how to filter images in a Deep Zoom Collection, there is an associate metadata.xml file that is created when you export you Deep Zoom Collection. The properties that are currently exported for each multiscale image are:

  • File name
  • X coordinate
  • Y coordinate
  • Width
  • Height
  • Z order
  • Tag

I was mainly interested in accomplishing 2 things; having a list of images that came from the metadata.xml file and having the ability to select an image and bring it into view.

dzlinksoverview_thumb

 

Since the metadata.xml file contains the file name (including the images source folder) I could easily loop through those tags and grab all of the images. I wanted to show these images as thumbnails. At this time, there is not an easy way to generate a thumbnail from the deep zoom collection. I manually resized my images and saved them off by appending "thumb_" in front of each image. Now that I had my thumbnails I could loop through the metadata.xml file, pull off the file name tag and associate that image with its corresponding thumbnail.

Each thumbnail is then placed in my ImageSlider control (great control Denislav Savkov). I tweaked the ImageSlider control to my liking and added repeatButtons for scrolling left and right so the user could hold down the mouse for a faster scroll. In the SelectionChanged event of the ImageSlider control I match up the thumbnail with the corresponding deep zoom image and then set the multiscale image control's viewport accordingly to bring that deep zoom image into view.

dzlinksselected_thumb

 

EDIT (June 26): The 'bug' is really no bug at all, instead a misunderstanding on my part. It turns out that the y coordinate is relative to the image's width. It also has to be negative ... negative goes down, right? (Thanks to Jaime Rodriguez and her blog post to clear this up!)

And there you have it, a simple way to see a collection of thumbnails and select the appropriate image to get the corresponding deep zoom image. If you have any questions / comments please let me know. And always, the source code is attached, enjoy!

Get Microsoft Silverlight
filefile size
DZLinks_Source.zip2.76 MB

0 comments

Popfly has gone offline ...

My last post described a silverlight game that I made with the current version of silverlight 2 beta. I was continuing to work on improving the game when my RSS reader showed me Adam Nathan's post about the Popfly Game Creator! Holy cow, this is awesome! This is what I have dreamt of for years, seriously. I have tried other programs that enable users to visually design their games, but MS got this game creator dead on. It's in alpha currently and there are some minor things that could be improved initially, but so far the possibilities are endless!

popflygamecreator_thumb

Popfly's game creator uses silverlight 1.0 currently with plans to upgrade to silverlight 2. There is awesome graphic work already included in many samples and you can use that artwork in your own game. You can also 'import' you own XAML graphics and other graphics from projects that people share on popfly. The basic idea behind the game creator is to use 'actors' as the visual objects that the user interacts with. Those 'actors' are then used in 1 or more 'scenes', or places in your game world. And that's basically it, pretty simple. Now you can customize your 'actors' with 'behaviors' so they act as you wish, and currently you can write your own javascript code for those 'behaviors'. There are also 'properties' that you can set on almost anything and further customize the way your 'actors' and interact.

battletankoverview_thumb

To see how easy this game creator was, I decided to replicate my silverlight tank game. Not everything is the same, but for the most part everything looks and acts the same. The grass background was provided by Popfly and it easily tiled to fill the available space that I specified for my game. The tank graphics are the same as my game, I simply copied my XAML path data into an actor and then gave that actor 5 behaviors; forward, backward, left, right and shoot. I duplicated that actor with Popfly's nifty shortcut menu so all I had to do was re-assign the keyboard values for the other actor. When I defined the shoot behavior I selected a circle graphic and gave it appropriate behaviors to disappear on collision with the other tank. Then I added in solid objects around the border and in a couple of places. I had to ensure that these solid objects had a mass greater than my tanks, which was easy enough to accomplish since all of the solid objects are duplicates of one actor and they all 'inherit' the appropriate properties. I then set when the game should go into a win and a lose (the other tank wins) scenes and then my game was done! Really, it was that easy.

battletankgameplay_thumb

Once you know your way around the simple menu in the game creator you can fly through and customize your game easily. I chose not to add sounds to my game as it was bogging down my experience (all though that could be my internet connections fault since I am using a Sprint aircard). I also used only 1 animation for the explosion of a tank that Popfly provided. After making the simple version of the game I decided I wanted to add an additional feature that my original tank game did not have yet, bombs! I added this ability for each player in a matter of minutes; with most of my time working on javascript to limit each player to 3 bombs per round.

battletankwinner_thumb

If you have further questions about the game creator check out Popfly's Game Creator forums.

Feel free to try out my battle tank game or play it at the top of this post! And as always, any and all feedback is appreciated.

0 comments

TankGame_MainScreen_Thumb

I've had a little bit of time to dig deeper into Silverlight 2. Instead of making a RIA that may contain useful information for all, I decided to make a mini tank game! Now this tank game is not intended to be a best hit or anything like that. It is intended as a simple example of how to make a mini game that users can play while waiting for something to load or process in the background. I do hope to expand its features in the future, especially if there is interest which will turn this little mini game into a full blown game that users can play anytime. I have attached the source code so feel free to download it and expand as you wish!

Before I describe this mini tank game, I got my inspiration from Andy Beaulieu and his great game work. Andy demonstrates some excellent best-practices for making simple games in general, but also specifics related to Silverlight. The other inspiration that pushed me into making this game was my love of video games. I've been a gamer all my life and have always wanted to make an actual game. I made a few in the past in different technologies that have been extremely simple, but school always came in the way. Now that I have some time, even just a little bit of time, I have been able to whip up a quick silverlight game.

TankGame_Fight_Thumb

There is no real object to this game, not yet at least. Currently, the user can create 1 or more tanks and move them around the available area. There is a surrounding boundary and some obstacles in the game that the user will 'bounce' off of if they collide. They can shoot at each other and when their life reaches 0 they die. That's the basic concept. Like I said before, a simple game. This mini tank game has the following features:

  • Set your tanks color (TankColor property)
    • Can be any brush so one could make a cool gradient brush in Blend and apply that to their tank
  • Set your tanks name (TankName property)
  • Set your tanks maximum life (MaximumHealth property)
  • Set the number of bullets that your tank can spew out in a row (NumberOfBullets property)
  • Set how fast you want your tank to turn (AngleSpeed property)
  • Set your tanks X and Y position (TankOffsetX and TankOffsetY properties)
  • Set your tanks controls to any key on your keyboard (ForwardKey, BackwardKey, LeftKey, RightKey an FireKey properties)
    • Forward
    • Backward
    • Turn Left
    • Turn Right
    • Fire Bullet
      • To set a user's controls to something, enter the string version of the key (ex. 'ctrl' will be the control key)
  • Create your own levels by adding / deleting/ moving the green solidblock objects (SolidBlock object)
    • Currently available through XAML or Blend
      • Can set the width, height and color of the solid block
  • Multiplayer support by having multiple tanks mapped to different keys on 1 computer
    • No internet multiplayer support yet

All the properties that have been described above, denoted by surrounding () can be set in straight XAML syntax or in Blend.

 

TankGame_SetControls_Thumb 

Default Tank Values:

Name: New Tank

Number of Bullets: 1

Maximum Health: 100

Angle Speed: 2

X Position: 10

Y Position: 10

Color: Light Gray

 

Default Keyboard Values:

Forward: Up arrow

Backward: Down arrow

Turn Left: Left arrow

Turn Right: Right arrow

Fire: Space Bar

TankGame_CreateTank_Thumb

Known Bugs:

There have been a couple of bugs in this release that are minor, but worth noting.

The first one is that sometimes when the user holds down 3 or more keys, the last key will not be reflected in the game. This only applies to certain keys and I am not sure why this is the case at the current moment.

If the user is holding down a key and then presses one of the buttons on the bottom of the screen ('Add / Edit Tank' or 'Set Player Controls') then the tank will continue to do the last key action.

Sometimes the collision physics get out of whack and the tank will be sucked into a solid block object. The user can try to wiggle their way out or wait for an enemy to settle the matter for them. The user could also edit the tanks X and Y position to get out of the bind.

One last bug, which is a silverlight bug and has been discussed in further detail here is that setting the visibility on a parent control does not allow that property to propagate to its children correctly. Sure, the elements are not visible, but they retain their physical space so if the user clicks on that space those children grab the focus instead of the intended control.

 TankGame_Winner_Thumb

TODO Features:

There are some things that I would like to gradually improve and some of those things can not be done until Silverlight matures more. Here is my list of features that I would like to accomplish, are there any that you would like to see?

  • User clickable way to set position of tank
  • Gradient color options for tank color
  • level maker
  • Saving ability on server for tanks / levels
  • Reset the tank when it is destroyed
  • Power-ups
  • More weapons and the ability for the user to 'make' their own weapons
  • Animations
    • Explosion when tank is destroyed
    • Red 'X' to grow / shrink
    • When tank is hit, flash current health and change its color
    • When new tank is created, animate it to appear and animate its statistics
  • Template listboxItems when a player is in a certain state (alive / dead / spectator)
  • Fix the wrappanel to wrap in a scrollviewer control
  • New overall layout

 

Controls:

I have used a couple controls in my application that I want to give credit towards. First is the Color Picker by Page Brooks. Great little utility to customize he color of your tank. The second is the WrapPanel control for silverlight 2 by lneir. Not sure why MS didn't give Silverlight this control, but it's a great control that I use to wrap the statistics of the tanks.

Hope you enjoy the game!

Update:be sure to check out my popfly game, Battle Tank that is a mock up of this game written from scratch in only a couple of hours!

filefile size
Silverlight 2 Tank Game.zip717.13 KB