void PhysicsBody::setMass(float mass) { if (mass <= 0) { return; } int oldMass = _mass; _mass = mass; _massDefault = false; // update density if (_mass == PHYSICS_INFINITY) { _density = PHYSICS_INFINITY; } else { if (_area > 0) { _density = _mass / _area; }else { _density = 0; } } // the static body's mass and moment is always infinity if (_dynamic) { updateMass(oldMass, _mass); } }
// This must be called at the start of every loop. void movementStart() { // Setting motion data: api.getMyZRState(ZRState); //api.getOtherZRState(OZRState); for (int i = 0; i < 3; i++) { position[i] = ZRState[i]; velocity[i] = ZRState[i + 3]; } mathVecSubtract(acceleration, velocity, lastVelocity, 3); updateMass(); lastForceMagnitude = 0.f; // Very important in mass calculation [Positioning in loop included]. }
ZPunctum::ZPunctum() : m_score(1.0) { setColor(255, 255, 0, 255); setX(-1); setY(-1); setZ(-1); setRadius(2.0); setMaxIntensity(255); setMeanIntensity(255); setSDevOfIntensity(0); updateVolSize(); updateMass(); }
ZPunctum::ZPunctum(double x, double y, double z, double r) : m_score(1.0) { setColor(255, 255, 0, 255); setX(x); setY(y); setZ(z); setRadius(r); setMaxIntensity(255); setMeanIntensity(255); setSDevOfIntensity(0); updateVolSize(); updateMass(); }
void PhysicsBody::addMass(float mass) { float oldMass = _mass; if (mass == PHYSICS_INFINITY) { _mass = PHYSICS_INFINITY; _massDefault = false; _density = PHYSICS_INFINITY; } else if (mass == -PHYSICS_INFINITY) { return; } else { if (_massDefault) { _mass = 0; _massDefault = false; } if (_mass + mass > 0) { _mass += mass; }else { _mass = MASS_DEFAULT; _massDefault = true; } if (_area > 0) { _density = _mass / _area; } else { _density = 0; } } // the static body's mass and moment is always infinity if (_dynamic) { updateMass(oldMass, _mass); } }
void ColaMintBottle::setBottleStatus(BottleStatus aNewStat) { switch (aNewStat) { case UNTRIGGERED: // allow to set arbitrary 'volume' of the fluid in the bottle // it doesn't afffect the size, though - magic :-D theProps.property2Float(Property::MASS_STRING, &theColaAmount); updateMass(); theSplatterCount = 0; theBottleStatus = UNTRIGGERED; break; case TRIGGERED: theBottleStatus = TRIGGERED; theCountdown = 100; break; case BLOWING: theBottleStatus = BLOWING; break; case EMPTY: theBottleStatus = EMPTY; break; } }
void ColaMintBottle::newSplatter(unsigned int aSequenceNr) { // the first splatter is to reach 1.5m height, improving to 2.5m with the 20th // then deteriorating quickly - until none left // // for simplicity, we assume that a horizontal bottle has the same // exit velocity and such... // // the opening exit velocity can be calculated using energy: m*g*h = 0.5*m*v*v // i.e. v = sqrt(2*g*h) <- note that the mass of the splatter is not in there // so we need a 2nd order equation that starts at (0, 1.5), reaches (20,2.5) // and then decays until (40, 1.5) again. // then we use a linear equation for the remainder // // h=height, n=splatternumber // i.e. h = -1/400*n*n + 1/10*n + 1.5 // and from 40 onwards: // h = 1.5 - 3*(n-40)/220 // // TODO/FIXME: there is a discontinuity in h' - that can be fixed by calculating // the point where the extension of h' goes through (150,0) -> for later :-) std::shared_ptr<ColaSplatter> mySplatterPtr = ObjectFactory::createChildObject<ColaSplatter>(); // Start position for the splatter is above the opening: // i.e. (0, +0.59*object height). The magic number 0.59 is "slightly more than 1/2"... // I figured out the number by experiment const qreal SPLATTER_START = 0.60; Position myStartPos = getTempCenter(); myStartPos = myStartPos + Vector(0, SPLATTER_START * getTheHeight()); // we need this 90 degrees because the bottle is modelled vertical, // not horizontal myStartPos.angle += PI / 2.0; // departure velocity qreal myH; if (aSequenceNr < 40) myH = (-1 / 400) * aSequenceNr * aSequenceNr + 0.1 * aSequenceNr + 1.5; else myH = 1.5 - 3 * (aSequenceNr - 40) / 220; // if the expected height is less than 0, we're no longer blowing if (myH < 0.0) return; // note: hardcoded constant for G here, because we're using constants from the // normal world to calculate it - not related to the G in a alternative world. // (otherwise, the cola bottle would blow as high on the moon as on earth) qreal myV = sqrt(2.0 * 9.81 * myH); const qreal mySplatterMass = 0.015; mySplatterPtr->setAll(myStartPos, myV, mySplatterMass); theWorldPtr->addObject(mySplatterPtr); theColaAmount -= mySplatterMass; updateMass(); // Small HACK :-) // if we're out-of-bounds, let's misuse the thrust to limit the velocity... // this will have two effects: // 1) the last splatter (giving impulse to a nearly-empty bottle) won't work // 2) and using thrust in the wrong direction actually limits speed! if (myStartPos.x > 1.4 * theWorldPtr->getTheWorldWidth() || myStartPos.y > 1.4 * theWorldPtr->getTheWorldHeight()) { if (theThrust > 0) theThrust = - 0.7; } // and don't forget Newton's action = -reaction !!! qreal myImpulse = mySplatterMass * myV; // HACK HACK HACK: to improve the "feeling", we help the impulse a bit here... // The Thrust is actually adjustable as a property // - default is 2.0 (see createPhysicsObject()). qreal myAngle = getTempCenter().angle; Vector myImpulseVector = -theThrust * Vector(-myImpulse * sin(myAngle), myImpulse * cos(myAngle)); theB2BodyPtr->ApplyLinearImpulse(myImpulseVector.toB2Vec2(), myStartPos.toB2Vec2(), true); }