MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // Define the scene scene = new Map(this); ui->graphicView->setScene(scene); ui->graphicView->setRenderHint(QPainter::Antialiasing); // Add tanks to this scene tank = new Tank(); scene->addItem(tank); // Set animation timer = new QTimer(this); connect(timer, SIGNAL(timeout()), scene, SLOT(advance())); timer->start(100); // Many connections... connect(scene, SIGNAL(toTarget(QPointF)), this, SLOT(moveTanks(QPointF))); }
Camera::Camera( const QVector3D & pos, const QVector3D & target, float fov,\ float zNear, float zFar, int width, int height ) : pos_( pos ) , dir_( DEFAULT_DIR_VEC ) , up_( DEFAULT_UP_VEC ) , side_( DEFAULT_SIDE_VEC ) , transform_() , fov_( fov ) , zNear_( zNear ) , zFar_( zFar ) , width_( width ) , height_( height ) , aspect_( 0.0f ) { computeAspect(); toTarget( target ); computeMatrix(); }
void loop() { api.getMyZRState(myState); time = api.getTime(); picNum = game.getMemoryFilled(); DEBUG(("%d picture(s) have been taken\n", picNum)); DEBUG(("STATE = %d\n",state)); DEBUG(("ARRAY = %d,%d,%d\n",goodPOI[0],goodPOI[1],goodPOI[2])); DEBUG(("TARGET = %f,%f,%f\n",target[0],target[1],target[2])); if(takePic > -1){ //takePic is used to make sure you take an accurate picture. takePic--; } if(time%60 == 0){ for(int i = 0; i < 3; i++){ goodPOI[i] = 1; } state = ST_GET_POI; } if((time > solarFlareBegin - 25)&&(time < solarFlareBegin)){ if((state < ST_SHADOW)||(state > ST_SHADOW + 9)){ state = ST_SHADOW; //if not in shadow state go there. } } else if(time == solarFlareBegin + 3){ state = ST_GET_POI + 1; } else if (game.getNextFlare() != -1) { solarFlareBegin = api.getTime() + game.getNextFlare(); DEBUG(("Next solar flare will occur at %ds.\n", solarFlareBegin)); } switch(state){ case ST_GET_POI: //POI selection closestPOI(goodPOI,POI,23); getPOILoc(POIproj, POIID, 23); takePic = 23; //25 probably needs to be changed. only good for the first cycle. DEBUG(("POI Coors = %f,%f,%f\n",POI[0],POI[1],POI[2])); state = ST_OUTER; break; case ST_GET_POI + 1: //if coming from shadow zone closestPOI(goodPOI,POI,30); getPOILoc(POIproj, POIID, 30); takePic = 30; //25 probably needs to be changed. only good for the first cycle. DEBUG(("POI Coors = %f,%f,%f\n",POI[0],POI[1],POI[2])); state = ST_OUTER; break; case ST_OUTER: //outer picture wp = false; //find closest place to take picture memcpy(target, POIproj, 3*sizeof(float)); //copy the projected POI location to target for(int i = 0; i < 3; i++){ target[i] *= 0.465/mathVecMagnitude(POI,3); //dilate target to outer zone } mathVecSubtract(facing,origin,target,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); if(pathToTarget(myState,target,waypoint)){ setWaypoint(waypoint,originalVecBetween); state = ST_OUTER + 1; for (int i = 0; i < 3; i++) tempTarget[i] = target[i]; } else{ state = ST_OUTER + 2; } break; case ST_OUTER + 1: //something is in the way so go to waypoint wp = true; mathVecSubtract(facing,POIproj,target,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); if(goToWaypoint(target,waypoint,tempTarget,originalVecBetween)){ goToWaypoint(target,waypoint,tempTarget,originalVecBetween); } else{ state = ST_OUTER + 2; } break; case ST_OUTER + 2://go to target mathVecSubtract(facing,origin,myState,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); toTarget(); if(takePic == 0){ game.takePic(POIID); } if(game.getMemoryFilled() > checkNum){ checkNum++; getPOILoc(POIproj, POIID, 5); state = ST_INNER; } break; case ST_INNER: //inner picture wp = false; memcpy(target, POIproj, 3*sizeof(float)); for(int i = 0; i < 3; i++){ target[i] *= 0.34/mathVecMagnitude(POI,3); } mathVecSubtract(facing,POIproj,target,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); haulAssTowardTarget(target,8); state = ST_INNER + 1; break; case ST_INNER + 1: //after outer picture is taken, rush to inner zone. mathVecSubtract(facing,POIproj,myState,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); if(distance(myState,target)<0.02){ haulAssTowardTarget(target,10); } else{ haulAssTowardTarget(target,2); } if(game.alignLine(POIID)){ game.takePic(POIID); } if(game.getMemoryFilled() > checkNum){ checkNum++; state = ST_UPLOAD; } break; case ST_SHADOW: //shadow zone wp = false; target[0] = 0.39; //arbitrary point in the shadow zone target[1] = 0.00; target[2] = 0.00; if(pathToTarget(myState,target,waypoint)){ setWaypoint(waypoint,originalVecBetween); goToWaypoint(target,waypoint,tempTarget,originalVecBetween); state = 31; } else{ state = 32; } break; case ST_SHADOW + 1: wp = true; if(goToWaypoint(target,waypoint,tempTarget,originalVecBetween)){ goToWaypoint(target,waypoint,tempTarget,originalVecBetween); } else{ toTarget(); state = 32; } break; case ST_SHADOW + 2: mathVecSubtract(facing,earth,myState,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); toTarget(); game.uploadPic(); break; case ST_UPLOAD: //upload, needs to be fixed for(int i = 0; i < 3; i++){ uploadPos[i] = myState[i] / mathVecMagnitude(myState, 3) * 0.65; } mathVecSubtract(facing,earth,uploadPos,3); mathVecNormalize(facing,3); api.setAttitudeTarget(facing); haulAssTowardTarget(uploadPos,1.8); state = ST_UPLOAD + 1; break; case ST_UPLOAD + 1: //get to the closest place, keep trying to upload api.setAttitudeTarget(facing); if(distance(myState,origin)>0.54){ api.setPositionTarget(myState); game.uploadPic(); } else{ if(distance(myState,origin)>0.51){ api.setPositionTarget(uploadPos); } else{ haulAssTowardTarget(uploadPos,1.8); } } if(picNum == 0){ DEBUG(("LOOKING FOR POI")); state = ST_GET_POI; } break; } }
void Bot::RegisterVisibleEnemies() { if(G_ISGHOSTING(self) || GS_MatchState() == MATCH_STATE_COUNTDOWN || GS_ShootingDisabled()) return; CheckIsInThinkFrame(__FUNCTION__); // Compute look dir before loop vec3_t lookDir; AngleVectors(self->s.angles, lookDir, nullptr, nullptr); float fov = 110.0f + 69.0f * Skill(); float dotFactor = cosf((float)DEG2RAD(fov / 2)); struct EntAndDistance { int entNum; float distance; EntAndDistance(int entNum_, float distance_): entNum(entNum_), distance(distance_) {} bool operator<(const EntAndDistance &that) const { return distance < that.distance; } }; // Do not call inPVS() and G_Visible() for potential targets inside a loop for all clients. // In worst case when all bots may see each other we get N^2 traces and PVS tests // First, select all candidate targets along with distance to a bot. // Then choose not more than BotBrain::maxTrackedEnemies nearest enemies for calling OnEnemyViewed() // It may cause data loss (far enemies may have higher logical priority), // but in a common good case (when there are few visible enemies) it preserves data, // and in the worst case mentioned above it does not act weird from player POV and prevents server hang up. // Note: non-client entities also may be candidate targets. StaticVector<EntAndDistance, MAX_EDICTS> candidateTargets; for (int i = 1; i < game.numentities; ++i) { edict_t *ent = game.edicts + i; if (botBrain.MayNotBeFeasibleEnemy(ent)) continue; // Reject targets quickly by fov Vec3 toTarget(ent->s.origin); toTarget -= self->s.origin; float squareDistance = toTarget.SquaredLength(); if (squareDistance < 1) continue; float invDistance = Q_RSqrt(squareDistance); toTarget *= invDistance; if (toTarget.Dot(lookDir) < dotFactor) continue; // It seams to be more instruction cache-friendly to just add an entity to a plain array // and sort it once after the loop instead of pushing an entity in a heap on each iteration candidateTargets.emplace_back(EntAndDistance(ENTNUM(ent), 1.0f / invDistance)); } std::sort(candidateTargets.begin(), candidateTargets.end()); // Select inPVS/visible targets first to aid instruction cache, do not call callbacks in loop StaticVector<edict_t *, MAX_CLIENTS> targetsInPVS; StaticVector<edict_t *, MAX_CLIENTS> visibleTargets; static_assert(AiBaseEnemyPool::MAX_TRACKED_ENEMIES <= MAX_CLIENTS, "targetsInPVS capacity may be exceeded"); for (int i = 0, end = std::min(candidateTargets.size(), botBrain.MaxTrackedEnemies()); i < end; ++i) { edict_t *ent = game.edicts + candidateTargets[i].entNum; if (trap_inPVS(self->s.origin, ent->s.origin)) targetsInPVS.push_back(ent); } for (auto ent: targetsInPVS) if (G_Visible(self, ent)) visibleTargets.push_back(ent); // Call bot brain callbacks on visible targets for (auto ent: visibleTargets) botBrain.OnEnemyViewed(ent); botBrain.AfterAllEnemiesViewed(); CheckAlertSpots(visibleTargets); }
//----------------------------------------------------------------------------- // Purpose: Give the buster a slight attraction to striders. // Ported back from the magnade. //----------------------------------------------------------------------------- void CWeaponStriderBuster::BusterFlyThink() { if (IsAttachedToStrider()) return; // early out. Think no more. // If we're nosediving, forget about magnetism. if ( m_bNoseDiving ) { if ( VPhysicsGetObject() ) VPhysicsGetObject()->ApplyForceCenter( Vector( 0, 0, striderbuster_dive_force.GetFloat() ) ); SetNextThink(gpGlobals->curtime + 0.01f); return; } // seek? const float magradius = 38.0 * sk_striderbuster_magnet_multiplier.GetFloat(); // radius of strider hull times multiplier if (magradius > 0 && GetMoveType() == MOVETYPE_VPHYSICS && VPhysicsGetObject() ) { // find the nearest enemy. CBaseEntity *pList[16]; Vector origin = GetAbsOrigin(); // do a find in box ( a little faster than sphere ) int count; { Vector mins,maxs; mins = origin; mins -= magradius; maxs = origin; maxs += magradius; count = UTIL_EntitiesInBox(pList, 16, mins, maxs, FL_NPC); } float magradiusSq = Square( magradius ); float nearestDistSq = magradiusSq + 1; int bestFit = -1; Vector toTarget(0.0f, 0.0f, 0.0f); // will be garbage unless something good is found CNPC_Strider *pBestStrider = NULL; for ( int ii = 0 ; ii < count ; ++ii ) { CNPC_Strider *pStrider = dynamic_cast<CNPC_Strider *>(pList[ii]); if ( pStrider && !pStrider->CarriedByDropship() ) // ShouldStickToEntity() doesn't work because the strider NPC isn't what we glue to { // get distance squared VectorSubtract( pStrider->GetAdjustedOrigin(), GetAbsOrigin(), toTarget ); //NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + toTarget, 128, 0, 128, false, 0.1 ); float dSq = toTarget.LengthSqr(); if (dSq < nearestDistSq) { bestFit = ii; nearestDistSq = dSq; pBestStrider = pStrider; } } } if (bestFit >= 0) // we found something and should attract towards it. (hysterisis later?) { if ( striderbuster_debugseek.GetBool() ) { NDebugOverlay::Circle( GetAbsOrigin() + toTarget, magradius, 255, 255, 255, 255, true, .1 ); NDebugOverlay::Cross3D( GetAbsOrigin() + toTarget, magradius, 255, 255, 255, true, .1 ); } // force magnitude. float magnitude = GetMass() * striderbuster_magnetic_force_strider.GetFloat(); int falloff = striderbuster_falloff_power.GetInt(); switch (falloff) { case 1: VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / nearestDistSq) ); // dividing through by distance squared normalizes toTarget and gives a linear falloff break; case 2: VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / (nearestDistSq * sqrtf(nearestDistSq))) ); // dividing through by distance cubed normalizes toTarget and gives a quadratic falloff break; case 3: VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / (nearestDistSq * nearestDistSq)) ); // dividing through by distance fourth normalizes toTarget and gives a cubic falloff break; case 4: { Vector toTarget; pBestStrider->GetAttachment( "buster_target", toTarget ); if ( striderbuster_debugseek.GetBool() ) { NDebugOverlay::Cross3D( toTarget, magradius, 255, 0, 255, true, .1 ); NDebugOverlay::Cross3D( toTarget, magradius, 255, 0, 255, true, .1 ); } toTarget -= GetAbsOrigin(); toTarget.NormalizeInPlace(); VPhysicsGetObject()->ApplyForceCenter( toTarget * magnitude ); } break; default: // arbitrary powers VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude * powf(nearestDistSq,(falloff+1.0f)/2)) ); // square root for distance instead of squared, add one to normalize toTarget break; } } SetNextThink(gpGlobals->curtime + 0.01f); } }