Spawning question

Topics: Developer Forum
Coordinator
Sep 6, 2008 at 11:31 PM
Edited Sep 6, 2008 at 11:33 PM
Indeed there is.

There is a method in the Geom class called Collide().

Collide() takes a Vector2 position or another Geom.

EDIT: Geom also have a AABB property that contains the dimentions (boundaries) of the Geom. This chould also be used.
Coordinator
Sep 7, 2008 at 1:23 AM
You have the possibility of passing in a geom. In your case you would have to use the Vector2.

The Collide() method returns a bool. This bool is true if there is a collision and false if there is not.
Coordinator
Sep 7, 2008 at 2:04 PM
I think that disabling the geom while it overlaps another is a bad idea. The body of the Node will still fall in gravity and thus still continue to overlap.
Example:

if you spawn a node at the position Vector2(level.WorldScreenSize.X + 20, level.WorldScreenSize.Y / 3). Then new nodes will overlap the other if the original Node did not move out of the way. If you disable it when it overlaps it will fall to the ground excatly as the original Node does. (Provided they have the same mass, drag and so on).

A better way might be to spawn the Node higher up if it overlaps the other node.
You could create new Nodes higher on the Y axis than the last Node.

float offset = 2f;
newNode.Body.Position = new Vector2(level.WorldScreenSize.X + 20, lastNode.Body.Position.Y + newNode.Size.Y + offset);
Coordinator
Sep 7, 2008 at 8:46 PM
Yes, the if (!geom.Collide(body.Position)) will always return true. And thats because you tell it to be :)

Let me explain:

The Body class reacts on gravity and provides the position of the element in the "world". It can be rotated and moved
The Geom class provides collision detection.

The Geom is positioned the same place as the body. So when you execute this line of code: if (!geom.Collide(body.Position)) You are checking if the geom collides with the position that the body is in. And it does, because the positions are the same.

If you do this: 

if (!geom.Collide(new Vector2(100,100)))
{
 game.Exit();
}

Then the game will exit when the geom touches X 100 Y 100. Collide() checks if the geom collides with the provided position.
Coordinator
Sep 8, 2008 at 12:49 AM
Edited Sep 8, 2008 at 12:50 AM
"I just need a method to check if there are bodies within a certain area"

Bodies does not provide that kind of features, only Geoms do and as I said before, you could use Collide or AABB.

I rewrote Demo1 from the samples to demonstrate how to use AABB. Here is the code:

using

 

System.Text;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Factories;
using FarseerGames.FarseerPhysicsDemos.DrawingSystem;
using FarseerGames.FarseerPhysicsDemos.ScreenSystem;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

 

 

namespace

 

FarseerGames.FarseerPhysicsDemos.Demos.Demo1
{

 

 

 

public class Demo1Screen : GameScreen
{

 

 

 

private Texture2D _bodyTexture;
private Vector2 _origin;
private Body _rectangleBody;
private Geom _rectangleGeom;
private AABB _aabb;
public override void Initialize()
{
PhysicsSimulator =
new PhysicsSimulator(new Vector2(0, 0));
base.Initialize();
}

public
override void LoadContent()
{

 

 

 

//load texture that will visually represent the physics body
_bodyTexture = DrawingHelper.CreateRectangleTexture(ScreenManager.GraphicsDevice, 128, 128, Color.Gold,Color.Black);
_origin =
new Vector2(_bodyTexture.Width / 2f, _bodyTexture.Height / 2f);
//use the body factory to create the physics body
_rectangleBody = BodyFactory.Instance.CreateRectangleBody(PhysicsSimulator, 128, 128, 1);
_rectangleBody.Position = ScreenManager.ScreenCenter;
_rectangleGeom =
GeomFactory.Instance.CreateRectangleGeom(_rectangleBody, 128, 128);
_aabb =
new AABB(new Vector2(0, 0), new Vector2(400, 400));

 

 

 

base.LoadContent();
}

 

 

 

public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
{
if (AABB.Intersect(_aabb, _rectangleGeom.AABB))
ExitScreen();
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

 

 

 

public override void Draw(GameTime gameTime)
{
ScreenManager.SpriteBatch.Begin(
SpriteBlendMode.AlphaBlend);
ScreenManager.SpriteBatch.Draw(_bodyTexture, _rectangleBody.Position,
null, Color.White,_rectangleBody.Rotation, _origin, 1, SpriteEffects.None, 0);
ScreenManager.SpriteBatch.End();
base.Draw(gameTime);
}
}
}

 

 

It creates an area with the size of 400x400 and if the AABB (area) of the Geom touches the 400x400 area, then it will exit. Remember this is just a sample.
If you want a list of Geom's in an area, then you could create a list and add all Geom's to the list that touches the area (touches or is inside it).

"or if the body in question is currently colliding with another one."
But there is and I've already said it :) Collide() takes another Geom (not a body, bodies does not provide collision detection). You can easily test if a Geom is colliding with another Geom by calling FirstGeom.Collide(SecondGeom);

" I take it there's no way to find out if the body doesn't currently have a collision if you have to use the Event method?"
From what I just wrote, you should be able to figure that out your self :) There are 2 ways to check if a collision occurs: using Collide() or using the Collision event.

