This example is located in the Chess.cs file of the Tutorial in the distribution. This example demonstrates how Bling data binding can be used for a concrete use case: to implement fake lighting in a chess game. The lighting in this case is a simple highlight image that is separated from a piece image. First, we define a sun thumb to represent our light source:
ThumbBl sun = new ThumbBl(MainCanvas) {
  LeftTop = new PointBl(10, 10), Background = Brushes.Yellow,
  Size = new PointBl(20, 20), 
  Map = p => p.Clamp(new PointBl(0, 0), MainCanvas.Size - new PointBl(20, 20)),
  CanDrag = true,
  ZIndex = 100,
Since CanDrag is true, we can drag the sun around with the mouse on the canvas. Now we define the piece and thumb that allows us to move the piece:
ImageBl piece = new ImageBl(MainCanvas) {
  Source = Properties.Resources.piece,
  ZIndex = 1, IsHitTestVisible = false,
ThumbBl thumb = new ThumbBl(MainCanvas) {
  Size = piece.Size,
  Background = Brushes.Transparent,
  Foreground = Brushes.Transparent,
  ZIndex = 0, Opacity = .01,
  Map = p => p.Clamp(new PointBl(0, 0), MainCanvas.Size - piece.Size),
  CanDrag = true,
piece.CenterPosition = thumb.CenterPosition;
The piece object is a simple image where hit testing is disabled so the thumb underneath it can receive mouse input. The thumb object is then defined to be the size of the piece with a transparent color and low opacity so that it is virtually invisible even if it can still be hit test. As with sun, CanBeDrag is true on thumb so it can be moved with the mouse. Finally, the center position of piece is bound to the center position of the thumb so that it moves with the thumb. Now for the highlight:
ImageBl highlight = new ImageBl(MainCanvas) {
  CenterTop = piece.CenterTop, ZIndex = 2,
  Source = Properties.Resources.highlight,
A highlight is smaller than piece but trimmed so we can simply position it by binding its CenterTop with piece's. Its ZIndex is set to two so that it appears on top of of piece (whose ZIndex is one). The result looks something like this:
Now the rotation of highlight is defined with respect to the position of our lightsource sun:
highlight.RenderTransform[piece.CenterPosition - highlight.LeftTop].Rotate = 
  (sun.CenterPosition - piece.CenterPosition).Angle.ToDegrees() + 90.ToDegrees();
We want to rotate the highlight around piece's center position. However, since transform centers are defined with respect to the element being transformed, we have to subtract highlight's left top position from piece's center to get the center used in the rotation. Point subtraction gives us a vector around the origin that we can then convert into a radian angle (via atan in System.Math) that must then be converted into a degree angle that rotation is expressed according to. Given a mismatch between radian and degree angles, we additionally add another 90 degrees to this result. We can also vary the intensity of the highlight with respect to distance from the sun lightsource:
highlight.Opacity = .5 + (1d - (sun.CenterPosition - piece.CenterPosition).Length / MainCanvas.Size.Length) * .5;
Length of the piece from sun is transformed into a ration relative to the size of the canvas, that is then used in the Opacity binding of highlight. The reuslt looks like this:

Last edited Feb 20, 2009 at 7:16 AM by mcdirmid, version 3


No comments yet.