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; }
void Game::update() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float dt = FRAMETIME_SECONDS; //Get delta mouse movement int mousedx, mousedy; SDL_GetRelativeMouseState(&mousedx, &mousedy); // Apply mouse movement to view player.rotation->x -= mousedy * sensitivity; player.rotation->y -= mousedx * sensitivity; // Restrict rotation in horizontal axis if(player.rotation->x < -1.5f) player.rotation->x = -1.5f; if(player.rotation->x > 1.5f) player.rotation->x = 1.5f; if(!player.isDead() && !player.hasWon()) { // Reset x and z speed player.velocity->x = 0; player.velocity->z = 0; // Apply gravity to yspeed player.velocity->y -= GRAVITY*dt; if(player.velocity->y < -MAXSPEED) player.velocity->y = -MAXSPEED; if(player.velocity->y > MAXSPEED) player.velocity->y = MAXSPEED; // Move forward if(keystates['w']) { player.velocity->z -= cos(player.rotation->y)*PLAYER_MOVESPEED*dt; player.velocity->x -= sin(player.rotation->y)*PLAYER_MOVESPEED*dt; } // Move backward if(keystates['s']) { player.velocity->z += cos(player.rotation->y)*PLAYER_MOVESPEED*dt; player.velocity->x += sin(player.rotation->y)*PLAYER_MOVESPEED*dt; } // Strafe left if(keystates['a']) { player.velocity->x -= cos(player.rotation->y)*PLAYER_MOVESPEED*dt; player.velocity->z += sin(player.rotation->y)*PLAYER_MOVESPEED*dt; } // Strafe right if(keystates['d']) { player.velocity->x += cos(player.rotation->y)*PLAYER_MOVESPEED*dt; player.velocity->z -= sin(player.rotation->y)*PLAYER_MOVESPEED*dt; } if(keystates[' '] && (player.isOnGround() || gameMap.jetpackIsEnabled())) { if(player.isOnGround()) { player.velocity->y = JUMPPOWER; } } if(keystates[225]) { if(gameMap.jetpackIsEnabled()) { player.velocity->y += JETPACK_ACC*dt; } } // Disable portals if R is held if(keystates['r']) { portals[0].disable(); portals[1].disable(); } float newx = player.position->x + player.velocity->x * dt; float newy = player.position->y + player.velocity->y * dt; float newz = player.position->z + player.velocity->z * dt; Box bbox; bbox.set(newx-0.5, player.position->y, player.position->z-0.5, newx+0.5, player.position->y+1.8, player.position->z+0.5); if(gameMap.collidesWithWall(bbox) == false || portals[0].inPortal(bbox) || portals[1].inPortal(bbox)) { player.position->x = newx; } // Check for collision in y-axis bbox.set(player.position->x-0.5, player.position->y, newz-0.5, player.position->x+0.5, player.position->y+1.8, newz+0.5); if(gameMap.collidesWithWall(bbox) == false || portals[0].inPortal(bbox) || portals[1].inPortal(bbox)) { player.position->z = newz; } // Check for collision in z-axis bbox.set(player.position->x-0.5, newy, player.position->z-0.5, player.position->x+0.5, newy+1.8, player.position->z+0.5); player.setOffGround(); if(gameMap.collidesWithWall(bbox) == false || portals[0].inPortal(bbox) || portals[1].inPortal(bbox)) { player.position->y = newy; } else { // If player was falling it means must have hit the ground if(player.velocity->y < 0) { player.setOnGround(); } player.velocity->y = 0; } // Check if player has fallen into an acid pool bbox.set(player.position->x-0.5, player.position->y, player.position->z-0.5, player.position->x+0.5, player.position->y+1.8, player.position->z+0.5); if(gameMap.collidesWithAcid(bbox) == true) { player.kill(); } // Check if player has fallen into void if(player.position->y <= -30) { player.kill(); } // Check if player has taken the cake if(gameMap.collidesWithCake(bbox) == true) { player.setHasWon(); } // Check if player has entered a portal if(portalsActive()) { for(int i = 0; i < 2; i++) { if(portals[i].throughPortal(player.position->x, player.position->y+0.9f,player.position->z)) { // Calculate rotation between portals float rotation = 0.f; rotation += portals[i].getToRotation()*DEGRAD; rotation += portals[(i+1)%2].getFromRotation()*DEGRAD; player.rotation->y += rotation; // Distance from portal to player float xdist = player.position->x - portals[i].position.x; float zdist = player.position->z - portals[i].position.z; // Calculate this distance when rotated float nxdist = xdist*cos(rotation) + zdist*sin(rotation); float nzdist = zdist*cos(rotation) - xdist*sin(rotation); // Move player to destination portal player.position->x = portals[(i+1)%2].position.x + nxdist; player.position->y = player.position->y + portals[(i+1)%2].position.y - portals[i].position.y; player.position->z = portals[(i+1)%2].position.z + nzdist; } } } } // If player is dying else if(player.isDead()) { player.position->y -= (0.60f*dt); } // Update shots and check their collision with walls for(int i = 0; i < 2; i++) { Shot *shot = &shots[i]; if(shot->active) { shot->update(dt); Box sbox; if(gameMap.pointInWall(shot->position.x, shot->position.y, shot->position.z, &sbox)) { shot->update(-dt); // Reverse time to before collision // Collision really should be interpolated instead if(sbox.type == TID_WALL) { portals[i].placeOnBox(sbox, shot->position.x, shot->position.y, shot->position.z, gameMap); } shot->active = false; } } } }