Hi I have an object which is composed by several bodies, the differences between them is that someone is a filter and someone else is not.
I want my actor to be destroyed when colliding with the physic side and to have a different effect when colliding with the sensor one.
So how can I check in my collision listener if the contact is happening in one part or in another?
Let's say you have a table and a bunch of cows, you want to determine if any cow collided with the table.
Body table;
Array<Body> cows;
//define the table and cows
ContactListener listener = new ContactListener() {
#Override
public void beginContact(Contact contact) {
Body bodyA = contact.getFixtureA().getBody();
Body bodyB = contact.getFixtureB().getBody();
for (Body cow : cows) {
if (((cow == bodyA) || (cow == bodyB)) &&
((table == bodyA) || (table == bodyB))) {
//do something
}
}
}
};
It's a generic answer, but It tells you how to check which bodies have collided which I believe answers your question.
There are probably many ways to do this, but here is how I do my physics to game object mapping. Not something I stick to religiously, but I try to - there are always exceptions.
If I have a "game object", it has one body. The bodies user data is set to that object.
If I have a "game object" that is made up of parts, these parts are "game object parts", and they will be the userdata of the Fixtures of the body.
My "Game Object" is a composite of the "Part Objects" in the same way as a Body has Fixture parts.
If you have something like this, then you can distinguish between the parts of your object in collisions easily I think. If you truly want your "Game Object" to be made up of multiple bodies for some other reason, then I would still make the "Game Object" have "Parts" that are set to the user data of the bodies that make it up. Hope that helps.
I also take it another step further - my "game objects" have their own collection of collision handlers. So my single registered collision listener gets the userdata objects and calls their collision handlers with the same parameters. Leverage the polymorphism dude. Now I can attach the collision behaviour I want for a given object to that object. I don't have to loop through all my objects to decide what to do in my registered collision listener.
Related
I am making a game in which multiple character fire towards each other and on hitting the fire they will act with different animations like: blast, bounce, blur and so on. For now the thing where i am stuck is that while fire is traveling how will we check that its intersecting with other objects of not? I mean run animations only on targeted characters.
You could save your objects that want to check in a vector and schedule an update in your scene that checks if they collide.
This is an answer for Box2D.
Create a body def for each of the objects you are firing. Using some of the code below. Make sure you change shapes to fit what you need. Pixel to meter ratio I set to 32.0 in my code.
b2BodyDef bulletDef;
bulletDef.type = b2_dynamicBody;
bulletDef.position.Set(startPositionX / Pixel_To_Meter_Ratio,
startPositionY / Pixel_To_Meter_Ratio);
auto b2PolygonShape bulletShape;
bulletShape.SetAsBox(bulletWidth / Pixel_To_Meter_Ratio,
bulletHeight / Pixel_To_Meter_Ratio);
auto bulletBody = physicsWorld->CreateBody(bulletDef)
Apply velocity to the body def in the position that you want the bullet to go.
bulletBody->ApplyLinearImpulse(b2Vec(bulletDirectionX,
bulletDirectionY),
physicsBody->GetPosition(),
true);
Add a contact listener to the physics world that inherits from b2ContactListener
// Node that manages the physics world from box2d
class PhysicsNode : public b2ContactListener
{
void BeginContact(b2Contact* contact);
}
// register this listener with the box2d world
auto physicsWorld = new b2World(b2Vec2(0, -9.8f));
physicsWorld ->SetContactListener(this);
Implement the BeginContact function and handle the collision in there.
void PhysicsNode::BeginContact(b2Contact* contact)
{
// Get the physics bodies
auto objectOne = contact->GetFixtureA()->GetBody();
auto objectTwo = contact->GetFixtureB()->GetBody();
// Cast to the type you set as your user data
auto collidableOne = static_cast<Collidable*>(objectOne->GetUserData());
auto collidableTwo = static_cast<Collidable*>(objectTwo->GetUserData());
// Handle your collisions. Apply blur/explode/whatever you need
collidableOne->handleCollision(collidableTwo->isReactableCollision());
collidableTwo->handleCollision(collidableOne->isReactableCollision());
}
I hope this helps. This is what I use to achieve the functionality you are looking for.
I'm trying to implement a collision detector between my Player (Actor) and my Obstacle (Actor too), and I wonder what's the best way to perform a collision detection between them. I see some users saying that they create a Rectangle object in the class and update its bounds every frame, but I don't know if this is the best way to perform this (I'm also trying to make this, but my collision detector method triggers before my Player touches the Obstacle).
This is what I'm trying to check:
public boolean touchedWall() {
// Loop for the obstacles
for (Obstacle obstacle : this.world.getObstacles()) {
// Check if player collided with the wall
if (this.bounds.overlaps(obstacle.getBounds())) {
Gdx.app.log(Configuration.TAG, "collided with " + obstacle.getName());
return true;
}
}
return false;
}
And this is where the method triggers (it should trigger when the Player bounds hit the wall):
I figured out! Instead of using this.bounds.set(x, y, width, height), I was using this.bounds.set(x, y, height, width) like this:
this.bounds.set(this.getX(), this.getY(), this.getHeight(), this.getWidth());
Sorry for my mistake.
This is mostly a question about code design. What you see here is a very condensed version of the original code.
An example of the code is:
player.rest();
This makes the player sleep.
I have other methods such as walk, run, talk etc. which all work great. The one that is a problem is polymorph. It changes the player from a human object to another object. The solution I came up with is this:
class main
{
var human:Human = new Human;
var alien:Alien = new Alien;
var cow:Cow = new Cow;
var player = human;
enterframe loop{
//other code
if (player does something)
player.polymorph = "alien";
switch (player.polymorph)
{
case "alien":
player = alien;
break;
case "cow":
player = cow;
break;
//etc
}
player.update();
}
}
I want something that looks like this:
class main
{
var human:Human = new Human;
var alien:Alien = new Alien;
var player = human;
enterframe loop
{
player.polymorph(alien);
}
}
I know my original solution is the wrong way to go about things as it encourages spaghetti code. How could I do it differently? I don't mind a whole rewrite, but need an example to help push me in the right direction. I hope this makes sense and thanks for the help.
If the second one can work, what would the polymorph function look like?
I thought of making a class called player and changing what that extends, but to my knowledge that can't be done? Plus I would like to change the character to something already in game rather than a new object.
One solution to your problem would be using a single class, in this case, your Player class, and a finite state machine. You'd have a Player class, which can be set to different states, such as HUMAN, ALIEN, COW, etc. When a polymorph event occurs you update the Player's state, perhaps by calling an initState() method, and handle the logic for being a human, alien, cow, accordingly in whatever method updates your player.
Assuming the player has an update() method it could contain the following:
switch (state) {
case ALIEN:
// do alien stuff
case COW:
// do cow stuff
case HUMAN:
// do human stuff
}
Next, instead of handling the various polymorph states in a switch statement, your Player class could have a polyMorph method that takes a state as a parameter:
public function polymorph(newState:Int) {
state = newState;
initState(state); // You could even just call the initState method instead, and completely omit the polymorph method
}
Using a finite state machine here would eliminate the need for numerous objects.
I am using Box2D for the first time seriously in a medium sized Flash Game that I am working on. My current experience with Box2D is limited to creating a world, bodies and adding those bodies to the world in a functional manner.
I'm finding it easy enough to integrate Box2D into my game environment, maintaining well-written code and have completed a few tutorials that walk through dealing with collisions. The issue that I'm facing now is that my game will have many bodies, each interacting with other bodies in different ways, and I'm finding it hard to write my own b2ContactListener subclass without it getting extremely messy.
Based off a tutorial I used, I have created my own subclass of b2ContactListener and added an override of the BeginContact() method. The argument that BeginContact() receives when it is called will reference an instance of b2Contact, through which I can access two b2Fixture instances (the two instances that have collided). I am then able to access the b2Body instance associated with each of those b2Fixtures.
Problem: Currently I have a roundabout way of finding out what two things collided (i.e. whether they're a wall and a missile, or the player and a tree, etc) which uses GetUserData() and looks like this as an example:
var f1Player:Boolean = contact.GetFixtureA().GetBody().GetUserData() is Player
var f2Player:Boolean = contact.GetFixtureB().GetBody().GetUserData() is Player
var f1Tree:Boolean = contact.GetFixtureA().GetBody().GetUserData() is Tree
var f2Tree:Boolean = contact.GetFixtureB().GetBody().GetUserData() is Tree
// ... continutes with all possible combinations.
// Example of managing a collision:
if(f1Player && f2Tree)
{
// Player (FixtureA) and Tree (FixtureB)
}
if(f2Player && f1Tree)
{
// Player (FixtureB) and Tree (FixtureA)
}
As you can see, this is going to end up extremely long and unmanageable. I also have to write each set of actions to perform twice to cater for a certain element being FixtureA or FixtureB, or vice versa (obviously in the form of a function call with the parameters swapped around rather than literally re-written).
This is clearly not the correct approach, but I haven't been able to locate resources that more thoroughly explain collision detection management.
Does anyone have experience with collision detection management using Box2D that they can share? Also, is using SetUserData( entityThatOwnsTheBody ); the correct way to be using that method?
Yeah, it's a bit of a nuisance indeed. Actually I think the way you have it is quite typical.
fwiw Box2D itself has to deal with a similar problem when testing whether fixtures overlap. There are a bunch of functions such as b2CollideCircles, b2CollidePolygonAndCircle, b2CollidePolygons etc, and when two fixtures come near each other the engine chooses which of these functions should be used.
It does this by putting the function pointers in a 2-dimensional array, then looks up the appropriate function in this array by using the two shape types as index. See the first three functions in b2Contact.cpp for details.
Of course, if you can't pass around function references like this in AS3 then I guess this answer doesn't help much, but I thought I would post anyway as C/C++/JS users might come by.
I've used c++ version of Box2d, but I think the same approach will work in actionscript. I create a class Object, that contain a b2Body *_body pointer and a pointer to graphical representation. _body's UserData was set to point to Object *. class Object had the following methods:
virtual bool acceptsContacts ();
virtual void onContactBegin (const ContactData &data);
virtual void onContactEnded (const ContactData &data);
virtual void onContactPreSolve (const ContactData &data);
virtual void onContactPostSolve (const ContactData &data);
When collision was detected in b2ContactListener subclass, it checked if collided bodies have user data. If so, it casted their user data to Object* and if any of the collided objects accepted contacts - it created ContactData ( a class with all required information about collision) and put it in it's internal list to deliver later.
When b2World::update method returned, ContactListener delivers all contact information to objects to process. Delivery was delayed in order you could create new bodies, joints and so on, right when processing collision (which is not allowed while update is executing)
Also you must notify ContactListener (just put a pointer to it inside ContactData) if one of the collided body was deleted during collision processing, so it can invalidate appropriate contacts and not deliver them
I've come up with something much nicer than the original.
Firstly, I just have my Being class (which owns a b2Body) set itself as its bodies' UserData. This class will also contain an onContact() method and look similar to the below:
public class Being
{
private var _body:b2Body;
public function Being()
{
// Define the body here.
// ...
_body.SetUserData(this);
}
public function onCollision(being:Being = null):void
{
//
}
}
Then in my own b2ContactListener implementation, I simply pass the colliding Being (or null, if there is no Being assigned to the colliding b2Body's UserData) to the opposing Being's onCollision():
override public function BeginContact(contact:b2Contact):void
{
var bodyA:b2Body = contact.GetFixtureA().GetBody();
var bodyB:b2Body = contact.GetFixtureB().GetBody();
var beingA:Being = bodyA.GetUserData() as Being || null;
var beingB:Being = bodyB.GetUserData() as Being || null;
beingA && beingA.onCollision(beingB);
beingB && beingB.onCollision(beingA);
}
And finally in each of my subclasses of Being, I can easily prepare logic appropriate for a collision between other Beings of a certain type:
class Zombie extends Being
{
override public function onCollision(being:Being = null):void
{
if(being && being is Bullet)
{
// Damage this Zombie and remove the bullet.
// ...
}
}
}
How would you adhere to the "Tell, don't ask" principle (henceforth "the principle") in the following simple scenario? In a Tetris game, I have Board, BlockGrid and Piece classes relevant to the following example:
public class Board
{
private var fallingPiece:Piece;
private var blockGrid:BlockGrid;
...
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
blockGrid.movePiece(fallingPiece, xDirection, yDirection);
}
}
Once fallingPiece is placed in the bottom row of BlockGrid, it should no longer be the "fallingPiece". Am I right in that I'm not violating the principle with the following?
if(blockGrid.getPiecePosition(piece).y == 0)
{
fallingPiece = null;
}
But is that really different from this, which I think clearly violates the principle?
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
if(blockGrid.getPiecePosition(piece).y > 0)
{
blockGrid.movePiece(fallingPiece, xDirection, yDirection);
}
else
{
fallingPiece = null;
}
}
I'm not assuming that I've designed these class relationships in the proper way to work with the principle. Please advice on an alternate design if that's what I'm missing.
EDIT, Proposed solution:
I went with the answers proposing "command feedback" via events. Board tells BlockGrid to move a piece. BlockGrid's movePiece method dispatches MOVED_TO or MOVE_FAILED events depending on the result, which Board can listen to and use to determine whether a piece has stopped falling. Please don't hesitate to provide feedback on this solution.
public class Board
{
...
public function Board()
{
...
blockGrid.addEventListener(PieceMoveEvent.MOVE_FAILED, onPieceMoveFailed);
...
}
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
blockGrid.movePiece(fallingPiece, xDirection, yDirection);
}
public function onPieceMoveFailed(event:MovePieceEvent):void
{
if(event.instance == currentlyFallingPiece && event.fromPosition.y != event.toPosition.y)
{
currentlyFallingPiece = null;
}
}
I think, to better follow the Tell, Don't Ask principle, you should have blockGrid notifying your Board class when fallingPiece has reaches it's resting point. In both scenarios above, you are asking blockGrid if the piece's position.y == 0 in order to determine whether or not fallingPiece should be null. Instead, you want blockGrid to tell the Board class that fallingPiece.y has hit 0.
What you are looking for is Event driven programming. You need a Listener interface with a method called .event() and an Event interface to represent the events. Objects will register with other objects ( callbacks ) to the Listener interface.
when you create a Piece and Board they should implement the Listener interface. Then you can set the Board with registerListener(board); Then when things happen inside Piece it will loop thru all the registered listeners and call .event(event) on each. Same with the Board, call board.registerListener(piece) each time you create a new piece, as it decides things are happening it can tell all the registered listeners what has happened. Then you can tell a piece it is no longer falling by the Board object deciding this. Here is the obligitory Wikipedia entry.
I would expect a class representing each shape (without position information), a controller containing a shape, position and orientation, and another class representing the current resulting grid of "landed" shapes. The landed-grid would have a
testLanded(shape, shapePosition, orientation)
method which would be called before/after each move operation to decide if the shape is to join the landed grid or should move and stay as the falling piece.
I'm going on the idea of not giving data to objects that shouldn't really own that data - but I've never implemented Tetris...
You may need to rethink your design. Does Board really need to track the falling piece or should that belong to BlockGrid? Iron out who owns what behavior.
Keep position information on your Piece class and possibly have your Piece class hold an instance of the BlockGrid.
You can then try something like this in your Board class...
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
blockGrid.moveFallingPiece(xDirection, yDirection);
}
Then in BlockGrid's moveFallingPiece method...
public function moveFallingPiece(xDirection:int, yDirection:int):void
{
fallingPiece.move(xDirection, yDirection);
}
In Piece's move method, add your logic...
public function move(xDirection:int, yDirection:int):void
{
setPosition(xDirection, yDirection);
if (getPosition().y <= 0)
{
blockGrid.setFallingPiece(null);
// this can bubble up to Board if need be
}
}
Not sure of all the power of AS3, but it would make sense to use abstractions here. (i.e., have your Piece class depend on ITrackFallingPieces instead of BlockGrid and have BlockGrid implement ITrackFallingPieces).
Good luck!