Camera not scrolling properly

Jan 26, 2011 at 1:51 PM

I am just getting started using Physics Helper and have a question regarding the camera.  I have created a simple ball that has a force applied to it when keys are pressed to get it to fly around the screen.  When I attach a camera to the ball and run the program the screen does not scroll to the ball (it moves in the direction of the ball but not far enough to keep it within the screen).  Am I doing something wrong?

Thanks

Jan 28, 2011 at 6:21 PM

I had a similar problem when I was first trying to use the CameraControllerMain class supplied with the library. After a bit of debugging, I noticed the problem arose from the following two statements:

currentTargetXOffset = Convert.ToInt32(_targetElement.BodyObject.Position.X);
currentTargetYOffset = Convert.ToInt32(_targetElement.BodyObject.Position.Y);

As you would notice, BodyObject.Position has (much) smaller values which definitely don't represent the pixel coordinates of the object (_targetElement).

So our workaround was to import CameraControllerMain.cs itself into the project, and change those two lines to this instead:

currentTargetXOffset = Convert.ToInt32(_targetElement.Position.X);
currentTargetYOffset = Convert.ToInt32(_targetElement.Position.Y);
This way, the camera accurately follows the _targetElement. I wrote about this problem in my blogpost.

 

Feb 1, 2011 at 10:01 AM

Another way of doing it with importing the class is to use the TargetOverrideX and TargetOverrideY properties on the camera.


You'll need to register to the physicscontroller timer event and use something like this sample code:

 

        void _physicsController_TimerLoop(object source)
        {

            double overrideX = (_rectangle.Position.X + _rectangle.Width / 2);
            double overrideY = (_rectangle.Position.Y + _rectangle.Height / 2);
            _cameraControllerMain.TargetOverrideX = overrideX;
            _cameraControllerMain.TargetOverrideY = overrideY;

        }

Feb 3, 2011 at 10:03 AM
Edited Feb 3, 2011 at 10:06 AM

Hello there,

I'm messing about with the same thing and having trouble.  Mccabela, there are no properties on the camera at all, so there is nothing there to change.  I would have to import the source and rebuild it.  Which brings me to a different question: where the good golly gosh (excuse my foul language) is the source code installed to?!  I cannot find a separate download for the latest version either so I am assuming it is copied somewhere for me as well.

Thank you for the pointers, both of you!

*Edit* Found it, literally seconds after the post.  Feel rather stupid...

Feb 3, 2011 at 10:17 AM

Hi Timmy,

There are definetly properties on the camera, but I'm deving in visual studio silverlight so your tool may be different.  Examples of these properties are below as well as the properties in my post above.

            _cameraControllerMain = new CameraControllerMain();

            _cameraControllerMain.ZoomEnabled = false;
            _cameraControllerMain.ZoomSpeed = 0;
            _cameraControllerMain.ZoomPercentage = 130;

            _cameraControllerMain.ScrollEnabled = true;
            _cameraControllerMain.ScrollSpeed = 0;

            _cameraControllerMain.Initialize(LayoutRoot, _physicsController);
            _cameraControllerMain.Target = "cnvPlayerControl";

 

Good luck with it.

 

Cheers

Feb 3, 2011 at 11:53 AM

Ah I see, you aren't using the camera behaviour at all, just the CameraControllerMain object?  I wasn't aware we could just plug one of those in and get real control of it.  Is the implementation of that just as you have stated above - create the object and set it's target?  If I do use this would I then no longer need the behaviour attached as well?

Lots of questions, sorry!  Hehehe.  I tried working around the camera by building my own method using canvases.  The performance on the phone was unacceptable, sadly.

Feb 10, 2011 at 12:24 PM

Just for others that may have the same issues:

Yes you can just use the CameraControllerMain object and not use the Behavior.  The only way I could get it to work, however, is to use the code posted above by mccabela in the first loop of your application.  So when the first loop runs you can then initialize and set the target of the CameraControllerMain.

The bad news is that it runs at too poor a performance level on my HTC HD7 (which is poor performing anyway).  My scene is 4 rectangles and one isosceles triangle falling under gravity.  If I take the camera off, everything performs smoothly.  I've tried to do the camera myself through moving canvases but this performs poorly too.  I'm now going to try this in XNA and pray it performs better.

Thanks for the help mccabela!

Feb 10, 2011 at 4:40 PM

Timmy,

I'm building a prototype that will be using the camera as well.  I have a samsung focus.  Now I'm worried because of your last post.  I don't want to get so far ahead and publish a game only to find out I get tons of reviews from those with the HTC HD7 about perf issues.  I would love to give what you have a shot on my focus (your basic scene etc) and get back to you with what I find and maybe tweak it so the perf is good on both of our phones.  If we start just with basic shapes etc like you mentioned and get all the perf issues sorted then we can go our own ways after that.  I would love to help!  FYI - I'm also working on animations within elements that have the physics object behavior as detailed in this post http://physicshelper.codeplex.com/Thread/View.aspx?ThreadId=244918

Feb 10, 2011 at 10:16 PM

Timmy,

I did some testing with the camera working/tracking properly as well.  When you set Application.Current.Host.Settings.EnableRedrawRegions = true; you can see what is being redrawn every frame.  For every frame that the camera moves it redraws all elements that have a physicsbehavior on them, even static ones.  For the most part that can be ok, but, once you start to have non static elements collide and bounce around on the screen then perf gets bad quickly.  Simply turn on the redraw regions and you will see whats going on.  Where it can bee good perf is if your elements dont touch each other, once they touch eachother they combine to create a much larger rectangle that gets drawn to the screen.  You can see this by putting three rects on a canvas and have the middle one (with the camera) fall in between the other two, the only thing being drawn is the elements themselves.

