Archive for April, 2008

Silverlight 3D flip animation

Up until now I have not had an opportunity to create any Silverlight procedural animations that were more complicated then positioning an object with some simple easing. I thought it would be fun to attempt to duplicate one of the transitions used on the iPhone. While making a phone call, if you choose to display the keypad there is a cool 3D flip that occurs. Here is a quick video of the transition. [[VIDEO]] In hopes not to reinvent the wheel, I embarked on an endless search of the Internet for anything resembling a flip. After some quality time on Google, I stumbled upon a great Flash site called reflektions by Paul Ortchanian. This site has a ton of Flash examples that highlight 2D and 3D effects done in flash. Those of us new to interactive development can learn a ton from the techniques Flash and Flex developers have used for years. To get started I created a simple page that contained two Grid controls, one for the front of the flip and one for the back. Both were placed inside of a single canvas named “screens”.

The guts of this effect has been encapsulated in a method called “AnimateFlip”. The result of this method is a DobuleAnimation with approximately 48 descreate keys frames.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
private TimeSpan AnimateFlip(Storyboard sb, ScaleTransform scale, 
out TimeSpan tsLastFrame)
{
    double speed = 4
    double flipRotation = 0
    double flipped = 2
    tsLastFrame = new TimeSpan()
    TimeSpan tsSideFlipped = new TimeSpan()
 
    int frames = 1
    DoubleAnimationUsingKeyFrames daX = 
	new DoubleAnimationUsingKeyFrames()
    tsLastFrame = new TimeSpan()
    while (flipRotation != flipped * 180)
    {
        flipRotation += speed
        double flipRadian = flipRotation * (Math.PI / 180)
        double size = Math.Cos(flipRadian)
        double scalar = (1 / (1 / size))
 
        DiscreteDoubleKeyFrame ddkfX = new DiscreteDoubleKeyFrame()
        ddkfX.Value = (size * scalar) 
 
        tsLastFrame = TimeSpan.FromMilliseconds(frames * 7)
 
        //the first time we flip to negative capture the 
	//tsLastFrame so we know when we will need to
        //visualize the flip side
        flipped = (size < 0) ? +1 : +0
        if (flipped == 1 && tsSideFlipped.Ticks == 0)
        {
            tsSideFlipped = tsLastFrame
        }
 
        ddkfX.KeyTime = KeyTime.FromTimeSpan(tsLastFrame)
 
        //add the DiscreteDoubleKeyFrame to the 
	//DoubleAnimationUsingKeyFrames
        daX.KeyFrames.Add(ddkfX)
 
        flipRotation %= 360
        frames++
    }
 
    Storyboard.SetTarget(daX, scale)
    Storyboard.SetTargetProperty(daX, "ScaleX")
    sb.Children.Add(daX)
 
    VisualizeSide(sb, tsSideFlipped, 0, TimeSpan.FromMilliseconds
		((tsSideFlipped.Milliseconds + 100)), 
		back.Opacity, this.back)
    VisualizeSide(sb, TimeSpan.FromMilliseconds((
		tsSideFlipped.Milliseconds - 100)), front.Opacity, 
		tsSideFlipped, 0, this.front)
    back.Opacity = 0
    return tsLastFrame
}

At the very bottom of the above method their is two calls to “VisualizeSide”. This method is responsible for visualizing the second side when the screen has rotated 180 degrees (Flipped).

My animation is by no means exact, but a pretty good first attempt. If you watch the video very slowly you might notice that on the iPhones rotation it looks like it rotates in perspective. I would love to add this, but am at a lost

Code: ScreenFlip.zip

Tunnel Trouble on Silverlight.net

For those of you who might not have seen our presentation at Mix, Terralever recently completed a second Silverlight game for Miniclip.com called Tunnel Trouble. This game is entirely written against the Silverlight 2 Beta 1 plugin. I am not sure that it has been spotlighted on there web site, but Microsoft has placed it on the home page of Silverlight.net. When you get a chance give it a play we are very happy with how it came out.

Silverlight how-to: Video Player

In my ongoing quest to work with Silverlight 2 I embarked on building my own video player using the standard MediaElement and a few of the new System Controls (ToggleButon, Slider and Button). My goal was to build a video player using no custom user controls, but instead leveraging controls styles and templates.  Here is the Video Player I ended up developing.

As you can see from my example, I was able to get a pretty clean look and feel with minimal artistic skills required.   The way my player is constructed, I have opted to encapsulate the controls for playing video into its own UserControl.  This allowed me to have a single place responsible for managing playback while allowing the main xaml page to control how the MediaElement is presented.  To give the controller access to a specific MediaElement, I pass it to my controller via a public property.

