void debug_map(map *p_map, SDL_Renderer *renderer, int x_from, int x_to, int y_from, int y_to, int tile_x_index, int tile_y_index){ int print_x = 0; fontmap_printf(p_map->p_fontmap, print_x, 0, renderer, "SCR W %3d SCR H %3d", SCREEN_WIDTH, SCREEN_HEIGHT); fontmap_printf(p_map->p_fontmap, print_x, 8, renderer, "CAM X %3d CAM Y %3d\n\ X FRM %3d X TO %3d\nY FRM %3d Y TO %3d\n\ X INDX %2d Y INDX %2d", p_map->o_camera.x, p_map->o_camera.y, x_from, x_to, y_from, y_to, tile_x_index, tile_y_index); SDL_Point iso_cam = cart_to_iso_i(p_map->o_camera.x, p_map->o_camera.y); SDL_Point iso_from = cart_to_iso_i(x_from, y_from); SDL_Point iso_to = cart_to_iso_i(x_to, y_to); fontmap_printf(p_map->p_fontmap, print_x, 8*5, renderer, "\n----------ISO-----------\n\ X FRM %3d X TO %3d\nY FRM %3d Y TO %3d", iso_cam.x, iso_cam.y, iso_from.x, iso_to.x, iso_from.y, iso_to.y); }
void debug_map(map *p_map, SDL_Renderer *renderer, int x_from, int x_to, int y_from, int y_to, int tile_x_index, int tile_y_index){ fontmap_printf(p_map->p_fontmap, 0, 0, renderer, "CAM X %d CAM Y %d\nX FROM %d X TO %d\nY FROM %d Y TO %d\nX INDEX %d Y INDEX %d", p_map->o_camera.x, p_map->o_camera.y, x_from, x_to, y_from, y_to, tile_x_index, tile_y_index); }
void level_draw(SDL_Surface* destination) { for (int i=0;i<LEVEL_HEIGHT;i++){ for (int j=0;j<LEVEL_WIDTH;j++){ if(level[i][j] != 0){ image_draw_part(gfx, destination, j * TILE_SIZE, i * TILE_SIZE, (level[i][j] -1) * TILE_SIZE, 0, TILE_SIZE, TILE_SIZE); } #ifdef DEBUG fontmap_printf(j * TILE_SIZE, i * TILE_SIZE, destination, "%d", level[i][j]); #endif } } }
void play(SDL_Surface* screen) { int x; int y; x = 10; while (g_playloop == 1) { y = 23; SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 5, 5, 5)); fontmap_printf(x, y, screen, "304-PACMAN <PAYET-S> + 1UP: 0 + " "SCORE: %03d + TIME: %d", g_score, g_time); y += FONTMAP_SIZE * 2; fontmap_print(x, y, screen, g_prompt.c_str()); y += FONTMAP_SIZE * 2; handle_event(screen, y); y += FONTMAP_SIZE * 2; for (auto line : g_map) { fontmap_print(x, y, screen, line.c_str()); y += FONTMAP_SIZE; } if (g_choose_file == 1) g_prompt = "$> Choose a map."; else if (g_count <= (g_score / 10)) g_prompt = "$> Congratulation!"; else if (g_pause == 0) { g_prompt = "$> GO!"; g_time += 1; if ((g_time % 100) == 0) { move_player(); move_ghost(); } } else if (g_pause == 1) { g_prompt = "$> Game is paused."; } SDL_Flip(screen); } }
game_status state_game_over(SDL_Renderer* renderer, game* p_game) { bool done=false; timer* p_timer = timer_init(); timer_start(p_timer); int total=0; for(int i=0;i<3;i++)total += p_game->state[i]; while (!done) { if(timer_get_ticks(p_timer) >= 5 * 1000){ done = true; } SDL_Event event; SDL_JoystickUpdate(); while(SDL_PollEvent(&event)){ if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN) || (event.type == SDL_JOYBUTTONDOWN && event.jbutton.button == 5)){ done = true; } } //print the score fontmap_printf(p_game->p_fontmap, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2, renderer, "%d", p_game->score); SDL_RenderPresent(renderer); } free(p_timer); return IN_GAME; }
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; }
/** Display a menu to resize the map enter the new map size for width, height and depth. TODO if the value entered is lower than the current map size ask if the tiles to delete are at front or at rear TODO if the value entered is higher than the current map size ask if the tile to create are at front or a rear and select in the chipset which tile to fill */ game_status state_resize_menu(SDL_Renderer *renderer, game* p_game){ bool done=false; char text[BUFSIZ] = {'\0'}; map *p_map = p_game->p_map; int new_width, new_height, new_depth; //flush the keys input which triggered this game state SDL_FlushEvent(SDL_TEXTINPUT); SDL_StartTextInput(); while (!done){ //draw SDL_RenderClear(renderer); SDL_SetRenderDrawColor(renderer, 0x22, 0x22, 0x42, 0x4F); SDL_Rect r = {.x=0, .y=0, .w=SCREEN_WIDTH, .h=SCREEN_HEIGHT}; SDL_RenderFillRect(renderer, &r); fontmap_printf(p_game->p_fontmap, 0, p_game->p_fontmap->size, renderer, "CURRENT MAP SIZE WIDTH %d HEIGHT %d DEPTH %d\n\ ENTER NEW SIZE WITH FORMAT %d-%d-%d ", p_map->width, p_map->height, p_map->depth, p_map->width, p_map->height, p_map->depth); //print back to the user the entered text fontmap_printf(p_game->p_fontmap, 0, p_game->p_fontmap->size*3, renderer, text); //render SDL_RenderPresent(renderer); //input SDL_Event event; while (SDL_PollEvent(&event)){ if(event.type == SDL_QUIT){ exit(EXIT_SUCCESS); } switch ( event.type ) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_q: done=true; break; case SDLK_RETURN: //assign integers from the formated input sscanf(text, "%d-%d-%d", &new_width, &new_height, &new_depth); //allocate memory tile *tiles = calloc(new_width*new_height*new_depth, sizeof(tile)); //copy the current map tile into the new tiles memmove(tiles, p_map->tiles, p_map->height*p_map->width*p_map->depth); //free map tiles free(p_map->tiles); //allocate new tiles p_map->tiles = tiles; p_map->width = new_width; p_map->height = new_height; p_map->depth = new_depth; break; case SDLK_BACKSPACE: //remove the last character by replacing it by the EOS char text[strlen(text)-1] = '\0'; break; } break; case SDL_TEXTINPUT: strcat(text, event.text.text); break; } } } SDL_StopTextInput(); return STAY; } void game_tile_click(game* p_game, int x, int y, Uint8 button){ map *p_map = p_game->p_map; int x_offset = p_map->p_chipset->width; int y_offset = p_map->p_chipset->height; if(x < x_offset && y < y_offset){ //the click was on the chipset part //set the chipset tile p_map->chipset_tile_x_index = x / p_map->tile_width; p_map->chipset_tile_y_index = y / p_map->tile_height; } else{ //the clic was on the map part //change the clicked map tile with the selected chipset tile //check if the index is in the map boundaries if(p_map->map_tile_x_index >= 0 && p_map->map_tile_x_index < p_map->width && p_map->map_tile_y_index >= 0 && p_map->map_tile_y_index < p_map->height){ tile* p_tile = map_get_tile(p_map, p_map->map_tile_x_index, p_map->map_tile_y_index, p_map->map_tile_z_index); switch(p_game->tile_mode){ default: case TILE: tile_set_coord(p_tile, p_map->chipset_tile_x_index, p_map->chipset_tile_y_index); break; case LINE: if(p_game->tile_from_x < 0 || p_game->tile_from_y < 0 || p_game->tile_from_z < 0){ //set the tile to draw from p_game->tile_from_x = p_map->map_tile_x_index; p_game->tile_from_y = p_map->map_tile_y_index; p_game->tile_from_z = p_map->map_tile_z_index; } else{ //set the tile to draw to //the tile to draw to is always superior to the tile to draw from if(p_map->map_tile_x_index < p_game->tile_from_x){ p_game->tile_to_x = p_game->tile_from_x; p_game->tile_from_x = p_map->map_tile_x_index; } else{ p_game->tile_to_x = p_map->map_tile_x_index; } if(p_map->map_tile_y_index < p_game->tile_from_y){ p_game->tile_to_y = p_game->tile_from_y; p_game->tile_from_y = p_map->map_tile_y_index; } else{ p_game->tile_to_y = p_map->map_tile_y_index; } if(p_map->map_tile_z_index < p_game->tile_from_z){ p_game->tile_to_z = p_game->tile_from_z; p_game->tile_from_z = p_map->map_tile_z_index; } else{ p_game->tile_to_z = p_map->map_tile_z_index; } for(int x=p_game->tile_from_x;x<=p_game->tile_to_x;x++){ for(int y=p_game->tile_from_y;y<=p_game->tile_to_y;y++){ for(int z=p_game->tile_from_z;z<=p_game->tile_to_z;z++){ p_tile = map_get_tile(p_map, x, y, z); tile_set_coord(p_tile, p_map->chipset_tile_x_index, p_map->chipset_tile_y_index); } } } p_game->tile_from_x = -1; p_game->tile_from_y = -1; p_game->tile_from_z = -1; p_game->tile_to_x = -1; p_game->tile_to_y = -1; p_game->tile_to_z = -1; } break; } } } #ifdef DEBUG printf("map clicked at index %d %d %d\n", p_map->map_tile_x_index, p_map->map_tile_y_index, p_map->map_tile_z_index); #endif }
void handle_event(SDL_Surface* screen, int y) { static int i = 0; static int idx = 0; static t_str name("NULL"); static const int lim = 60; u32 pressed; WPAD_ScanPads(); pressed = WPAD_ButtonsUp(WPAD_CHAN_0); if (pressed & WPAD_BUTTON_HOME) { exit(EXIT_SUCCESS); } else if (g_choose_file && g_file.size() > 0) { if (pressed & WPAD_BUTTON_LEFT) { idx = (g_file.size() + idx - 1) % g_file.size(); name = g_file[idx]; } else if (pressed & WPAD_BUTTON_RIGHT) { idx = (g_file.size() + idx + 1) % g_file.size(); name = g_file[idx]; } else if (strcmp(name.c_str(), "NULL") != 0 && (pressed & WPAD_BUTTON_A)) { g_fname += "/"; g_fname += name; read_file(g_fname.c_str()); g_choose_file = 0; g_time = 0; g_score = 0; } if (i < (lim / 2)) fontmap_printf(23, y, screen, "<%s>", name.c_str()); else fontmap_printf(23, y, screen, " %s ", name.c_str()); i = (i + 1) % lim; } else if (pressed & WPAD_BUTTON_MINUS) { g_choose_file = 1; g_fname = "/maps"; } else if (pressed & WPAD_BUTTON_PLUS) { g_pause ^= 1; } else if (pressed & WPAD_BUTTON_UP) { g_pos_p[2] = DIR_UP; } else if (pressed & WPAD_BUTTON_LEFT) { g_pos_p[2] = DIR_LEFT; } else if (pressed & WPAD_BUTTON_RIGHT) { g_pos_p[2] = DIR_RIGHT; } else if (pressed & WPAD_BUTTON_DOWN) { g_pos_p[2] = DIR_DOWN; } else { fontmap_printf(23, y, screen, "PLAYER <%02u;%02u;%u> + GHOST <%02u;%02u;%u>", g_pos_p[0], g_pos_p[1], g_pos_p[2], g_pos_f[0], g_pos_f[1], g_pos_f[2]); } }