Removing body (balls) from physics engine - famo.us

I've been trying to remove elements (balls) that have been added to the Physics engine, but I can't find a way to do it.
This is the code I'm using to add the molecules to the Physics Engine:
var numBodies = 15;
function _addMolecules() {
for (var i = 0; i < numBodies; i++) {
var radius = 20;
var molecule = new Surface({
size: [radius * 2, radius * 2],
properties: {
borderRadius: radius + 'px',
backgroundColor: '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6)
}
});
molecule.body = new Circle({
radius: radius,
mass: 2
});
this.pe.addBody(molecule.body);
this.molecules.push(molecule);
this.moleculeBodies.push(molecule.body);
molecule.state = new Modifier({origin: [0.5, 0.5]});
//** This is where I'm applying the gravity to the balls and also where I'm checking the position of each ball
molecule.state.transformFrom(addBodyTransform.bind(molecule.body));
this._add(molecule.state).add(molecule);
}
}
and on the addBodyTransform function I'm adding the gravity to the balls and checking their position, and for any that are outside the top part of the viewport I want to remove it completely (I'm only using walls on the left, right and bottom edges of the viewport).
function addBodyTransform() {
var pos;
for (var i = 0; i < thisObj.moleculeBodies.length; i++) {
pos = thisObj.moleculeBodies[i].getPosition();
if(pos[1]<(-windowY/2)){
//I tried this but it doesn't work
thisObj.pe.removeBody(thisObj.moleculeBodies[i]);
thisObj.moleculeBodies[i].render = function(){ return null; };
}
}
thisObj.gravity.applyForce(this);
return this.getTransform();
}
It doesn't work. I tried a couple of other things, but no luck. Whereas changing the position of the balls on the function above worked fine:
thisObj.moleculeBodies[i].setPosition([0, 0]);
Does anybody have any idea how to remove a body (a circle in this case)?
P.S.: thisObj is the variable I'm assign the "this" object to in the constructor function and thisObj.pe is the instance of the PhysicsEngine(). Hope that makes sense.

After some investigation, using the unminified source code and trying out different things, I realised that there was something weird going on in the library.
Having a look at the repository, I found out that the function _getBoundAgent is being used before it is defined, which matched with the error I was getting (you can check it here: https://travis-ci.org/Famous/physics). So it looks like it is a bug in the Famo.us source-code. Hopefully it will be fixed in the next release.
For the time being, I had to create a hack, which is basically detaching all agents (as well as gravity) from the balls that go outside the viewport and setting their (fixed) position far outside the viewport (about -2000px in both directions).
I know it is not the best approach (a dirty one indeed), but if you have the same problem and want to use it until they release a fix for that, here is what I did:
function addBodyTransform() {
var pos = this.body.getPosition();
//Check if balls are inside viewport
if(pos[1]<(-(windowY/2)-100)){
if(!this.removed){
//flagging ball so the code below is executed only once
this.removed = true;
//Set position (x and y) of the ball 2000px outside the viewport
this.body.setPosition([(-(windowX/2)-2000), (-(windowY/2)-2000)]);
}
return this.body.getTransform();
}else{
//Add gravity only if inside viewport
thisObj.gravity.applyForce(this.body);
return this.body.getTransform();
}
}
and on the _addMolecules function, I'm adding a "molecule.removed = false":
function _addMolecules() {
for (var i = 0; i < numBodies; i++) {
...
molecule.state = new Modifier({origin: [0.5, 0.5]});
//Flagging molecule so I know which ones are removed
molecule.removed = false;
molecule.state.transformFrom(addBodyTransform.bind(molecule));
this._add(molecule.state).add(molecule);
}
}
Again, I know it is not the best approach and I will be keen in hearing from someone with a better solution. :)

Related

OpenGL Collisions between 2 spheres sometimes not detected

