
A Simple Physics Game using Silverlight and Farseer Engine

Physics Engine Basics
A physics engine is basically a set of classes, that helps in simulating response of objects to forces and collisions. With a physics engine, we first programmatically create a 'World' with different types of 'Bodies'. Then we apply 'Force' to one or more body and 'Step' through time. The physics engine automatically updates the positions of these objects in the 'World' with respect to time.private void Init() { _world = new World(new Vector2(0,0)); InitializeGameBoard(); CreateStaticObjects(); CreateDynamicObjects(); }Two crucial things involved in using a physics engine are:
- Continuously stepping the world forward in time and calculating new positions of bodies.
- Representing the 'Bodies' of the "World" graphically on the game screen using a suitable drawing API.
public void DrawEverything() { canvas1.Children.Clear(); canvas1.Children.Add(gameboard); foreach (Body b in _world.BodyList.Where(n => (n.UserData is ObjectTypes && ObjectTypes.Border != (ObjectTypes)n.UserData))) DrawItem(b); } public void DrawItem(Body item) { if (item != null) { if (item.FixtureList != null && item.FixtureList.Count > 0) { FarseerPhysics.Collision.Shapes.Shape s = item.FixtureList[0].Shape; if (s != null) { if (item.FixtureList[0].ShapeType == FarseerPhysics.Collision.Shapes.ShapeType.Polygon) { Polygon poly = new Polygon(); PolygonShape ps = (PolygonShape)item.FixtureList[0].Shape; int vertexCount = ps.Vertices.Count; poly.Points = new PointCollection(); gameTransform.Rotation = item.Rotation; if (ps != null) for (int i = 0; i < vertexCount; ++i) { poly.Points.Add(gameTransform.Transform(new Point(ps.Vertices[i].X, ps.Vertices[i].Y))); } poly.Stroke = new SolidColorBrush(Color.FromArgb(125, 0, 0, 0)); Canvas.SetLeft(poly, (item.Position.X-7.5)/scalefactor ); Canvas.SetTop(poly, (item.Position.Y+7.5)/scalefactor ); if (item.UserData is ObjectTypes) { ObjectTypes ot = (ObjectTypes)item.UserData; switch (ot) { case ObjectTypes.Sink : poly.Fill = SinkColorBrush; break; case ObjectTypes.Cubes : poly.Fill = normalObjectBrush; break; case ObjectTypes.Striker: poly.Fill = StrikerBrush; break; } } canvas1.Children.Add(poly); } } } } }
Basic idea behind the game
My game is pretty basic . It is very similar to carrom with the exception that all pieces are rectangular. The blue piece is called the 'striker' which you can move using arrow keys. All other pieces should be pushed in the four holes on the corner of the board, by colliding the striker against them. If you can get rid of all pieces within time, you win,else you loose.

Using BackgroundWorker to do the processing
As shown in the above diagram, refreshing the game screen is part of continuous loop which constantly updates positions of all game objects. The process of calculation of new positions happens when we make the "World" take a "Step" in time . To achieve this in Silverlight application , I have used the BackgroundWorker class.bool World_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact) { if (fixtureB.Body.UserData is ObjectTypes && ObjectTypes.Cubes == (ObjectTypes)fixtureB.Body.UserData) { _world.BodyList.Remove(fixtureB.Body); } score = (max_score - _world.BodyList.Where(n => n.UserData.Equals(ObjectTypes.Cubes)).Count()); if (score == max_score) { isGameOn = false; button1.IsEnabled = true; } _worker.ReportProgress(0, score); return true; } void Worker_DoWork(object sender, DoWorkEventArgs e) { if ((_worker.CancellationPending == true)) { e.Cancel = true; } else { _world.Step(1.0f); gametimectr--; if (gametimectr <= 0) isGameOn = false; } } void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {label1.Content = e.UserState.ToString();} void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { DrawEverything(); lblTime.Content = gametimectr.ToString(); if (!_worker.IsBusy && isGameOn) { _worker.RunWorkerAsync(); } label1.Content = score; if (!isGameOn && max_score == score) { ShowEndGameMessage("You Won!"); return; } if (!isGameOn) { ShowEndGameMessage("Game Over!"); return; } }The method 'Worker_DoWork' is executed via 'BackgroundWorker' to 'Step' further in our 'World'. The 'World_OnCollision' method is configured to handle all collisions that happen in our 'World'.Since this method is called from the 'BackgroundWorker', it does not have access to UI elements. Hence it calls '_worker.ReportProgress' to update the UI.
Doing more!
As I said earlier, this is my first attempt at using a physics engine. Currently my code only handles rectangles . Soon I will add code to handle more types of objects. I plan to write more articles after exploring features offered by the'Farseer' engine. I hope you found this article helpful for getting started with physics engines. Do let me know your comments, advice or criticism. Tip: Use the 'Write a Comment' link in the header bar to write a comment.Copyright (c) 2007-2019 Ashish Patil . Please read FAQ for more details.