void CharacterController::UpdateAITarget(const Ogre::Vector3& target, std::shared_ptr< Environment > env, float velocity) { if (target.squaredDistance(_CurrentTarget) > 0.001 || _CurrentPathAge > 0.1) { //boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time(); _CurrentPath = env->QueryPath(GetPosition(), target); //boost::posix_time::ptime t2 = boost::posix_time::microsec_clock::universal_time(); _CurrentPathIndex = 0; _CurrentTarget = target; _CurrentVelocity = velocity; //std::cerr << "Pathfinding in " << (t2-t1).total_microseconds() << " µs\n"; } }
void EnemyCharacter::_actionShoot(const std::string& target) { //look at entity target LevelData::BaseEntity* entity = LuaManager::getSingleton().getEntity(target); //if the target isn't a NPC/Enemy, I don't want my enemy wasting his ammo. if(entity->getType() == LevelData::NPC || entity->getType() == LevelData::ENEMY) { Ogre::Vector3 targetPosition = static_cast<NPCCharacter*>(entity)->getPosition(); Ogre::Vector3 sourcePosition = _node->getOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z; sourcePosition.y = 0; Utility::rotateToTarget(_node,targetPosition,true); //after rotation, fire? _currentWeapon.weapon->fire(); _damageInterface->registerShotAtPlayer(_currentWeapon.weapon->getGunshotData(),sourcePosition.squaredDistance(targetPosition)); } }
//------------------------------------------------------------------------------- void Crate::unpausedTick(const Ogre::FrameEvent &evt) { GraLL2GameObject::unpausedTick(evt); //If gotta move, move. if (mMoving) { btTransform oldTrans, bodyTrans; mFixedBody->getMotionState()->getWorldTransform(oldTrans); mBody->getMotionState()->getWorldTransform(bodyTrans); Ogre::Real speed = CRATE_MOVE_SPEED * evt.timeSinceLastFrame; Ogre::Vector3 currPos = BtOgre::Convert::toOgre(oldTrans.getOrigin()); if (currPos.squaredDistance(mTarget) < speed*speed) { //If next move'll take us overboard, just jump to the target. mFixedBody->getMotionState()->setWorldTransform(btTransform(oldTrans.getRotation(), BtOgre::Convert::toBullet(mTarget))); mMoving = false; } else { //Else move toward target. btVector3 vel = BtOgre::Convert::toBullet((mTarget - currPos).normalisedCopy() * speed); mFixedBody->getMotionState()->setWorldTransform(btTransform(oldTrans.getRotation(), oldTrans.getOrigin() + vel)); } //Update the body itself. Y = Y of body X,Z = X,Z of fixed body. mFixedBody->getMotionState()->getWorldTransform(oldTrans); mBody->setWorldTransform(btTransform(oldTrans.getRotation(), btVector3(oldTrans.getOrigin().x(), bodyTrans.getOrigin().y(), oldTrans.getOrigin().z()))); if (!mSound->isPlaying()) mSound->play(); } else if (mSound->isPlaying()) mSound->stop(); //We might fall of. checkFell(); //Python utick event. NGF_PY_CALL_EVENT(utick, evt.timeSinceLastFrame); }
// units can be changed to a pointer that has UnitNodes removed when no longer needed. // This will use less memory, but is more complicated. void Game::checkUnitUnit(QuadtreeNode *node, std::vector<UnitNodes> units) { units.insert(units.begin(), node->units.begin(), node->units.end()); if(node->children) { for(int i=0; i<4; i++) { checkUnitUnit(&node->children[i], units); } } // If a QuadtreeNode has no children. // This is a LEAF. All nodes in std::vector units are in a possible collision. else { // Check each unit in units with every other unit in units. for(unsigned int i = 0; i<units.size(); i++) { GAME::UnitNodes *unitsI = &units.at(i); // Must be called to clean up the unitController enemy pointers first. unitsI->unitController->cleanUpEnemyPointers(); Ogre::Vector3 ILocation = unitsI->unitController->getPosition(); ILocation.y = 0; float unitsISquaredCombatRadii = float(unitsI->unitController->combatRadii * unitsI->unitController->combatRadii); float unitsISquaredDetectionRadii = float(unitsI->unitController->detectionRadii * unitsI->unitController->detectionRadii); for(unsigned int j = 0; j<units.size(); j++) { GAME::UnitNodes *unitsJ = &units.at(j); if( i==j || unitsJ->unitController->isHidden() ) continue; if( !unitsI->unitController->getConfusedBy() && unitsI->controller != unitsJ->controller && unitsJ->unitController->getConfusedBy() != unitsI->controller ) { // Improves preformance by doing this less often. Ogre::Vector3 JLocation = unitsJ->unitController->getPosition(); JLocation.y = 0; float squaredDistance = ILocation.squaredDistance(JLocation); // CHECK FOR COMBAT if (unitsISquaredCombatRadii >= squaredDistance) { //units.at(i) IN RANGE OF units.at(j). unitsI->unitController->inCombat(unitsJ->unitController); } // CHECK FOR DETECTION if (unitsISquaredDetectionRadii >= squaredDistance) { //units.at(i) IN RANGE OF units.at(j). unitsI->unitController->enemyUnitInRange(unitsJ->unitController); } } else if( unitsI->unitController->getConfusedBy() && unitsI->unitController->getConfusedBy() != unitsJ->controller ) { Ogre::Vector3 JLocation = unitsJ->unitController->getPosition(); JLocation.y = 0; float squaredDistance = ILocation.squaredDistance(JLocation); // CHECK FOR COMBAT if (unitsISquaredCombatRadii >= squaredDistance) { //units.at(i) IN RANGE OF units.at(j). unitsI->unitController->inCombat(unitsJ->unitController); } // CHECK FOR DETECTION if (unitsISquaredDetectionRadii >= squaredDistance) { //units.at(i) IN RANGE OF units.at(j). unitsI->unitController->enemyUnitInRange(unitsJ->unitController); } } } } } // Should not need since the data is passed, not the memory location. //units.erase(units.end() - node->units.size(), units.end()); }
void Tank::update(const float& deltaTime, std::vector<PowerUpSpawn*> mPowerUpSpawns){ //this check must be first if (!isAlive()) { deathTimer -= deltaTime; if (deathTimer <= 0.f) { deathTimer = 0.f; resetAll(); std::random_device rd; std::mt19937 random(rd()); if (tankSide == 1) { std::uniform_real_distribution<double> randomGen1(1, 5); int tempNumber = randomGen1(random); std::uniform_real_distribution<double> randomGen2(0, 36); int tempNumber2 = (36 * (int)randomGen2(random)) + (int)tempNumber; Ogre::Vector3 position = pathFindingGraph->getPosition(tempNumber2); mTankBodyNode->setPosition(position); } else if(tankSide == 2){ std::uniform_real_distribution<double> randomGen1(31, 35); int tempNumber = randomGen1(random); std::uniform_real_distribution<double> randomGen2(0, 36); int tempNumber2 = (36 * (int)randomGen2(random)) + (int)tempNumber; Ogre::Vector3 position = pathFindingGraph->getPosition(tempNumber2); mTankBodyNode->setPosition(position); } mTankBodyNode->setVisible(true); setSelected(false); } } //Check for tank powerups sphereSceneTime += deltaTime; if(sphereSceneTime > 0.2) { sphereSceneTime = 0; Ogre::Vector3 tankCenter = mTankBodyNode->getPosition(); int location; bool found = false; for(int i = 0; i < mPowerUpSpawns.size(); i++) { Ogre::Vector3 powerUpLocation = mPowerUpSpawns[i]->spawnNode->getPosition(); if(tankCenter.squaredDistance(powerUpLocation) < 5625) //squaredDistance is better { found = true; location = i; } } if (found) { if(mPowerUpSpawns[location]->getIsPowerUp()) { char tempType = mPowerUpSpawns[location]->pickupPowerUp(mSceneMgr); printf("Got Powerup %c\n", tempType); switch(tempType) { case ('H'): //health { hp += 0.1f; if (hp > 1.0f) { hp = 1.0f; } printf("Got Health\n"); //update healthbar float healthBarAdjuster = (1.0 - hp) / 2; mHealthBarBB->setTexcoordRect(0.0 + healthBarAdjuster, 0.0, 0.5 + healthBarAdjuster, 1.0); } break; case ('R'): //fire rate { fireRate = 1.f; powerUpDurationR = 6.f; } break; case ('S'): //speed { mRotSpd = 75.0f; ms = 100.f; mMoveSpd = 100.f; powerUpDurationS = 6.f; } break; case ('P'): //damage { dmg = 30.f; powerUpDurationP = 6.f; } break; default: printf("Unknown Powerup\n"); break; } } currentState = WANDER; resetWander(); wanderAStar(); } } decrementPowerups(deltaTime); //weapontimer weaponTimer += deltaTime; //seek powerups /* Ogre::Real distancePowerUp = 0; int powerUpNo = 0; bool firstTimeDistanceCheck = true; for(int i = 0; i < mPowerUpSpawns.size(); i++) { if(mPowerUpSpawns[i]->getIsPowerUp()) { Ogre::Real tempDistancePowerUp = mTankBodyNode->getPosition().distance(mPowerUpSpawns[i]->getPowerLocation()); if(firstTimeDistanceCheck) { firstTimeDistanceCheck = false; distancePowerUp = tempDistancePowerUp; } if(tempDistancePowerUp < distancePowerUp) { distancePowerUp = tempDistancePowerUp; powerUpNo = i; } } }*/ /* if(distancePowerUp < 500 && distancePowerUp > 0 && currentState != POSSESSED) { if(mPowerUpSpawns[powerUpNo]->getIsPowerUp()) { if(currentState != SEEK) { currentState = SEEK; seekTarget = mPowerUpSpawns[powerUpNo]->getPowerLocation(); seekAStar(); } } else currentState = WANDER; }*/ //check if the user is like somewhere and stopped ocassionally if (currentState != POSSESSED) { checkPosition += deltaTime; if(checkPosition > 3) { if(mTankBodyNode->getPosition().x == previousLocation.x) { if(mTankBodyNode->getPosition().z == previousLocation.z) { checkWhereAt(); } } checkPosition = 0; previousLocation = mTankBodyNode->getPosition(); } checkOrientation += deltaTime; if(checkOrientation > 15) { if(currentState != A_STAR) { if(!orientationEquals(initBodyOrientation, mTankBodyNode->getOrientation())) { mTankBodyNode->setOrientation(initBodyOrientation); } if(!orientationEquals(initBarrelOrientation, mTankBarrelNode->getOrientation())) { mTankBarrelNode->setOrientation(initBarrelOrientation); } if(!orientationEquals(initTurretOrientation, mTankTurretNode->getOrientation())) { mTankTurretNode->setOrientation(initTurretOrientation); } } checkOrientation = 0; } } //no movement for body yet //A_STAR, SEEK, WANDER, ESCAPE, STOP switch(currentState) { case A_STAR: //initiate astar if(tankStarted == false) { tankStarted = true; aStar(tankSide); //creates the path to get out of there } else { aStarMovement(deltaTime); } break; case FIRE: { Ogre::Vector3 targetPosition = getPredictPos(target); targetPosition.y = 16.f; Ogre::Degree angle = getShootingAngle(targetPosition); mTankTurretNode->lookAt(targetPosition, Ogre::Node::TransformSpace::TS_WORLD, Ogre::Vector3::NEGATIVE_UNIT_X); //barrelDegree = angle; if (weaponTimer > 4) { tnkMgr->createProjectile(mTankBodyNode->getPosition(), mTankTurretNode->_getDerivedOrientation(), angle, shootingVelocity, dmg); weaponTimer = 0; } if (target->hp <= 0 || mTankBodyNode->getPosition().distance(target->getPosition()) > 600 ) currentState = WANDER; } case WANDER: //wander(deltaTime); wanderMovement(deltaTime); break; case SEEK: //seek(mPowerUpSpawns[powerUpNo]->getPowerLocation(), deltaTime); //seek(Ogre::Vector3::ZERO, deltaTime); //seekMovement(deltaTime); break; case ESCAPE: break; case STOP: break; case POSSESSED: { Ogre::Vector3 rayDest; if (mMove < 0) rayDest = mTankBodyNode->getOrientation() * Ogre::Vector3(-1,0,0); else if (mMove > 0) rayDest = mTankBodyNode->getOrientation() * Ogre::Vector3(1,0,0); //THIS IS WHERE THE TANK IS MOVED WHEN PROCESSING //if (rayDest != NULL) { Ogre::Ray shootToCheckWall = Ogre::Ray(mTankBodyNode->getPosition(), rayDest); Ogre::RaySceneQuery* mRaySceneQuery = mSceneMgr->createRayQuery(shootToCheckWall, Ogre::SceneManager::ENTITY_TYPE_MASK); mRaySceneQuery->setSortByDistance(true); // Ray-cast and get first hit Ogre::RaySceneQueryResult &result = mRaySceneQuery->execute(); Ogre::RaySceneQueryResult::iterator itr = result.begin(); bool hit = false; for (itr = result.begin(); itr != result.end(); itr++) { std::string x = itr->movable->getName(); printf("Check %s \n", x.c_str()); if (x[0] == 'C' && itr->distance < 10) { printf("Too close to %s: %f \n", x.c_str(), (float)itr->distance); hit = true; } } if(hit == false) { mTankBodyNode->translate(mMove * deltaTime * mMoveSpd, 0, 0, Ogre::Node::TransformSpace::TS_LOCAL); } } mTankBodyNode->yaw(Ogre::Degree(bodyRotate * deltaTime * mRotSpd)); // Rotate the tank turret mTankTurretNode->yaw(Ogre::Degree(turretRotation * deltaTime * mRotSpd * 1.5)); turretDegree += turretRotation; //to move barrel change barrelRotation float barrelChange = barrelRotation * deltaTime * mRotSpd; barrelDegree += barrelChange; if(barrelDegree > 30) barrelDegree = 30; else if(barrelDegree < 0) barrelDegree = 0; else mTankBarrelNode->roll(Ogre::Degree(-barrelChange)); } break; } Ogre::Vector3 setpos = mTankBodyNode->getPosition(); setpos.y = 13.f; mTankBodyNode->setPosition(setpos); }
//Probably the most involved behavior so far. void NPCCharacter::_behaviorTalk(const std::string& targetName) { //have to start moving to the target entity until the distance is acceptable LevelData::BaseEntity* targetEnt = LuaManager::getSingleton().getEntity(targetName); //Can't talk to a trigger zone or door(though I *could* do the door, it would be an easter egg). if(targetEnt->getType() != LevelData::NPC && targetEnt->getType() != LevelData::ENEMY) { _isBhvFinished = true; return; } if(targetEnt->getType() == LevelData::NPC) { NPCCharacter* targetNpc = static_cast<NPCCharacter*>(targetEnt); //choosing to ignore the y-value to get a true 4 unit distance horizontally from the target. //might remove if it doesn't make a difference. Ogre::Vector3 tgtNpc = targetNpc->getPosition(); tgtNpc.y = 0; Ogre::Vector3 pos = getPosition(); pos.y = 0; //position has to be less than 16 units to talk to the entity. //chose to use 18 instead due to float inaccuracies(might have a value like 16.0178) if(tgtNpc.squaredDistance(pos) > 18) { //move towards the entity(not using the _behaviorMove function though) //or can I?? //yes I can actually. *does a jig* //generate a more correct position Ogre::Vector3 target,tmp; tmp = targetNpc->getPosition() - getPosition(); //distance and direction to the target tmp.y = 0; Ogre::Real len = tmp.normalise(); //original + (unit direction vector * desired distance from target[non-squared]) target = getPosition() + (tmp * ( len - 1)); _behaviorMove(target); if(_isBhvFinished) { //reached the destination, but behavior isn't done yet. _isBhvFinished = false; } } else { //rotate to face the target Ogre::Vector3 dir = tgtNpc - pos; dir.normalise(); Ogre::Vector3 src = _node->getOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z; src.y = 0; _node->rotate(src.getRotationTo(dir)); //make sure any other blends are finished first. if(_animHandler.getTarget() == nullptr) { //this ends the behavior until the talk animation or sound file is implemented _isBhvFinished = true; //this would be the actual way to finish the behavior(or even with the end of a sound file) if(_animHandler.getSource()->getAnimationName() == "Talk") { _isBhvFinished = true; } else { //start the blend to the talk animation. //_animHandler.blend([animation],[blend technique],.2,true); } } } return; } if(targetEnt->getType() == LevelData::ENEMY) { //nothing for now. return; } return; }