For this project i use OpenGl.
I'm trying to detect the collision between two spheres, I think it's pretty simple.
It works but sometimes (very often actually...) the collision between these two spheres is not detected, and I really don't know why...
I tried to change the algorithm of detection and it allways ends by a non detection sometimes...
void MyGlWindow::checkMoverIsHit()
{
for (size_t i = 0; i < m_container->m_movers.size(); i++)
{
if (m_container->m_ball != m_container->m_movers[i]) {
float size = m_container->m_ball->m_size + m_container->m_movers[i]->m_size;
if (size >= (m_container->m_ball->m_position - m_container->m_movers[i]->m_position).magnitude())
{
score += 10;
m_container->m_movers.erase(std::remove(m_container->m_movers.begin(), m_container->m_movers.end(), m_container->m_movers[i]), m_container->m_movers.end());
for (size_t i = 0; i < (score / 10) + 1; i++)
createMover();
reload();
}
}
}
}
I call this function in my update function
void MyGlWindow::update()
{
TimingData::get().update();
if (!run) return;
float lastFrameDuration = (float)TimingData::get().lastFrameDuration;
float duration = lastFrameDuration * 0.003;
totalTimePrecise += lastFrameDuration;
totalTimeSec = totalTimePrecise / 1000;
if (totalTimeSec > 60) {
writeBestScoreInFile();
restart();
}
if (totalTimeSec == 40)
windBlowing = true;
if (duration <= 0.0f) return;
m_container->update(duration);
if (windBlowing == true)
m_container->windBlow();
checkBallDetachFromAnchor();
checkMoverIsHit(); // !!! ITS CALLED HERE !!!
m_world->runPhysics(duration);
}
m_container is my container of movers: it contains basically all the "movers" of my scene.
m_container->m_ball is a pointer of one of these movers. It's the ball I launched to "shoot" the other movers.
After I think everything is pretty clear, ask me if something is not.
Hope someone can help me... I've done everything in my project it's the only thing bugging !
Here is a GIF, the first ball worked, the second didn't:
I finally manage to find out what was happening.
The problem is that my world is avoiding collisions. What I mean by that is: when two objects collide, they automatically bounce against each other.
This behaviour was the problem because the goal of my hunting ball is to collide against the other objects so.... randomly... it was not detecting some collisions, because it was boucing.
To fix it, I removed from my hunting ball the fact that it was iteracting with the other movers of the scene. So now it's only checking in my function checkMoverIsHit(); if it's colliding with the other movers.
It now works perfectly.

Slowdown when loading the same SpriteFrame used in an animation in Cocos2dx

I am currently experiencing some heavy slowdowns with my game. I have narrowed it down to something related with texture animations.
In my game there are characters that walk in 1 of 4 possible directions, they will walk up to a point, then change direction and continue walking (sort of like a tower defense game).
First i am loading the sprite frame cache like this
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("characters.plist");
This code is only run once during the life time of my application.
When the characters get loaded to the screen their animation is being set using the following code:
int direction = 0;
int number = 0;
if (this->to_x < 0) // Left
{
direction = 1;
number = 1;
}
else if(this->to_x > 0) // Right
{
direction = 2;
number = 1;
}
if (this->to_y < 0) // Down
{
direction = 0;
number = 0;
}
else if(this->to_y > 0) // Up
{
direction = 3;
number = 2;
}
int s = 0; //skin
// Set the animation
Animation *animation = Animation::create();
for (int i = 0; i < INT16_MAX; i++)
{
string frame_sprite_name = StringUtils::format("%s_%d_%d_%d.png",parameters[name].image_name.c_str(),s,number,i);
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frame_sprite_name);
if (frame) {
animation->addSpriteFrame(frame);
} else {
break;
}
}
// Invert the sprite when they go right
if (direction == 2) {
setFlippedX(true);
}else{
setFlippedX(false);
}
// Set the pace of the animation based on the type
if (name=="runner") {
animation->setDelayPerUnit(0.15f);
} else{
animation->setDelayPerUnit(0.3f);
}
Animate *animate = Animate::create(animation);
this->stopAllActions();
this->runAction(RepeatForever::create(animate));
What this code does is:
Check the direction
Get the sprite frame from the cache based on the direction
Run the action with repeat forever.
However this code is ran every time they change direction to set the new animation of the active characters. Also, at one time I can have around 40-50 of these characters going around.
I've noticed that after a few minutes in the game the slowdown starts to happen as soon as a new "character" is created, (since they are created in rapid succession in waves). And the slowdown also happens when the characters change in direction. So this makes me believe I am using the textures wrong.
If anyone knows how to fix this please let me know.
PD: I was thinking about the possibility of pre-loading all the animations and then just having each of the sprites that represent the characters run the corresponding animation.
You should definitely cache the animation in the AnimationCache with addAnimation and getAnimation methods.

