game_status state_in_game(SDL_Renderer* renderer, game* p_game) { bool done=false; //the return code is always GAME_OVER, the player try to beat his hi-score //until his demise game_status ret_code = GAME_OVER; long timelastcall=SDL_GetTicks(); //initialize the states of completed lines to 0 memset(p_game->state, 0, STATE_NUM * sizeof(int)); p_game->score = 0; int level_cur = 0; int level_max = 10; level_init(); //declare two shapes, one controled by the player, the other to indicates //the type of the next shape shape o_falling_shape, o_preview_shape; //set the falling shape type randomly shape_set(&o_falling_shape, rand() % SHAPE_NB); shape_default_coord(&o_falling_shape); shape_type next_shape_type = rand() % SHAPE_NB; shape_set(&o_preview_shape, next_shape_type); //put the preview shape on the side of the board o_preview_shape.x = LEVEL_WIDTH + 1; o_preview_shape.y = o_preview_shape.len - SHAPE_SIZE / 2 + 2; while (!done){ //drawing SDL_SetRenderDrawColor(renderer, 0, 42, 0, 255); SDL_RenderClear(renderer); //draw the falling shape shape_draw(&o_falling_shape, p_game->p_fontmap, renderer); //draw the next shape as a preview shape_draw(&o_preview_shape, p_game->p_fontmap, renderer); //draw the level (empty blocks and alderly placed shapes) level_draw(renderer, &o_falling_shape, p_game->p_fontmap); int game_speed = level_max * 100 - level_cur * 100; int total=0; for(int i=0;i<3;i++)total += p_game->state[i]; //draw a line between the board and the score / next shape area SDL_SetRenderDrawColor( renderer, 0x00, 0x00, 0xFF, 0xFF ); SDL_RenderDrawLine(renderer, TILE_SIZE * 12, 0, TILE_SIZE * 12, SCREEN_HEIGHT); //draw the score fontmap_printf(p_game->p_fontmap, SCREEN_WIDTH - 7*5, SCREEN_HEIGHT - 120, renderer, "%d", p_game->score); SDL_Event event; while (SDL_PollEvent(&event)){ if((event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN)|| (event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 5)){ ret_code = state_paused(renderer); if(ret_code!=STAY){ done = 1; } } if(event.type == SDL_QUIT){ exit(EXIT_SUCCESS); } switch ( event.type ) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_RIGHT: if(shape_move(&o_falling_shape, 1, 0))o_falling_shape.x++; break; case SDLK_LEFT: if(shape_move(&o_falling_shape, -1, 0))o_falling_shape.x--; break; case SDLK_DOWN: if(shape_move(&o_falling_shape, 0, 1)) timelastcall=SDL_GetTicks()+game_speed; break; case SDLK_SPACE: while(shape_move(&o_falling_shape, 0, 1)) o_falling_shape.y++; timelastcall=SDL_GetTicks()+game_speed; break; case SDLK_f: shape_rotate(&o_falling_shape, 0); break; case SDLK_d: shape_rotate(&o_falling_shape, 1); break; case SDLK_q: exit(EXIT_SUCCESS); break; default: break; } break; case SDL_JOYBUTTONDOWN: switch(event.jbutton.button) { case 0: while(shape_move(&o_falling_shape, 0, 1)) o_falling_shape.y++; timelastcall=SDL_GetTicks()+game_speed; break; case 2: shape_rotate(&o_falling_shape, 1); break; case 3: shape_rotate(&o_falling_shape, 0); break; case 6: done=true; ret_code = QUIT; break; case 19: done=true; ret_code = QUIT; break; default: break; } break; } } if(SDL_GetTicks() - timelastcall > game_speed) { //check if the falling shape can move if(shape_move(&o_falling_shape, 0, 1)){ //update coord o_falling_shape.y++; }else{ //the shape can not move int i; level_add_shape(&o_falling_shape); int lines_in_a_row=0; //tab of line index to remove int rem_tab[SHAPE_SIZE]; int line_nb = level_check_line(rem_tab); for(i=1;i<line_nb;i++){ if(rem_tab[i] == rem_tab[i-1]+1)lines_in_a_row++; else lines_in_a_row = 0; } if(line_nb){ //blink completed line(s) blink(renderer, rem_tab, line_nb, p_game->p_fontmap); for(i=0;i<line_nb;i++)level_remove_line(rem_tab[i]); //remove completed line(s) p_game->score += line_nb * (lines_in_a_row + 1); //update score p_game->state[lines_in_a_row]++; //update game states if(line_nb == 2 && lines_in_a_row == 0)p_game->state[0]++; level_cur = p_game->score / 1000; //eventually update level number if(level_cur >= level_max)level_cur = level_max; } if(level_check_game_over()){ done = 1; ret_code = GAME_OVER; } else{ //"create" a new falling block by chaning the falling shape type //to the next shape and reseting the coords shape_set(&o_falling_shape, next_shape_type); shape_default_coord(&o_falling_shape); //pick a next shape type randomly for the preview and the next falling //block next_shape_type = rand() % SHAPE_NB; shape_set(&o_preview_shape, next_shape_type); } } //update timer timelastcall=SDL_GetTicks(); } SDL_RenderPresent(renderer); } return ret_code; }
static int tetris(int argc, char ** argv) { struct console * con = get_console_stdout(); u32_t x, y, shape; u32_t newx, newy, newshape; bool_t fell = FALSE; bool_t try_again = FALSE; u32_t code; if(!con) return -1; console_setcursor(con, FALSE); console_cls(con); srand(jiffies + rand()); do { screen_init(); y = 3; x = GAME_AREA_WIDTH / 2; shape = rand() % ARRAY_SIZE(shapes); shape_draw(x, y, shape); refresh(); while(1) { newx = x; newy = y; newshape = shape; if(console_stdin_getcode_with_timeout(&code, 250)) { switch(code) { case 0x10: /* up */ newshape = shapes[shape].plus90; fell = FALSE; break; case 0xe: /* down */ if(y < GAME_AREA_HEIGHT - 1) newy = y + 1; fell = TRUE; break; case 0x2: /* left */ if(x > 0) newx = x - 1; fell = FALSE; break; case 0x6: /* right */ if(x < GAME_AREA_WIDTH - 1) newx = x + 1; fell = FALSE; break; default: newy++; fell = TRUE; break; } } else { newy++; fell = TRUE; } if((newx == x) && (newy == y) && (newshape == shape)) continue; shape_erase(x, y, shape); if(shape_hit(newx, newy, newshape) == FALSE) { x = newx; y = newy; shape = newshape; } else if(fell == TRUE) { shape_draw(x, y, shape); y = 3; x = GAME_AREA_WIDTH / 2; shape = rand() % ARRAY_SIZE(shapes); collapse(); if(shape_hit(x, y, shape)) { try_again = FALSE; break; } } shape_draw(x, y, shape); refresh(); } }while(try_again); console_setcursor(con, TRUE); console_setcolor(con, TCOLOR_WHITE, TCOLOR_BLACK); console_cls(con); return 0; }