Advertisement
Sektor

CHDK-DE tetris

Dec 9th, 2011
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 25.27 KB | None | 0 0
  1. #include "stdlib.h"
  2. #include "keyboard.h"
  3. #include "platform.h"
  4. #include "core.h"
  5. #include "lang.h"
  6. #include "gui.h"
  7. #include "gui_draw.h"
  8. #include "gui_lang.h"
  9. #include "gui_batt.h"
  10. #include "gui_mbox.h"
  11. #include "gui_tetris.h"
  12.  
  13. #define BOARD_WIDTH     (10)
  14. #define BOARD_HEIGHT    (22)
  15. /* Initial time delay (in miliseconds) between falling moves */
  16. #define INI_DELAY_FALL  (540)
  17. /* Score points given by filled rows */
  18. #define SCORE_1_FILLED_ROW  (40)
  19. #define SCORE_2_FILLED_ROW  (100)
  20. #define SCORE_3_FILLED_ROW  (300)
  21. #define SCORE_4_FILLED_ROW  (1200)
  22. /* Number of filled rows required to increase the game level */
  23. #define FILLED_ROWS_FOR_LEVEL_UP    (10)
  24. /* The falling delay is multiplied by this factor with every level up */
  25. #define DELAY_FACTOR_FOR_LEVEL_UP   (0.9)
  26.  
  27. #define GAME_ERROR_NONE         (0)     /* Everything is OK, oh wonders!      */
  28. #define GAME_ERROR_USER_QUITS   (1)     /* The user quits (bored?), our fail  */
  29. #define GAME_ERROR_NO_MEMORY    (-1)    /* Not enough memory                  */
  30. #define GAME_ERROR_NO_VIDEO     (-2)    /* Video system was not initialized   */
  31. #define GAME_ERROR_NO_IMAGES    (-3)    /* Problem loading the image files    */
  32. #define GAME_ERROR_ASSERT       (-100)  /* Something went very very wrong...  */
  33.  
  34. #define EVENT_NONE          (0)
  35. #define EVENT_MOVE_DOWN     (1 << 1)
  36. #define EVENT_MOVE_LEFT     (1 << 2)
  37. #define EVENT_MOVE_RIGHT    (1 << 3)
  38. #define EVENT_ROTATE_CW     (1 << 4)    /* rotate clockwise         */
  39. #define EVENT_ROTATE_CCW    (1 << 5)    /* rotate counter-clockwise */
  40. #define EVENT_DROP          (1 << 6)
  41. #define EVENT_PAUSE         (1 << 7)
  42. #define EVENT_RESTART       (1 << 8)
  43. #define EVENT_SHOW_NEXT     (1 << 9)    /* toggle show next tetromino */
  44. // Tetromino definitions (used as indexes: must be between 0-6)
  45. #define TETROMINO_I     (0)
  46. #define TETROMINO_O     (1)
  47. #define TETROMINO_T     (2)
  48. #define TETROMINO_S     (3)
  49. #define TETROMINO_Z     (4)
  50. #define TETROMINO_J     (5)
  51. #define TETROMINO_L     (6)
  52. /* Tetromino colors */
  53. #define TETRIS_COLOR_CYAN      COLOR_SPLASH_PINK
  54. #define TETRIS_COLOR_RED       COLOR_RED
  55. #define TETRIS_COLOR_BLUE      COLOR_BLUE
  56. #define TETRIS_COLOR_ORANGE    COLOR_WHITE
  57. #define TETRIS_COLOR_GREEN     COLOR_GREEN
  58. #define TETRIS_COLOR_YELLOW    COLOR_YELLOW
  59. #define TETRIS_COLOR_PURPLE    COLOR_BLACK
  60. #define EMPTY_CELL  (-1)
  61. /* screen colors */
  62. #define TETRIS_COLOR_BG        MAKE_COLOR(COLOR_GREY,COLOR_GREY)
  63. #define TETRIS_COLOR_BOARD     MAKE_COLOR(COLOR_SPLASH_GREY,COLOR_SPLASH_GREY)
  64.  
  65. typedef struct StcTetramino {
  66.     int cells[4][4];
  67.     int x;
  68.     int y;
  69.     int size;
  70.     int type;
  71. } StcTetramino;
  72.  
  73. typedef struct StcPlatform StcPlatform;
  74.  
  75. typedef struct StcGame {
  76.     int map[BOARD_WIDTH][BOARD_HEIGHT];
  77.  
  78.     StcTetramino nextBlock;     /* next tetromino               */
  79.     StcTetramino fallingBlock;  /* current falling tetromino    */
  80.     StcPlatform *platform;      /* platform hidden data         */
  81.     int errorCode;              /* game error code              */
  82.     long systemTime;            /* system time in miliseconds   */
  83.     int delay;          /* delay time for falling tetrominoes   */
  84.     int isOver;         /* 1 if the game is over, 0 otherwise   */
  85.     int isPaused;       /* 1 if the game is paused, 0 otherwise */
  86.     int showPreview;    /* 1 if we must show preview tetramino  */
  87.     long lastFallTime;  /* last time the game moved the falling tetromino */
  88.  
  89.     int events;
  90.  
  91.     struct {
  92.         long score;         /* user score for current game      */
  93.         long high;          /* high score                       */
  94.         int lines;          /* total number of lines cleared    */
  95.         int totalPieces;    /* total number of tetraminoes used */
  96.         int pieces[7];      /* number of tetraminoes per type   */
  97.         int level;          /* current game level               */
  98.     } stats;
  99. } StcGame;
  100. StcGame *createGame();
  101. void deleteGame(StcGame *pGame);
  102. int gameInit(StcGame *gameInstance);
  103. void gameEnd(StcGame *gameInstance);
  104. void gameUpdate(StcGame *gameInstance);
  105.  
  106.  
  107. StcGame *game;
  108.  
  109.  
  110. int platformInit(StcGame *gameInstance){ return GAME_ERROR_NONE;}
  111. void platformEnd(StcGame *gameInstance){}
  112.  
  113. /* Read input device and notify game */
  114. void platformReadInput(StcGame *gameInstance){}
  115. #define PREVIEW_X 150
  116. #define PREVIEW_Y 10
  117. #define BOARD_X 10
  118. #define BOARD_Y 10
  119. #define TILE_SIZE 10
  120. /* Render the state of the game */
  121. int tmp[BOARD_WIDTH][BOARD_HEIGHT];
  122. int tmp2[BOARD_WIDTH][BOARD_HEIGHT];
  123.  
  124. int prevNextBlockType = -1;
  125. void platformRenderGame(StcGame *gameInstance){
  126.     int i, j;
  127.  
  128.     for(i = 0; i < BOARD_WIDTH; ++i) {
  129.         for (j = 0; j < BOARD_HEIGHT; ++j){
  130.           tmp[i][j] = EMPTY_CELL;
  131.           tmp2[i][j] = EMPTY_CELL;
  132.         }
  133.     }
  134.  
  135.     /* Draw preview block */
  136.     if(game->nextBlock.type != prevNextBlockType){
  137.         prevNextBlockType = game->nextBlock.type;
  138.         for (i = 0; i < 4; ++i) {
  139.             for (j = 0; j < 4; ++j) {
  140.                 if (game->nextBlock.cells[i][j] != EMPTY_CELL) {
  141.                     draw_filled_rect(CAM_TS_BUTTON_BORDER+PREVIEW_X + (TILE_SIZE * i),
  142.                             PREVIEW_Y + (TILE_SIZE * j),
  143.                             CAM_TS_BUTTON_BORDER+PREVIEW_X + (TILE_SIZE * i)+TILE_SIZE-1,
  144.                             PREVIEW_Y + (TILE_SIZE * j)+TILE_SIZE-1,
  145.                              MAKE_COLOR(game->nextBlock.cells[i][j], game->nextBlock.cells[i][j]));
  146.                 }else{
  147.                     draw_filled_rect(CAM_TS_BUTTON_BORDER+PREVIEW_X + (TILE_SIZE * i),
  148.                             PREVIEW_Y + (TILE_SIZE * j),
  149.                             CAM_TS_BUTTON_BORDER+PREVIEW_X + (TILE_SIZE * i)+TILE_SIZE-1,
  150.                             PREVIEW_Y + (TILE_SIZE * j)+TILE_SIZE-1,
  151.                             TETRIS_COLOR_BG);
  152.                 }
  153.             }
  154.         }
  155.     }
  156.    
  157.     /* Draw the cells in the board */
  158.     for (i = 0; i < BOARD_WIDTH; ++i) {
  159.         for (j = 0; j < BOARD_HEIGHT; ++j){
  160.             if (game->map[i][j] != EMPTY_CELL) {
  161.                 tmp2[i][j] = game->map[i][j];
  162.             }
  163.         }
  164.     }
  165.     /* Draw falling tetromino */
  166.     for (i = 0; i<4; ++i) {
  167.         for (j = 0; j < 4; ++j) {
  168.             if (game->fallingBlock.cells[i][j] != EMPTY_CELL) {
  169.               tmp[i+game->fallingBlock.x][j+game->fallingBlock.y] = game->fallingBlock.cells[i][j];
  170.             }
  171.         }
  172.     }
  173.  
  174.     for (i = 0; i < BOARD_WIDTH; ++i) {
  175.         for (j = 0; j < BOARD_HEIGHT; ++j){
  176.                     if(tmp[i][j] != EMPTY_CELL){
  177.                     draw_filled_rect(CAM_TS_BUTTON_BORDER+BOARD_X + (TILE_SIZE * i),
  178.                             BOARD_Y + (TILE_SIZE * j),
  179.                             CAM_TS_BUTTON_BORDER+BOARD_X + (TILE_SIZE * i)+TILE_SIZE-1,
  180.                             BOARD_Y + (TILE_SIZE * j)+TILE_SIZE-1,
  181.                              MAKE_COLOR(tmp[i][j], tmp[i][j]));
  182.                     }else if(tmp2[i][j] != EMPTY_CELL){
  183.                     draw_filled_rect(CAM_TS_BUTTON_BORDER+BOARD_X + (TILE_SIZE * i),
  184.                             BOARD_Y + (TILE_SIZE * j),
  185.                             CAM_TS_BUTTON_BORDER+BOARD_X + (TILE_SIZE * i)+TILE_SIZE-1,
  186.                             BOARD_Y + (TILE_SIZE * j)+TILE_SIZE-1,
  187.                              MAKE_COLOR(tmp2[i][j], tmp2[i][j]));
  188.                     }else{
  189.                     draw_filled_rect(CAM_TS_BUTTON_BORDER+BOARD_X + (TILE_SIZE * i),
  190.                             BOARD_Y + (TILE_SIZE * j),
  191.                             CAM_TS_BUTTON_BORDER+BOARD_X + (TILE_SIZE * i)+TILE_SIZE-1,
  192.                             BOARD_Y + (TILE_SIZE * j)+TILE_SIZE-1,
  193.                              TETRIS_COLOR_BOARD);
  194.                     }
  195.         }
  196.     }
  197.     /* output game info */
  198.     char str_buf[100];
  199.     unsigned long t;
  200.     static struct tm *ttm;
  201.       sprintf(str_buf,"High:    %5d",game->stats.high);
  202.       draw_string(CAM_TS_BUTTON_BORDER+150,35,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  203.       sprintf(str_buf,"Points:  %5d",game->stats.score);
  204.       draw_string(CAM_TS_BUTTON_BORDER+150,55,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  205.       sprintf(str_buf,"Lines:   %5d",game->stats.lines);
  206.       draw_string(CAM_TS_BUTTON_BORDER+150,75,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  207.       sprintf(str_buf,"Level:   %5d",game->stats.level);
  208.       draw_string(CAM_TS_BUTTON_BORDER+150,95,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  209.      sprintf(str_buf,"UP  -> Pause");
  210.      draw_string(CAM_TS_BUTTON_BORDER+150,135,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  211.      sprintf(str_buf,"SET -> Rotate");
  212.      draw_string(CAM_TS_BUTTON_BORDER+150,155,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  213.      t = time(NULL);
  214.       ttm = localtime(&t);
  215.       sprintf(str_buf,"Time:    %2u:%02u", ttm->tm_hour, ttm->tm_min);
  216.      draw_string(CAM_TS_BUTTON_BORDER+150,195,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  217.      sprintf(str_buf,"Batt:     %3d%%", get_batt_perc());
  218.      draw_string(CAM_TS_BUTTON_BORDER+150,215,str_buf, MAKE_COLOR(TETRIS_COLOR_BG, COLOR_BLACK));
  219. }
  220.  
  221. /* Return the current system time in milliseconds */
  222. long platformGetSystemTime(){return get_tick_count();}
  223.  
  224. /* Set matrix elements to indicated value */
  225. static void setMatrixCells(int *matrix, int width, int height, int value) {
  226.     int i, j;
  227.     for (i = 0; i < width; ++i) {
  228.         for (j = 0; j < height; ++j) {
  229.             *(matrix + i + (j * width)) = value;
  230.         }
  231.     }
  232. }
  233.  
  234. /* Initialize tetromino cells for every tipe of tetromino */
  235. static void setTetramino(int indexTetramino, StcTetramino *tetramino) {
  236.  
  237.     /* Initialize tetromino cells to empty cells */
  238.     setMatrixCells(&tetramino->cells[0][0], 4, 4, EMPTY_CELL);
  239.  
  240.     /* Almost all the blocks have size 3 */
  241.     tetramino->size = 3;
  242.  
  243.     /* Initial configuration from: http://www.tetrisconcept.com/wiki/index.php/SRS */
  244.     switch (indexTetramino) {
  245.     case TETROMINO_I:
  246.         tetramino->cells[0][1] = TETRIS_COLOR_CYAN;
  247.         tetramino->cells[1][1] = TETRIS_COLOR_CYAN;
  248.         tetramino->cells[2][1] = TETRIS_COLOR_CYAN;
  249.         tetramino->cells[3][1] = TETRIS_COLOR_CYAN;
  250.         tetramino->size = 4;
  251.         break;
  252.     case TETROMINO_O:
  253.         tetramino->cells[0][0] = TETRIS_COLOR_YELLOW;
  254.         tetramino->cells[0][1] = TETRIS_COLOR_YELLOW;
  255.         tetramino->cells[1][0] = TETRIS_COLOR_YELLOW;
  256.         tetramino->cells[1][1] = TETRIS_COLOR_YELLOW;
  257.         tetramino->size = 2;
  258.         break;
  259.     case TETROMINO_T:
  260.         tetramino->cells[0][1] = TETRIS_COLOR_PURPLE;
  261.         tetramino->cells[1][0] = TETRIS_COLOR_PURPLE;
  262.         tetramino->cells[1][1] = TETRIS_COLOR_PURPLE;
  263.         tetramino->cells[2][1] = TETRIS_COLOR_PURPLE;
  264.         break;
  265.     case TETROMINO_S:
  266.         tetramino->cells[0][1] = TETRIS_COLOR_GREEN;
  267.         tetramino->cells[1][0] = TETRIS_COLOR_GREEN;
  268.         tetramino->cells[1][1] = TETRIS_COLOR_GREEN;
  269.         tetramino->cells[2][0] = TETRIS_COLOR_GREEN;
  270.         break;
  271.     case TETROMINO_Z:
  272.         tetramino->cells[0][0] = TETRIS_COLOR_RED;
  273.         tetramino->cells[1][0] = TETRIS_COLOR_RED;
  274.         tetramino->cells[1][1] = TETRIS_COLOR_RED;
  275.         tetramino->cells[2][1] = TETRIS_COLOR_RED;
  276.         break;
  277.     case TETROMINO_J:
  278.         tetramino->cells[0][0] = TETRIS_COLOR_BLUE;
  279.         tetramino->cells[0][1] = TETRIS_COLOR_BLUE;
  280.         tetramino->cells[1][1] = TETRIS_COLOR_BLUE;
  281.         tetramino->cells[2][1] = TETRIS_COLOR_BLUE;
  282.         break;
  283.     case TETROMINO_L:
  284.         tetramino->cells[0][1] = TETRIS_COLOR_ORANGE;
  285.         tetramino->cells[1][1] = TETRIS_COLOR_ORANGE;
  286.         tetramino->cells[2][0] = TETRIS_COLOR_ORANGE;
  287.         tetramino->cells[2][1] = TETRIS_COLOR_ORANGE;
  288.         break;
  289.     }
  290.     tetramino->type = indexTetramino;
  291. }
  292.  
  293. /*  Start a new game */
  294. static void startGame(StcGame *game) {
  295.     int i;
  296.  
  297.     /* Initialize game data */
  298.     game->errorCode = GAME_ERROR_NONE;
  299.     game->systemTime = platformGetSystemTime();
  300.     game->lastFallTime = game->systemTime;
  301.     game->isOver = 0;
  302.     game->isPaused = 0;
  303.     game->showPreview = 1;
  304.     game->events = EVENT_NONE;
  305.     game->delay = INI_DELAY_FALL;
  306.     /* Initialize game statistics */
  307.     game->stats.score = 0;
  308.     game->stats.lines = 0;
  309.     game->stats.totalPieces = 0;
  310.     game->stats.level = 0;
  311.     for (i = 0; i < 7; ++i) {
  312.         game->stats.pieces[i] = 0;
  313.     }
  314.  
  315.     /* Initialize rand generator */
  316.     srand(game->systemTime);
  317.  
  318.     /* Initialize game tile map */
  319.     setMatrixCells(&game->map[0][0], BOARD_WIDTH, BOARD_HEIGHT, EMPTY_CELL);
  320.  
  321.     /* Initialize falling tetromino */
  322.     setTetramino(rand() % 7, &game->fallingBlock);
  323.     game->fallingBlock.x = (BOARD_WIDTH - game->fallingBlock.size) / 2;
  324.     game->fallingBlock.y = 0;
  325.  
  326.     /* Initialize preview tetromino */
  327.     setTetramino(rand() % 7, &game->nextBlock);
  328. }
  329.  
  330. /* Create new game object */
  331. StcGame *createGame() {
  332.     /* Allocate space for our game object */
  333.     StcGame *game = (StcGame *) malloc(sizeof(StcGame));
  334.     return game;
  335. }
  336.  
  337. /*
  338.  * Initializes the game, if there are no problems returns GAME_ERROR_NONE.
  339.  */
  340. int gameInit(StcGame *game) {
  341.     int errorCode;
  342.  
  343.     errorCode = platformInit(game);
  344.     if (errorCode == GAME_ERROR_NONE) {
  345.         startGame(game);
  346.         return GAME_ERROR_NONE;
  347.     }
  348.     return errorCode;
  349. };
  350.  
  351. void gameEnd(StcGame *game) {
  352.     /* Free platform resources */
  353.     platformEnd(game);
  354. }
  355.  
  356. void deleteGame(StcGame *game) {
  357.     free(game);
  358. }
  359.  
  360. /*
  361.  * Rotate falling tetromino. If there are no collisions when the
  362.  * tetromino is rotated this modifies the tetramino's cell buffer.
  363.  */
  364. void rotateTetramino(StcGame *game, int clockwise) {
  365.     int i, j;
  366.     int rotated[4][4];  /* temporary array to hold rotated cells */
  367.  
  368.     /* If TETRAMINO_O is falling return immediately */
  369.     if (game->fallingBlock.type == TETROMINO_O) {
  370.         return; /* rotation doesn't require any changes */
  371.     }
  372.  
  373.     /* Initialize rotated cells to blank */
  374.     setMatrixCells(&rotated[0][0], 4, 4, EMPTY_CELL);
  375.  
  376.     /* Copy rotated cells to the temporary array */
  377.     for (i = 0; i < game->fallingBlock.size; ++i) {
  378.         for (j = 0; j < game->fallingBlock.size; ++j) {
  379.             if (clockwise) {
  380.                 rotated[game->fallingBlock.size - j - 1][i] = game->fallingBlock.cells[i][j];
  381.             } else {
  382.                 rotated[j][game->fallingBlock.size - i - 1] = game->fallingBlock.cells[i][j];
  383.             }
  384.         }
  385.     }
  386.     /* Check collision of the temporary array */
  387.     for (i = 0; i < game->fallingBlock.size; ++i) {
  388.         for (j = 0; j < game->fallingBlock.size; ++j) {
  389.             if (rotated[i][j] != EMPTY_CELL) {
  390.                 /* Check collision with left, right or bottom borders of the map */
  391.                 if ((game->fallingBlock.x + i < 0) || (game->fallingBlock.x + i >= BOARD_WIDTH)
  392.                         || (game->fallingBlock.y + j >= BOARD_HEIGHT)) {
  393.                     return; /* there was collision therefore return */
  394.                 }
  395.                 /* Check collision with existing cells in the map */
  396.                 if (game->map[i + game->fallingBlock.x][j + game->fallingBlock.y] != EMPTY_CELL) {
  397.                     return; /* there was collision therefore return */
  398.                 }
  399.             }
  400.         }
  401.     }
  402.     /* There are no collisions, replace tetramino cells with rotated cells */
  403.     for (i = 0; i < 4; ++i) {
  404.         for (j = 0; j < 4; ++j) {
  405.             game->fallingBlock.cells[i][j] = rotated[i][j];
  406.         }
  407.     }
  408. }
  409.  
  410. /*
  411.  * Check if tetromino will collide with something if it is moved in the requested direction.
  412.  * If there are collisions returns 1 else returns 0.
  413.  */
  414. static int checkCollision(StcGame *game, int dx, int dy) {
  415.     int newx, newy, i, j;
  416.  
  417.     newx = game->fallingBlock.x + dx;
  418.     newy = game->fallingBlock.y + dy;
  419.  
  420.     for (i = 0; i < game->fallingBlock.size; ++i) {
  421.         for (j = 0; j < game->fallingBlock.size; ++j) {
  422.             if (game->fallingBlock.cells[i][j] != EMPTY_CELL) {
  423.                 /* Check the tetramino would be inside the left, right and bottom borders */
  424.                 if ((newx + i < 0) || (newx + i >= BOARD_WIDTH)
  425.                     || (newy + j >= BOARD_HEIGHT)) {
  426.                     return 1;
  427.                 }
  428.                 /* Check the tetromino won't collide with existing cells in the map */
  429.                 if (game->map[newx + i][newy + j] != EMPTY_CELL) {
  430.                     return 1;
  431.                 }
  432.             }
  433.         }
  434.     }
  435.     return 0;
  436. }
  437.  
  438. /* Game scoring: http://www.tetrisconcept.com/wiki/index.php/Scoring */
  439. static void onFilledRows(StcGame *game, int filledRows) {
  440.     /* Update total number of filled rows */
  441.     game->stats.lines += filledRows;
  442.  
  443.     /* Increase score accordingly to the number of filled rows */
  444.     switch (filledRows) {
  445.     case 1:
  446.         game->stats.score += (SCORE_1_FILLED_ROW * (game->stats.level));
  447.         break;
  448.     case 2:
  449.         game->stats.score += (SCORE_2_FILLED_ROW * (game->stats.level));
  450.         break;
  451.     case 3:
  452.         game->stats.score += (SCORE_3_FILLED_ROW * (game->stats.level));
  453.         break;
  454.     case 4:
  455.         game->stats.score += (SCORE_4_FILLED_ROW * (game->stats.level));
  456.         break;
  457.     default:
  458.         game->errorCode = GAME_ERROR_ASSERT;    /* This can't happen */
  459.     }
  460.     /* Check if we need to update level */
  461.     if (game->stats.lines >= FILLED_ROWS_FOR_LEVEL_UP * (game->stats.level)) {
  462.         game->stats.level++;
  463.  
  464.         /* Increase speed for falling tetrominoes */
  465.         game->delay *= DELAY_FACTOR_FOR_LEVEL_UP;
  466.     }
  467. }
  468.  
  469. /*
  470.  * Move tetramino in direction especified by (x, y) (in tile units)
  471.  * This function detects if there are filled rows or if the move
  472.  * lands a falling tetromino, also checks for game over condition.
  473.  */
  474. static void moveTetramino(StcGame *game, int x, int y) {
  475.     int i, j, hasFullRow, numFilledRows;
  476.    
  477.     /* Check if the move would create a collision */
  478.     if (checkCollision(game, x, y)) {
  479.         /* In case of collision check if move was downwards (y == 1) */
  480.         if (y == 1) {
  481.             /* Check if collision occur when the falling
  482.              * tetromino is in the 1st or 2nd row */
  483.             if (game->fallingBlock.y <= 1) {
  484.                 game->isOver = 1;   /* if this happens the game is over */
  485.             }
  486.             else {
  487.                 /* The falling tetromino has reached the bottom,
  488.                  * so we copy their cells to the board map */
  489.                 for (i = 0; i < game->fallingBlock.size; ++i) {
  490.                     for (j = 0; j < game->fallingBlock.size; ++j) {
  491.                         if (game->fallingBlock.cells[i][j] != EMPTY_CELL) {
  492.                             game->map[game->fallingBlock.x + i][game->fallingBlock.y + j]
  493.                                     = game->fallingBlock.cells[i][j];
  494.                         }
  495.                     }
  496.                 }
  497.  
  498.                 /* Check if the landing tetromino has created full rows */
  499.                 numFilledRows = 0;
  500.                 for (j = 1; j < BOARD_HEIGHT; ++j) {
  501.                     hasFullRow = 1;
  502.                     for (i = 0; i < BOARD_WIDTH; ++i) {
  503.                         if (game->map[i][j] == EMPTY_CELL) {
  504.                             hasFullRow = 0;
  505.                             break;
  506.                         }
  507.                     }
  508.                     /* If we found a full row we need to remove that row from the map
  509.                      * we do that by just moving all the above rows one row below */
  510.                     if (hasFullRow) {
  511.                         for (x = 0; x < BOARD_WIDTH; ++x) {
  512.                             for (y = j; y > 0; --y) {
  513.                                 game->map[x][y] = game->map[x][y - 1];
  514.                             }
  515.                         }
  516.                         numFilledRows++;    /* increase filled row counter */
  517.                     }
  518.                 }
  519.  
  520.                 /* Update game statistics */
  521.                 if (numFilledRows) {
  522.                     onFilledRows(game, numFilledRows);
  523.                 }
  524.                 game->stats.totalPieces++;
  525.                 game->stats.pieces[game->fallingBlock.type]++;
  526.                
  527.                 /* Use preview tetromino as falling tetromino.
  528.                  * Copy preview tetramino for falling tetramino */
  529.                 for (i = 0; i < 4; ++i) {
  530.                     for (j = 0; j < 4; ++j) {
  531.                         game->fallingBlock.cells[i][j] = game->nextBlock.cells[i][j];
  532.                     }
  533.                 }
  534.                 game->fallingBlock.size = game->nextBlock.size;
  535.                 game->fallingBlock.type = game->nextBlock.type;
  536.  
  537.                 /* Reset position */
  538.                 game->fallingBlock.y = 0;
  539.                 game->fallingBlock.x = (BOARD_WIDTH - game->fallingBlock.size) / 2;
  540.  
  541.                 /* Create next preview tetromino */
  542.                 setTetramino(rand() % 7, &game->nextBlock);
  543.             }
  544.         }
  545.     }
  546.     else {
  547.         /* There are no collisions, just move the tetramino */
  548.         game->fallingBlock.x += x;
  549.         game->fallingBlock.y += y;
  550.     }
  551. }
  552.  
  553. /* Hard drop */
  554. static void dropTetramino(StcGame *game) {
  555.    int y;
  556.    y = 1;
  557.    /* Calculate number of cells to drop */
  558.    while (!checkCollision(game, 0, y)) {
  559.        y++;
  560.    }
  561.    moveTetramino(game, 0, y - 1);
  562. }
  563.  
  564. /*
  565.  * Main function game called every frame
  566.  */
  567. void gameUpdate(StcGame *game) {
  568.     long sysTime;
  569.     /* Read user input */
  570.     platformReadInput(game);
  571.  
  572.     /* Update game state */
  573.     if (game->isOver) {
  574.        
  575.         if (game->stats.score > game->stats.high) {
  576.             game->stats.high = game->stats.score;
  577.             FILE * f;
  578.             long buf;
  579.             buf = game->stats.score;
  580.             mkdir_if_not_exist("A/CHDK/GAMES");
  581.             f = fopen ( "A/CHDK/GAMES/TETRIS.SCO" , "wb" );
  582.             fwrite (&buf , 1 , sizeof(buf) , f );
  583.             fclose (f);
  584.         }
  585.            
  586.        
  587.         //if (game->events & EVENT_RESTART) {
  588.         if (game->events & EVENT_PAUSE) {
  589.            
  590.             //TurnOnBackLight();
  591.            
  592.             game->isOver = 0;
  593.             startGame(game);
  594.            
  595.         }
  596.     }
  597.     else {
  598.         sysTime = platformGetSystemTime();
  599.  
  600.         /* Always handle pause event */
  601.         if (game->events & EVENT_PAUSE) {
  602.             game->isPaused = !game->isPaused;
  603.             game->events = EVENT_NONE;
  604.         }
  605.  
  606.         /* Check if the game is paused */
  607.         if (game->isPaused) {
  608.             /* We achieve the effect of pausing the game
  609.              * adding the last frame duration to lastFallTime */
  610.             game->lastFallTime += (sysTime - game->systemTime);
  611.         }
  612.         else {
  613.             if (game->events != EVENT_NONE) {
  614.                 if (game->events & EVENT_SHOW_NEXT) {
  615.                     game->showPreview = !game->showPreview;
  616.                 }
  617.                 if (game->events & EVENT_DROP) {
  618.                     dropTetramino(game);
  619.                 }
  620.                 if (game->events & EVENT_ROTATE_CW) {
  621.                     rotateTetramino(game, 1);
  622.                 }
  623.                 if (game->events & EVENT_MOVE_RIGHT) {
  624.                     moveTetramino(game, 1, 0);
  625.                 }
  626.                 else if (game->events & EVENT_MOVE_LEFT) {
  627.                     moveTetramino(game, -1, 0);
  628.                 }
  629.                 if (game->events & EVENT_MOVE_DOWN) {
  630.                     moveTetramino(game, 0, 1);
  631.                 }
  632.                 game->events = EVENT_NONE;
  633.             }
  634.             /* Check if it's time to move downwards the falling tetromino */
  635.             if (sysTime - game->lastFallTime >= game->delay) {
  636.                 moveTetramino(game, 0, 1);
  637.                 game->lastFallTime = sysTime;
  638.             }
  639.         }
  640.         game->systemTime = sysTime;
  641.     }
  642.     /* Draw game state */
  643.     platformRenderGame(game);
  644. }
  645.  
  646. void gui_tetris_init(){
  647.     draw_filled_rect(CAM_TS_BUTTON_BORDER+0,0,screen_width-CAM_TS_BUTTON_BORDER,screen_height, TETRIS_COLOR_BG);
  648.     draw_rect(CAM_TS_BUTTON_BORDER+BOARD_X-1,BOARD_Y-1,CAM_TS_BUTTON_BORDER+BOARD_WIDTH*TILE_SIZE+10,BOARD_HEIGHT*TILE_SIZE+10, COLOR_BLACK);
  649.     game = createGame();
  650.     gameInit(game);
  651.  
  652.     long buf;
  653.     FILE *f;    
  654.  
  655.     f=fopen("A/CHDK/GAMES/TETRIS.SCO","rb");
  656.     if(!f) {
  657.         game->stats.high = 0;
  658.     } else {
  659.    
  660.     fread( &buf, 1, sizeof( buf ), f );
  661.     game->stats.high = buf;
  662.    
  663.     }
  664.  
  665.     fclose (f);
  666.     startGame(game);
  667. }
  668.  
  669. void gui_tetris_draw(){
  670.   gameUpdate(game);
  671. }
  672.  
  673.  
  674. void gui_tetris_kbd_process() {
  675.         switch ( kbd_get_autoclicked_key() )
  676.         {
  677.             case KEY_UP:
  678.             if ((game->isPaused) || (game->isOver)) {
  679.                 TurnOnBackLight();
  680.             } else { TurnOffBackLight(); }
  681.                 game->events |= EVENT_PAUSE;
  682.                 break;
  683.             case KEY_LEFT:
  684.                 game->events |= EVENT_MOVE_LEFT;
  685.                 break;
  686.             case KEY_RIGHT:
  687.                 game->events |= EVENT_MOVE_RIGHT;
  688.                 break;
  689.             case KEY_DOWN:
  690.                 game->events |= EVENT_MOVE_DOWN;
  691.                 break;
  692.             //case KEY_SET:
  693.             //game->events |= EVENT_RESTART;
  694.             //break;
  695.             case KEY_DISPLAY:
  696.             case KEY_ERASE:
  697.             case KEY_SET:
  698.                 game->events |= EVENT_ROTATE_CW;
  699.                 break;
  700.             default:
  701.                 break;
  702.         }
  703. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement