// 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

};
Beispiel #3
0
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;
        }
    }
  }
}