Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C#
Tip/Trick

Comedy Desktop Tumbleweed

Rate me:
Please Sign up or sign in to vote.
4.36/5 (6 votes)
9 Jun 2014CPOL6 min read 12.8K   320   7   6
A comedy tumbleweed to bounce across your desktop

Introduction

This is a Windows Desktop application, that when run, rolls a tumbleweed graphic across the screen. There are several features coded into the application, press "H" while running for help details. This is not my usual posting, but every time it rolls across my desktop, it makes me laugh. This came about after a series of meetings where I was sharing my desktop with my co-workers, and when the opportunity to volunteer for some extra work came up, the meeting was silent. The image in my mind was the one from the movies of a tumbleweed awkwardly rolling across the screen. This little app realizes that image.

For a few more details on "Tumbleweed Moments", you can check out the definition on Urban Dictionary.

Image 1

Using the code

To activate, just run Tumbleweed.exe.

Points of Interest

While I am not really posting this application for its coding merit, there are some interesting pieces of code:

  1. The images in and sound that make up what rolls across the screen are any arbitrary images in the "Images" and "Sounds" folders in the application folder. To keep the post small, I have removed all but one of each, but you can play around with different combinations for different effects.
  2. The CommandLineDictionary code, used to parse command line parameters is somewhat handy, and is likely code that I will use elsewhere.
  3. The HandleKey() method deals with some common key events, like repeating, that I will likely use in other applications.
  4. The notion of saving settings as just a series of command line arguments (SaveRunningConfig), while very 1970, still works really well to solve simple problems like this.
  5. The play sound, with repeat, code is somewhat handy (PlaySound), and I will likely use it elsewhere.
  6. The use of multiple DispatcherTimers to achieve overlaying effects (Fade In, Move Right, Bump Up, etc..) was an interesting exercise. I am sure animation gurus will know better ways to solve problems like this, but for this simple little app, it worked okay.
  7. The debugging window that shows runtime animation stats is somewhat interesting. It was more there to help me fine tune the default animation values, but I can see a use case for a similar code on other projects.

Technical Notes

I wasn't planning on explaining this code, simply because it is not remarkable. However, it seems there are those that have some interest, so here it goes…

The basic application is a standard WPF application, with the primary window (MainWindow.xaml) being transparent and containing just one control, the image control used to render the tumbleweed. It roughly follows the MVVM pattern, wiring up a view model (VM) (AnimationViewModel.cs). The VM controls all activities and is triggered on load of MainWindow with a subsequent call to the VM's Start() method.

The VM looks for sounds in the /Sounds/ sub folder and starts the sound via the PlaySound() method. Likewise, the VM looks for pictures in the /Pictures/ sub folder and sets the image binding property (TheImage) via the SetImage() method.

All of the animations are predicated on the property binding features of WPF controls. For example, we move the image across the screen by adjusting the bound property Window.Left and raising the INotifyPropertyChanged event. I am quite certain this is a terrible way to animate things and likely horribly inefficient, but I tried a few times with GDI libraries and gave up. Given the primary intent of this app is humor (and the joy of coding), it met my needs, but also explains why I did not cover the code in more detail in the original posting.

The animation is handled via DispatchTimers, wired up on start of an action like VM Load() or Bump(), with the actual animation being performed in the .Tick() event handler (EH). In the case of the primary motion of moving right and rotating, this is done in the AnimationTimer.Tick EH, just setting the Rotation and WindowPosition properties to increment the rotation and move the image across the screen.

In the case of parallel animations, like the "Bump()" when the keyboard is hit, it just starts up a new DispatchTimer (BumpTimer) whose Tick EH carries out the up and down arc motion similar to the horizontal motion. The actual bump height (all that code around Random()) was more just trial and error to find an effect that was pleasing and felt natural.

Similar to the other two timers, the FadeTimer adjusts the opacity of the image container to achieve the proper fade in and fade out effects.

The program ends based on window position being out of bounds (or on Q key EH), which is checked in the primary AnimationTimer.Tick EH after each move.

Technical Challenges

  1. I did try to use GDI to do the actual animation, and was able to get things to render and move, but it would not paint the desktop underneath after the image moved and I was not able to work past that in a timely manner, which is why I chose the view model bound property approach.
  2. Binding string image file paths to an Image control was a bit challenging. The binding property wants an ImageSource, which in my case was a BitmapImage. How I addressed it was, OnPropertyChange of the string path to image (ImagePath), call a method (SetImage) to load the file, convert it to a BitmapImage, and then use that to set the ImageSource property, which raises a secondary event to notify the control of the change.
  3. The code to play the sound was somewhat similar, but easier since the MediaPlayer class has a nice .Open() method to open a file. There were two tricks to achieving the right effects, one was to start playing from a random position (in the MediaOpened event), and the second was to repeat (in the MediaEnded event).
  4. The CommandLineDictionay class is kind of neat, in that it takes a command line in the form of "/A:XXXX /B:YYY" and transforms it into a Dictionary<string,string> which makes parsing and working with parameters much easier. It is not perfect in that things like separators / and : within quoted strings will cause problems, but it is a handy little tool.
  5. The debug window is just another View bound to the VM that is driving the primary application, dumping out its properties. For better or worse, I dynamically add the bound properties to simplify coding. In hind sight, why I didn't just do this with reflection escapes me, but I am sure there was a reason since I am a fan of reflection. Given there is overhead to raising additional on property change events for things like WindowLeft (where the image is on the screen), there are precompiler wrappers around them to only compile into a Debug build.
  6. Getting the right mix of randomness versus consistency with the sound and images was challenging. The GetFilePath() method is used to assist with that, to try and get a random image/sound the first time, then cycle though the remaining found images in a looping sequence. In the end, I found the one image to be better, so I default to that (by setting IMAGE_INDEX = -1 it will increment to the valid value of 0 on first run making the default image, image 0).

I hope this satisfies those seeking details about the code. Please review the code and comments, or post questions for additional details, and enjoy!

History

  • 08 June 2014 - Initial public draft
  • 14 June 2014 - Updated with technical notes at readers request

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralPlease show and explain the code Pin
PIEBALDconsult9-Jun-14 14:27
mvePIEBALDconsult9-Jun-14 14:27 
GeneralRe: Please show and explain the code Pin
Brad Joss13-Jun-14 22:08
professionalBrad Joss13-Jun-14 22:08 
Question[My vote of 2] What's the use of this? Pin
Kundan Singh Chouhan9-Jun-14 6:28
Kundan Singh Chouhan9-Jun-14 6:28 
AnswerRe: [My vote of 2] What's the use of this? Pin
Brad Joss13-Jun-14 22:08
professionalBrad Joss13-Jun-14 22:08 
QuestionTumbleweeds - the comic Pin
bling9-Jun-14 6:25
bling9-Jun-14 6:25 
QuestionMy vote of 5 Pin
Manikandan109-Jun-14 4:07
professionalManikandan109-Jun-14 4:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.