Pirates Video

Here is a video of the Pirates game:

[youtube http://www.youtube.com/watch?v=b9LHFS1dKWg&hl=en_US&fs=1&color1=0x2b405b&color2=0x6b8ab6]

Yar, I do be re-visiting Pirates!

One of the first games I started building in Silverlight I called Pirates! Since working on Perenthia and various other tasks I have not re-visited the game for a long time. I really would like to get this game finished so I have to decided to spend some time working on it. I hope to include some videos soon that show the game in varied stages of development. The first screen shot displays what currently exists after implementing some path finding and the SilverSprite library:

Here is the post from the game blog: Pirates Game in Silverlight

Pirates! Progress

Rebuilding Pirates! in Silverlight 2 is coming along well. I got it running on my Silverlight game engine I was writing for use with Perenthia, which changed some of the way it worked initially. Anyway, I plan on doing a release once I get a few levels complete. In the mean time here is a screen shot of me testing sailing around.

Since I started over in Silverlight 2 and decided to use my game engine I am having to re-write a good portion of the functionality. I had to re-do movement since some of the structure of events has changed so this screen shot is the ship sailing around.

Silverlight 2 Sockets

I started working with Sockets in Silverlight 2 tonight and got my Silverlight application connected to the server and sending and receiving commands. I am going to write some code to testing sending commands from the server at the same time commands are coming from the client to see how the app and my code will handle it.

I will post some code as I get further along. Also, I made more progress on getting the Pirates game upgraded to Silverlight 2.

Silverlight 2.0 and My Game Engine

I got the chat portion of the game engine working with Silverlight 2.0 tonight. I am just using web services to send the commands back and forth for now. Once I complete incorporating the other portions of the engine into Silverlight I will start playing around with sockets. 

Silverlight Pirates! Prototype

The Silverlight Pirates! prototype is online!

Keep in mind that this is a very early prototype and about the only thing you can do is destroy that other ship that is sitting there. I didn't get the enemy AI quite where I wanted it but it will fire on you if you get close. You can sail around and dock at ports, although you can't buy anything yet. Once your ammo runs out you will have to refresh the page to reload the game. You will also have to refresh if the enemy ship kills you.

On my TODO list are:

  • boundaries to keep you from sailing on forever
  • merchant ships to attack
  • better enemy AI so the merchants will run and man-o-war will chase
  • sea monsters
  • whirlpools
  • storms, which should be a big challenge
  • menu for when you are at port to buy ammo or repair your ship
  • gold and/or ammo drops from enemy ships

If you find any funky bugs please let me know and of course, you will need Silverlight 1.1 in order to run the prototype.

Silverlight Pirates! Prototype 

Silverlight Pirates!

I'm going to put up the Silverlight Pirates prototype in another day or so. The prototype will only include one enemy ship. I was going to get the port menus completed so you could buy ammo and repair your ship but I think I am going to wait until the Silverlight 2.0 beta is released. 

I'm not competely happy with the enemy ship AI but I have time to work it out. Once I finish the prototype I am going to wait for Silverlight 2.0 to finish out the game.

Some Additional Silverlight Pirates! Screenshots

The first screenshot is just sailing around. I was working on positioning the cannons and making sure the mini map was working as planned.

 

 Silverlight Pirates!

 

The second screenshot is me docked at the port of this island. Ports will be places to repair your ship, buy cannons, cannon balls and rum.

 

Silverlight Pirates!

 

Silverlight Pirates! Arr!

Thought I would post a screenshot of the game so far. I still have a lot to do but it is coming along pretty well I think. I am hoping to get a playable prototype in the next few days, just depends on how development goes.

 

Silverlight Pirate Game and Farseer Physics Engine

I have recently been working on a Pirate Game in Silverlight 1.1 Alpha and decided to use the Farseer Physics Engine to handle collisions, etc. I used Andy Beaulieu's Getting Started with Farseer Physics and Silverlight to create my SpriteBase class. I originally used the Silverlight Games 101 tutorials to get started and got turned on to Farseer from that site.

Since this is a Pirate game you will be sailing around in a ship encountering other ships and various islands. One of the big challenges I ran into right from the start was getting the Vertices setup for collision with an island. I am unable to visualize more than a view Vertex points at a time so I was having trouble getting the island border setup correctly. For those unaware, Farseer provides a Body class which just represents a body in space. You can assign the Body a Geometry object that actually defines its physical structure within your world. The GeomFactory class provides methods for creating circle, rectangle and polygon geometries.Since I have a island I was in need of a ploygon geometry which is created using a collection of Vector2 instances within a Vertices instance.

Geom g = GeomFactory.Instance.CreatePolygonGeom(this.PhysicsSimulator, this.Body, vertices, 1);

When creating the Vector2 instances to add to the Vertices collection you have to specify the X and Y values in relation to the center of the geometry. In other words, if I have a geometry that will be 64 X 64 and want to set a Vertex at the top, left of the square the Vector2 instance would be new Vector2(-32, -32). For an island that is 512 X 512 that is a lot of going back and forth with the calculator.

Anyway, not matter what I did I still couldn't get the vertices correct. I eventually created a helper method in a Utils class that will accept the Vertices collection, a width and height and create a Path instance that I can add to my Canvas in order to see the Vertices. This greatly helped me to understand where I was placing my points. Here is the CreatePathFromVertices method I created:

public static Path CreatePathFromVertices(Vertices vertices, double width, double height)
        {
            Path path = new Path();
            path.Stroke = new SolidColorBrush(Colors.Magenta);
            path.StrokeThickness = 1;
            path.Fill = new SolidColorBrush(Colors.Transparent);
            PathGeometry pathGeom = new PathGeometry();
            PathFigureCollection figures = new PathFigureCollection();
            pathGeom.Figures = figures;
            PathFigure figure = new PathFigure();
            figure.StartPoint = new Point((double)vertices[0].X, (double)vertices[0].Y);
            figure.Segments = new PathSegmentCollection();
            pathGeom.Figures.Add(figure);

            foreach (var vector in vertices)
            {
                LineSegment line = new LineSegment() { Point = new Point((double)vector.X, (double)vector.Y) };
                figure.Segments.Add(line);
            }

            TranslateTransform trans = new TranslateTransform();
            trans.X = width / 2;
            trans.Y = height / 2;
            path.RenderTransform = trans;

            path.Data = pathGeom;
            return path;
        }

To use it all I do is call it after creating my Vertices collection and add the returned Path to my UserControl Canvas:

this.Root.Children.Add(Utils.CreatePathFromVertices(vertices, this.Root.Width, this.Root.Height));

This was working better but I wanted to be able to create the Vertices collection a little faster. I had originally created my island image in Photoshop and so I opened up the PSD and added a new transparent layer called Vertices. In the Vertices layer I proceeded to draw points around the island using a 1px Pencil of Magenta color. After I created a point based structure around the image I saved just the Vertices layer as a PNG. I then wrote a C# WinForms application to load up the PNG and parse it pixel by pixel, creating a Vertex for each of the Magenta points located within the image. The WinForms application then writes out the Vertices code required by the Farseer engine based on these Vertex instances.

Doing this gave me the Vertices I needed but not in the order I needed. The CreatePloygonGeom method requires the vertices to be in a clockwise or counter clockwise order. Parsing each pixel of an image only gives you the pixels in order from each x to y or y to x. I ended having to add the Image x and y location of each pixel as a comment to the end of the Vertices.Add line of code being generated by my WinForms application. From there I was able to use Photoshop to re-order the Vertices so that they rendered correctly.

vertices.Add(new Vector2(-208f, -173f)); // 48, 83
vertices.Add(new Vector2(-126f, -240f)); // 130, 16
vertices.Add(new Vector2(-61f, -200f)); // 195, 56

Using my CreatePathFromVertices method I was able to see the outline of the shape I created as the collision geometry for my island. One this I did notice was that I needed the very first line of the Vertices code to be repeated at the very end in order to join the geometry shape.

vertices.Add(new Vector2(-208f, -173f)); // 48, 83
vertices.Add(new Vector2(-126f, -240f)); // 130, 16
vertices.Add(new Vector2(-61f, -200f)); // 195, 56

vertices.Add(new Vector2(-208f, -173f)); // 48, 83

Here is a screenshot of the game with the Path around the island displayed. Granted the path is not perfect but sufficient for the game I think. I can always alter it but the more Vertices you add the longer it takes to load.

Here is the full code from the Constructor of my island class:

public SpringIsland(PhysicsSimulator physicsSimulator)
            : base (physicsSimulator)
        {
            System.IO.Stream s = this.GetType().Assembly.GetManifestResourceStream("Pirates.SpringIsland.xaml");
            this.Initialize(new System.IO.StreamReader(s).ReadToEnd());

            this.Body = BodyFactory.Instance.CreateRectangleBody(this.PhysicsSimulator, (float)this.Root.Width, (float)this.Root.Height, 1000);
            this.Body.IsStatic = true;

            #region Vertices
            Vertices vertices = new Vertices();
            vertices.Add(new Vector2(-208f, -173f)); // 48, 83
            vertices.Add(new Vector2(-126f, -240f)); // 130, 16
            vertices.Add(new Vector2(-61f, -200f)); // 195, 56
            vertices.Add(new Vector2(9f, -201f)); // 265, 55
            vertices.Add(new Vector2(43f, -241f)); // 299, 15
            vertices.Add(new Vector2(152f, -256f)); // 408, 0
            vertices.Add(new Vector2(235f, -209f)); // 491, 47
            vertices.Add(new Vector2(218f, -155f)); // 474, 101
            vertices.Add(new Vector2(118f, -145f)); // 374, 111
            vertices.Add(new Vector2(23f, -50f)); // 279, 206
            vertices.Add(new Vector2(114f, 55f)); // 370, 311
            vertices.Add(new Vector2(90f, 92f)); // 346, 348  
            vertices.Add(new Vector2(152f, 97f)); // 408, 353
            vertices.Add(new Vector2(235f, 148f)); // 491, 404
            vertices.Add(new Vector2(216f, 219f)); // 472, 475
            vertices.Add(new Vector2(147f, 252f)); // 403, 508
            vertices.Add(new Vector2(26f, 241f)); // 282, 497   
            vertices.Add(new Vector2(-62f, 234f)); // 194, 490
            vertices.Add(new Vector2(-118f, 203f)); // 138, 459
            vertices.Add(new Vector2(-126f, 167f)); // 130, 423
            vertices.Add(new Vector2(-156f, 143f)); // 100, 399
            vertices.Add(new Vector2(-218f, 129f)); // 38, 385
            vertices.Add(new Vector2(-233f, 103f)); // 23, 359
            vertices.Add(new Vector2(-232f, 35f)); // 24, 291
            vertices.Add(new Vector2(-200f, 16f)); // 56, 272
            vertices.Add(new Vector2(-195f, -32f)); // 61, 224
            vertices.Add(new Vector2(-230f, -95f)); // 26, 161
            vertices.Add(new Vector2(-199f, -141f)); // 57, 115
            vertices.Add(new Vector2(-208f, -173f)); // 48, 83
            #endregion

            this.Root.Children.Add(Utils.CreatePathFromVertices(vertices, this.Root.Width, this.Root.Height));

            Geom g = GeomFactory.Instance.CreatePolygonGeom(this.PhysicsSimulator, this.Body, vertices, 1);
            g.CollisionHandler += new FarseerGames.FarseerPhysics.Collisions.Geom.CollisionHandlerDelegate(this.HandleCollision);
        }

The code in the "Vertices" region was generated by the C# WinForms application and I re-ordered manually. I will release the source to the Pirate game once it is complete, if you want the prototype code just contact me. I will probably post the prototype online once I get the Ship AI and cannons working so at least there would be more to do that just sail around the island. 🙂

Here is the code for the C# WinForms app that will read the image pixel data and create the Vertices code segment: SilverlightImageToVertices.zip