Most of the customization techniques I used are pretty well documented on MSDN.  Nonetheless, mastering controls styles was definitely a challenge. For those unfamiliar with control styles, here is an example of the xaml I used to "skin" my mute button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<style x:key="speakerStyle" targettype="Button">
  <setter property="Template">
    <setter.value>
      <controltemplate targettype="Button">
        <grid x:name="RootElement">
          <path stretch="Fill" fill="#FFFFFFFF" data="F1 M 23.1457,
            26.5056L 23.1457,33.8944l 25.7913,33.8944l 28.8235,37.4722l 
            30.5346,37.4722l 30.5665,23.0833l 28.8995,23.0833l 25.8679,
            26.5056l 23.1457,26.5056 z " Width="7.42080116271973" 
            height="14.3889999389648"/>
        </grid>
      </controltemplate>
    </setter.value>
  </setter>
</style>

This is about as simple a skin as one can get. If I were doing this for a real client I would have certainly choose to give my button multiple states (MouseOver, Down, ect) In Silverlight 2 control states are achieved by including specific named Storyboards in your ControlTemplate resource dictionary. Each control provides a different set of pre defined states. Here is a list of the states available for a ToggleButton.

  • Checked State - The normal checked state of the control.
  • Indeterminate State - The normal indeterminate state of the control.
  • Normal State - The normal unchecked state of the control.
  • MouseOver Checked State - The state that is triggered when the mouse pointer is positioned over the checked control.
  • MouseOver Indeterminate State - The state that is triggered when the mouse pointer is positioned over the indeterminate control.
  • MouseOver Unchecked State - The state that is triggered when the mouse pointer is positioned over the unchecked control.
  • Pressed Checked State - The state that is triggered when the checked control is pressed.
  • Pressed Indeterminate State - The state that is triggered when the indeterminate control is pressed.
  • Pressed Unchecked State - The state that is triggered when the unchecked control is pressed.
  • Disabled Checked State - The state that is triggered when the checked control is disabled.
  • Disabled Indeterminate State - The state that is triggered when the indeterminate control is disabled.
  • Disabled Unchecked State - The state that is triggered when the unchecked control is disabled.

In my example I use the ToggleButton to control playback of the video.  Instead of creating two buttons, one for play and one for pause, I  choose to use a ToggleButton to combine them into one.  I display a play symbol when the video is stopped or paused, and a pause symbol when the video is playing.  The ToggleButton functions just like a checkbox, clicking it once "check’s" it while clicking it again "uncheck’s" it.   The following  is a sample of one of the Storyboards I used in skinning my ToggleButton. This animation controls which elements are visualized when a users presses the ToggleButton in an previously checked state.

1
2
3
4
5
6
7
8
9
10
11
<storyboard x:key="Pressed Checked State">
   <doubleanimation duration="0:0:0.1" 
     storyboard.targetname="playSymbol" 
     storyboard.targetproperty="Opacity" to="0" />
   <doubleanimation duration="0:0:0.1" 
     storyboard.targetname="pauseSymbol" 
     storyboard.targetproperty="Opacity" to="1" />
   <doubleanimation duration="0:0:0.1" 
    storyboard.targetname="buttonPressed" 
    storyboard.targetproperty="Opacity" to="1" />
</storyboard>

In the code above, I am ensuring that the play symbol is hidden while I show both a pause symbol and an glow image used to show the button is being pressed.

As for procedural code, all of the heavy lifting is done in the mediaControl.xaml.cs codebehind file.  The majority of code is event handlers responding to user interactions (clicks, drags,etc) or a single DispatcherTimer monitoring progress in the video playback.  My  DispatcherTimer fires a tick every 50 milliseconds which update how much time has played and visualizes on a slider how much time remains.

Code: VideoPlayer.zip

Mozilla CEO blasts Apple for putting security of the internet at risk

This article is a few weeks old, but quite interesting.  It makes claims that Jobs is using Apple Software Update (specifically iTunes) to piggyback the Safari browser onto Windows machines.  Just last week I was prompted with an Apple update and questioned why Safari was trying to update on my boot camp partition.  I was sure I never had installed that browser.  Sneaky Mr. Jobs

Click Me, Baby… One More Time

cover_101_0408.gif Check out this article in the April 2008 issue of OMMA. Scott our Director of Strategy had the following to say about privacy expectations.

But the reality is that there’s a new generation of consumers who have little or no privacy expectations, and they’re going to prove a rich source of performance data, suggests Scott McAndrew, director of strategy for Tempe, Ariz.-based interactive marketing agency and Facebook APP developer Terralever.

Not only that, as marketers get used to the rich demographic and preference information social networking sites can provide, their expectations will rise ever higher, McAndrew notes. “When they look at Facebook and all of that data, they’ll be looking for it in other mediums,” he says.

Check out Scott’s Online Marketing Performance blog.