Few questions

Jan 19, 2012 at 11:05 AM
Edited Jan 19, 2012 at 11:13 AM

OK, after take a more deep look in all,

I see objects cant send events indicating are moving, the only events I see object can send are:

COLLIDER, indicating collision happen. (this is correct?)

SEPARATE: no idea when this event happen explain please what is separate?

No any event indicating object star move? or stop move?

I need get position coordinates of objects.
The only way I see to check the position of specific object, is use TICK.

Using ticker I can get the position at every tick send by Physicalbox, the problem of this method is use CPU calculations all time getting the position, no matter object is stopped or not moving.
I know the simple calculation of position no is a expensive process, but when have high amount of objects this can result in a non necessary CPU usage.
Correct?
Some workaround for this?

I see 2 tickers:
TICK and UITick

What is the difference between this 2 tickers?


Another problem I have.
I making some test and found more problems and more questions.
For start clock just have to run:

PhysicalBox.Clock.Start();

For stop, should be?

PhysicalBox.Clock.Stop(); 

 but this return error:

No overload for method 'Stop' takes 0 arguments 

What Im doing wrong?


Finally I have another problem, i just maing a simple test and want try make multiple objects, rectangle, ellipse etc etc  bounce inside a canvas.
For make the objects not go outsde of canvas I located static rectangles at left of canvas, , right, top, bottom.
That work correctly, but if I resize the canvas at runtime, part of that rectangles not limit the objects, is like the physics of the rectangles at border fo canvas no is updated and only one potion of that rectangle act like static and limit objects.
How can fix this?

I see if I resize and after that star clock is ok, but when clock is started and i resize the canvas at runtime, no updates for the elements are resized.

Stop clock and start fix this?

Coordinator
Jan 19, 2012 at 5:08 PM

Collide and Separate are the only events that Fraser Physics has. The only way I could create a move event would be to test the position at every fame like you described. Separate is the opposite of Collide. It occurs when 2 bodies are no longer touching.

You can get the position of an object with Canvas.GetLeft(UIElement) and Canvas.GetTop(UIElement). This has to run on the ui thread. It's also possible to get the position directly from Fraser Physics. That doesn't have to run on the ui thread but you will probably not get the values you are looking for because all the physics are done with different units than pixels, and some of the positions are offset to the center of the object and some are the top left.

The clock has two events, Tick and UITTick. This is to enable somewhat realistic physics and a good frame rate at the same time. Fraser Physics works much better when you make small time steps between frames rather then large ones. If you start making large steps strange thing start happening, and it just doesn't look right. Objects can pass though each other or just get stuck together. You can change this with the Interval property. This frame rate is so fast that it's unnecessary to update the UI this much, so that's where UITick comes in. Every X amount of Tick events will come with a UITick. The default is 5 but you can adjust it with the UISteps property. Code to work with the UI should be triggered by UITick. Any other code should be triggered by the Tick event.

Stop has one Boolean parameter named Wait. Stopping the simulation can take a small amount of time if it's in the middle of a frame. It's not very much time but it could be important. If you need to wait for the simulation to stop completely send True, other wise just send False. Be careful to never send True if you are executing code as part of a frame. For example inside of the Tick or UITick event. If you do this the frame will not be able to end and you will be waiting forever.

Usually I put the PhysicalBox into a Viewbox with Stretch set to Uniform. This will make everything grow and shrink when you resize the window. This is by far the easiest solution. You can see an example of what I mean here http://xamlphysics.codeplex.com/SourceControl/changeset/view/11278#111442

Stopping and starting the clock isn't going to do what you want. Actually moving the border a bit more complicated. If that's really what you want to do it's probably best to just remove the old borders and add new ones. As long as it's in one frame nothing will be able to escape. You can read this discussion about adding and removing objects here http://xamlphysics.codeplex.com/discussions/266634

Jan 20, 2012 at 4:41 AM
Edited Jan 20, 2012 at 6:08 AM
Thank you for your repply, viewbox, no is usefull, bt not for me due change the size of objects.


My way should be create objects acts as containers creating that at runtime.


I continue testing in the last hours, and I can add object at runtime using this code.
But can find the way to delete LOL

