Animating objects in a PhysicsCanvas

Oct 29, 2012 at 3:37 PM

Hi there,

I've noticed that if I move an object on the PhysicsCanvas using a storyboard its simulated positions don't get updated, so it thinks the object is still at its original location.  I would like to load the canvas, pause it, add my controls, animate some parts and pause it again, I may like to do this a few time.

How would I achieve this?  I've tried calling "Update" on the PhysicsSprite but that doesn't seem to effect it.

Thanks in advance.

Firk

Coordinator
Oct 30, 2012 at 12:58 AM

Yeah, Storyboards cannot be used to re-position a PhysicsSprite. The physics engine does not generally behave well when objects change position often outside of the engine's own calculations.

You should instead use ApplyForce, ApplyLinearImpulse, ApplyTorque, etc. to get the elements where you want them.

If you absolutely must reposition them manually, then be sure to zero out linear velocity and angular velocity -

spr.BodyObject.LinearVelocity = Vector2

.Zero;

spr.BodyObject.AngularVelocity = 0;

 

 

 

Coordinator
Oct 30, 2012 at 12:59 AM

Should have added- you _can_ use Storyboards to animate items _within_ a PhysicsSprite. for example, maybe the eyes roll around on the face of a sprite, etc. These Storyboards are OK because they are outside of the physics engine.

Oct 30, 2012 at 8:40 PM
AndyBeaulieu wrote:

Yeah, Storyboards cannot be used to re-position a PhysicsSprite. The physics engine does not generally behave well when objects change position often outside of the engine's own calculations.

You should instead use ApplyForce, ApplyLinearImpulse, ApplyTorque, etc. to get the elements where you want them.

If you absolutely must reposition them manually, then be sure to zero out linear velocity and angular velocity -

 

 

spr.BodyObject.LinearVelocity = Vector2

.Zero;

 

 

 

 

spr.BodyObject.AngularVelocity = 0;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Hi Andy,

I tried as suggested but unfortunately it still acted as if my object was at its original starting position, prior to the doubleanimation that was performed on its canvas.y value.  Bearing in mind that these are only static objects I'm moving about at the moment, I managed to get it to get the position correctly by adding an additional method to the PhysicsSprite object,

        public void ResetPhysicsLocation()
        {
            xna.Vector2 offsetPosition = PhysicsUtilities.GetOffsetPositionInScreen(this);

            if (_position != Vector2.Zero)
                Position = _position;
            else
                BodyObject.Position = PhysicsCanvas.BoundaryHelper.ScreenToWorld(offsetPosition);
        }

Now when I run this after my storyboard completes for each object that's moved, it updates its location.  I haven't experienced any weirdness as yet.

Nick.

Nov 4, 2012 at 6:41 AM
Edited Nov 4, 2012 at 6:50 AM

I registered dependency properties of the position "X" and "Y" and used them for animation.

The UpdateAnimationX() and UpdateAnimationY() are kind of hackish as they're being called from a static method,

but it works okay.

 

public static readonly DependencyProperty XProperty = DependencyProperty.Register("X", typeof(double), typeof(PhysicsSprite), new PropertyMetadata((double)0, XPositionChanged));
        
        private static void XPositionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
            double blah = (double)e.NewValue;
            PhysicsSprite ps = obj as PhysicsSprite;
            ps.UpdateAnimationX();
            }

        private void UpdateAnimationX()
            {
            if (BodyObject != null )
                {
                float X = (float)(double)this.GetValue(XProperty);
                Vector2 bodyPosScreenCoords = PhysicsCanvas.BoundaryHelper.WorldToScreen(BodyObject.Position);
                bodyPosScreenCoords = new Vector2(X, bodyPosScreenCoords.Y);
                BodyObject.Position = PhysicsCanvas.BoundaryHelper.ScreenToWorld(bodyPosScreenCoords);
                }
            }
        
        public double X
            {
            get { return (double)this.GetValue(XProperty); }
            set { this.SetValue(XProperty, value); }
            }

        public static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double), typeof(PhysicsSprite), new PropertyMetadata((double)0));

        private void UpdateAnimationY()
        {
            if (BodyObject != null)
            {
                float Y = (float)(double)this.GetValue(YProperty);
                Vector2 bodyPosScreenCoords = PhysicsCanvas.BoundaryHelper.WorldToScreen(BodyObject.Position);
                bodyPosScreenCoords = new Vector2(bodyPosScreenCoords.X, Y);
                BodyObject.Position = PhysicsCanvas.BoundaryHelper.ScreenToWorld(bodyPosScreenCoords);
            }
        }

        public double Y
            {
            get { return (double)this.GetValue(YProperty); }
            set
                {
                if (BodyObject != null)
                    {
                    float Y = (float)value;
                    Vector2 tempPos = BodyObject.Position;
                    BodyObject.Position = new Vector2(tempPos.X, Y);
                    }
                }
            }