//Metodo principal void Juego::jugar() { //Cargo las variables de la partida a 0 reset(); //Loop principal while (true) { if (GetAsyncKeyState(VK_ESCAPE)) break; //Actualizo el auto del jugador jugador.mover(); jugador.dibujar(); //Chequeo colision colision = checkColision(jugador.getX(), jugador.getY(), enemigos[ultimoEnemigo]->getX(), enemigos[ultimoEnemigo]->getY()); if (colision) { //Si hay, disparo el metodo choque choque(); //Si no perdio el jugador, continuo la partida if (vidas > 0) continue; } //Si se cumplio el timer del enemigo (dado por su velocidad), lo actualizo if (tempo+paso < clock()) { //Aumento puntaje puntos+=10; mostrarPuntos(); //Actualizo y luego evaluo si aumento la dificultad actualizarEnemigos(); evaluaNivel(); //Reinicio el timer tempo = clock(); } } }
int main() { typedef std::deque<Invader> InvaderList; typedef std::deque<Shot> ShotList; cv::VideoCapture cap( DEFAULT_DEVICE ); if(!cap.isOpened()) { std::cerr << "Error opening VideoCapture!" << std::endl; return -1; } cap.set(CV_CAP_PROP_FRAME_WIDTH, 1024); cap.set(CV_CAP_PROP_FRAME_HEIGHT, 768); cv::namedWindow("SpaceInvaders", CV_WINDOW_AUTOSIZE); cv::Mat cameraImage; cap >> cameraImage; const cv::Size CameraImageSize( cameraImage.size() ); for (int key = -1; ' ' != key; key = cv::waitKey(WAIT_DELAY_MS)) { cap >> cameraImage; cv::flip(cameraImage, cameraImage, FLIPPING_AROUND_Y_AXIS); cv::putText(cameraImage, "Press space to play!", cv::Point(30,80), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar::all(255), 2, 8); cv::resize(cameraImage, cameraImage, CameraImageSize * 2); cv::imshow("SpaceInvaders", cameraImage); } const GameImage playerImage( PLAYER_PNG ); const GameImage invaderImage( INVADER_PNG ); const int YPlayerShot = CameraImageSize.height - playerImage.size().height; const int YGameOver = YPlayerShot - invaderImage.size().height; Player player(playerImage, CameraImageSize, SHOT_LINE_PIX); PlayerPosition playerPosition(player, HAARCASCADE_XML, CameraImageSize); Shot playerShot; bool gameOver = false; InvaderList invaders; std::generate_n(std::back_inserter(invaders), MAX_INVADERS, Invader::Factory(invaderImage, CameraImageSize, 5)); ShotList shots; cv::RNG rng(uint64(std::time(0))); for (int key = -1; 'q' != key; key = cv::waitKey(WAIT_DELAY_MS)) { cap >> cameraImage; cv::flip(cameraImage, cameraImage, FLIPPING_AROUND_Y_AXIS); if (!gameOver) { playerPosition.update(cameraImage); playerShot.update(); std::for_each(invaders.begin(), invaders.end(), GraphicUpdate); std::for_each(shots.begin(), shots.end(), GraphicUpdate); if (playerShot.isValid()) { const InvaderList::iterator iInvaderEnd = std::remove_if(invaders.begin(),invaders.end(), GraphicColision(playerShot.rect())); if (iInvaderEnd != invaders.end()) { invaders.erase(iInvaderEnd, invaders.end()); playerShot = Shot(); } } if (!shots.empty()) { const ShotList::iterator iShotsEnd = std::remove_if(shots.begin(), shots.end(), isInvalidShot); if (iShotsEnd != shots.end()) { shots.erase(iShotsEnd, shots.end()); } } for (InvaderList::const_iterator iInvader = invaders.begin(); iInvader != invaders.end() && !gameOver; ++iInvader) { const cv::Rect irect( iInvader->rect() ); if ((rng.uniform(0.0,1.0) < 0.05) && (shots.size() < MAX_INVADERS)) { cv::Point shotPos(irect.x + (irect.width / 2), irect.y + irect.height); shots.push_back( Shot(shotPos, SHOT_SPEED, cv::Scalar(100,50,100), CameraImageSize) ); } if (irect.y >= YGameOver) { gameOver = true; } } if (!playerShot.isValid() && player.isShooting()) { cv::Point shotPoint( player.facePosition().x, YPlayerShot ); playerShot = Shot(shotPoint, -SHOT_SPEED, cv::Scalar(100,170,10), CameraImageSize); } for (ShotList::iterator iShot(shots.begin()); iShot != shots.end() && !gameOver; ++iShot) { if (iShot->isValid() && checkColision(iShot->rect(),player.rect())) { gameOver = true; } } } std::for_each(invaders.begin(), invaders.end(), GraphicPaint(cameraImage)); std::for_each(shots.begin(), shots.end(), GraphicPaint(cameraImage)); player.paint(cameraImage); playerShot.paint(cameraImage); if (invaders.empty()) { cv::putText(cameraImage, "Winner!", cv::Point(30,80), cv::FONT_HERSHEY_SIMPLEX, 3, cv::Scalar::all(255), 2, 8); } else if (gameOver) { cv::putText(cameraImage, "Game Over!", cv::Point(30,80), cv::FONT_HERSHEY_SIMPLEX, 3, cv::Scalar::all(255), 2, 8); } cv::resize(cameraImage, cameraImage, CameraImageSize * 2); cv::imshow("SpaceInvaders", cameraImage); } return 0; }
inline bool operator()(const Graphic &g) const { return checkColision(a,g.rect()); }
///Modo de jogo em que só há uma vida, e termina apenas quando o jogador morre void survivalMode() { system("mode con:cols=90 lines=30"); //tamanho da tela de jogo LEVEL_SCENE hell = {RED, {176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,177, 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,177, 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,177,177, 176,176,176,176,176,176,176,176,178,178,176,176,176,176,176,176,178,177,177,177, 176,176,178,177,177,176,176,178,178,178,178,176,176,176,176,178,178,177,177,177, 176,176,178,177,177,177,176,178,178,178,178,176,176,176,176,178,178,178,177,177, 178,178,178,177,177,177,176,178,178,178,178,176,176,176,178,178,178,178,178,178, 178,178,177,177,177,177,176,178,178,178,178,178,176,178,178,178,178,177,178,178, 177,178,177,177,177,177,177,177,178,178,177,177,177,177,177,177,177,177,177,178, 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177 } }; //cenário do modo de jogo FILE *arq; int score; //pontuação int level; //como só há um level nesse jogo, esta variavél serve apenas para o peso da pontuação int speed; //velocidade do jogo int rows, columns; //Linhas e colunas do mapa int rocksNum; // Número de pedras int ratNum; //Indica qual o rato a ser gerado, há no máximo 4 ratos na tela int ratsEaten; int ratsColor; //Cor do rato a ser gerado int i; // Usado nos loops for int cont; //Usado para contabilizar o número de movimentos da snake char auxDirection; // BOOL isDead; //Flag de morte da snake char map[ROWSMAX][COLUMNSMAX]; int hasPassed[ROWSMAX*COLUMNSMAX]; SNAKE snake; POSN initialCoord; //Coordenada onde a snake começa o nível POSN rocks[ROWSMAX*COLUMNSMAX]; POSN rats[4]; ratNum = 0; ratsColor = 2; ratsEaten = 0; cont = 0; isDead = 0; level = 1; score = 0; speed = 200; //speed inicial for(i=0; i<rocksNum; i++) hasPassed[i]=0; readMap(42, &rows, &columns, map, &rocksNum, rocks, &initialCoord); restartLevel(&snake, columns, rows, rats, speed, &speed, initialCoord, &isDead); print_lvlART(hell, columns + 5, 0); fadeIN(rows, columns, GREY, 1); printMap(rows, columns, map, hell.color); printRocks(rows, columns, rocksNum, rocks, map); printSnake(&snake); getch(); //pausa o jogo while(!isDead) { for(i=0; i<rocksNum; i++) { if(hasPassed[i]!=0) hasPassed[i]+=1; } print_lvlART(hell, columns + 5, 0); printScore(score); eraseTrail(snake); updateSnakeCoord(&snake); printSnake(&snake); checkColision(&snake, &isDead, rows, columns, map, rocks, rocksNum, hasPassed, &score); if(score < 0) { score = 0; //Não há score negativo! } cont++; //contador de movimentos if(cont % 10 == 0) { makeRats(rows, columns, rats, ratNum, &snake, map, &ratsColor); //gera e printa um rato ratNum++; if(ratNum == 4) //Há 4 ratos, de 0 a 3, logo rato 4 == rato 0 { ratNum = 0; } } eatRat(&snake, rats, &ratsEaten, &score, level); //checa se um rato foi comido Sleep(speed); //controla a velocidade do jogo if(speed > 100) //máxima velocidade do jogo speed -= 1; auxDirection = changeDirection(snake.direction); //lê nova direção to teclado if(auxDirection == 'P') { getch(); //Pausa o jogo } else if(auxDirection == 'C') { cheatCode(&isDead, &isDead, &speed); //Lê cheat code } else if(auxDirection == 'Q' || auxDirection == ESC) //Se o jogador aperta para sair, perde suas vidas para encerrar { isDead = 1; } else snake.direction = auxDirection; //só troca a direção se a nova direção não for uma tecla de pause ou saída } fadeOUT(rows, columns, GREY, 1); //Efeito de fade out na tela printGameOver(); arq = fopen("highscore_survival.bin", "rb+"); //Abre arquivo de highscore, informando caso de erro if(arq == NULL) printf("error"); uptadeHighScore(score, arq); //coloca o score no rank system("cls"); }
///Executa uma fase do jogo no modo story void playOneLevel(int level, int objetivo, int speed, LEVEL_SCENE scenario, int *lifes, int *score) { int rows, columns; //Linhas e colunas do mapa int rocksNum; // Número de pedras int ratsEaten; //Número de ratos int ratNum; //Indica qual o rato a ser gerado, há no máximo 4 ratos na tela int ratsColor; //Cor do rato a ser gerado int i; // Usado nos loops for int cont; //Usado para contabilizar o número de movimentos da snake int actualSpeed; //velocidade que vai sendo aumentada char auxDirection; //recebe direção antes de trocar a direção da snake BOOL isDead; //Flag de morte da snake BOOL levelEnded; //Flag que indica se o nível chegou ao fim BOOL eatenAllRats; //Flag que indica se todos os ratos necessário para gerar a maçã foram comidos char map[ROWSMAX][COLUMNSMAX]; int hasPassed[ROWSMAX*COLUMNSMAX]; //array para indicar as pedras pelas quais a snake passou SNAKE snake; POSN initialCoord; //Coordenada onde a snake começa o nível POSN rocks[ROWSMAX*COLUMNSMAX]; POSN rats[4]; POSN apple = {500, 500}; //coordenada fora do mapa eatenAllRats = 0; ratsEaten = 0; ratNum = 0; ratsColor = GREEN; //primeiro rato é verde cont = 0; isDead = 0; levelEnded = 0; for(i=0; i<rocksNum; i++) hasPassed[i]=0; readMap(level, &rows, &columns, map, &rocksNum, rocks, &initialCoord); print_lvlART(scenario, columns + 5, 0); restartLevel(&snake, columns, rows, rats, speed, &actualSpeed, initialCoord, &eatenAllRats); fadeIN(rows, columns, GREY, 1); printMap(rows, columns, map, scenario.color); printRocks(rows, columns, rocksNum, rocks, map); printSnake(&snake); printInfo(level, *lifes, *score, ratsEaten, objetivo); getch(); //pausa o jogo while(*lifes > 0 && levelEnded == 0) { for(i=0; i<rocksNum; i++) { if(hasPassed[i] != 0) hasPassed[i] += 1; } print_lvlART(scenario, columns + 5, 0); printInfo(level, *lifes, *score, ratsEaten, objetivo); eraseTrail(snake); updateSnakeCoord(&snake); printSnake(&snake); checkColision(&snake, &isDead, rows, columns, map, rocks, rocksNum, hasPassed, score); teleport(&snake, rows, columns); if(*score < 0) { *score = 0; //Não há score negativo! } cont++; //conta o número de movimentos if(cont % 10 == 0 && ratsEaten < objetivo) //a cada 10 movimentos gera um rato, se não for atingido o objetivo { makeRats(rows, columns, rats, ratNum, &snake, map, &ratsColor); ratNum++; if(ratNum == 4) { ratNum = 0; } } eatRat(&snake, rats, &ratsEaten, score, level); eatApple(&snake, &apple, score, &levelEnded); if(ratsEaten >= objetivo && eatenAllRats == 0) //gera maçã se forem comidos todos os ratos necessários { eatenAllRats = 1; makeApple(rows, columns, &apple, rats, ratNum, &snake, map); } if(isDead || snake.size == 1) //Se a cobra teve uma colisão fatal ou perdeu todo o corpo exceto a cabeça { Beep(700, 100); isDead = 0; (*lifes)--; ratsEaten = 0; //Se morrer, deve comer todos os ratos de novo if(*lifes > 0) //Se ainda há vidas, continua o jogo { system("cls"); print_lvlART(scenario, columns + 5, 0); restartLevel(&snake, columns, rows, rats, speed, &actualSpeed, initialCoord, &eatenAllRats); printMap(rows, columns, map, scenario.color); printRocks(rows, columns, rocksNum, rocks, map); printSnake(&snake); printInfo(level, *lifes, *score, ratsEaten, objetivo); getch(); //pausa o jogo } } Sleep(speed); //controla a velocidade do jogo if(speed > 100) //máxima velocidade do jogo speed -= 1; auxDirection = changeDirection(snake.direction); //lê nova direção to teclado if(auxDirection == 'P') { getch(); //Pausa o jogo } else if(auxDirection == 'C') { cheatCode(&(*lifes), &levelEnded, &speed); //Lê cheat code } else snake.direction = auxDirection; if(snake.direction == 'Q' || snake.direction == ESC) //Se o jogador aperta para sair, perde suas vidas para encerrar { *lifes = 0; } } fadeOUT(rows, columns, GREY, 1); //Efeito de fade out na tela system("cls"); }