void Game::OnExecute() { if (m_state != GameState::INIT_SUCCESSFUL) { std::cerr << "Game INIT was not successful." << std::endl; return; } m_state = GameState::RUNNING; CreateAsteroid(Asteroids::Asteroid::AsteroidSize::BIG, 1); SDL_Event event; while (m_state == GameState::RUNNING) { // Input polling // while (SDL_PollEvent(&event)) { OnEvent(&event); } // OnUpdate(); OnRender(); } }
void Game::CreateDebris(Asteroids::Entity* entity) { auto currentAsteroid = dynamic_cast < Asteroids::Asteroid* >(entity); if (currentAsteroid != nullptr && currentAsteroid->GetSize() != Asteroids::Asteroid::AsteroidSize::SMALL) { auto newSize = (currentAsteroid->GetSize() == Asteroids::Asteroid::AsteroidSize::BIG) ? Asteroids::Asteroid::AsteroidSize::MEDIUM : Asteroids::Asteroid::AsteroidSize::SMALL; CreateAsteroid(newSize, 2, currentAsteroid->GetX(), currentAsteroid->GetY()); } }
/*! \brief function void StartGame () is designed for the beginning of the start of the game. This function is implemented in the field of generation of food in a particular area and the size of the player The function code is as follows: \code void StartGame() { //the data of all objects in the beginning of the game srand(GetTickCount()); RECT r = {0,0,700,500}; for (int i=0;i<ASTEROID_COUNT;i++) { asteroids[i] = CreateAsteroid(r); } ship.Y = 100; ship.X = 100; ship.health = 20; ship.isSelected = false; } \endcode */ void StartGame() { ///the data of all objects in the beginning of the game srand(GetTickCount()); RECT r = {0,0,700,500}; for (int i=0;i<ASTEROID_COUNT;i++) { asteroids[i] = CreateAsteroid(r); } ship.Y = 100; ship.X = 100; ship.health = 20; ship.isSelected = false; }
void Asteroids::OnTimer(int value) { if (value == SHOW_GAME_OVER) { mGameOverLabel->SetVisible(true); } if (value == START_NEXT_LEVEL) { mLevel++; int num_asteroids = 10 + 2 * mLevel; for (int i = 0; i < num_asteroids; i++) { mGameWorld->AddObject(CreateAsteroid()); mAsteroidCount++; } } if (value == CREATE_NEW_PLAYER) { mSpaceship->Reset(); mGameWorld->AddObject(static_cast< SmartPtr<GameObject> >( mSpaceship )); } }
/*! \brief This function is responsible for drawing player, foods, background playing field and shows all the text in the game. As it prescribe management in our game. For control of the game and drawing the background playing field meets the code. \code switch (message) { case WM_CREATE: hBitmap = (HBITMAP)LoadImage(hInst, L"1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); break; case WM_KEYDOWN: switch (wParam) { //Repeat game case 'O': pause= !pause; break; case 'P': if(GameOver == 1) { GameOver=0; ship.health = 20; RECT r = {0,0,700,500}; for (int i=0;i<ASTEROID_COUNT;i++) { asteroids[i] = CreateAsteroid(r); } } break; } case WM_MOUSEMOVE: //Passing the coordinates of the mouse cursor. xPos = GET_X_LPARAM(lParam); targetx=xPos; yPos = GET_Y_LPARAM(lParam); targety=yPos; break; InvalidateRect(hWnd,NULL,1); break; \endcode This part of the code responsible for drawing player and foods. Drawing in WinApi performed using brushes and pens. With feathers, we draw the contours of our player and foods. With a brush paints we figure our color. \code case WM_PAINT: hdc = BeginPaint(hWnd, &ps); RECT rect; BITMAP bitmap; HDC hdcMem; HGDIOBJ oldBitmap; GetClientRect(hWnd, &rect); width=rect.right; height=rect.bottom; backbuffDC = CreateCompatibleDC(hdc); backbuffer = CreateCompatibleBitmap( hdc, width, height); savedDC = SaveDC(backbuffDC); SelectObject( backbuffDC, backbuffer ); // Draw HERE //clear window hBrush = CreateSolidBrush(RGB(255,0,255)); FillRect(backbuffDC,&rect,hBrush); DeleteObject(hBrush); hdcMem = CreateCompatibleDC(hdc);//! oldBitmap = SelectObject(hdcMem, hBitmap);//! //draw background GetObject(hBitmap, sizeof(bitmap), &bitmap);//! BitBlt(backbuffDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);//! //draw ball //Rectangle(backbuffDC,0, 0, 785, 663); //draw asteroids //Drawing food for (int i=0;i<ASTEROID_COUNT;i++) { hPen = CreatePen(PS_SOLID, 1, RGB(asteroids[i].dY, asteroids[i].dX, asteroids[i].dX+40)); hOldPen = (HPEN)SelectObject(backbuffDC, hPen); Ellipse(backbuffDC,asteroids[i].X-asteroids[i].r, asteroids[i].Y-asteroids[i].r,asteroids[i].X+asteroids[i].r,asteroids[i].Y+asteroids[i].r); SelectObject(backbuffDC, hOldPen); DeleteObject(hPen); hPen = CreatePen(PS_SOLID, asteroids[i].r, RGB(asteroids[i].dY, asteroids[i].dX, asteroids[i].dX+40)); hOldPen = (HPEN)SelectObject(backbuffDC, hPen); Ellipse(backbuffDC, asteroids[i].X - (asteroids[i].r/1.9), asteroids[i].Y - (asteroids[i].r/1.9),asteroids[i].X + (asteroids[i].r/1.9), asteroids[i].Y + (asteroids[i].r/1.9)); Ellipse(backbuffDC, asteroids[i].X - (asteroids[i].r/2.1), asteroids[i].Y - (asteroids[i].r/2.1),asteroids[i].X + (asteroids[i].r/2.1), asteroids[i].Y + (asteroids[i].r/2.1)); SelectObject(backbuffDC, hOldPen); DeleteObject(hPen); } //Drawing collor player hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); hOldPen = (HPEN)SelectObject(backbuffDC, hPen); Ellipse(backbuffDC,ship.X-ship.health,ship.Y-ship.health,ship.X+ship.health,ship.Y+ship.health); SelectObject(backbuffDC, hOldPen); DeleteObject(hPen); \endcode This part of the code responsible for entering text on a screen. To enter text on the screen creates an array of characters. Using this array, we can create the text. If the number of characters exceeds the specified number of the program will display an error. The text displayed on the screen at a certain place and under certain conditions. The implementation is shown below \code WCHAR s[30]; if(GameOver == 1){ wsprintf(s, _T("Game over!")); //Conclusion inscriptions "Game over!" TextOut(backbuffDC, 350, 250, s, wcslen(s)); wsprintf(s, _T("Replay enter P")); TextOut(backbuffDC, 350, 270, s, wcslen(s)); wsprintf(s,_T("score %d"),ship.health-20);// The conclusion points during the end game TextOut(backbuffDC,350,300,s,wcslen(s)); } else {wsprintf(s,_T("score %d"),ship.health-20);// The conclusion points during the game TextOut(backbuffDC,20,630,s,wcslen(s));} if(pause){ wsprintf(s, _T("Pause")); //Conclusion inscriptions "pause" TextOut(backbuffDC, 350, 250, s, wcslen(s)); } wsprintf(s,_T("ver 1.2.5"));//ver game TextOut(backbuffDC,700,630,s,wcslen(s)); wsprintf(s,_T("Replay enter P")); TextOut(backbuffDC,20,30,s,wcslen(s)); wsprintf(s,_T("Pause enter O")); TextOut(backbuffDC,20,50,s,wcslen(s)); \endcode */ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; int savedDC; HDC backbuffDC; int width, height; HBITMAP backbuffer; HBRUSH hBrush; int xPos, yPos; HPEN hPen, hOldPen; switch (message) { ///Paint background case WM_CREATE: hBitmap = (HBITMAP)LoadImage(hInst, L"1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); break; case WM_KEYDOWN: switch (wParam) { case 'O': pause= !pause; break; ///Repeat game case 'P': if(GameOver == 1) { GameOver=0; ship.health = 20; RECT r = {0,0,700,500}; for (int i=0;i<ASTEROID_COUNT;i++) { asteroids[i] = CreateAsteroid(r); } } break; } ///Passing the coordinates of the mouse cursor. case WM_MOUSEMOVE: xPos = GET_X_LPARAM(lParam); targetx=xPos; yPos = GET_Y_LPARAM(lParam); targety=yPos; break; InvalidateRect(hWnd,NULL,1); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); RECT rect; BITMAP bitmap; HDC hdcMem; HGDIOBJ oldBitmap; GetClientRect(hWnd, &rect); width=rect.right; height=rect.bottom; backbuffDC = CreateCompatibleDC(hdc); backbuffer = CreateCompatibleBitmap( hdc, width, height); savedDC = SaveDC(backbuffDC); SelectObject( backbuffDC, backbuffer ); ///clear window hBrush = CreateSolidBrush(RGB(255,0,255)); FillRect(backbuffDC,&rect,hBrush); DeleteObject(hBrush); hdcMem = CreateCompatibleDC(hdc);//! oldBitmap = SelectObject(hdcMem, hBitmap);//! ///draw background GetObject(hBitmap, sizeof(bitmap), &bitmap);//! BitBlt(backbuffDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);//! ///draw ball ///Rectangle(backbuffDC,0, 0, 785, 663); ///draw asteroids //Drawing food for (int i=0;i<ASTEROID_COUNT;i++) { hPen = CreatePen(PS_SOLID, 1, RGB(asteroids[i].dY, asteroids[i].dX, asteroids[i].dX+40)); hOldPen = (HPEN)SelectObject(backbuffDC, hPen); Ellipse(backbuffDC,asteroids[i].X-asteroids[i].r, asteroids[i].Y-asteroids[i].r,asteroids[i].X+asteroids[i].r,asteroids[i].Y+asteroids[i].r); SelectObject(backbuffDC, hOldPen); DeleteObject(hPen); hPen = CreatePen(PS_SOLID, asteroids[i].r, RGB(asteroids[i].dY, asteroids[i].dX, asteroids[i].dX+40)); hOldPen = (HPEN)SelectObject(backbuffDC, hPen); Ellipse(backbuffDC, asteroids[i].X - (asteroids[i].r/1.9), asteroids[i].Y - (asteroids[i].r/1.9),asteroids[i].X + (asteroids[i].r/1.9), asteroids[i].Y + (asteroids[i].r/1.9)); Ellipse(backbuffDC, asteroids[i].X - (asteroids[i].r/2.1), asteroids[i].Y - (asteroids[i].r/2.1),asteroids[i].X + (asteroids[i].r/2.1), asteroids[i].Y + (asteroids[i].r/2.1)); SelectObject(backbuffDC, hOldPen); DeleteObject(hPen); } ///Drawing collor player hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); hOldPen = (HPEN)SelectObject(backbuffDC, hPen); Ellipse(backbuffDC,ship.X-ship.health,ship.Y-ship.health,ship.X+ship.health,ship.Y+ship.health); SelectObject(backbuffDC, hOldPen); DeleteObject(hPen); WCHAR s[30]; if(GameOver == 1){ ///Conclusion inscriptions "Game over!" wsprintf(s, _T("Game over!")); TextOut(backbuffDC, 350, 250, s, wcslen(s)); wsprintf(s, _T("Replay enter P")); TextOut(backbuffDC, 350, 270, s, wcslen(s)); /// The conclusion points during the end game wsprintf(s,_T("score %d"),ship.health-20); TextOut(backbuffDC,350,300,s,wcslen(s)); } /// The conclusion points during the game else {wsprintf(s,_T("score %d"),ship.health-20); TextOut(backbuffDC,20,630,s,wcslen(s));} ///Conclusion inscriptions "pause" if(pause){ wsprintf(s, _T("Pause")); TextOut(backbuffDC, 350, 250, s, wcslen(s)); } wsprintf(s,_T("ver 1.2.5")); TextOut(backbuffDC,700,630,s,wcslen(s)); wsprintf(s,_T("Replay enter P")); TextOut(backbuffDC,20,30,s,wcslen(s)); wsprintf(s,_T("Pause enter O")); TextOut(backbuffDC,20,50,s,wcslen(s)); /// End application-specific layout section. BitBlt(hdc,0,0,width,height,backbuffDC,0,0,SRCCOPY); RestoreDC(backbuffDC,savedDC); DeleteObject(backbuffer); DeleteDC(backbuffDC); SelectObject(hdcMem, oldBitmap); DeleteDC(hdcMem); /// End drawing EndPaint(hWnd, &ps); break; /// Post Uninstall window background case WM_ERASEBKGND: return 1; /// The message about the destruction of the window case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; }
/*! \brief Function void DoPhysics responsible for all of physics in the game. In this function implements the player position on the playing field, check with player touch the food. While the player touched the food, score increased and if a player touched the food more than he that game over . The game ends when the player earns 100 points. \code for (int i=0;i<ASTEROID_COUNT;i++) { //repulsion of food from the walls asteroids[i].X -= ((double)dT/1000)*asteroids[i].dX; if ((asteroids[i].X-asteroids[i].r < 0) && (asteroids[i].dX > 0) || (asteroids[i].X+asteroids[i].r > 785) && (asteroids[i].dX < 0)) { asteroids[i].dX= -1* asteroids[i].dX; } asteroids[i].Y -= ((double)dT/1000)*asteroids[i].dY; if ((asteroids[i].Y-asteroids[i].r < 0) && (asteroids[i].dY > 0) || (asteroids[i].Y+asteroids[i].r > 663) && (asteroids[i].dY < 0) ) { asteroids[i].dY= -1* asteroids[i].dY; } //check for player collision with food and increase its size double dx = asteroids[i].X - ship.X; double dy = asteroids[i].Y - ship.Y; if (sqrt(dx*dx + dy*dy) <= asteroids[i].r + ship.health) { if(asteroids[i].r>ship.health) { GameOver=1; } else { ship.health += asteroids[i].r/10; asteroids[i] = CreateAsteroid(r); } } //check for a collision between a food and the absorption more less for (int z=1;z<ASTEROID_COUNT-i;z++) { double dX = asteroids[i].X - asteroids[i+z].X ; double dY = asteroids[i].Y - asteroids[i+z].Y ; if (sqrt(dX*dX + dY*dY) <= asteroids[i].r+asteroids[i+1].r) { if(asteroids[i].r < asteroids[i+z].r) { asteroids[i+z].r+=asteroids[i].r; asteroids[i] = CreateAsteroid(r); } else { asteroids[i].r+=asteroids[i+z].r; asteroids[i+z] = CreateAsteroid(r); } } } //the condition of finishing the game if (ship.health>120) { GameOver=1; } } \endcode */ void DoPhysics(ULONGLONG dT) { RECT r = {0,0,785,663}; ///the player position and speed of the food at the end of the game if(GameOver == 1) { ship.X=100; ship.Y=100; for (int i=0;i<ASTEROID_COUNT;i++) { asteroids[i].dX=0; asteroids[i].dY=0; } } for (int i=0;i<ASTEROID_COUNT;i++) { ///repulsion of food from the walls asteroids[i].X -= ((double)dT/1000)*asteroids[i].dX; if ((asteroids[i].X-asteroids[i].r < 0) && (asteroids[i].dX > 0) || (asteroids[i].X+asteroids[i].r > 785) && (asteroids[i].dX < 0)) { asteroids[i].dX= -1* asteroids[i].dX; } asteroids[i].Y -= ((double)dT/1000)*asteroids[i].dY; if ((asteroids[i].Y-asteroids[i].r < 0) && (asteroids[i].dY > 0) || (asteroids[i].Y+asteroids[i].r > 663) && (asteroids[i].dY < 0) ) { asteroids[i].dY= -1* asteroids[i].dY; } ///check for player collision with food and increase its size double dx = asteroids[i].X - ship.X; double dy = asteroids[i].Y - ship.Y; if (sqrt(dx*dx + dy*dy) <= asteroids[i].r + ship.health) { if(asteroids[i].r>ship.health) { GameOver=1; } else { ship.health += asteroids[i].r/10; asteroids[i] = CreateAsteroid(r); } } ///check for a collision between a food and the absorption more less for (int z=1;z<ASTEROID_COUNT-i;z++) { double dX = asteroids[i].X - asteroids[i+z].X ; double dY = asteroids[i].Y - asteroids[i+z].Y ; if (sqrt(dX*dX + dY*dY) <= asteroids[i].r+asteroids[i+1].r) { if(asteroids[i].r < asteroids[i+z].r) { asteroids[i+z].r+=asteroids[i].r; asteroids[i] = CreateAsteroid(r); } else { asteroids[i].r+=asteroids[i+z].r; asteroids[i+z] = CreateAsteroid(r); } } } ///the condition of finishing the game if (ship.health>120) { GameOver=1; } } ///The player speed by X and Y (if the speed decreases) if(GameOver==0){ ship.vx= (targetx-ship.X); ship.vy= (targety-ship.Y); ship.vy=ship.vy/ship.health*30; ship.vx=ship.vx/ship.health*30; ship.X += ((double)dT/1000)*ship.vx; ship.Y += ((double)dT/1000)*ship.vy; } }
/** Start an asteroids game. */ void Asteroids::Start() { // Add a player (watcher) to the game world mGameWorld->AddListener(&mPlayer); // Add a score keeper to the game world mGameWorld->AddListener(&mScoreKeeper); // Add this class as a listener of the score keeper mScoreKeeper.AddListener(this); // Add this class as a listener of the game world mGameWorld->AddListener(this); // Add this class as a listener of the player mPlayer.AddListener(this); // Create user interface CreateGUI(); // Create an ambient light to show sprite textures GLfloat ambient_light[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat diffuse_light[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_light); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_light); glEnable(GL_LIGHT1); mSelectedShape = new Shape("ASSETS/selected.shape"); Animation *explosion_anim = AnimationManager::GetInstance().CreateAnimationFromRawRGBA("explosion", 64, 1024, 64, 64, "ASSETS/explosion_fs.raw", "ASSETS/explosion_fs_alpha.raw"); Animation *asteroid1_anim = AnimationManager::GetInstance().CreateAnimationFromRawRGBA("asteroid1", 128, 8192, 128, 128, "ASSETS/asteroid1_fs.raw", "ASSETS/asteroid1_fs_alpha.raw"); Animation *asteroidOre1_anim = AnimationManager::GetInstance().CreateAnimationFromRawRGBA("asteroidOre1", 128, 8192, 128, 128, "ASSETS/asteroidOre1_fs.raw", "ASSETS/asteroidOre1_fs_alpha.raw"); //Animation *droid_anim = AnimationManager::GetInstance().CreateAnimationFromRawRGBA("droid1", ); Animation *spaceship_anim = AnimationManager::GetInstance().CreateAnimationFromRawRGBA("spaceship", 128, 128, 128, 128, "ASSETS/spaceship_fs.raw", "ASSETS/spaceship_fs_alpha.raw"); // Add this as a listener to the world and the keyboard mGameWindow->AddKeyboardListener(this); // Add this as a listener to the world and the mouse mGameWindow->AddMouseListener(this); // Add the selection box to the world mGameWorld->GiveSelectionBox(mSelectionBox); // Create a spaceship and add it to the world //mGameWorld->AddObject(CreateSpaceship()); // Create some asteroids and add them to the world mLevel = 1; mAsteroidCount = 1; int w = mGameDisplay->GetWidth(); int h = mGameDisplay->GetHeight(); cout << "width : " << w; cout << "height : " << h; // creating asteroids for (int i = 0; i < 10; i++) { int x = (rand() % w) - w/2; int y = (rand() % h) - h/2; mGameWorld->AddObject(CreateAsteroid(x,y)); mAsteroidCount++; } //creating ore asteroids for (int i = 0; i < 10; i++) { int x = (rand() % w) - w/2; int y = (rand() % h) - h/2; mGameWorld->AddObject(CreateAsteroidOre(x,y)); mAsteroidCount++; } // creating drones float rAngle = 0; GLVector3f zero(0.0, 0.0, 0.0); for(int i = 0; i < 2; i++){ GLVector3f new_drone_offset(cos(DEG2RAD*rAngle), sin(DEG2RAD*rAngle), 0.0); new_drone_offset.normalize(); GLVector3f drone_position = zero + (new_drone_offset * 20); mGameWorld->AddObject(CreateDrone(drone_position.x,drone_position.y)); rAngle += 360 / 2; } // creaing a single ore for testing mGameWorld->AddObject(CreateOre(100,0)); // Start the game GameSession::Start(); }
void Asteroids::OnObjectRemoved(GameWorld* world, SmartPtr<GameObject> object) { if (object->GetType() == GameObjectType("Asteroid")) { SmartPtr<GameObject> explosion = CreateExplosion(); explosion->SetPosition(object->GetPosition()); explosion->SetRotation(object->GetRotation()); mGameWorld->AddObject(explosion); mAsteroidCount--; if(object->GetScale() > 0.2) { float newVel[4][2] = { {-1.0,-1.0}, { 1.0,-1.0}, { 1.0, 1.0}, {-1.0, 1.0} }; GLVector3f obPos = object->GetPosition(); for(int i = 0; i < 4; i++) { SmartPtr<GameObject> newAsteroid = CreateAsteroid(obPos.x, obPos.y); float f = 5; //force newAsteroid->SetVelocity(GLVector3f(newVel[i][0] * f + (rand() % 4), newVel[i][1] * f + (rand() % 4), 0.0)); newAsteroid->SetScale(object->GetScale()/2); mGameWorld->AddObject(newAsteroid); mAsteroidCount++; } } if (mAsteroidCount <= 0) { SetTimer(500, START_NEXT_LEVEL); } } if (object->GetType() == GameObjectType("AsteroidOre")) { SmartPtr<GameObject> explosion = CreateExplosion(); explosion->SetPosition(object->GetPosition()); explosion->SetRotation(object->GetRotation()); mGameWorld->AddObject(explosion); float newPos[4][2] = { {-1.0,-1.0}, { 1.0,-1.0}, { 1.0, 1.0}, {-1.0, 1.0} }; GLVector3f obPos = object->GetPosition(); float obRot = object->GetRotation(); int sep = 5; // how much to separate the ore fromt he position of the asteroid for(int i = 0; i < 4; i++) { SmartPtr<GameObject> ore = CreateOre(); ore->SetPosition(GLVector3f(obPos.x + newPos[i][0] * sep + (rand() % 4), obPos.y + newPos[i][1] * sep + (rand() % 4), 0.0)); ore->SetRotation(obRot); mGameWorld->AddObject(ore); } int noA = 1 + (rand() % 3); cout << "RAND A: " << noA << endl; for (int i = 0; i < noA; i++) { SmartPtr<GameObject> newAsteroid = CreateAsteroid(obPos.x, obPos.y); float rA = rand() % 360; // a random angle cout << "RAND ANGLE: " << rA << endl; newAsteroid->SetVelocity(GLVector3f( cos(DEG2RAD * rA), sin(DEG2RAD * rA), 0.0)); cout << "Object Scale: " << object->GetScale() << endl; newAsteroid->SetScale(object->GetScale()); mGameWorld->AddObject(newAsteroid); mAsteroidCount++; } } }