WPF 4: coordinate direction and speed?

Topics: Developer Forum
Nov 13, 2010 at 2:25 PM

I'm working on a Farseer 3.1 sample in WPF 4.0 and have two questions:

  • Does the coordinate plane in WPF work the opposite of XNA and Silverlight (at least the Y axis)? It seems like a gravity vector of (0,20) pulls objects "down" (toward the bottom of the screen) in WPF where that vector would move objects "up" in XNA and Silverlight.
  • In WPF, I'm able to render a simple fixture(e.g. a circle) and the body moves and seems to be "obeying" the properties I've applied to the world/other fixtures  (e.g., the circle bounces when it hits a static rectangle body I've placed near the bottom of the screen), but the movement is extremely slow compared to XNA or Silverlight. I think it may have to do with the way I'm looping, I tried to replicate the GameTime/storyboard method of the Silverlight 3.1 Simple Samples, and it's working, but it's slow. What's the "right" way to simulate the game loop in WPF? A Timer? DispatchTimer? Storyboard? Something else? Would be fantastic if someone had a Hello World-type sample for WPF. I'll gladly post if I get mine working.

Posting code might be tough since there's a decent amount of it, but I'm happy to do it. I'd be happy to post a video, too, of what I mean by "slow".

I'm very familiar with Farseer 2.1.x, and I've used the Box2D engine in other formats (e.g., from Flash/Javascript). I'm new to full-blown Box2D and Farseer 3. Is there something else I need to set with regards to the world or frame rates?

Nov 13, 2010 at 2:31 PM

 

Also - seems like I have the same slow results when using the GameLoop method from the WPF 2.1.3 Simple Samples (subscribing to the BeforeRender event).

Coordinator
Nov 13, 2010 at 7:04 PM

I'm not familiar with WPF and Silverlight, but the basics should be the same. If your timer "ticks" 60 times per second you should supply a delta time of 1/60. The time you give it is the time the engine should work with - it is the time that it took since the last frame.

A value of 1/30 will make the engine run "faster" (because you tell it that it took a longer time since the last update) if your game calls Step() 60 times per second (60 FPS).

Nov 15, 2010 at 4:06 AM

Thanks. The more I dig into the Box2D engine, the more I'm suspecting it has to do with scaling/transforms. I can (mostly) follow the Simple Silverlight samples, and it seems like the SL display is scaling/transforming the physics world down to a 500x500 view.

Nov 15, 2010 at 8:34 PM
Edited Nov 16, 2010 at 2:41 AM

I was able to get the new engine working on WPF 4. I'll try to clean up a sample app and post. This isn't a complete explanation, but maybe it will help someone until I get a chance to post some samples.

The trick is Scale and Translate transforms. I created a decent working sample by doing to following:

Create a drawing canvas on the main .XAML page of your WPF app, create a TransformGroup for the canvas and add two transforms: a Scale and Translate transform. Set the scale transform's ScaleY to -1; this will "invert" the Y axis which puts the WPF canvas's coordinate system in the same "direction" as the Farseer/Box2D world. There are a few other things you probably want to do with the scale transform like set the CenterX and CenterY properties to one-half the width/height of the canvas's width/height. The scale of that transform will also control the relative movement between the world and your app. The world is moving in units like meters/second. I scaled my app up (set ScaleX/ScaleY to 10 and -10, respectively) which translates to 10 pixels of movement on the canvas for every 1 meter of movement in the physics world.

Next, set the translate transform's OffsetX and OffsetY properties to width/2 and height/2, respectively. This will realign your canvas's coordinate system from 0,0 in the upper-left to 0,0 in the center of the canvas.

There's one more trick around drawing visual objects on the screen. Because you're "upping" the scale transform of the canvas, you need to scale down anything you draw on the screen. You can either create a scale transform for every visual object you add to the screen or create the object at 1/n its normal size where n is the scale factor you used in the canvas's scale transform.