Raphael - How delay an animation with set elements

I'd like create an echo effect with many circles with smaller circle than the next one.
for(i=0; i<n; i++){
circle = paper.circle(...);
myset.push(circle);
}
Here's is an example that may do what you want, if not, there should be enough bits in it to show how you could. You don't really need a set, but you could add it if you want to do something with it later.
The animation element includes a delay parameter you can use, and then apply the animation to the shape.
var paper = Raphael("container"), myCircle, myAnimation;
myAnimation = Raphael.animation({r: 100, opacity: 1}, 3000, "linear", function() { this.remove() });
for( var c=1; c<10; c++ ) {
myCircle = paper.circle(10,10,10)
.attr("opacity", 0.2)
.animate( myAnimation.delay(c*300) );
}
With a working jsfiddle here... http://jsfiddle.net/9QmRe/9/

RaphaelJS hide shape onmouseout

I've created 4 rects using for loop. If you hover on any of these rects a rect will be displayed alongside. But the problem is that newly displayed rect doesn't hide on mouse out. What is wrong with my code?
JS Fiddle
window.onload = function() {
var paper = Raphael(0, 0, 640, 540);
function aa(h1,h2){
var showbox = paper.rect(h1+300,h2,100,100);
}
function ab(){
showbox.hide();
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
(function(i, j) {
var boxes = paper.rect(0 + (j * 100), 0 + (i * 100), 100, 100).attr({
fill: '#303030',
stroke: 'white'
});
boxes.node.onmouseover = function() {
var h1 = boxes.getBBox().x;
var h2 = boxes.getBBox().y;
aa(h1,h2);
};
boxes.node.onmouseout = function() {
ab();
};
})(i, j);
}
}
You've got javascript scope problems (plus two other smaller problems, see below).
The variable showbox is defined within function aa. So your onmouseout function can't see it. Get Firebug or your browser's equivalent up and you'll see a stack of showbox is not defined errors.
Tip: When working with Raphael, I usually create an object or array that contains all my created objects, keyed for easy access and scoped above all my Raphael-related functions so all of them can access it (see jsfiddle example below).
How to access your Raphael objects is a piece of application design you need to decide on early on, else you'll need to do lots of refactoring further down the line (been there, it hurts!).
Here's an adapted version of your code that works:
jsfiddle
Edit: I added comments explaining each change.
It also fixes two other problems:
(In the jsfiddle code) No such attr as display: none; in Raphael, try .attr({opacity:0}) or .hide()...
...BUT... don't! Your mouseover event creates rectangles, your mouseout event... hides them...? You're going to have an ever-growing stack of invisible rectangles that could eventually crash someone's browser. Either show, then hide, or create, then remove - don't create then hide!
The mouseover / mouseout events themselves are actually fine! :-)

3D rotation of a element in RaphaelJS

I am hoping you might be able to help me determine if the following animation is allowed in raphael.js. I am trying to have an element fly off the page, the idea is to have it appear to fall/fly off in 3D. I am able to tell the element to rotate X degrees and slide off but its lacking the look of the element being independent of hte background. What I would like to do is be able to tell raphael to rotate the top corner "out" as it falls giving the illusion of it falling out of view as picture falling off of a wall. Is this even possible or does Raphael only operate in two dimensional space?
Raphael only deals with 2D space. To implement a 3D flip you have to fake it. Thankfully Raphael implements Scale(sx,sy,x,y) as a transform op, so you can scale about an origin to fake a 3D 'flip' rotation.
For example:
Raphael.el.flipXTransform = function (parentBbox) {
var x = this.getBBox().x;
var width = this.getBBox().width;
parentBbox = parentBbox || { width:width, x: x};
var parentWidth = parentBbox.width;
var parentX = parentBbox.x;
var originX = parentX - x + parentWidth / 2;
return 's-1,1,' + originX + ',0';
};
Raphael.el.flipX = function (duration, easing, parentBbox) {
duration = duration || 500;
easing = easing || 'easeInOut';
var scale = this.flipXTransform(parentBbox);
this.animate({ transform: '...' + scale }, duration, easing);
};
Here's a fiddle example for you to play with. The downside is this doesn't convey a perspective like a true 3D rotate does.