This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
user:ccornair:portfolio:hpc1 [2013/12/14 02:28] – ccornair | user:ccornair:portfolio:hpc1 [2013/12/14 02:33] (current) – ccornair | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====Objective==== | ||
+ | |||
+ | To build a tetris game using tutorials | ||
+ | |||
+ | ====Prerequisites==== | ||
+ | |||
+ | found a tetris tutorial | ||
+ | |||
+ | ====Background==== | ||
+ | |||
+ | is a tile-matching puzzle video game originally designed and programmed by Alexey Pajitnov in the Soviet Union. It was released on June 6, 1984,[1] while he was working for the Dorodnicyn Computing Centre of the Academy of Science of the USSR in Moscow.[2] He derived its name from the Greek numerical prefix tetra- (all of the game's pieces contain four segments) and tennis, Pajitnov' | ||
+ | |||
+ | It is also the first entertainment software to be exported from the USSR to the US and published by Spectrum HoloByte for Commodore 64 and IBM PC. The Tetris game is a popular use of tetrominoes, | ||
+ | |||
+ | ====Code==== | ||
+ | |||
+ | Defines.h | ||
+ | < | ||
+ | |||
+ | #pragma once | ||
+ | // Window related defines // | ||
+ | #define WINDOW_WIDTH | ||
+ | #define WINDOW_HEIGHT | ||
+ | #define WINDOW_CAPTION " | ||
+ | |||
+ | // Game related defines // | ||
+ | #define FRAMES_PER_SECOND 30 | ||
+ | #define FRAME_RATE | ||
+ | |||
+ | #define GAME_AREA_LEFT | ||
+ | #define GAME_AREA_RIGHT | ||
+ | #define GAME_AREA_BOTTOM 298 | ||
+ | |||
+ | #define NUM_LEVELS | ||
+ | #define POINTS_PER_LINE | ||
+ | #define POINTS_PER_LEVEL 6300 | ||
+ | |||
+ | #define INITIAL_SPEED | ||
+ | #define SPEED_CHANGE | ||
+ | |||
+ | |||
+ | #define SLIDE_TIME | ||
+ | |||
+ | #define SQUARES_PER_ROW | ||
+ | #define SQUARE_MEDIAN | ||
+ | |||
+ | // Starting position of the focus block // | ||
+ | #define BLOCK_START_X | ||
+ | #define BLOCK_START_Y | ||
+ | |||
+ | // Location on game screen for displaying... // | ||
+ | #define LEVEL_RECT_X | ||
+ | #define LEVEL_RECT_Y | ||
+ | #define SCORE_RECT_X | ||
+ | #define SCORE_RECT_Y | ||
+ | #define NEEDED_SCORE_RECT_X 42 // score needed for next level | ||
+ | #define NEEDED_SCORE_RECT_Y 360 | ||
+ | #define NEXT_BLOCK_CIRCLE_X 214 // next block in line to be focus block | ||
+ | #define NEXT_BLOCK_CIRCLE_Y 347 | ||
+ | |||
+ | // Locations within bitmap of background screens // | ||
+ | #define LEVEL_ONE_X | ||
+ | #define LEVEL_ONE_Y | ||
+ | #define LEVEL_TWO_X | ||
+ | #define LEVEL_TWO_Y | ||
+ | #define LEVEL_THREE_X 300 | ||
+ | #define LEVEL_THREE_Y 0 | ||
+ | #define LEVEL_FOUR_X | ||
+ | #define LEVEL_FOUR_Y | ||
+ | #define LEVEL_FIVE_X | ||
+ | #define LEVEL_FIVE_Y | ||
+ | |||
+ | // Location within bitmap of colored squares // | ||
+ | #define RED_SQUARE_X | ||
+ | #define RED_SQUARE_Y | ||
+ | #define PURPLE_SQUARE_X 620 | ||
+ | #define PURPLE_SQUARE_Y 400 | ||
+ | #define GREY_SQUARE_X | ||
+ | #define GREY_SQUARE_Y | ||
+ | #define BLUE_SQUARE_X | ||
+ | #define BLUE_SQUARE_Y | ||
+ | #define GREEN_SQUARE_X | ||
+ | #define GREEN_SQUARE_Y | ||
+ | #define BLACK_SQUARE_X | ||
+ | #define BLACK_SQUARE_Y | ||
+ | #define YELLOW_SQUARE_X 720 | ||
+ | #define YELLOW_SQUARE_Y 400 | ||
+ | |||
+ | </ | ||
+ | |||
+ | enums.h | ||
+ | |||
+ | < | ||
+ | |||
+ | #pragma once | ||
+ | |||
+ | enum BlockType | ||
+ | { | ||
+ | SQUARE_BLOCK, | ||
+ | T_BLOCK, | ||
+ | L_BLOCK, | ||
+ | BACKWARDS_L_BLOCK, | ||
+ | STRAIGHT_BLOCK, | ||
+ | S_BLOCK, | ||
+ | BACKWARDS_S_BLOCK | ||
+ | }; | ||
+ | |||
+ | enum Direction | ||
+ | { | ||
+ | LEFT, | ||
+ | RIGHT, | ||
+ | DOWN | ||
+ | }; | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | cSquare.h | ||
+ | < | ||
+ | |||
+ | #pragma once | ||
+ | |||
+ | #include " | ||
+ | |||
+ | class cBlock | ||
+ | { | ||
+ | private: | ||
+ | |||
+ | int m_CenterX; | ||
+ | int m_CenterY; | ||
+ | |||
+ | |||
+ | BlockType m_Type; | ||
+ | |||
+ | |||
+ | cSquare* m_Squares[4]; | ||
+ | |||
+ | public: | ||
+ | |||
+ | cBlock(int x, int y, SDL_Surface* bitmap, BlockType type) : m_CenterX(x), | ||
+ | m_Type(type) | ||
+ | { | ||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | m_Squares[i] = NULL; | ||
+ | } | ||
+ | |||
+ | SetupSquares(x, | ||
+ | } | ||
+ | |||
+ | |||
+ | void SetupSquares(int x, int y, SDL_Surface* bitmap) | ||
+ | { | ||
+ | |||
+ | m_CenterX = x; | ||
+ | m_CenterY = y; | ||
+ | |||
+ | // Make sure that any current squares are deleted // | ||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | if (m_Squares[i]) | ||
+ | delete m_Squares[i]; | ||
+ | } | ||
+ | |||
+ | switch (m_Type) | ||
+ | { | ||
+ | case SQUARE_BLOCK: | ||
+ | { | ||
+ | |||
+ | m_Squares[0] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | |||
+ | m_Squares[1] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | |||
+ | m_Squares[2] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Lower right // | ||
+ | m_Squares[3] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | } break; | ||
+ | case T_BLOCK: | ||
+ | { | ||
+ | // Top // | ||
+ | m_Squares[0] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Middle // | ||
+ | m_Squares[1] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Left // | ||
+ | m_Squares[2] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | // Right // | ||
+ | m_Squares[3] = new cSquare(x + (SQUARE_MEDIAN * 3), y + SQUARE_MEDIAN, | ||
+ | } break; | ||
+ | case L_BLOCK: | ||
+ | { | ||
+ | |||
+ | m_Squares[0] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | |||
+ | m_Squares[1] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | |||
+ | m_Squares[2] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | | ||
+ | m_Squares[3] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | } break; | ||
+ | case BACKWARDS_L_BLOCK: | ||
+ | { | ||
+ | // | // | ||
+ | m_Squares[0] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // | // | ||
+ | m_Squares[1] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // _| // | ||
+ | m_Squares[2] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // __ // | ||
+ | m_Squares[3] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | } break; | ||
+ | case STRAIGHT_BLOCK: | ||
+ | { | ||
+ | // Top // | ||
+ | m_Squares[0] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | m_Squares[1] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | m_Squares[2] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | m_Squares[3] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Bottom // | ||
+ | } break; | ||
+ | case S_BLOCK: | ||
+ | { | ||
+ | // Top right // | ||
+ | m_Squares[0] = new cSquare(x + (SQUARE_MEDIAN * 3), y - SQUARE_MEDIAN, | ||
+ | // Top middle // | ||
+ | m_Squares[1] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Bottom middle // | ||
+ | m_Squares[2] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Bottom left // | ||
+ | m_Squares[3] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | } break; | ||
+ | case BACKWARDS_S_BLOCK: | ||
+ | { | ||
+ | // Top left // | ||
+ | m_Squares[0] = new cSquare(x - SQUARE_MEDIAN, | ||
+ | // Top middle // | ||
+ | m_Squares[1] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Bottom middle // | ||
+ | m_Squares[2] = new cSquare(x + SQUARE_MEDIAN, | ||
+ | // Bottom right // | ||
+ | m_Squares[3] = new cSquare(x + (SQUARE_MEDIAN * 3), y + SQUARE_MEDIAN, | ||
+ | } break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void Draw(SDL_Surface* Window) | ||
+ | { | ||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | m_Squares[i]-> | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void Move(Direction dir) | ||
+ | { | ||
+ | switch (dir) | ||
+ | { | ||
+ | case LEFT: | ||
+ | { | ||
+ | m_CenterX -= SQUARE_MEDIAN * 2; | ||
+ | } break; | ||
+ | case RIGHT: | ||
+ | { | ||
+ | m_CenterX += SQUARE_MEDIAN * 2; | ||
+ | } break; | ||
+ | case DOWN: | ||
+ | { | ||
+ | m_CenterY += SQUARE_MEDIAN*2; | ||
+ | } break; | ||
+ | } | ||
+ | |||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | m_Squares[i]-> | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void Rotate() | ||
+ | { | ||
+ | int x1, y1, x2, y2; | ||
+ | |||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | x1 = m_Squares[i]-> | ||
+ | y1 = m_Squares[i]-> | ||
+ | |||
+ | x1 -= m_CenterX; | ||
+ | y1 -= m_CenterY; | ||
+ | |||
+ | x2 = - y1; | ||
+ | y2 = x1; | ||
+ | |||
+ | x2 += m_CenterX; | ||
+ | y2 += m_CenterY; | ||
+ | |||
+ | m_Squares[i]-> | ||
+ | m_Squares[i]-> | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | int* GetRotatedSquares() | ||
+ | { | ||
+ | int* temp_array = new int[8]; | ||
+ | int x1, y1, x2, y2; | ||
+ | |||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | x1 = m_Squares[i]-> | ||
+ | y1 = m_Squares[i]-> | ||
+ | |||
+ | x1 -= m_CenterX; | ||
+ | y1 -= m_CenterY; | ||
+ | |||
+ | x2 = - y1; | ||
+ | y2 = x1; | ||
+ | |||
+ | x2 += m_CenterX; | ||
+ | y2 += m_CenterY; | ||
+ | |||
+ | temp_array[i*2] | ||
+ | temp_array[i*2+1] = y2; | ||
+ | } | ||
+ | |||
+ | return temp_array; | ||
+ | } | ||
+ | |||
+ | |||
+ | cSquare** GetSquares() | ||
+ | { | ||
+ | return m_Squares; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | main.cpp | ||
+ | < | ||
+ | |||
+ | |||
+ | #pragma comment(lib, | ||
+ | #pragma comment(lib, | ||
+ | #pragma comment(lib, | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | |||
+ | struct StateStruct | ||
+ | { | ||
+ | void (*StatePointer)(); | ||
+ | }; | ||
+ | |||
+ | // Global data // | ||
+ | stack< | ||
+ | SDL_Surface* | ||
+ | SDL_Surface* | ||
+ | SDL_Event | ||
+ | int | ||
+ | integer | ||
+ | cBlock* | ||
+ | cBlock* | ||
+ | block | ||
+ | vector< | ||
+ | int | ||
+ | int | ||
+ | int | ||
+ | |||
+ | // Init and Shutdown functions // | ||
+ | void Init(); | ||
+ | void Shutdown(); | ||
+ | |||
+ | // Functions to handle the states of the game // | ||
+ | void Menu(); | ||
+ | void Game(); | ||
+ | void Exit(); | ||
+ | void GameWon(); | ||
+ | void GameLost(); | ||
+ | |||
+ | |||
+ | void DrawBackground(); | ||
+ | void ClearScreen(); | ||
+ | void DisplayText(string text, int x, int y, int size, int fR, int fG, int fB, int bR, int bG, int bB); | ||
+ | void HandleMenuInput(); | ||
+ | void HandleGameInput(); | ||
+ | void HandleExitInput(); | ||
+ | void HandleWinLoseInput(); | ||
+ | bool CheckEntityCollisions(cSquare* square, Direction dir); | ||
+ | bool CheckWallCollisions(cSquare* square, Direction dir); | ||
+ | bool CheckEntityCollisions(cBlock* block, Direction dir); | ||
+ | bool CheckWallCollisions(cBlock* block, Direction dir); | ||
+ | bool CheckRotationCollisions(cBlock* block); | ||
+ | void CheckWin(); | ||
+ | void CheckLoss(); | ||
+ | void HandleBottomCollision(); | ||
+ | void ChangeFocusBlock(); | ||
+ | int CheckCompletedLines(); | ||
+ | |||
+ | int main(int argc, char **argv) | ||
+ | { | ||
+ | Init(); | ||
+ | |||
+ | |||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.top().StatePointer(); | ||
+ | } | ||
+ | |||
+ | Shutdown(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | void Init() | ||
+ | { | ||
+ | |||
+ | SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER); | ||
+ | g_Window = SDL_SetVideoMode(WINDOW_WIDTH, | ||
+ | SDL_WM_SetCaption(WINDOW_CAPTION, | ||
+ | g_Timer = SDL_GetTicks(); | ||
+ | |||
+ | |||
+ | g_Bitmap = SDL_LoadBMP(" | ||
+ | |||
+ | // Seed our random number generator // | ||
+ | srand( time(0) ); | ||
+ | |||
+ | // Initialize blocks and set them to their proper locations. // | ||
+ | g_FocusBlock = new cBlock(BLOCK_START_X, | ||
+ | g_NextBlock | ||
+ | |||
+ | |||
+ | StateStruct state; | ||
+ | state.StatePointer = Exit; | ||
+ | g_StateStack.push(state); | ||
+ | |||
+ | |||
+ | state.StatePointer = Menu; | ||
+ | g_StateStack.push(state); | ||
+ | |||
+ | // Initialize the true type font library // | ||
+ | TTF_Init(); | ||
+ | } | ||
+ | |||
+ | |||
+ | void Shutdown() | ||
+ | { | ||
+ | // Shutdown the true type font library // | ||
+ | TTF_Quit(); | ||
+ | |||
+ | // Free our surfaces // | ||
+ | SDL_FreeSurface(g_Bitmap); | ||
+ | SDL_FreeSurface(g_Window); | ||
+ | |||
+ | |||
+ | cSquare** temp_array_1 = g_FocusBlock-> | ||
+ | cSquare** temp_array_2 = g_NextBlock-> | ||
+ | |||
+ | // Delete our blocks // | ||
+ | delete g_FocusBlock; | ||
+ | delete g_NextBlock; | ||
+ | |||
+ | // Delete the temporary arrays of squares // | ||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | delete temp_array_1[i]; | ||
+ | delete temp_array_2[i]; | ||
+ | } | ||
+ | |||
+ | // Delete the squares that are in the game area // | ||
+ | for (int i=0; i< | ||
+ | { | ||
+ | delete g_OldSquares[i]; | ||
+ | } | ||
+ | |||
+ | // Tell SDL to shutdown and free any resources it was using // | ||
+ | SDL_Quit(); | ||
+ | } | ||
+ | |||
+ | |||
+ | void Menu() | ||
+ | { | ||
+ | |||
+ | if ( (SDL_GetTicks() - g_Timer) >= FRAME_RATE ) | ||
+ | { | ||
+ | |||
+ | HandleMenuInput(); | ||
+ | |||
+ | |||
+ | ClearScreen(); | ||
+ | |||
+ | DisplayText(" | ||
+ | DisplayText(" | ||
+ | |||
+ | |||
+ | SDL_UpdateRect(g_Window, | ||
+ | g_Timer = SDL_GetTicks(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void Game() | ||
+ | { | ||
+ | |||
+ | static int force_down_counter = 0; | ||
+ | |||
+ | static int slide_counter = SLIDE_TIME; | ||
+ | if ( (SDL_GetTicks() - g_Timer) >= FRAME_RATE ) | ||
+ | { | ||
+ | HandleGameInput(); | ||
+ | |||
+ | force_down_counter++; | ||
+ | |||
+ | if (force_down_counter >= g_FocusBlockSpeed) | ||
+ | { | ||
+ | // Always check for collisions before moving anything // | ||
+ | if ( !CheckWallCollisions(g_FocusBlock, | ||
+ | { | ||
+ | g_FocusBlock-> | ||
+ | force_down_counter = 0; // reset our counter | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | if ( CheckWallCollisions(g_FocusBlock, | ||
+ | { | ||
+ | slide_counter--; | ||
+ | } | ||
+ | |||
+ | else | ||
+ | { | ||
+ | slide_counter = SLIDE_TIME; | ||
+ | } | ||
+ | |||
+ | if (slide_counter == 0) | ||
+ | { | ||
+ | slide_counter = SLIDE_TIME; | ||
+ | HandleBottomCollision(); | ||
+ | } | ||
+ | |||
+ | // Make sure nothing from the last frame is still drawn. // | ||
+ | ClearScreen(); | ||
+ | |||
+ | // Draw the background // | ||
+ | DrawBackground(); | ||
+ | |||
+ | // Draw the focus block and next block. // | ||
+ | g_FocusBlock-> | ||
+ | g_NextBlock-> | ||
+ | |||
+ | // Draw the old squares. // | ||
+ | for (int i=0; i < g_OldSquares.size(); | ||
+ | { | ||
+ | g_OldSquares[i]-> | ||
+ | } | ||
+ | |||
+ | // Draw the text for the current level, score, and needed score. // | ||
+ | |||
+ | |||
+ | char temp[256]; | ||
+ | |||
+ | string score = " | ||
+ | itoa(g_Score, | ||
+ | score.append( temp ); | ||
+ | |||
+ | string nextscore = " | ||
+ | itoa(g_Level*POINTS_PER_LEVEL, | ||
+ | nextscore.append(temp); | ||
+ | |||
+ | string level = " | ||
+ | itoa(g_Level, | ||
+ | level.append(temp); | ||
+ | |||
+ | DisplayText(score, | ||
+ | DisplayText(nextscore, | ||
+ | DisplayText(level, | ||
+ | |||
+ | |||
+ | SDL_UpdateRect(g_Window, | ||
+ | |||
+ | |||
+ | g_Timer = SDL_GetTicks(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void Exit() | ||
+ | { | ||
+ | |||
+ | if ( (SDL_GetTicks() - g_Timer) >= FRAME_RATE ) | ||
+ | { | ||
+ | HandleExitInput(); | ||
+ | |||
+ | // Make sure nothing from the last frame is still drawn. // | ||
+ | ClearScreen(); | ||
+ | |||
+ | DisplayText(" | ||
+ | |||
+ | |||
+ | SDL_UpdateRect(g_Window, | ||
+ | |||
+ | |||
+ | g_Timer = SDL_GetTicks(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Display a victory message. // | ||
+ | void GameWon() | ||
+ | { | ||
+ | if ( (SDL_GetTicks() - g_Timer) >= FRAME_RATE ) | ||
+ | { | ||
+ | HandleWinLoseInput(); | ||
+ | |||
+ | ClearScreen(); | ||
+ | |||
+ | DisplayText(" | ||
+ | DisplayText(" | ||
+ | |||
+ | SDL_UpdateRect(g_Window, | ||
+ | |||
+ | g_Timer = SDL_GetTicks(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Display a game over message. // | ||
+ | void GameLost() | ||
+ | { | ||
+ | if ( (SDL_GetTicks() - g_Timer) >= FRAME_RATE ) | ||
+ | { | ||
+ | HandleWinLoseInput(); | ||
+ | |||
+ | ClearScreen(); | ||
+ | |||
+ | DisplayText(" | ||
+ | DisplayText(" | ||
+ | |||
+ | SDL_UpdateRect(g_Window, | ||
+ | |||
+ | g_Timer = SDL_GetTicks(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // This function draws the background // | ||
+ | void DrawBackground() | ||
+ | { | ||
+ | SDL_Rect source; | ||
+ | |||
+ | |||
+ | switch (g_Level) | ||
+ | { | ||
+ | case 1: | ||
+ | { | ||
+ | SDL_Rect temp = { LEVEL_ONE_X, | ||
+ | source = temp; | ||
+ | } break; | ||
+ | case 2: | ||
+ | { | ||
+ | SDL_Rect temp = { LEVEL_TWO_X, | ||
+ | source = temp; | ||
+ | } break; | ||
+ | case 3: | ||
+ | { | ||
+ | SDL_Rect temp = { LEVEL_THREE_X, | ||
+ | source = temp; | ||
+ | } break; | ||
+ | case 4: | ||
+ | { | ||
+ | SDL_Rect temp = { LEVEL_FOUR_X, | ||
+ | source = temp; | ||
+ | } break; | ||
+ | case 5: | ||
+ | { | ||
+ | SDL_Rect temp = { LEVEL_FIVE_X, | ||
+ | source = temp; | ||
+ | } break; | ||
+ | } | ||
+ | |||
+ | SDL_Rect destination = { 0, 0, WINDOW_WIDTH, | ||
+ | |||
+ | SDL_BlitSurface(g_Bitmap, | ||
+ | } | ||
+ | |||
+ | void ClearScreen() | ||
+ | { | ||
+ | |||
+ | SDL_FillRect(g_Window, | ||
+ | } | ||
+ | |||
+ | |||
+ | void DisplayText(string text, int x, int y, int size, int fR, int fG, int fB, int bR, int bG, int bB) | ||
+ | { | ||
+ | TTF_Font* font = TTF_OpenFont(" | ||
+ | |||
+ | SDL_Color foreground | ||
+ | SDL_Color background | ||
+ | |||
+ | |||
+ | SDL_Surface* temp = TTF_RenderText_Shaded(font, | ||
+ | |||
+ | SDL_Rect destination = { x, y, 0, 0 }; | ||
+ | |||
+ | |||
+ | SDL_BlitSurface(temp, | ||
+ | |||
+ | SDL_FreeSurface(temp); | ||
+ | |||
+ | |||
+ | TTF_CloseFont(font); | ||
+ | } | ||
+ | |||
+ | |||
+ | void HandleMenuInput() | ||
+ | { | ||
+ | |||
+ | if ( SDL_PollEvent(& | ||
+ | { | ||
+ | |||
+ | if (g_Event.type == SDL_QUIT) | ||
+ | { | ||
+ | |||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | } | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Handle keyboard input here // | ||
+ | if (g_Event.type == SDL_KEYDOWN) | ||
+ | { | ||
+ | if (g_Event.key.keysym.sym == SDLK_ESCAPE) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | return; | ||
+ | } | ||
+ | // Quit // | ||
+ | if (g_Event.key.keysym.sym == SDLK_q) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | return; | ||
+ | } | ||
+ | // Start Game // | ||
+ | if (g_Event.key.keysym.sym == SDLK_g) | ||
+ | { | ||
+ | StateStruct temp; | ||
+ | temp.StatePointer = Game; | ||
+ | g_StateStack.push(temp); | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void HandleGameInput() | ||
+ | { | ||
+ | |||
+ | static bool down_pressed | ||
+ | static bool left_pressed | ||
+ | static bool right_pressed = false; | ||
+ | |||
+ | |||
+ | if ( SDL_PollEvent(& | ||
+ | { | ||
+ | |||
+ | if (g_Event.type == SDL_QUIT) | ||
+ | { | ||
+ | |||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | } | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Handle keyboard input here // | ||
+ | if (g_Event.type == SDL_KEYDOWN) | ||
+ | { | ||
+ | if (g_Event.key.keysym.sym == SDLK_ESCAPE) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (g_Event.key.keysym.sym == SDLK_UP) | ||
+ | { | ||
+ | // Check collisions before rotating // | ||
+ | if (!CheckRotationCollisions(g_FocusBlock)) | ||
+ | { | ||
+ | g_FocusBlock-> | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | if (g_Event.key.keysym.sym == SDLK_LEFT) | ||
+ | { | ||
+ | left_pressed = true; | ||
+ | } | ||
+ | if (g_Event.key.keysym.sym == SDLK_RIGHT) | ||
+ | { | ||
+ | right_pressed = true; | ||
+ | } | ||
+ | if (g_Event.key.keysym.sym == SDLK_DOWN) | ||
+ | { | ||
+ | down_pressed = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | if (g_Event.type == SDL_KEYUP) | ||
+ | { | ||
+ | if (g_Event.key.keysym.sym == SDLK_LEFT) | ||
+ | { | ||
+ | left_pressed = false; | ||
+ | } | ||
+ | if (g_Event.key.keysym.sym == SDLK_RIGHT) | ||
+ | { | ||
+ | right_pressed = false; | ||
+ | } | ||
+ | if (g_Event.key.keysym.sym == SDLK_DOWN) | ||
+ | { | ||
+ | down_pressed = false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | if (down_pressed) | ||
+ | { | ||
+ | if ( !CheckWallCollisions(g_FocusBlock, | ||
+ | !CheckEntityCollisions(g_FocusBlock, | ||
+ | { | ||
+ | g_FocusBlock-> | ||
+ | } | ||
+ | } | ||
+ | if (left_pressed) | ||
+ | { | ||
+ | if ( !CheckWallCollisions(g_FocusBlock, | ||
+ | !CheckEntityCollisions(g_FocusBlock, | ||
+ | { | ||
+ | g_FocusBlock-> | ||
+ | } | ||
+ | } | ||
+ | if (right_pressed) | ||
+ | { | ||
+ | if ( !CheckWallCollisions(g_FocusBlock, | ||
+ | !CheckEntityCollisions(g_FocusBlock, | ||
+ | { | ||
+ | g_FocusBlock-> | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void HandleExitInput() | ||
+ | { | ||
+ | if ( SDL_PollEvent(& | ||
+ | { | ||
+ | |||
+ | if (g_Event.type == SDL_QUIT) | ||
+ | { | ||
+ | |||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | } | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Handle keyboard input here // | ||
+ | if (g_Event.type == SDL_KEYDOWN) | ||
+ | { | ||
+ | if (g_Event.key.keysym.sym == SDLK_ESCAPE) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (g_Event.key.keysym.sym == SDLK_y) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (g_Event.key.keysym.sym == SDLK_n) | ||
+ | { | ||
+ | StateStruct temp; | ||
+ | temp.StatePointer = Menu; | ||
+ | g_StateStack.push(temp); | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void HandleWinLoseInput() | ||
+ | { | ||
+ | if ( SDL_PollEvent(& | ||
+ | { | ||
+ | // Handle user manually closing game window // | ||
+ | if (g_Event.type == SDL_QUIT) | ||
+ | { | ||
+ | // While state stack isn't empty, pop // | ||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | } | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Handle keyboard input here // | ||
+ | if (g_Event.type == SDL_KEYDOWN) | ||
+ | { | ||
+ | if (g_Event.key.keysym.sym == SDLK_ESCAPE) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | if (g_Event.key.keysym.sym == SDLK_y) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (g_Event.key.keysym.sym == SDLK_n) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | |||
+ | StateStruct temp; | ||
+ | temp.StatePointer = Exit; | ||
+ | g_StateStack.push(temp); | ||
+ | |||
+ | temp.StatePointer = Menu; | ||
+ | g_StateStack.push(temp); | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | bool CheckEntityCollisions(cSquare* square, Direction dir) | ||
+ | { | ||
+ | |||
+ | int distance = SQUARE_MEDIAN * 2; | ||
+ | |||
+ | // Center of the given square // | ||
+ | int centerX = square-> | ||
+ | int centerY = square-> | ||
+ | |||
+ | // Determine the location of the square after moving // | ||
+ | switch (dir) | ||
+ | { | ||
+ | case DOWN: | ||
+ | { | ||
+ | centerY += distance; | ||
+ | } break; | ||
+ | |||
+ | case LEFT: | ||
+ | { | ||
+ | centerX -= distance; | ||
+ | } break; | ||
+ | |||
+ | case RIGHT: | ||
+ | { | ||
+ | centerX += distance; | ||
+ | } break; | ||
+ | } | ||
+ | |||
+ | |||
+ | for (int i=0; i< | ||
+ | { | ||
+ | if ( ( abs(centerX - g_OldSquares[i]-> | ||
+ | ( abs(centerY - g_OldSquares[i]-> | ||
+ | { | ||
+ | return true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | return false; | ||
+ | } | ||
+ | |||
+ | |||
+ | bool CheckEntityCollisions(cBlock* block, Direction dir) | ||
+ | { | ||
+ | |||
+ | cSquare** temp_array = block-> | ||
+ | |||
+ | |||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | if ( CheckEntityCollisions(temp_array[i], | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | return false; | ||
+ | } | ||
+ | |||
+ | |||
+ | bool CheckWallCollisions(cSquare* square, Direction dir) | ||
+ | { | ||
+ | // Get the center of the square // | ||
+ | int x = square-> | ||
+ | int y = square-> | ||
+ | |||
+ | |||
+ | switch (dir) | ||
+ | { | ||
+ | case DOWN: | ||
+ | { | ||
+ | if ( (y + (SQUARE_MEDIAN*2)) > GAME_AREA_BOTTOM ) | ||
+ | { | ||
+ | return true; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | return false; | ||
+ | } | ||
+ | } break; | ||
+ | |||
+ | case LEFT: | ||
+ | { | ||
+ | if ( (x - (SQUARE_MEDIAN*2)) < GAME_AREA_LEFT ) | ||
+ | { | ||
+ | return true; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | return false; | ||
+ | } | ||
+ | } break; | ||
+ | |||
+ | case RIGHT: | ||
+ | { | ||
+ | if ( (x + (SQUARE_MEDIAN*2)) > GAME_AREA_RIGHT ) | ||
+ | { | ||
+ | return true; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | return false; | ||
+ | } | ||
+ | } break; | ||
+ | } | ||
+ | |||
+ | return false; | ||
+ | } | ||
+ | |||
+ | |||
+ | bool CheckWallCollisions(cBlock* block, Direction dir) | ||
+ | { | ||
+ | |||
+ | cSquare** temp_array = block-> | ||
+ | |||
+ | |||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | if ( CheckWallCollisions(temp_array[i], | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | return false; | ||
+ | } | ||
+ | |||
+ | // Check for collisions when a block is rotated // | ||
+ | bool CheckRotationCollisions(cBlock* block) | ||
+ | { | ||
+ | |||
+ | int* temp_array = block-> | ||
+ | |||
+ | |||
+ | int distance = SQUARE_MEDIAN * 2; | ||
+ | |||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | // Check to see if the block will go out of bounds // | ||
+ | if ( (temp_array[i*2] < GAME_AREA_LEFT) || (temp_array[i*2] > GAME_AREA_RIGHT) ) | ||
+ | { | ||
+ | delete temp_array; | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | if ( temp_array[i*2+1] > GAME_AREA_BOTTOM ) | ||
+ | { | ||
+ | delete temp_array; | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | |||
+ | for (int index=0; index< | ||
+ | { | ||
+ | if ( ( abs(temp_array[i*2] | ||
+ | ( abs(temp_array[i*2+1] - g_OldSquares[index]-> | ||
+ | { | ||
+ | delete temp_array; | ||
+ | return true; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | delete temp_array; | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | |||
+ | void HandleBottomCollision() | ||
+ | { | ||
+ | ChangeFocusBlock(); | ||
+ | |||
+ | |||
+ | int num_lines = CheckCompletedLines(); | ||
+ | |||
+ | if ( num_lines > 0 ) | ||
+ | { | ||
+ | |||
+ | g_Score += POINTS_PER_LINE * num_lines; | ||
+ | |||
+ | |||
+ | if (g_Score >= g_Level * POINTS_PER_LEVEL) | ||
+ | { | ||
+ | g_Level++; | ||
+ | CheckWin(); | ||
+ | g_FocusBlockSpeed -= SPEED_CHANGE; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | CheckLoss(); | ||
+ | } | ||
+ | |||
+ | void ChangeFocusBlock() | ||
+ | { | ||
+ | |||
+ | cSquare** square_array = g_FocusBlock-> | ||
+ | |||
+ | // Add focus block squares to g_OldSquares // | ||
+ | for (int i=0; i<4; i++) | ||
+ | { | ||
+ | g_OldSquares.push_back(square_array[i]); | ||
+ | } | ||
+ | |||
+ | delete g_FocusBlock; | ||
+ | g_FocusBlock = g_NextBlock; | ||
+ | g_FocusBlock-> | ||
+ | |||
+ | |||
+ | g_NextBlock = new cBlock(NEXT_BLOCK_CIRCLE_X, | ||
+ | } | ||
+ | |||
+ | int CheckCompletedLines() | ||
+ | { | ||
+ | |||
+ | int squares_per_row[13]; | ||
+ | |||
+ | |||
+ | for (int index=0; index< | ||
+ | squares_per_row[index] = 0; | ||
+ | |||
+ | int row_size | ||
+ | int bottom | ||
+ | int top = bottom - 12 * row_size; | ||
+ | |||
+ | int num_lines = 0; | ||
+ | int row; | ||
+ | |||
+ | |||
+ | |||
+ | for (int i=0; i< | ||
+ | { | ||
+ | |||
+ | row = (g_OldSquares[i]-> | ||
+ | |||
+ | |||
+ | squares_per_row[row]++; | ||
+ | } | ||
+ | |||
+ | // Erase any full lines // | ||
+ | for (int line=0; line<13; line++) | ||
+ | { | ||
+ | // Check for completed lines // | ||
+ | if (squares_per_row[line] == SQUARES_PER_ROW) | ||
+ | { | ||
+ | |||
+ | num_lines++; | ||
+ | |||
+ | |||
+ | for (int index=0; index< | ||
+ | { | ||
+ | if ( ( (g_OldSquares[index]-> | ||
+ | { | ||
+ | delete g_OldSquares[index]; | ||
+ | g_OldSquares.erase(g_OldSquares.begin() + index); // remove it from the vector | ||
+ | index--; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | for (int index=0; index< | ||
+ | { | ||
+ | for (int line=0; line<13; line++) | ||
+ | { | ||
+ | // Determine if this row was filled // | ||
+ | if (squares_per_row[line] == SQUARES_PER_ROW) | ||
+ | { | ||
+ | // If it was, get the location of it within the game area // | ||
+ | row = (g_OldSquares[index]-> | ||
+ | |||
+ | // Now move any squares above that row down one // | ||
+ | if ( row < line ) | ||
+ | { | ||
+ | g_OldSquares[index]-> | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | return num_lines; | ||
+ | } | ||
+ | |||
+ | |||
+ | void CheckWin() | ||
+ | { | ||
+ | |||
+ | if (g_Level > NUM_LEVELS) | ||
+ | { | ||
+ | // Clear the old squares vector // | ||
+ | for (int i=0; i< | ||
+ | { | ||
+ | delete g_OldSquares[i]; | ||
+ | } | ||
+ | g_OldSquares.clear(); | ||
+ | |||
+ | // Reset score and level // | ||
+ | g_Score = 0; | ||
+ | g_Level = 1; | ||
+ | |||
+ | // Pop all states // | ||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | } | ||
+ | |||
+ | // Push the victory state onto the stack // | ||
+ | StateStruct win; | ||
+ | win.StatePointer = GameWon; | ||
+ | |||
+ | g_StateStack.push(win); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void CheckLoss() | ||
+ | { | ||
+ | |||
+ | if ( CheckEntityCollisions(g_FocusBlock, | ||
+ | { | ||
+ | |||
+ | for (int i=0; i< | ||
+ | { | ||
+ | delete g_OldSquares[i]; | ||
+ | } | ||
+ | g_OldSquares.clear(); | ||
+ | |||
+ | // Reset score and level // | ||
+ | g_Score = 0; | ||
+ | g_Level = 1; | ||
+ | |||
+ | // Pop all states // | ||
+ | while (!g_StateStack.empty()) | ||
+ | { | ||
+ | g_StateStack.pop(); | ||
+ | } | ||
+ | |||
+ | |||
+ | StateStruct lose; | ||
+ | lose.StatePointer = GameLost; | ||
+ | |||
+ | g_StateStack.push(lose); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ====reflection==== | ||
+ | |||
+ | even this being a tutorial I worked diligently to get an understanding on how and why the code was there. | ||
+ | |||
+ | ====References==== | ||
+ | |||
+ | http:// | ||