EDIT: Damn... codeplex REALLY makes code ugly...
Coordinator
Sep 8, 2008 at 2:26 PM
Thats right, you will need to check against all other geoms.

Welcome to Farseer discussions by the way. We are here to help.
Developer
Sep 8, 2008 at 9:55 PM
@sensorium7 - If you only need to find an empty spot to spawn a body then add a AABB check that can move the bodies position until there is no initial collision between AABB's. This is very easy to do - find the overlap of the 2 AABB's then move the position that far. Bodies sticking together is a big problem farseer. If you've ever used Box2D you can't get objects to stick together even if you place them directly on top of each other. Adding a simple AABB test before positioning a body will solve the problem when creating objects but not for hard impacts that can cause objects to imbed in each other. By placing the AABB collision check in the collision handler event and simply checking the amount of overlap of the 2 colliding geoms you can determine whether or not to provide a manual reposition. By doing this geoms will only be separated if they overlap by a certain amount. This gives farseer a chance to allow a little overlap with out jumping objects around. I had a demo of this but lost it in a computer crash. It offered very similar results to Box2D with almost no performance impact. If you need a demo I will take some time and redo it as I will be needing again anyway and also I might see if we can have this feature added to the 2.0 release.

@genbox - I sure you have tested out Box2D. It's ability to quickly separate overlapping objects is outstanding. While what I describe above is not the same technique used in Box2D, it is a simple feature to possibly add to farseer. Geoms that overlap can create a huge drag on the engine and waste precious collision contacts. If you think adding a separation ability would help please let me know and I'll try to provide a demo of how it works.
Coordinator
Sep 8, 2008 at 10:05 PM
@mattbettcher - The positioning of bodies/geom on the screen should normally be solved in the game. Implementing it in the physics engine would force users to use an implementation that might not be perfect for their setup. As I do not know the impact of this feature yet, it's hard to say.

But, implementing it and give the users an ability to use it could be a posibillity, and I would be happy to see how it works for future implementation in Farseer 2.0.
I will write it down on my list of things to do. :)

Thanks mattbettcher.
Developer
Sep 9, 2008 at 2:56 AM
I got a simple demo working. Seems to work pretty good for almost all the different tests I put it through. Send me a personal message with your email and I'll send you a copy. It's very simple just add the handler to any objects likely to overlap when created.
Developer
Sep 9, 2008 at 5:46 AM
@sensorium7 - Your code is very much like my original code. The demo code I sent you is quite different. It allows any geoms that become "stuck" inside each other to be separated.
Coordinator
Sep 9, 2008 at 8:27 AM
@sensorium7 - Just as a little note, the AABB class have 2 properties called width and height if I remember correctly.