Can tell me please how can delete?
  List<UIElement> Add = new List<UIElement>();


        private void UITick(object sender, XamlPhysics.WPF.GameLoop.TickEventArgs e)
        {
            Dispatcher.Invoke((Action)delegate()
            {
                    foreach (var Element in Add)
                    {
                        Drag.Children.Add(Element);
                    }
                    PhysicalBox.FindNewBodies();
                    Add.Clear();
            });
        }



private void button1_Click(object sender, RoutedEventArgs e)
        {
            Rectangle topR = new Rectangle();
            topR.Name = "topR";
            topR.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topR, 100);
            Canvas.SetTop(topR, 100);
            topR.Height = 300;
            topR.Width = 10;
            XamlPhysics.WPF.RectangleBody rectangleBody = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topR, rectangleBody);
            rectangleBody.IsStatic = true;
            rectangleBody.IgnoreGravity = true;
            Add.Add(topR);


            Rectangle topL = new Rectangle();
            topL.Name = "topL";
            topL.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topL, 400);
            Canvas.SetTop(topL, 100);
            topL.Height = 300;
            topL.Width = 10;
            XamlPhysics.WPF.RectangleBody rectangleBodyL = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topL, rectangleBodyL);
            rectangleBodyL.IsStatic = true;
            Add.Add(topL);

            Rectangle topB = new Rectangle();
            topB.Name = "topB";
            topB.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topB, 100);
            Canvas.SetTop(topB, 400);
            topB.Height = 10;
            topB.Width = 310;
            XamlPhysics.WPF.RectangleBody rectangleBodyB = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topB, rectangleBodyB);
            rectangleBodyB.IsStatic = true;
            Add.Add(topB);
        }


  private void button2_Click(object sender, RoutedEventArgs e)
        {
      
        //how delete that 3 rectangles?

        }




Jan 20, 2012 at 9:12 AM
Edited Jan 20, 2012 at 9:38 AM
I find the way to delete the 3 rectangles I created, 
objects deleted by physics continue in the place where object is before delete.
Some help with this liserdart?
This is my code for delete:


UIElement[] tmp = new UIElement[Drag.Children.Count]; Drag.Children.CopyTo(tmp, 0); // Iterate the uielements foreach (UIElement uielement in tmp) { Shape myShape = uielement as Shape; // Make sure we have a shape and the shape has a tag if (myShape != null && myShape.Tag != null) { // We only want to remove our dynamically created shapes if (myShape.Tag.ToString().Contains("tagname")) { Drag.Children.Remove(uielement); } }
Coordinator
Jan 20, 2012 at 8:21 PM
Edited Jan 20, 2012 at 8:27 PM

The example I linked to has a solution to remove objects. I changed your code to use it. Also you removed the condition around the call to FindNewBodies which is going to hurt your frame rate, so I added it back in.

List<UIElement> Add = new List<UIElement>();
List<UIElement> Remove = new List<UIElement>();
List<UIElement> BoundingBorders = new List<UIElement>();


        private void UITick(object sender, XamlPhysics.WPF.GameLoop.TickEventArgs e)
        {
            Dispatcher.Invoke((Action)delegate()
            {
                if (Add.Count > 0)
                {
                    foreach (var Element in Add)
                    {
                         Drag.Children.Add(Element);
                    }
                    Add.Clear();
                    PhysicalBox.FindNewBodies();
                }

                foreach (var Element in Remove)
                {
                    PhysicalBox.World.RemoveBody(XamlPhysics.WPF.PhysicalBox.GetBody(Element));
                    Drag.Children.Remove(Element);
                }
                Remove.Clear();
           });
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            Remove.AddRange(BoundingBorders);
            BoundingBorders.Clear();
            
            Rectangle topR = new Rectangle();
            topR.Name = "topR";
            topR.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topR, 100);
            Canvas.SetTop(topR, 100);
            topR.Height = 300;
            topR.Width = 10;
            XamlPhysics.WPF.RectangleBody rectangleBody = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topR, rectangleBody);
            rectangleBody.IsStatic = true;
            rectangleBody.IgnoreGravity = true;
            Add.Add(topR);
            BoundingBorders.Add(topR);

            Rectangle topL = new Rectangle();
            topL.Name = "topL";
            topL.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topL, 400);
            Canvas.SetTop(topL, 100);
            topL.Height = 300;
            topL.Width = 10;
            XamlPhysics.WPF.RectangleBody rectangleBodyL = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topL, rectangleBodyL);
            rectangleBodyL.IsStatic = true;
            Add.Add(topL);
            BoundingBorders.Add(topL);

            Rectangle topB = new Rectangle();
            topB.Name = "topB";
            topB.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topB, 100);
            Canvas.SetTop(topB, 400);
            topB.Height = 10;
            topB.Width = 310;
            XamlPhysics.WPF.RectangleBody rectangleBodyB = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topB, rectangleBodyB);
            rectangleBodyB.IsStatic = true;
            Add.Add(topB);
            BoundingBorders.Add(topB);
        }

