//Start the ball moving using direction and power from GLUI input void launchBall(int i){ ballMoving = true; launchAngleRadians = (float) launchAngle * (PI/180); launchVector = normalize(vec3(sin(launchAngleRadians), 0.0, cos(launchAngleRadians))); Level *currentLevel = levelController->getCurrentLevel(); Ball *ball = currentLevel->getBall(); Physics *physics = ball->getPhysics(); puttSFX(physics->getSpeed(), sound); float prevY = physics->getDirection().y; physics->setDirection(glm::vec3(launchVector.x, prevY, launchVector.z)); // If new tile is flat make sure no y-component if(levelController->getCurrentLevel()->getTile(ball->getCurrentTileID())->getShapes().at(0)->normals()[0] == glm::vec3(0.0,1.0,0.0)){ physics->setDirection( glm::vec3(physics->getDirection().x, 0.0, physics->getDirection().z)); } // If new tile is not flat add y-component else{ glm::vec3 oldDirection = physics->getDirection(); glm::vec3 upVector = glm::vec3(0.0,1.0,0.0); // Get current tile normal glm::vec3 tileNormal = levelController->getCurrentLevel()->getTile(ball->getCurrentTileID())->getShapes().at(0)->normals()[0]; glm::vec3 xVector = glm::cross(oldDirection, upVector); glm::vec3 newDirection = glm::normalize(glm::cross(tileNormal, xVector)); physics->setDirection(newDirection); } physics->setSpeed(launchPower/100.1f); // Increment current hole score and update glui currentHoleScore++; numStrokes->set_int_val(currentHoleScore); angleSpinner->disable(); powerSpinner->disable(); fireButton->disable(); }
// Run by GLUT every [tickspeed] miliseconds void tick(int in) { // Local handles to objects Level *currentLevel = levelController->getCurrentLevel(); Ball *ball = currentLevel->getBall(); Physics *physics = ball->getPhysics(); Tile* currentTile = currentLevel->getTile(ball->getCurrentTileID()); vector<int> borderIDs = currentTile->getNeighborIDs(); vector<Shape*> borderShapes = currentTile->getBorders()->getInwardShapes(); vec3 ballPosition = physics->getPosition(); // Debug -- Highlight current tile if (DEBUG_TILE_PAINT) { currentTile->getShapes()[0]->changeColor(TILE_HIGHLIGHT_COLOR); currentTile->getShapes()[0]->reload(); } // Collision with cup glm::vec3 ballPos = physics->getPosition(); glm::vec3 cupPos = currentLevel->getCup()->getPhysics()->getPosition(); float cupPlaneDist = sqrt(((ballPos.x - cupPos.x)*(ballPos.x - cupPos.x)) + ((ballPos.z - cupPos.z)*(ballPos.z - cupPos.z))); if(cupPlaneDist < (CUP_RADIUS - (0.8 * BALL_RADIUS)) && abs(cupPos.y - ballPos.y) <= 1.1*BALL_OFFSET){ // allow for slight error //Play SFX for falling in hole sound->getEngine()->play2D("sfx/retro_cup.wav"); //----------------CHANGE TO NEXT HOLE----------------// nextHole(); } // Physics and collision calculations vec3 newDirection = physics->getDirection(); // used for tile transitions if(ballMoving) { // Check for collision if(detectCollisions(currentTile, physics, sound)){ newDirection = physics->getDirection(); } // Update ball direction newDirection = updateBallDirection(levelController, sound); // Update current tile currentTile = currentLevel->getTile(ball->getCurrentTileID()); // Update ball speed double ballSpeed = physics->getSpeed(); if(currentTile->getShapes().at(0)->normals()[0] == glm::vec3(0.0,1.0,0.0)){ // flat tile if(ballSpeed > 0.01){ physics->setSpeed(ballSpeed - TILE_DEFAULT_FRICTION); ballSpeed = physics->getSpeed(); } else{ physics->setSpeed(0.0); ballStopped(); } } else if(newDirection.y > 0){ // going up hill //cout << endl << "UP"; //cout << "Direction y-value: " << newDirection.y << endl; if(ballSpeed > 0.01){ physics->setSpeed(ballSpeed - (TILE_DEFAULT_FRICTION + (2.0*currentTile->getSlope()*TILE_DEFAULT_FRICTION))); ballSpeed = physics->getSpeed(); } } else{ // going down hill //cout << endl << "DOWN"; //cout << "Direction y-value: " << newDirection.y << endl; if(ballSpeed <= (100.0/100.1)){ physics->setSpeed(ballSpeed + TILE_DEFAULT_FRICTION); } else{ // clmap speed ballSpeed = (100.0/100.1); } } // Update ballPosition physics->updatePosition(); // Update shape using velocity Shape* ballShape = ball->getShapes().at(0); ballShape->translate(physics->getVelocity()); // Update ball direction physics->setDirection(newDirection); // Snap ball to correct y value -- hacky if(currentTile->getShapes().at(0)->normals()[0] == glm::vec3(0.0,1.0,0.0)){ // flat tile if(physics->getPosition().y != (currentTile->getPhysics()->getPosition().y + BALL_OFFSET)){ // Snap ball shape ball->getShapes()[0]->translate(vec3(0.0, -(physics->getPosition().y), 0.0)); ball->getShapes()[0]->translate(vec3(0.0, (currentTile->getPhysics()->getPosition().y + BALL_OFFSET), 0.0)); // Update ball physics physics->setPosition(vec3(physics->getPosition().x, (currentTile->getPhysics()->getPosition().y + BALL_OFFSET), physics->getPosition().z)); } } else{// sloped tile float correctY = currentTile->getShapes()[0]->yValueAtPoint(physics->getPosition().x, physics->getPosition().z); if(physics->getPosition().y != correctY){ // Snap ball shape ball->getShapes()[0]->translate(vec3(0.0, -(physics->getPosition().y), 0.0)); ball->getShapes()[0]->translate(vec3(0.0, correctY, 0.0)); // Update ball physics physics->setPositionY(correctY); } } // Reload shape ballShape->reload(); } // Update HUD currentLevel = levelController->getCurrentLevel(); updateHUD(currentLevel->getLevelName(), fileIO->getNumHoles(), currentHoleScore, currentLevel->getPar()); //If controls are enabled (ball not yet launched), then make ball direction equal to launchVector if (angleSpinner->enabled) { float launchAngleRadians = launchAngle * (PI/180); launchVector = normalize(vec3(sin(launchAngleRadians), 0.0, cos(launchAngleRadians))); updateCamera(physics->getPosition(), launchVector, false); } else { updateCamera(physics->getPosition(), physics->getDirection(), true); } glutTimerFunc(tickSpeed, tick, 0); }