void Projectile::orient(b2Vec2 target) { float bodyAngle = body_->GetAngle(); float desiredAngle = atan2f(-target.x, target.y); float nextAngle = body_->GetAngle() + body_->GetAngularVelocity() / _TICKTIME_; float totalRotation = desiredAngle - bodyAngle; while (totalRotation < M_PI) totalRotation += 2 * M_PI; while (totalRotation > M_PI) totalRotation -= 2 * M_PI; float change = 10 * DR; //allow 20 degree rotation per time step float newAngle = bodyAngle + std::min(change, std::max(-change, totalRotation)); float vel = body_->GetLinearVelocity().Length(); b2Vec2 newVel(vel * cos(newAngle), vel * sin(newAngle)); //body_->SetLinearVelocity(newVel); //body_->SetTransform(body_->GetPosition(), newAngle); //vx = magnitude * cos(angle) //vy = magnitude * sin(angle) }
// --------------------------------------------------------------- // advance solution by one timestep // return max safe timestep Real AMRNavierStokes::advance() { if (s_verbosity >= 2) { pout () << "AMRNavierStokes::advance " << m_level << ", starting time = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << m_time << ", dt = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << dt() << endl; } #ifdef DEBUG // if we're at the beginning of a composite timestep, // save current multilevel state if (m_level == 0) { AMRNavierStokes* levelPtr = this; // figure out finest level while (!levelPtr->finestLevel()) { levelPtr = levelPtr->finerNSPtr(); } int finest_level = levelPtr->m_level; levelPtr = this; for (int lev=0; lev<= finest_level; lev++) { levelPtr->m_saved_time = m_time; levelPtr->newVel().copyTo(levelPtr->newVel().interval(), *levelPtr->m_vel_save_ptr, levelPtr->m_vel_save_ptr->interval()); levelPtr->newLambda().copyTo(levelPtr->newLambda().interval(), *levelPtr->m_lambda_save_ptr, levelPtr->m_lambda_save_ptr->interval()); for (int comp=0; comp<s_num_scal_comps; comp++) { levelPtr->newScal(comp).copyTo(levelPtr->newScal(comp).interval(), *levelPtr->m_scal_save[comp], levelPtr->m_scal_save[comp]->interval()); } levelPtr = levelPtr->finerNSPtr(); } } #endif Real old_time = m_time; Real new_time = m_time + m_dt; m_dt_save = m_dt; swapOldAndNewStates(); const DisjointBoxLayout levelGrids = newVel().getBoxes(); // initialize flux registers if (!finestLevel()) { m_flux_register.setToZero(); for (int comp=0; comp<s_num_scal_comps; comp++) { m_scal_fluxreg_ptrs[comp]->setToZero(); } m_lambda_flux_reg.setToZero(); } // compute advection velocities -- if we're using the // patchGodunov approach, these will have ghost cells. IntVect advVelGhost(IntVect::Unit); LevelData<FluxBox> advectionVel(levelGrids, 1, advVelGhost); if (s_set_bogus_values) { setValLevel(advectionVel, s_bogus_value); } computeAdvectionVelocities(advectionVel); // now that advection velocities have been computed, // update advected scalars // do scalar boundary conditions on lambda // (also grow to appropriate size) LevelData<FArrayBox> lambdaTemp; fillLambda(lambdaTemp, old_time); LevelFluxRegister* crseLambdaFluxRegPtr = NULL; if (m_level > 0) { crseLambdaFluxRegPtr = &(crseNSPtr()->m_lambda_flux_reg); } advectScalar(newLambda(), lambdaTemp, advectionVel, crseLambdaFluxRegPtr, m_lambda_flux_reg, m_patchGodLambda, m_dt); // now do advected-diffused scalars if (s_num_scal_comps > 0) { // loop over scalar components for (int comp=0; comp<s_num_scal_comps; comp++) { BCHolder scalPhysBCs = m_physBCPtr->scalarTraceFuncBC(comp); LevelData<FArrayBox> scalarTemp; fillScalars(scalarTemp, old_time,comp); // now get coarse-level scalars for BC's if necessary LevelData<FArrayBox>* newCrseScalPtr = NULL; LevelData<FArrayBox>* oldCrseScalPtr = NULL; Real oldCrseTime = -s_bogus_value; Real newCrseTime = s_bogus_value; LevelFluxRegister* crseScalFluxRegPtr = NULL; if (m_level > 0) { newCrseScalPtr = &(crseNSPtr()->newScal(comp)); oldCrseScalPtr = &(crseNSPtr()->oldScal(comp)); newCrseTime = crseNSPtr()->time(); oldCrseTime = newCrseTime - crseNSPtr()->dt(); crseScalFluxRegPtr = (crseNSPtr()->m_scal_fluxreg_ptrs[comp]); } advectDiffuseScalar(newScal(comp), scalarTemp, advectionVel, s_scal_coeffs[comp], oldCrseScalPtr, newCrseScalPtr, oldCrseTime, newCrseTime, crseScalFluxRegPtr, *(m_scal_fluxreg_ptrs[comp]), *(m_patchGodScalars[comp]), scalPhysBCs, m_dt, comp); } // end loop over components } // end advected-diffused scalars // now predict velocities -- this returns the advection term // put this in "new_vel" LevelData<FArrayBox>& uStar = newVel(); predictVelocities(uStar, advectionVel); computeUStar(uStar); // if a coarser level exists, will need coarse-level data for proj LevelData<FArrayBox>* crseVelPtr = NULL; if (m_level > 0) { const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes(); crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim); // coarse velocity BC data is interpolated in time crseNSPtr()->fillVelocity(*crseVelPtr, new_time); } // need to do physical boundary conditions and exchanges bool isViscous = (s_nu > 0); VelBCHolder velBC(m_physBCPtr->uStarFuncBC(isViscous)); velBC.applyBCs(uStar, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // noel -- all time in level project m_projection.LevelProject(uStar, crseVelPtr, new_time, m_dt); // as things stand now, physical BC's are re-set in LevelProjection // compute maximum safe timestep for next iteration Real newDt = computeDt(); // clean up temp storage if (crseVelPtr != NULL) { delete crseVelPtr; crseVelPtr = NULL; } ++m_level_steps; if (s_verbosity >= 2) { pout () << "AMRNavierStokes::advance " << m_level << ", end time = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << m_time << ", dt = " << setiosflags(ios::fixed) << setprecision(6) << setw(12) << dt() << endl; } return newDt; }
// --------------------------------------------------------------- void AMRNavierStokes::computeAdvectionVelocities(LevelData<FluxBox>& a_advVel) { if (s_verbosity >= 3) { pout() << "AMRNavierStokes::computeAdvectionVelocities: " << m_level << endl; } bool isViscous = (s_nu > 0.0); const DisjointBoxLayout& levelGrids = newVel().getBoxes(); /// need to build grown grids to get be able to do all of /// tracing properly IntVect advect_grow(D_DECL(ADVECT_GROW, ADVECT_GROW, ADVECT_GROW)); LevelData<FArrayBox> old_vel(levelGrids, SpaceDim, advect_grow); LevelData<FArrayBox> viscousSource(levelGrids, SpaceDim, advect_grow); LevelData<FArrayBox>* crseVelPtr = NULL; if (s_set_bogus_values) { setValLevel(old_vel, s_bogus_value); setValLevel(viscousSource, s_bogus_value); } // m_time contains the time at which the new state is centered Real old_time = m_time - m_dt; fillVelocity(old_vel, old_time); // set physical boundary conditions here // set physical boundary conditions on velocity if (isViscous) { LevelData<FArrayBox> viscousVel(levelGrids, SpaceDim, advect_grow); DataIterator dit = viscousVel.dataIterator(); // rather than resetting BC's on old_vel, and then setting them // back, just copy old_vel to a temporary holder, and set // BCs on that one. for (dit.begin(); dit.ok(); ++dit) { viscousVel[dit].copy(old_vel[dit]); } VelBCHolder velBC(m_physBCPtr->viscousVelFuncBC()); velBC.applyBCs(viscousVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // if crse level exists, fill coarse velocity BC if (m_level > 0) { const DisjointBoxLayout& crseGrids = crseNSPtr()->newVel().getBoxes(); crseVelPtr = new LevelData<FArrayBox>(crseGrids, SpaceDim); crseNSPtr()->fillVelocity(*crseVelPtr, old_time); } computeLapVel(viscousSource, viscousVel, crseVelPtr); for (dit.reset(); dit.ok(); ++dit) { viscousSource[dit].mult(s_nu); } } else { setValLevel(viscousSource, 0.0); } // tracing will use inviscid BC's { VelBCHolder velBC(m_physBCPtr->tracingVelFuncBC()); velBC.applyBCs(old_vel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous } // call utility function to do tracing traceAdvectionVel(a_advVel, old_vel, viscousSource, m_patchGodVelocity, old_time, m_dt); EdgeVelBCHolder edgeVelBC(m_physBCPtr->advectionVelFuncBC(isViscous)); edgeVelBC.applyBCs(a_advVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // noel levelMacProject is big guy // now MAC project m_projection.levelMacProject(a_advVel, old_time, m_dt); // finally, add volume discrepancy correction if (m_projection.etaLambda() > 0 && s_applyFreestreamCorrection) { LevelData<FluxBox>& grad_e_Lambda = m_projection.grad_eLambda(); DataIterator dit = levelGrids.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { FluxBox& thisGrad_eLambda = grad_e_Lambda[dit]; FluxBox& thisAdvVel = a_advVel[dit]; for (int dir=0; dir<SpaceDim; dir++) { thisAdvVel[dir] += thisGrad_eLambda[dir]; } } } edgeVelBC.applyBCs(a_advVel, levelGrids, m_problem_domain, m_dx, false); // inhomogeneous // clean up storage if (crseVelPtr != NULL) { delete crseVelPtr; crseVelPtr = NULL; } }
void GWaker::runEvent(const Particle& part, const double dt) const { GlobalEvent iEvent(getEvent(part)); iEvent.setdt(dt); //We only trust the schedulers time, as we don't //track the motion of the system in Globals #ifdef DYNAMO_DEBUG if (boost::math::isnan(iEvent.getdt())) M_throw() << "A NAN Interaction collision time has been found" << iEvent.stringData(Sim); if (iEvent.getdt() == HUGE_VAL) M_throw() << "An infinite Interaction (not marked as NONE) collision time has been found\n" << iEvent.stringData(Sim); #endif Sim->dSysTime += iEvent.getdt(); Sim->ptrScheduler->stream(iEvent.getdt()); Sim->dynamics.stream(iEvent.getdt()); Sim->dynamics.getLiouvillean().updateParticle(part); //Here is where the particle goes to sleep or wakes ++Sim->eventCount; _neighbors = 0; //Add the interaction events Sim->ptrScheduler->getParticleNeighbourhood(part, magnet::function::MakeDelegate(this, &GWaker::nblistCallback)); // if (_neighbors < 10) // { iEvent.addTime(Sim->freestreamAcc); Sim->freestreamAcc = 0; ParticleEventData EDat(part, Sim->dynamics.getSpecies(part), iEvent.getType()); Vector newVel(Sim->normal_sampler(),Sim->normal_sampler(),Sim->normal_sampler()); newVel *= _wakeVelocity / newVel.nrm(); const_cast<Particle&>(part).getVelocity() = newVel; const_cast<Particle&>(part).setState(Particle::DYNAMIC); EDat.setDeltaKE(0.5 * EDat.getSpecies().getMass(part.getID()) * (part.getVelocity().nrm2() - EDat.getOldVel().nrm2())); Sim->signalParticleUpdate(EDat); BOOST_FOREACH(shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, EDat); // } // else // Sim->freestreamAcc += iEvent.getdt(); //Now we're past the event, update the scheduler and plugins Sim->ptrScheduler->fullUpdate(part); }
// ----------------------------------------------------------------------------- // This does the actual computation to update the state variables. // I've included this function since the initializeGlobalPressure() and advance() // functions are, for the most part, the same piece of code. // ----------------------------------------------------------------------------- void AMRNavierStokes::PPMIGTimeStep (const Real a_oldTime, const Real a_dt, const bool a_updatePassiveScalars, const bool a_doLevelProj) { CH_TIME("AMRNavierStokes::PPMIGTimeStep"); pout() << setiosflags(ios::scientific) << setprecision(8) << flush; // Set up some basic values const RealVect& dx = m_levGeoPtr->getDx(); const DisjointBoxLayout& grids = newVel().getBoxes(); DataIterator dit = grids.dataIterator(); const Box domainBox = m_problem_domain.domainBox(); const bool isViscous = (s_nu > 0.0); // Initialize all flux registers if (!finestLevel()) { m_vel_flux_reg.setToZero(); for (int comp = 0; comp < s_num_scal_comps; ++comp) { m_scal_fluxreg_ptrs[comp]->setToZero(); } m_lambda_flux_reg.setToZero(); } // Sanity checks CH_assert(m_levGeoPtr->getBoxes() == grids); CH_assert(m_levGeoPtr->getDomain() == m_problem_domain); CH_assert(Abs(a_oldTime - (m_time - a_dt)) < TIME_EPS); CH_assert(s_num_scal_comps <= 1); CH_assert(s_num_scal_comps > 0 || s_gravityMethod == ProblemContext::GravityMethod::NONE); // Reference new holders LevelData<FArrayBox>& new_vel = newVel(); LevelData<FArrayBox>& new_lambda = newLambda(); LevelData<FArrayBox> new_b; if (s_num_scal_comps > 0) { aliasLevelData(new_b, &(newScal(0)), Interval(0,0)); } // Compute advecting velocities LevelData<FArrayBox> old_vel(grids, SpaceDim, m_tracingGhosts); fillVelocity(old_vel, a_oldTime); old_vel.exchange(m_tracingExCopier); LevelData<FluxBox> adv_vel(grids, 1, IntVect::Unit); // Changed from m_tracingGhosts to 1 computeAdvectingVelocities(adv_vel, old_vel, a_oldTime, a_dt); if (a_updatePassiveScalars) { // Lambda update LevelData<FArrayBox> old_lambda; fillLambda(old_lambda, a_oldTime); old_lambda.exchange(m_tracingExCopier); LevelData<FArrayBox> dLdt(grids, 1); getNewLambda(dLdt, new_lambda, old_lambda, old_vel, adv_vel, a_oldTime, a_dt, a_dt); } LevelData<FArrayBox> old_b; if (s_num_scal_comps > 0) { // Scalar update fillScalars(old_b, a_oldTime, 0); old_b.exchange(m_tracingExCopier); LevelData<FArrayBox> dSdt(grids, 1); getNewScalar(dSdt, new_b, old_b, old_vel, adv_vel, a_oldTime, a_dt, a_dt, 0); } for (int comp = 1; comp < s_num_scal_comps; ++comp) { // Scalar update LevelData<FArrayBox> old_scal; fillScalars(old_scal, a_oldTime, comp); old_scal.exchange(m_tracingExCopier); LevelData<FArrayBox> dSdt(grids, 1); getNewScalar(dSdt, newScal(comp), old_scal, old_vel, adv_vel, a_oldTime, a_dt, a_dt, comp); } { // Update CC velocities LevelData<FArrayBox> dUdt(grids, SpaceDim); getNewVelocity(dUdt, new_vel, old_vel, adv_vel, a_oldTime, a_dt, a_dt); } if (s_num_scal_comps > 0) { // Do implicit gravity update and CC projection. doCCIGProjection(new_vel, new_b, old_vel, old_b, adv_vel, a_oldTime, a_dt, a_doLevelProj); } else { // Do a standard CC projection. doCCProjection(new_vel, a_oldTime + a_dt, a_dt, a_doLevelProj); } }
/** * This method executes the action for the given frame of time. The dTime * parameter is the time elapsed since the last call. * * @param particleSystem The particle system on which to operate. * @param dTime Elapsed time in seconds. */ void CollidePSA::execute( ParticleSystem &particleSystem, float dTime ) { BW_GUARD; SourcePSA* pSource = static_cast<SourcePSA*>( &*particleSystem.pAction( PSA_SOURCE_TYPE_ID ) ); if ( !pSource ) return; RompColliderPtr pGS = pSource->groundSpecifier(); if ( !pGS ) return; uint64 tend = timestamp() + stampsPerSecond() / 2000; bool soundHit = false; float maxVelocity = 0; Vector3 soundPos; uint materialKind; Particles::iterator it = particleSystem.begin(); Particles::iterator end = particleSystem.end(); WorldTriangle tri; //bust out of the loop if we take more than 0.5 msec //Sprite particles don't calculate spin while ( it != end && timestamp()<tend ) { Particle &particle = *it++; if (!particle.isAlive()) { continue; } //note - particles get moved after actions. Vector3 velocity; particle.getVelocity(velocity); Vector3 pos; Vector3 newPos; if(particleSystem.isLocal()) { Matrix world = particleSystem.worldTransform(); pos = world.applyPoint(particle.position()); Vector3 nPos; particleSystem.predictPosition( particle, dTime, nPos ); newPos = world.applyPoint(nPos); } else { pos = particle.position(); particleSystem.predictPosition( particle, dTime, newPos ); } float tValue = pGS->collide( pos, newPos, tri ); if ( tValue >= 0.f && tValue <= 1.f ) { // calc v as a dotprod of the two normalised vectors (before and after collision) Vector3 oldVel = velocity / velocity.length(); tri.bounce( velocity, elasticity_ ); particle.setVelocity( velocity ); float newSpeed = velocity.length(); Vector3 newVel(velocity / newSpeed); float severity = oldVel.dotProduct(newVel); //DEBUG_MSG("severity: %1.3f, speed=%1.3f\n", severity, newSpeed); float v = (1 - severity) * newSpeed; //now spin the particle ( mesh only ) if ( !spriteBased_ ) { //first, calculate the current rotation, and update the pitch/yaw value. Matrix currentRot; currentRot.setRotate( particle.yaw(), particle.pitch(), 0.f ); Matrix spin; float spinSpeed = particle.meshSpinSpeed(); Vector3 meshSpinAxis = particle.meshSpinAxis(); // If there is no spin direction then creating a rotation // matrix can create weird matrices - e.g. matrices with // negative scale components and a translation. We choose the // velocity as the spin direction (aribitrarily choosing, for // example up looks weird). if (meshSpinAxis == Vector3::zero()) { meshSpinAxis = velocity; meshSpinAxis.normalise(); } D3DXMatrixRotationAxis ( &spin, &meshSpinAxis, spinSpeed * (particle.age()-particle.meshSpinAge()) ); currentRot.preMultiply( spin ); particle.pitch( currentRot.pitch() ); particle.yaw( currentRot.yaw() ); //now, reset the age of the spin particle.meshSpinAge( particle.age() ); //finally, update the spin ( stored in the particle's colour ) float addedSpin = unitRand() * (maxAddedRotation_-minAddedRotation_) + minAddedRotation_; addedSpin *= min( newSpeed, 1.f ); spinSpeed = Math::clamp( 0.f, spinSpeed + addedSpin, 1.f ); particle.meshSpinSpeed(spinSpeed); particle.meshSpinAxis(meshSpinAxis); } if ( soundEnabled_ && v > 0.5f ) { soundHit = true; if (v > maxVelocity) { maxVelocity = v; soundPos = particle.position(); materialKind = tri.materialKind(); } } } } if ( soundHit ) { SmartPointer < RompSound > rs = RompSound::getProvider(); if (rs) { if (!soundTag_.empty()) { rs->playParticleSound( soundTag_.c_str(), soundPos, maxVelocity, soundSrcIdx_, materialKind ); } } } }
// --------------------------------------------------------------- // tag cells for regridding void AMRNavierStokes::tagCells(IntVectSet & a_tags) { if (s_verbosity >= 3) { pout () << "AMRNavierStokes::tagCells " << m_level << endl; } IntVectSet local_tags; // create tags based on something or other // for now, don't do anything const DisjointBoxLayout& level_domain = newVel().getBoxes(); if (s_tag_vorticity) { LevelData<FArrayBox> vorticity; LevelData<FArrayBox> mag_vorticity; if (SpaceDim == 2) { vorticity.define(level_domain,1); } else if (SpaceDim == 3) { vorticity.define(level_domain,SpaceDim); mag_vorticity.define(level_domain,1); } computeVorticity(vorticity); Interval vortInterval(0,0); if (SpaceDim == 3) { vortInterval = Interval(0,SpaceDim-1); } Real tagLevel = norm(vorticity, vortInterval, 0); // Real tagLevel = 1.0; //tagLevel *= s_vort_factor/m_dx; // actually tag where vort*dx > s_vort_factor*max(vort) tagLevel = s_vort_factor/m_dx; if (tagLevel > 0) { // now tag where vorticity magnitude is greater than or equal // to tagLevel DataIterator dit = vorticity.dataIterator(); for (dit.reset(); dit.ok(); ++dit) { FArrayBox& vortFab = vorticity[dit]; // this only needs to be done in 3d... if (SpaceDim==3) { FArrayBox& magVortFab = mag_vorticity[dit]; FORT_MAGVECT(CHF_FRA1(magVortFab,0), CHF_CONST_FRA(vortFab), CHF_BOX(level_domain[dit])); } BoxIterator bit(vortFab.box()); for (bit.begin(); bit.ok(); ++bit) { const IntVect& iv = bit(); if (SpaceDim == 2) { if (abs(vortFab(iv)) >= tagLevel) { local_tags |= iv; } } else if (SpaceDim == 3) { FArrayBox& magVortFab = mag_vorticity[dit]; if (abs(magVortFab(iv)) >= tagLevel) { local_tags |= iv; } } // end if DIM=3 } // end loop over interior of box } // loop over grids } // if taglevel > 0 } // if tagging on vorticity a_tags = local_tags; }
void InputHandler::handlePlayerEvents() { if (!m_player) return; // check to see if mouse is hovering s_pos = gdata.toScreenPixels(m_player->getAbsolutePosition()); s_pos.y = gdata.window->getSize().y - s_pos.y; Vector2 d = gdata.mouse - s_pos; if (d.getMagnitude() <= (0.5 * WORLD_SCALE * gdata.zoom)) { if (!m_player->hover) { m_player->hover = true; m_player->shrink_thickness = m_player->circle.getOutlineThickness(); } } else { m_player->hover = false; } if (gdata.keys[KEY_MOUSE_RIGHT].isKeyPressed) { if (selecting && !launched) angle_lock = !angle_lock; } if (gdata.keys[sf::Keyboard::Space].isKeyPressed) { angle_snap = angle_snap == 1 ? 0 : 1; gdata.angle_snap = angle_snap; } if (gdata.keys[sf::Keyboard::F1].isKeyPressed) { gdata.show_help = !gdata.show_help; } if (gdata.keys[sf::Keyboard::C].isKeyPressed) { gdata.random_colors = !gdata.random_colors; } if (gdata.keys[KEY_MOUSE_LEFT].isKeyPressed) { if (!launched) { s_pos = gdata.toScreenPixels(m_player->getAbsolutePosition()); s_pos.y = gdata.window->getSize().y - s_pos.y; Vector2 d = gdata.mouse - s_pos; if (d.getMagnitude() <= (0.5 * WORLD_SCALE * gdata.zoom)) { selecting = true; m_player->shot = true; //power = 10; } } } if (gdata.keys[KEY_MOUSE_LEFT].isKeyDown) { if (selecting) { if (!angle_lock) { e_pos = gdata.mouse; // don't allow for zero velocity if (e_pos == s_pos) ++e_pos.y; vel = s_pos - e_pos; vel.setMagnitude(vel.getMagnitude()); if (vel.getMagnitude() > max_dist) vel.setMagnitude(max_dist); if (vel.getMagnitude() < min_dist) vel.setMagnitude(min_dist); float vel_percent = vel.getMagnitude() / max_dist; float speed = m_player->maxSpeed * vel_percent; vel.setMagnitude( speed ); if (angle_snap > 0) { float a = utils::roundNearest(vel.getAngle(),angle_snap); Vector2 newVel(speed,0); newVel.rotate(a); vel = newVel; } power = utils::roundNearest(vel_percent*100,1); angle = vel.getAngle(); m_player->angle = angle; m_player->power = power; } else { Vector2 m = s_pos - gdata.mouse; // don't change the angle just change the magnitude if (m.getMagnitude() > max_dist) vel.setMagnitude(max_dist); else if (m.getMagnitude() < min_dist) vel.setMagnitude(min_dist); else vel.setMagnitude(m.getMagnitude()); float vel_percent = vel.getMagnitude() / max_dist; vel.setMagnitude( m_player->maxSpeed * vel_percent ); power = utils::roundNearest(vel_percent*100,1); angle = vel.getAngle(); m_player->power = power; m_player->angle = angle; } } } if (gdata.keys[KEY_MOUSE_LEFT].isKeyReleased) { if (selecting && !launched) { m_player->shootPlayer(); //m_player->currentSpeed = vel.getMagnitude(); //m_player->trail.addPoint( m_player->getAbsolutePosition() ); //m_player->setLinearVelocity(vel); //m_player->trail.length = MAX_TAIL_LENGTH * (vel.getMagnitude() / m_player->maxSpeed); launched = true; selecting = false; gdata.last_angle = vel.getAngle(); gdata.first_shot = false; Vector2 dir(50,0); dir.rotate(vel.getAngle()); gdata.p1 = m_player->getAbsolutePosition(); gdata.p2 = gdata.p1 + dir; gdata.audio->playSound("shoot",true); // need to keep track for direction, speed and time BallShotData bsd(timer,vel.getAngle(),power); gdata.shotData.push_back(bsd); cout << "timer:" << timer << endl; } } }