Jan 20, 2012 at 9:40 PM

Thankyou for your repply, but cant make this work have this error:


PhysicalBox.World.RemoveBody(XamlPhysics.WPF.PhysicalBox.GetBody(Element));


Error	2	Argument 1: cannot convert from 'XamlPhysics.WPF.PhysicalBody' to 'FarseerPhysics.Dynamics.Body'	


Error	1	The best overloaded method match for 'FarseerPhysics.Dynamics.World.RemoveBody(FarseerPhysics.Dynamics.Body)' has some invalid arguments	


Have that 2 errors on that line.




Coordinator
Jan 20, 2012 at 10:02 PM

Oops. Change the line to this.

PhysicalBox.World.RemoveBody(XamlPhysics.WPF.PhysicalBox.GetBody(Element).Body);
Jan 20, 2012 at 10:25 PM
Edited Jan 20, 2012 at 10:31 PM

Thank you for your faster reply like always, i feel shame to abuse of you asking and asking and asking.
Please apologize.
You accept donations?
If yes i can send at end of money some donation  i feel better if i compensate for this help.


Again another new question, with this code you show me, what should be the code for remove.
I trying with my code, i just have a simple button i want when pres that 3 rectangles disappear,  etc etc.
I try with my code, i add tag to the rectangles and not work, object are deleted but physics of body rectangle remain.
What is the code?

 

private void button2_Click(object sender, RoutedEventArgs e)
        {
      
        //code???

        }
Coordinator
Jan 23, 2012 at 11:07 PM

I don't have anything set up to receive donations. If you want to send me money you can use paypal to send it to liserdarts at yahoo.com.

This is the code that will remove the objects

 

Remove.AddRange(BoundingBorders);
BoundingBorders.Clear();

I put it in button1_Click. If you want it in button2_Click, just move it.

 

Jan 24, 2012 at 11:16 PM

Thankyou this work perfect.
One extra question, how can delete only desired or specific element?


Example if i wnant delte only element based on name or tag?

example, delete only topL:




Rectangle topL = new Rectangle();
            topL.Name = "topL";
            topL.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topL, 400);
            Canvas.SetTop(topL, 100);
            topL.Height = 300;
            topL.Width = 10;
            XamlPhysics.WPF.RectangleBody rectangleBodyL = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topL, rectangleBodyL);
            rectangleBodyL.IsStatic = true;
            Add.Add(topL);
            BoundingBorders.Add(topL);
Jan 27, 2012 at 10:41 AM
Edited Jan 28, 2012 at 3:45 PM

Ignore my question:

 

 

Rectangle topL = new Rectangle();
            topL.Name = "topL";
            ui-element-to-delete = topL;
            topL.Fill = new SolidColorBrush(Colors.Green);
            Canvas.SetLeft(topL, 400);
            Canvas.SetTop(topL, 100);
            topL.Height = 300;
            topL.Width = 10;
            XamlPhysics.WPF.RectangleBody rectangleBodyL = new XamlPhysics.WPF.RectangleBody();
            XamlPhysics.WPF.PhysicalBox.SetBody(topL, rectangleBodyL);
            rectangleBodyL.IsStatic = true;
            Add.Add(topL);
            BoundingBorders.Add(topL);

 PhysicalBox.World.RemoveBody(XamlPhysics.WPF.PhysicalBox.GetBody(ui-element-to-delete).Body);
 Drag.Children.Remove(ui-element-to-delete);

 

 

 

Coordinator
Feb 10, 2012 at 11:08 PM

If you want to remove an element you should just add it to the Remove list from my example.

Remove.Add(ui-element-to-delete);
This will make sure it's done on a UI tick. If you do it directly on a button click or something like that you could end up removing it from the physics engine while it's in the middle of a frame and crash it.