So I am making a physics engine that only uses rectangles (axis-aligned bounding boxes) as shapes. I have implemented a method from christer ericsons book that returns the collision time and normal of two moving aabbs. I also have made another method that takes two aabbs velocities, positions and a normal that responds to the collision and give the aabbs new velocities.
The actual problem now is is that I don't know how the loop, that checks the collisions between all aabbs and responds to them, should look like. Simply I don't understand how to order the collisions by the time of impact, and which collision I should respond to.
A loop written in pseudo code that shows how to order all collisions would be really helpful.
Another thing I've mentioned is that it's possible thata moving box could bounce between two static boxes hundreds of times in a single frame if it's velocity is really high, how do you handle that?
You should let a simple priority queue take care of the right order of execution. Conceptually, this would end up looking something like this:
queue<CollisionEvent> q = new empty queue
while (!q.isEmpty) {
nextCollision = q.dequeueMinimum
/* run animation until nextCollision.time
...
*/
newMovingParticles = nextCollision.movingParticles
newCollisions = computeCollisionEvents(newMovingParticles, allOtherParticles);
for each event in newCollisions {
q.enqueue(event, event.time);
}
}
What about boxes that move with large velocities: I don't know. Physically, it would make sense to just accept that it can happen that there is a sequence of very frequent collision events. I can not explain why, but for some reason I do not expect any infinite loops or zeno-type-problems. I would rather expect that even frontal collisions of very heavy boxes with very light boxes, where the light box is trapped between the heavy box and the wall, end in finitely many steps. This is what makes the rigid bodies rigid, I think one should just accept this as a feature.
Related
If I have two instances called block1 and block2. And they move off the stage. It scrolls down the y position and it respawns back on top. But I don't want the x/y position colliding with the other blocks? I want it to respawn back to position, but I want it randomized but at the same time I don't want it touching each other?
Heres my code:
if (block1.y > stage.stageHeight)
{
block1.y = -550;
block1.x = (Math.floor(Math.random() * (maxNum - minNum + 5)) + minNum);
}
I'm pretty sure I'm calculating the respawn coordinates the wrong way, but I'm not sure how to put it in a random x and y position without colliding with other blocks.
A very simple method can be just to spawn your box, do a collision check, then if collision, remove and respawn and recheck until you find an empty spot where it fits
This is obviously quite inefficient, but is pretty simple to implement quickly if you have some sort of collision detection already working. Keep in mind if there is no spot that it can fit in, then it'll loop forever so you may want to set a max try count or something of that sort.
How fast/well it'll actually work will depend on if the spawn area is pretty sparse or pretty dense, which will increase/decrease the percentage that it'll find a good empty spot the first few times.
There is some room for improvement, going down this path though, such as if your collision detection system gives a minimum translation vector, you could just move the new shape over and use that position to spawn.
Other simple methods could involve keeping track of known occupied positions and adjusting your random range to avoid those values.
I'm developing a cocos2d-x game (version 3.8). My game uses chipmunk physics and it has a static body that works like an interruptor. This interruptor is enabled when another body is over it. The interruptor is disabled when bodies separate each other.
I want to:
Moving body don't collision with interruptor. It has to cross interruptor with no bounce
I want to detect when moving body separates the interruptor
My first approach was implementing onContactBegin method. I return false when those two bodies get in touch. This way the body crosses the interruptor and does not bounce.
The problem is onContactSeparate method is not called, because contact did not happen.
If I return true in onContactBegin method, onContactSeparate is called and I can detect it. The problem is the body does not cross the interruptor, it bounces.
[EDIT] More info
This is the scenario where two sprites are separated. The ball can move and interruptor is a static body. Ball could be over the interruptor.
This is the scenario where two sprites are in contact and object1 (the ball) is over the interruptor. I want to detect where two sprites separate each other.
Any help would be appreciated!
It seems to me like you are using Box2D within cocos, so I'll answer with that as my base assumption.
This is what i would do.
My interrupter would be a b2Body* with no BodyDef dimensions defined or just a 0x0 dimension def.
I would set the user data for the bodyDef to a rectangle that describes my interruption area. This way you can always have your interruption area represented, but will not collide with anything.
(Optional) If you want the interruption area to move around based on the fake body you assigned to it, you can updated it just after the step function using something like below.
world->Step(delta, 10, 10);
for (auto physicsBody = _world->GetBodyList(); physicsBody; physicsBody = physicsBody->GetNext())
{
auto userData = static_cast<Node*>(physicsBody->GetUserData());
if(userData != NULL)
{
// Set interruptor area rectangle = physicsBody->GetPosition();
}
}
To let the rest of the system know when I have left the interrupter I would store a function pointer to the function I want to call when this happens, When a object enters the interruption area I would flag it saying "I'm in the area" after that, the first update step you get when it's not in the area anymore I would fire the callback and reset the flags I used to get to that point.
I hope this helps. You are not giving a lot of context for what you want to do, an image would be helpful. Especially when it comes to looking for help with code that has a visual representation as well.
[EDIT]
Based on the behaviour you want this is the way I did this. The first thing to know is that you don't need physics collisions for the behaviour you want. You can do this by using bounding box intersection tests and use flags and callbacks to figure out the rest.
I have an object that knows about both the ball and my interrupter nodes. In the update loop of this object I check if the two intersects. I set a flag indicating "I am in the interrupter", the next frame that I am not in the interrupter and my flag is still true I call the function that I assigned with my "leaving logic" in it, and set then flag back to false.
I have a car object, and I want it to gradually rotate to the direction where the user clicked.
Every frame I did math to calculate the new direction it needs, and it's stored at car.direction. The actual direction is of course in car.rotation.
Now I want to update the rotation every frame until it's equal to the direction. However I tried everything and can't figure out how to do that.
By the way, I'm using FireFly, that is a gameengine built on top of Starling Framework, But I don't think it's relevant.
I would go with Marty's suggestion, use the smallestAngle function to determine which direction you should be rotating. Basically you can move some percentage of the smallestAngle during every frame update until the percentage of that smallestAngle is below some threshold (and have it "snap" the rest of the way).
Something like
//each time this is called it will get 1/4 closer, but never get to 0, hence the need for a threshold avoid paradoxes
//http://en.wikipedia.org/wiki/Zeno's_paradoxes#Dichotomy_paradox
var angleToMove:Number = smallestAngle()/4; //the divide by 4 here means get 1/4 of the angle gap closer each time this function is called, I assume this is on a timer or frame handler, making the 4 greater will make it follow more slowly, making it lower will make it follow more quickly, never reduce to or below 0 unless you want wonkiness
if(angleToMove<someRadianThreshold)
angleToMove = smallestAngle();
//use angleToMove to adjust the current heading/rotation
I am using starling and tweenMax frameworks in my project.
The trouble I am running into is this:
For the purpose of animating along different paths, I am using tweenmax.
There is one _leaderEnemy that animates along a path and I am pushing several other _shooterEnemy (they are of the same class) into it.
public function createEnemies(enemyNo:int, path:Array, offset:int):void
{
for(var i:uint=1;i<=enemyNo;i++){
if (i==1){
_leaderCount++;
_leaderEnemy = new ShooterEnemy();
_leaderEnemy.x=600;
_leaderEnemy.y=300;
_leaderEnemy.name="_shooterEnemy"+_leaderCount;
this.addChild(_leaderEnemy);
leaderEnemyArray.push(_leaderEnemy);
}
else
{
_leaderCount++;
_shooterEnemy= new ShooterEnemy();
_shooterEnemy.x=0;
_shooterEnemy.y=(offset*(i-1));
_shooterEnemy.name="_shooterEnemy"+_leaderCount;
trace("no: "+_shooterEnemy.name);
leaderEnemyArray.push(_shooterEnemy);
_leaderEnemy.addChild(_shooterEnemy);
}
}
Now I want to check for collision using starling between each of the _leaderEnemy and the _shooterEnemy inside it with _shooterHero.
Running this array successfully checks collision with the whole group i.e. _leaderEnemy but not the individual ones inside it.
Technically, I should be able to do this just by:
var Track:Object;
for(var i:uint=0;i<leaderEnemyArray.length;i++) {
Track=leaderEnemyArray[i];
if (Track.bounds.intersects(_shooterHero.bounds)){
Track.rotation=deg2rad(70);
}
}
It may be something stupid I am doing. But I have not been able to solve this.
Any help on this would be appreciated.
Some other questions I have:
Can I check for collision with _shooterHero from inside the _shooterEnemy's class?
I have tried:
if (this.bounds.intersects(stage.getChildByName("_hero"))){
}
although it did not work.
Can I check for collision of one Enemy with everything on stage, so I can assign individual functions for his each contact?
For example: hit with hero: die; hit with another enemy: turn around
If you need more info, I will be happy to provide it.
Thank You.
Can I check for collision of one Enemy with everything on stage, so I can assign individual functions for his each contact? For example: hit with hero: die; hit with another enemy: turn around
Of course you can. You should! This is approximatively how collision engines works.
Running this array successfully checks collision with the whole group i.e. _leaderEnemy but not the individual ones inside it.
Nope. It won't work. Because the bounds property use the parent coordinates.
Meaning you can intersect each child display (of same container) with each other.
But you shouldn't intersect a child display of A with a child display of B.
Except if you convert every bounds coordinates (which are local) to global.
http://doc.starling-framework.org/core/starling/display/DisplayObject.html#localToGlobal()
Using Track.bounds.intersects is one way of checking collosions. Another would be to use hitTest method of starling.displayDisplayObject
You could also check the distance of your hero and other enemies calculated by a pythagorean theorem type calculation.
Are you checking enemies against each other? If you have many enemies you might want to look into "flocking" algorithms. Keith Petes covers this subject nicely in his book Advanced Actionscript Animation.
I need to do an endless horizontal scroll of elements within a parent MovieClip.
No matter what ever method I try, an element of 'drift' occurs and eventually the elements start to overlap.
I've tried using relative recursive tweening for each element according
but this method seems prone to quite a bit of error after repeated starts and stops.
//CODE START
function doScroll():void {
TweenLite.to(this, .25, {x:"20", ease:Linear.easeNone,onUpdate:checkPos,onComplete:doScroll});
}
//CODE END
I've reverted to doing absolute tweens to a predefined position using a contant speed. This seems to be more accurate but still some 'drift' occurs.
//CODE START
//_dest is predefined
var speed:Number = 500;
var dist:Number = this.x - _dest;
var distAbs:Number = dist < 0 ? -dist : dist;
//kludge to get constant velocity by recalculating time every frame
_time = distAbs / speed;
TweenLite.to(this, _time, {x:_dest, ease:Linear.easeNone,onComplete:reset});
//CODE END
Thought this should be very simple.
Can anyone point me to any possible tutorials or make any suggestions?
Any help appreciated.
Solution/Discussion at http://forums.greensock.com/viewtopic.php?f=1&t=6800
(warning: this is gonna require a rather lengthy explanation...)
It's a logic problem in your code. In your onUpdate, you were running conditional logic such that if the x position is beyond 980, it kills the tween and moves x back to -980 and starts things over. You're doing that for each individual item, each of which begins at a different position. That initial position affects when it crosses that threshold, thus when they reposition, the offsets are different.
For example, let's say item1 starts at an x position of 0 and item2 starts at 490 and both start moving at 400 pixels per second and your frame rate is 60, thus they'll move 6.66666 pixels per frame. Item1 will take 147 frames to hit 980. However, item2 will take 74 frames (actually 73.5, but there's no such thing as a half-frame) to cross the 980 threshold, but when it does so it will be at an x position of 983.333333. At that point it jumps back to -980 due to your conditional logic, but notice that it traveled an EXTRA 3.333333 pixels. You intended Item1 and item2 to travel at the exact same velocities and they do during the tween, but your onUpdate logic is misaligning them on the reposition such that in the end, some are traveling more than others which affects their overall velocity.
Another issue has to do with the fact that Flash rounds x/y coordinates of DisplayObjects to the nearest 0.05. So when you do your manual reposition (wrap), small rounding errors creep in. For example, let's say TweenLite sets the exact x value to 980.799. Flash will actually round that to 980.75. Then when you reposition it like this.x -= 980 and then tween it, the value would have just lost almost 0.05 pixels on that round. Do that many times and it can add up to a half-pixel or whole pixel (or more). All your items are crossing the threshold at slightly different spots, thus the rounding errors aren't the same, thus you start seeing slight variances in the spacing. Again, this is NOT an issue with the tweening engine. You'll see that the engine itself sets the values correctly, but Flash rounds them internally when applied to DisplayObjects.
A solution was posted at http://forums.greensock.com/viewtopic.php?f=1&t=6800 that includes an FLA and support files.
As others have suggested, I'd recommend having a single chunk of code that manages ALL the items that you're aligning/scrolling. It would lay things out from a single reference point so that everything lines up perfectly every time. You could tween a getter/setter that applies the logic. I use that technique all the time and it works great. You can see a smaller-scale example in the code I attached in the above URL (the scrollX getter/setter in ItemBase.as)
If you will be tweening all background elements at the same rate indefinitely on a single dimension - why not use a Timer and bypass tweening libraries entirely?