// Main function int main(int iArgc, char** cppArgv) { // Creates all LevelMaps LevelMap level1, level2; level1 = LevelMap("Level1.txt", 0); activeMaps.push_back(&level1); // Links all LevelMaps //level1.AddConnection(Vector3(9, 2.5, 9), 0, &level2, Vector3(17, 0, 13), 270); // Determines the current LevelMap based on posX and posZ currentMap = &level1; // GetCurrentMap(posX, posZ); // Sets starting position posY float addHeight = GetGroundHeight(posX, posZ, currentMap); if (addHeight != noCeilingHeight) posY = playerHeight + addHeight; // Initiates keyTable and keyHandled for (int i = 0; i < 256; i++) { keyTable[i] = false; keyHandled[i] = false; } // Initiates prevPosList for (int i = 0; i < prevListCount; i++) { prevPosList.push_back(new Vector3(posX, posY, posZ)); } //texture = LoadTexture("./FloorTile.bmp"); glutInit(&iArgc, cppArgv); // Initializes glut glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Sets the parameters for GLUT glutInitWindowSize(screenW, screenH); // Initializes the window size glutInitWindowPosition((1920 - screenW) / 2, (1080 - screenH) / 2); // Initializes the window position glutCreateWindow("Example"); // Sets the window name glEnable(GL_DEPTH_TEST); glutSetCursor(GLUT_CURSOR_NONE); glutWarpPointer(centerX, centerY); glutDisplayFunc(Display); glutIdleFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(KeyPressed); glutKeyboardUpFunc(KeyUp); glutMotionFunc(MouseMovement); glutPassiveMotionFunc(MouseMovement); glutTimerFunc(1000, SecondPassed, 0); glutMainLoop(); // Runs the program using the callback functions that were specified before, never returns return 0; }
// "Bend" our line of sight around corners until we can "see" the point. bool CCSBot::BendLineOfSight(const Vector *eye, const Vector *point, Vector *bend) const { // if we can directly see the point, use it TraceResult result; UTIL_TraceLine(*eye, *point + Vector(0, 0, HalfHumanHeight), ignore_monsters, ENT(pev), &result); if (result.flFraction == 1.0f && !result.fStartSolid) { // can directly see point, no bending needed *bend = *point; return true; } // "bend" our line of sight until we can see the approach point Vector v = *point - *eye; float startAngle = UTIL_VecToYaw(v); float length = v.Length2D(); v.NormalizeInPlace(); float angleInc = 10.0f; for (float angle = angleInc; angle <= 135.0f; angle += angleInc) { // check both sides at this angle offset for (int side = 0; side < 2; ++side) { float actualAngle = (side) ? (startAngle + angle) : (startAngle - angle); float dx = BotCOS(actualAngle); float dy = BotSIN(actualAngle); // compute rotated point ray endpoint Vector rotPoint(eye->x + length * dx, eye->y + length * dy, point->z); TraceResult result; UTIL_TraceLine(*eye, rotPoint + Vector(0, 0, HalfHumanHeight), ignore_monsters, ENT(pev), &result); // if this ray started in an obstacle, skip it if (result.fStartSolid) { continue; } Vector ray = rotPoint - *eye; float rayLength = ray.NormalizeInPlace(); float visibleLength = rayLength * result.flFraction; // step along ray, checking if point is visible from ray point const float bendStepSize = 50.0f; for (float bendLength = bendStepSize; bendLength <= visibleLength; bendLength += bendStepSize) { // compute point along ray Vector rayPoint = *eye + bendLength * ray; // check if we can see approach point from this bend point UTIL_TraceLine(rayPoint, *point + Vector(0, 0, HalfHumanHeight), ignore_monsters, ENT(pev), &result); if (result.flFraction == 1.0f && !result.fStartSolid) { // target is visible from this bend point on the ray - use this point on the ray as our point // keep "bent" point at correct height along line of sight if (!GetGroundHeight(&rayPoint, &rayPoint.z)) { rayPoint.z = point->z; } *bend = rayPoint; return true; } } } } *bend = *point; // bending rays didn't help - still can't see the point return false; }
// Checks inputs and moves the player. Gets called each frame void CheckInputs() { // Checks inputs if (keyTable['d']) direction.first = -1; if (keyTable['a']) direction.first = 1; if (!keyTable['d'] == !keyTable['a']) direction.first = 0; if (keyTable['s']) direction.second = -1; if (keyTable['w']) direction.second = 1; if (!keyTable['s'] == !keyTable['w']) direction.second = 0; if ((GetAsyncKeyState(VK_LCONTROL) & 0x8000) && !inAir && !flying) { // Ctrl posY = max(posY - crouchSpeed, groundHeight + crouchHeight); if (!crouching) crouching = true; } if (!(GetAsyncKeyState(VK_LCONTROL) & 0x8000) && crouching && posY != groundHeight + playerHeight && !flying && !inAir) { posY = min(posY + crouchSpeed, groundHeight + playerHeight); if (crouching && posY == groundHeight + playerHeight) crouching = false; } if (keyTable[32] && !keyHandled[32] && !inAir && !crouching && !flying) { // Space velocityY = jumpVelocity; jumping = true; keyHandled[32] = true; } if (keyTable['f'] && !keyHandled['f'] && !crouching) { flying = !flying; keyHandled['f'] = true; inAirDuration = 0; } if (keyTable['r'] && !keyHandled['r'] && !crouching) { showRedLine = !showRedLine; keyHandled['r'] = true; } if (keyTable[27]) // Escape exit(0); // Finds the X and Z coordinates of the player after it has moved in the direction that it is going if (crouching) speed = crouchingSpeed; if (!crouching || flying) speed = walkingSpeed; Move(speed, 180.0 - 90.0 * direction.first + 45.0 * direction.first * direction.second - 180.0 * (((direction.second == -1 || direction.second == 0) && direction.first == 0) ? 1 : 0)); // TODO: add wall strafing (player now stops when making contact with slanted wall) if (!flying) { // Checks for collisions with walls in up, left, right and down directions nH = GetGroundHeight(newX, newZ, currentMap); lH = GetGroundHeight(newX - minDist, newZ, currentMap); rH = GetGroundHeight(newX + minDist, newZ, currentMap); uH = GetGroundHeight(newX, newZ - minDist, currentMap); dH = GetGroundHeight(newX, newZ + minDist, currentMap); collisionCheck = true; if ((lH + playerHeight - posY > stepThreshold && !crouching) || (lH + crouchHeight - posY > stepThreshold && crouching)) { posX = floor(posX / gridSep) * gridSep + minDist + epsilon; collisionCheck = false; } if ((rH + playerHeight - posY > stepThreshold && !crouching) || (rH + crouchHeight - posY > stepThreshold && crouching)) { posX = ceil(posX / gridSep) * gridSep - minDist - epsilon; collisionCheck = false; } if ((uH + playerHeight - posY > stepThreshold && !crouching) || (uH + crouchHeight - posY > stepThreshold && crouching)) { posZ = floor(posZ / gridSep) * gridSep + minDist + epsilon; collisionCheck = false; } if ((dH + playerHeight - posY > stepThreshold && !crouching) || (dH + crouchHeight - posY > stepThreshold && crouching)) { posZ = ceil(posZ / gridSep) * gridSep - minDist - epsilon; collisionCheck = false; } // Checks for step-ups if (((nH + playerHeight - posY <= stepThreshold && !crouching) || (nH + crouchHeight - posY <= stepThreshold && crouching))) groundHeight = nH; // Sets posY if it is below the correct position if (posY < groundHeight + playerHeight && !crouching) posY = groundHeight + playerHeight; if (posY < groundHeight + crouchHeight && crouching) posY = groundHeight + crouchHeight; // Sets posY if it is above the ceiling nC = GetCeilingHeight(newX, newZ, currentMap); if (posY > nC - minDist - epsilon) { posY = nC - minDist - epsilon; velocityY = 0.0; } // Checks for collisions between ceilings of different heights lC = GetCeilingHeight(newX - minDist, newZ, currentMap); rC = GetCeilingHeight(newX + minDist, newZ, currentMap); uC = GetCeilingHeight(newX, newZ - minDist, currentMap); dC = GetCeilingHeight(newX, newZ + minDist, currentMap); if (posY + minDist > lC && lC != noCeilingHeight) { posX = floor(posX / gridSep) * gridSep + minDist; collisionCheck = false; } if (posY + minDist > rC && rC != noCeilingHeight) { posX = ceil(posX / gridSep) * gridSep - minDist; collisionCheck = false; } if (posY + minDist > uC && uC != noCeilingHeight) { posZ = floor(posZ / gridSep) * gridSep + minDist; collisionCheck = false; } if (posY + minDist > dC && dC != noCeilingHeight) { posZ = ceil(posZ / gridSep) * gridSep - minDist; collisionCheck = false; } // If no collision: move to new position if (collisionCheck) { posX = newX; posZ = newZ; } // Checks whether the player is falling down FallingCheck(); } }
// Compute shortest path to goal position via A* algorithm // If 'goalArea' is NULL, path will get as close as it can. bool CCSBot::ComputePath(CNavArea *goalArea, const Vector *goal, RouteType route) { // Throttle re-pathing if (!m_repathTimer.IsElapsed()) return false; // randomize to distribute CPU load m_repathTimer.Start(RANDOM_FLOAT(0.4f, 0.6f)); DestroyPath(); CNavArea *startArea = m_lastKnownArea; if (!startArea) return false; // note final specific position Vector pathEndPosition; if (!goal && !goalArea) return false; if (!goal) pathEndPosition = *goalArea->GetCenter(); else pathEndPosition = *goal; // make sure path end position is on the ground if (goalArea) pathEndPosition.z = goalArea->GetZ(&pathEndPosition); else GetGroundHeight(&pathEndPosition, &pathEndPosition.z); // if we are already in the goal area, build trivial path if (startArea == goalArea) { BuildTrivialPath(&pathEndPosition); return true; } // Compute shortest path to goal CNavArea *closestArea = nullptr; PathCost pathCost(this, route); bool pathToGoalExists = NavAreaBuildPath(startArea, goalArea, goal, pathCost, &closestArea); CNavArea *effectiveGoalArea = (pathToGoalExists) ? goalArea : closestArea; // Build path by following parent links // get count int count = 0; CNavArea *area; for (area = effectiveGoalArea; area; area = area->GetParent()) { count++; } // save room for endpoint if (count > MAX_PATH_LENGTH - 1) count = MAX_PATH_LENGTH - 1; if (count == 0) return false; if (count == 1) { BuildTrivialPath(&pathEndPosition); return true; } // build path m_pathLength = count; for (area = effectiveGoalArea; count && area; area = area->GetParent()) { count--; m_path[count].area = area; m_path[count].how = area->GetParentHow(); } // compute path positions if (ComputePathPositions() == false) { PrintIfWatched("Error building path\n"); DestroyPath(); return false; } if (!goal) { switch (m_path[m_pathLength - 1].how) { case GO_NORTH: case GO_SOUTH: pathEndPosition.x = m_path[m_pathLength - 1].pos.x; pathEndPosition.y = effectiveGoalArea->GetCenter()->y; break; case GO_EAST: case GO_WEST: pathEndPosition.x = effectiveGoalArea->GetCenter()->x; pathEndPosition.y = m_path[m_pathLength - 1].pos.y; break; } GetGroundHeight(&pathEndPosition, &pathEndPosition.z); } // append path end position m_path[m_pathLength].area = effectiveGoalArea; m_path[m_pathLength].pos = pathEndPosition; m_path[m_pathLength].ladder = nullptr; m_path[m_pathLength].how = NUM_TRAVERSE_TYPES; m_pathLength++; // do movement setup m_pathIndex = 1; m_areaEnteredTimestamp = gpGlobals->time; m_spotEncounter = nullptr; m_goalPosition = m_path[1].pos; if (m_path[1].ladder) SetupLadderMovement(); else m_pathLadder = nullptr; return true; }