Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Wednesday, August 19, 2009

The easiest way to convert vector graphics to XAML

Wow, this is sooooo simple. I've been converting WMF, EMF, CDX, CDR, AI, EPS, PDF and SVG to XAML all day. This is actually fun!

First get a vector graphic and a program that can open it. I've used Adobe Illustrator, CorelDraw, Inkscape and even Windows Picture and Fax Viewer.

Next get a vector graphic that your program can open.

Finally get the Microsoft XPS printer driver if it is not already installed.

Now open the file in your program of choice and print it to the XPS printer driver.

Now rename the resultant XPS file to ZIP.

Open the ZIP file and inside the Documents/1/Pages folder is a file named 1.fpage.

Extract the file and rename it to .XAML.

Now you have a XAML file that will open in Internet Explorer, but if you want to have a XAML file that will open kaxaml or for use in a WPF or a Silverlight application, open the file in notepad and replace the FixedPage tag with the Canvas tag.

Here is a XAML graphic I converted from my Corel Gallery. (Either open link in IE7/IE8 or download the XAML file and open it in your XAML viewer of choice)

Older posts from other blogs tell you to use Inkscape and print to PDF and then open the PDF in Adobe PDF Viewer. Fron the Adobe PDF Viewer you can then print to the XPS printer driver. The reason was that Inkscape converted the file to a raster image. Then and only then could you retrieve the 1.fpage file. This was because Inkscape sent the graphic to the printer as a raster image, not a vector image.

Well, since those blog posts were written, there have been updates to Inkscape, and now Inkscape prints a vector image as a vector, so there is now no need for converting it to an intermediate format (PDF).

Saturday, March 28, 2009

How to make Asymmetrical Board Game maps in Silverlight

Or, how I spent my evenings at MIX09 in Las Vegas.

Last year, I began looking into writing board games with an asymmetrical map boards. I started with Awful Green Things from Outer Space (AGTFOS), a classic beer and pretzels game by Tom Wham. I started with an alternate game board graphic I downloaded from boardgamegeeks.com.



But, since the map is asymmetrical, there is no simple math function that, given an X,Y coordinate, would tell me what room in the spaceship I clicked on.

After a lot of googling, I found that boardgame programmers use a 2D array where every every element in the array corresponds to a pixel in the map image. Then set al the array elements to values that equal what room that pixel is in. This worked great, but it has a problem - No scaling. I could not scale the graphic and still know what room I was in.

WPF and Silverlight to the rescue!

So, as a proof of concept, I took a states map of the USA in SVG from Wikipedia and used ZamlTune to convert the SVG to XAML. Since all the elements in WPF are scalable and clickable, I was able to, with just a few lines of code, make the map aware of what element I was clicking and change its fill color.

That solved half of the problem of a asymmetrical board game map. The other issue is for movement and conflict. We need to know what states directly border the selected state. For this we need to go back to Comp Sci 350 - Data Structures. We need a graph.

Graphs have Vertexes and Edges. A vertex can be thought of as a location and the Edges as the roads to and from these locations. So, if we had a Graph with a vertex for each State and an edge to each bordering State, we could easily find out what States border each other.

Unlike previous silverlight examples I've posted, this one cannot be embeded since it needs to resize, so you need to open the link to run my example USA map. If we wanted to play Risk on a USA map, this would be a large positive step towards that goal.

As, you can see in the image the selected State is in Blue and the bordering States are in Light Blue. (Click on Image to Open The Silverlight Application)


Unfortunately the Graph object I wrote for this proof of concept is not nearly as full featured a Graph object as per my previous post.

And here is a zip file containing the entire Visual Studio 2008 Project.

Sunday, February 8, 2009

Fancy fonts in XAML (Silverlight and WPF)

Outline, Shadow, Embossed and Engraved text in XAML.

Here are a few quick and easy ways to spice of your text in XAML.

To use these tricks, you need to have the ability to exactly place the text. For that you need to use a Canvas Layout control.


<UserControl x:Class="SilverlightApplication2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="320" Height="200">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions >
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Margin="3">
<Canvas Width="800" Height="60">
<TextBlock FontSize="36"
Canvas.Top="2" Canvas.Left="10">Outline</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="2" Canvas.Left="12">Outline</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="4" Canvas.Left="10">Outline</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="4" Canvas.Left="12">Outline</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="3" Canvas.Left="11"
Foreground="White">Outline</TextBlock>
</Canvas>
</Button>
<Button Grid.Column="0" Grid.Row="1" Margin="3">
<Canvas Width="800" Height="60">
<TextBlock FontSize="36"
Canvas.Top="5" Canvas.Left="4"
Foreground="Black">Shadow</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="3" Canvas.Left="2"
Foreground="Gray">Shadow</TextBlock>
</Canvas>
</Button>
<Button Grid.Column="1" Grid.Row="0" Margin="3">
<Canvas Width="800" Height="60">
<TextBlock FontSize="36"
Canvas.Top="3" Canvas.Left="0"
Foreground="Gray">Engrave</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="5" Canvas.Left="2"
Foreground="White">Engrave</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="4" Canvas.Left="1"
Foreground="Black">Engrave</TextBlock>
</Canvas>
</Button>
<Button Grid.Column="1" Grid.Row="1" Margin="3">
<Canvas Width="800" Height="60">
<TextBlock FontSize="36"
Canvas.Top="5" Canvas.Left="3"
Foreground="Gray">Emboss</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="2" Canvas.Left="2"
Foreground="White">Emboss</TextBlock>
<TextBlock FontSize="36"
Canvas.Top="4" Canvas.Left="4"
Foreground="Black">Emboss</TextBlock>
</Canvas>
</Button>
</Grid>
</UserControl>

Tuesday, November 11, 2008

Dynamically adding XAML strings from C#

In designing the screen for my silverlight game Switcheroo, I wanted to be able to dynamically add XAML chunks that represent the pieces (Ellipse). True, I could have just created the graphic elements property by property, but since the only difference between all the game pieces is if they are black or red, I thought that if it only took one or two lines of code, it would be a more elegant solution.

I wanted to separate the internal representation of the gameboard in the gaming object from the XAML front end. Then I could just clear the gameboard and recreate all the pieces after the gameboard object was updated. The question was, how?

Well I googled high and low but though I found many "solutions" to my problem, none of them worked. After trying different combinations of the aforementioned solutions, I got closer. This is my first try that made any headway:

const string red =
"<Ellipse Stroke='Black' Fill='Red' Height='30' Width='30' Margin='10,10,10,10' />";

LayoutRoot.Children.Add((Ellipse)XamlReader.Load(red));


But the error I got back was:

AG_E_PARSER_MISSING_DEFAULT_NAMESPACE [Line: 0 Position: 0]

Not a very helpful error message! Well, googling this error I found others that were getting the same error and a simple answer - the element must contain the same namespace. The only namespace is the one at the beginning of the XAML document thought. Well, I thought, it's worth a shot. So I added the namespace lines from the beginning of the element. Our code now looked like this:

const string red =
"<Ellipse xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' Stroke='Black' Fill='Red' Height='30' Width='30' Margin='10,10,10,10' />";

LayoutRoot.Children.Add((Ellipse)XamlReader.Load(red));


And low and behold! It worked!

So when you have lots of repetitious XAML or elements like named colors that cannot be easily replicated in code, just use the XAML string!