I'm assuming how things get drawn in XNA would perform much better but maybe not for 2d sprites.

Coordinator
Feb 10, 2011 at 11:17 PM

A few ideas:

Be sure that you set CacheMode="BitmapCache" on any physics elements. For example, if you add a PhysicsObjectBehavior to a Canvas element, add the attribute CacheMode="BitmapCache" to that Canvas.

This will handle rendering of that element over to the GPU, which is much faster.

Just keep in mind that video memory is limited on WP7. Keep an eye on your frame rate counters and other perf as explained here: http://www.andybeaulieu.com/Default.aspx?EntryID=196&tabid=67

Feb 10, 2011 at 11:29 PM

DOH!  Cant believe I forgot that, and that I didn't think of that during all that flickering, goodness!  I do this on my other games.  Thanks for the reminder, it's like night and day, perf is great now.

Feb 15, 2011 at 10:26 AM

Hi guys, sorry for the delay, I only get to work on this stuff Tuesdays and Thursdays (damn the part time day-job).  I am now on this and will give you my results soon when I test this all out.

Thanks very much to you all for the responses - watch this space...

Feb 15, 2011 at 10:44 AM

Andy, that worked a treat.  It's now performing exactly as I would expect it to even with the camera.

I'm still amazed at what something small like this can do to the performance.  When I tried my canvas method (moving an inner game canvas around in an outer "view-port" canvas using left and top) the performance was awful, yet the calculations for it were trivial.  I'm from a web/silverlight development background and so graphics have never really come into it before.  I feel I need a good book to catch up!

Again, thanks for the advice.  Intrawebs, you mentioned wanting to test my scene - I may as well post the xaml, its so small.  With the bitmapcahces on though it works fine, even on my HD7.

    <Canvas Background="{StaticResource PhoneBackgroundBrush}"
            HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <Canvas x:Name="GameRoot" CacheMode="BitmapCache" >
    	    <i:Interaction.Behaviors>
    		    <pb:PhysicsControllerBehavior GravityVertical="2" RotationalDragCoefficient="0.02" FrictionDefault="0.2" />
    	    </i:Interaction.Behaviors>

            <mycontrols:Ship x:Name="playerShip" Canvas.Top="50" Canvas.Left="250" CacheMode="BitmapCache">
                <i:Interaction.Behaviors>
                    <pb:PhysicsObjectBehavior/>
                </i:Interaction.Behaviors>
            </mycontrols:Ship>
            <Rectangle Fill="#FF4EFF00" Height="68" Stroke="Green" StrokeThickness="5" Canvas.Top="-72" Width="912" CacheMode="BitmapCache">
            	<i:Interaction.Behaviors>
            		<pb:PhysicsObjectBehavior IsStatic="True"/>
            	</i:Interaction.Behaviors>
            </Rectangle>
            <Rectangle Fill="#FF4EFF00" Height="1122" Canvas.Left="-76" Stroke="Green" StrokeThickness="5" Canvas.Top="-72" Width="76" CacheMode="BitmapCache">
            	<i:Interaction.Behaviors>
            		<pb:PhysicsObjectBehavior IsStatic="True"/>
            	</i:Interaction.Behaviors>
            </Rectangle>
            <Rectangle Fill="#FF4EFF00" Height="66" Canvas.Left="4" Stroke="Green" StrokeThickness="5" Canvas.Top="984" Width="908" CacheMode="BitmapCache">
            	<i:Interaction.Behaviors>
            		<pb:PhysicsObjectBehavior IsStatic="True"/>
            	</i:Interaction.Behaviors>
            </Rectangle>
            <Rectangle Fill="#FF4EFF00" Height="980" Canvas.Left="836" Stroke="Green" StrokeThickness="5" Width="76" CacheMode="BitmapCache">
            	<i:Interaction.Behaviors>
            		<pb:PhysicsObjectBehavior IsStatic="True"/>
            	</i:Interaction.Behaviors>
            </Rectangle>

        </Canvas>
Mar 1, 2011 at 12:39 PM

Hi Timmy,

Thanks for posting the code. BTW - "Ship" looks promising, I have a feeling there is something on a spacetheme going on here... I'm looking forward to see where you end up with your project.

/Pettrer, Sweden

Apr 2, 2011 at 6:28 PM

I've tried the suggestions posted on this thread and have managed to get my camera to focus on my character. The problem comes about when I move the character (ApplyImpulse). The camera barely moves (it does slightly), yet the player moves off screen. Is there a way to keep the camera stuck to the player so that the player remains in the middle of the screen? I'm using this in the timer loop (from the example above)

double overrideX = (block.Position.X + 150);
double overrideY = (block.Position.Y + 300);
_cameraController.TargetOverrideX = overrideX;
_cameraController.TargetOverrideY = overrideY;

Also from this thread, I've set up my camera like this:

 

_cameraController = new CameraControllerMain();
            
_cameraController.ZoomEnabled = false;
_cameraController.ZoomSpeed = 0;
_cameraController.ZoomPercentage = 130;
            
_cameraController.ScrollEnabled = true;
_cameraController.ScrollSpeed = 0;

_cameraController.Initialize(LayoutRoot, _physicsController);
_cameraController.Target = "player";

 

This positions the camera nicely, when the level first starts, but it doesn't keep track of the object. Is there a property I'm missing somewhere?