// Move to the previous hole void prevHole(){ // Load prev hole if(levelController->getCurrentLevel()->getLevelID() == 0){ // Load last level if on first level levelController->loadLevel(fileIO, (fileIO->getNumHoles() - 1)); } else{ // Load prev level levelController->loadPrevLevel(fileIO); } // Move arrow to ball's starting position arrow->translate(levelController->getCurrentLevel()->getBall()->getPhysics()->getPosition()); arrow->translate(glm::vec3(0.0, BALL_OFFSET, 0.0)); // Reload shapes shapes.clear(); shapes = levelController->getCurrentLevel()->getLevelShapes(); reloadAllShapes(&verts, &color, &norms, shapes); // Set flags ballStopped(); };
// Move to the next hole void nextHole(){ // Load next hole if(fileIO->getNumHoles() - 1 == levelController->getCurrentLevel()->getLevelID()){ // Load first level if on final level levelController->loadLevel(fileIO, 0); // Update highscores //saveAndResetScore(); updateHighScoresList(); //cout << endl << "High Scores:" << endl; // debug //for(int i = 0; i < NUM_HIGH_SCORES; i++){ // cout << i << ": " << highScores[i] << endl; //} } else{ // Load next level levelController->loadNextLevel(fileIO); // Update total score updateTotalScore(totalScore, currentHoleScore); } // Move arrow to ball's starting position arrow->translate(levelController->getCurrentLevel()->getBall()->getPhysics()->getPosition()); arrow->translate(glm::vec3(0.0, BALL_OFFSET, 0.0)); // Reload shapes shapes.clear(); shapes = levelController->getCurrentLevel()->getLevelShapes(); reloadAllShapes(&verts, &color, &norms, shapes); // Set flags ballStopped(); //cout << endl << "total score: " << totalScore << endl; // debug };
void StateBadVista::update() { const int LOGO_SIDE = logo.getWidth() / 2; const int LOGO_TOP = logo.getHeight() / 2; arm.setScaleX(1); arm.setScaleY(1); arm.setRotation(-armAngle); logo.setScaleX(1); logo.setScaleY(1); logo.setRotation(-armAngle * 0.5f); if(bvState == BV_WINDUP) { float radians = armAngle * 3.14159f / 180.0f; logo.setPosition( (int) LOGO_INIT_X + (armAngle * 0.25f) - (50 * sin(radians)), (int) LOGO_INIT_Y - 100 + (100 * cos(radians))); return; } if(bvState == BV_PITCHED) { // Calculate motion region #ifdef PENJIN_FIXED SimpleRegion tempRegion(logoX, logoY, fixedpoint::fix2int(logoX + logoVelocityX), fixedpoint::fix2int(logoY + logoVelocityY)); #else SimpleRegion tempRegion(logoX, logoY, logoX + logoVelocityX, logoY + logoVelocityY); #endif SimpleRegion motion( tempRegion.x1() - LOGO_SIDE, tempRegion.y1() - LOGO_TOP, tempRegion.x2() + LOGO_SIDE, tempRegion.y2() + LOGO_TOP); if (hitObstacle(horizontalObstacles, motion)) { if (bounce.isPlaying()) bounce.stop(); bounce.play(); logoVelocityX *= BOUNCE_DECAY; logoVelocityY *= BOUNCE_DECAY; logoVelocityY *= -1; numBounces++; } if (hitObstacle(verticalObstacles, motion)) { if (bounce.isPlaying()) bounce.stop(); bounce.play(); logoVelocityX *= BOUNCE_DECAY; logoVelocityY *= BOUNCE_DECAY; logoVelocityX *= -1; } // Sometimes the ball gets caught inside the side of the litter can: // neither inside nor out. The following two paragraphs seek to prevent // that. if (hitObstacle(basketLeft, motion)) { bounce.play(); logoVelocityX *= BOUNCE_DECAY; logoVelocityY *= BOUNCE_DECAY; if (logoX >= BASKET_LEFT_INSIDE && logoVelocityX < 0) logoVelocityX *= -1; if (logoX < BASKET_LEFT_INSIDE && logoVelocityX > 0) logoVelocityX *= -1; } if (hitObstacle(basketRight, motion)) { bounce.play(); logoVelocityX *= BOUNCE_DECAY; logoVelocityY *= BOUNCE_DECAY; if (logoX >= BASKET_RIGHT_INSIDE && logoVelocityX < 0) logoVelocityX *= -1; if (logoX < BASKET_RIGHT_INSIDE && logoVelocityX > 0) logoVelocityX *= -1; } if (hitObstacle(playerObstacle, motion)) { init(); return; } SimpleRegion logoPosition(logoX - LOGO_SIDE, logoY - LOGO_TOP, logoX + LOGO_SIDE, logoY + LOGO_TOP); // Check for end of game if (ballStopped()) { bool won = inBasket(); variables[0].setValue(won ? 1 : 0); if (won) bvState = BV_WON; else bvState = BV_LOST; counter.start(); } // Ensure gravity doesn't overcome the bounce decay if (inBasket()) { // Once the logo enters the basket, don't let it bounce out float newYPos = GRAVITY + logoVelocityY + logoY + LOGO_TOP; if (logoVelocityY < 1 && BASKET_BOT - logoY < LOGO_TOP + 5) { logoVelocityY = 0; logoVelocityX = 0; logoY = BASKET_BOT - LOGO_TOP; } else if (BASKET_TOP < newYPos && newYPos < BASKET_BOT) logoVelocityY += GRAVITY; else if (newYPos > BASKET_BOT) logoVelocityY = BASKET_BOT - logoY - LOGO_TOP; else logoVelocityY = BASKET_TOP - logoY - LOGO_TOP; } else { if (GRAVITY + logoVelocityY + logoY + LOGO_TOP < FLOOR) logoVelocityY += GRAVITY; else logoVelocityY = FLOOR - logoY - LOGO_TOP; } #ifdef PENJIN_FIXED logoY += fixedpoint::fix2int(logoVelocityY); logoX += fixedpoint::fix2int(logoVelocityX); #else logoY += logoVelocityY; logoX += logoVelocityX; #endif logo.setPosition(logoX - LOGO_SIDE, logoY - LOGO_TOP); return; } if(bvState == BV_LOST) { if(pwned) { bounce.loadSound("music/BadVista/chimes.ogg"); bounce.play(); backsound.stop(); backsound.loadMusic("music/BadVista/pp.bv.windows.e.egg.ogg"); backsound.setLooping(false); backsound.play(); if (pwned_count < PWNED_PWNED) loserBackground.loadSprite("images/BadVista/stopped.jpg"); else loserBackground.loadSprite("images/BadVista/lost.png"); bvState = BV_PWNED; } else if(counter.getScaledTicks() > END_DELAY) setNextState(STATE_MAIN); } if(bvState == BV_WON) { if(counter.getScaledTicks() > END_DELAY) setNextState(STATE_MAIN); } if(bvState == BV_PWNED) { if(counter.getScaledTicks() > LOSER_DELAY && !backsound.isPlaying()) setNextState(STATE_MAIN); } }
// 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); }
void Ball::doCollision() { if(!stopped){ if(birdDeadCounter>0) { --birdDeadCounter; if(birdDeadCounter<=0) { scene()->removeItem(removeBird); } } //check ob es eine Kollision gibt QList<QGraphicsItem*> collideList = scene()->collidingItems(this); //if(!(collideList.isEmpty())) for(int i=0; i<collideList.size(); ++i) { //finde Typ des kollidierenden Objectes heraus (BorderLine oder GroundMaterial) int sw = collideList.at(i)->type(); switch(sw) { case CourtElement::borderline_type: //Kollision mit Spielfeldrand, abprallen { //Jetzt weis man, dass es eine Borderline ist, also caste QGraphicsItem* in BorderLine* BorderLine* borderline = static_cast<BorderLine*>(collideList.at(i)); int angle = borderline->getAngle(); if(canCollide<=0) { emit soundPlay(SoundEngine::borderCollisionSound); //angle ist relativ zu 3 Uhr (Uhrzeigersinn), rotation ist relativ zu 12 Uhr (Uhrzeigersinn) setRotation(2*(angle+90.0-rotation()) + rotation()); speed = speed * borderline->getReflectionCoefficient(); canCollide = 3; } } break; case CourtElement::groundmaterial_type: { GroundMaterial* groundmaterial = static_cast<GroundMaterial*>(collideList.at(i)); double maxspeed = groundmaterial->getMaxSpeed(); double minspeed = groundmaterial->getMinSpeed(); double friction = groundmaterial->getFrictionCoefficient(); switch(groundmaterial->getMaterial()) { case GroundMaterial::water_material: { emit soundPlay(SoundEngine::waterSound); speed -= friction*speed; if(speed<minspeed) { speed = 0.0; emit ballInWater(); } } break; case GroundMaterial::nonNewtonian_material: if(speed > minspeed) { speed -= speed*friction; } else if(speed<minspeed) { speed = 0.0; emit soundPlay(SoundEngine::lavaSound); emit ballInWater(); //Ist ja im Prinzip das gleiche wie bei Wasser } break; case GroundMaterial::hole_material: if(speed<maxspeed) { emit soundPlay(SoundEngine::cheeringSound); speed = 0.0; stopped=true; emit ballInHole(); } break; case GroundMaterial::grass_material: { speed -= friction; if(speed<minspeed) { speed = 0.0; if(!stopped) emit ballStopped(); stopped = true; } } break; case GroundMaterial::sand_material: { emit(soundPlay(SoundEngine::sandSound)); speed -= 1.5*friction; if(speed<minspeed) { speed = 0.0; if(!stopped) emit ballStopped(); stopped = true; } } break; //unused materials: /* case GroundMaterial::speedUp_material: case GroundMaterial::concrete_material: case GroundMaterial::wood_material: */ default: break; } } break; case 7: //Vogel abgeschossen! (7 = Pixmap) { if (isBirdDead == false) { emit soundPlay(SoundEngine::birdHitSound); emit birdHit(); isBirdDead = true; } removeBird = static_cast<QGraphicsPixmapItem*>(collideList.at(i)); removeBird->setPixmap(birdDeadPicture); birdDeadCounter = 30; } break; default: break; } } } }