/* * Copyright (C) 2021 P. J. McDermott * * This file is part of Dodge Balls * * Dodge Balls is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dodge Balls is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Dodge Balls. If not, see . */ #include #include #include #include "collision.h" #include "defs.h" #include "dirs.h" #include "help.h" #include "output.h" #include "util.h" const char *_db_help_text = PACKAGE_NAME " version " PACKAGE_VERSION "\n" "\n" "Press Esc or Enter to exit help\n" "\n" "Evade the balls and get to the target! Dodge Balls is a simple " "puzzle game with obstacle courses consisting of moving balls.\n" "\n" "The classic game is a liberated remake of a 2007 game, Dodgeball " "v3.0, by the same author. It features 10 levels, each harder than " "the last.\n" "\n" "How to Play\n" "\n" "Move your character (a smiley face in the classic game) through the " "obstacle course to reach the target (a star in the classic game). If " "you are hit by a ball, the level is restarted.\n" "\n" "Controls\n" "\n" "Up: Move up\n" "Down: Move down\n" "Left: Move left\n" "Right: Move right\n" "...\n" "\n" "Hints\n" "\n" "Use the map to your advantage. You can go through walls that appear " "to be hollow. Try to anticipate where balls will be. Remember that " "they bounce off walls in the opposite direction. To stop, move " "against a wall."; static int _db_help_quit; static void _db_help_triangle(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int x_min, int y_min, int dir) { int i; int y; int x; SDL_Point points[(DB_SCROLL_W * (DB_SCROLL_W + 2)) / 4]; i = 0; for (y = 0; y < DB_SCROLL_H; ++y) { for (x = y; x < (DB_SCROLL_W - y); ++x) { points[i].x = x_min + x; if (dir > 0) { points[i].y = y_min + y; } else { points[i].y = y_min + DB_SCROLL_H - 1 - y; } ++i; } } SDL_SetRenderDrawColor(renderer, r, g, b, a); SDL_RenderDrawPoints(renderer, points, i); } int db_help(SDL_Window *window) { char *font_path; SDL_Renderer *renderer; TTF_Font *font; SDL_Color color; SDL_Surface *surface; SDL_Texture *texture; SDL_Rect text_src_rect; SDL_Rect text_dst_rect; SDL_Rect up_rect; SDL_Rect dn_rect; int up_over; int dn_over; SDL_Event event; font_path = db_strcat(db_get_fonts_dir(), "/UbuntuTitling-Bold.ttf"); renderer = SDL_GetRenderer(window); if (renderer == NULL) { db_err("Failed to get renderer (%s)", SDL_GetError()); return -1; } font = TTF_OpenFont(font_path, DB_FONT_TEXT_SIZE); if (font == NULL) { db_err("Failed to open font (%s)", TTF_GetError()); free(font_path); return -1; } color.r = DB_COLOR_FORE_R; color.g = DB_COLOR_FORE_G; color.b = DB_COLOR_FORE_B; color.a = DB_COLOR_FORE_A; surface = TTF_RenderText_Blended_Wrapped(font, _db_help_text, color, DB_WINDOW_W - DB_WINDOW_P * 2 - DB_SCROLL_W); if (surface == NULL) { db_err("Failed to create surface (%s)", TTF_GetError()); return -1; } TTF_CloseFont(font); texture = SDL_CreateTextureFromSurface(renderer, surface); if (texture == NULL) { db_err("Failed to create texture (%s)", SDL_GetError()); return -1; } text_src_rect.x = 0; text_src_rect.y = 0; text_src_rect.w = DB_WINDOW_W - DB_WINDOW_P * 2 - DB_SCROLL_W; text_src_rect.h = DB_WINDOW_H - DB_WINDOW_P * 2; text_dst_rect.x = DB_WINDOW_P; text_dst_rect.y = DB_WINDOW_P; text_dst_rect.w = DB_WINDOW_W - DB_WINDOW_P * 2 - DB_SCROLL_W; text_dst_rect.h = DB_WINDOW_H - DB_WINDOW_P * 2; up_rect.x = DB_WINDOW_W - DB_WINDOW_P - DB_SCROLL_W; up_rect.y = DB_WINDOW_P; up_rect.w = DB_SCROLL_W; up_rect.h = DB_SCROLL_H; dn_rect.x = DB_WINDOW_W - DB_WINDOW_P - DB_SCROLL_W; dn_rect.y = DB_WINDOW_H - DB_WINDOW_P - DB_SCROLL_H; dn_rect.w = DB_SCROLL_W; dn_rect.h = DB_SCROLL_H; up_over = 0; dn_over = 0; _db_help_quit = 0; while (SDL_WaitEvent(&event)) { switch (event.type) { case SDL_QUIT: _db_help_quit = 2; break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_UP: text_src_rect.y -= DB_SCROLL_S; if (text_src_rect.y < 0) { text_src_rect.y = 0; } break; case SDLK_DOWN: text_src_rect.y += DB_SCROLL_S; if (text_src_rect.y > surface->h - text_src_rect.h) { text_src_rect.y = surface->h - text_src_rect.h; } break; case SDLK_HOME: text_src_rect.y = 0; break; case SDLK_END: text_src_rect.y = surface->h - text_src_rect.h; break; case SDLK_ESCAPE: case SDLK_RETURN: case SDLK_KP_ENTER: _db_help_quit = 1; break; default: break; } break; case SDL_MOUSEMOTION: if (event.motion.state != 0) { break; } if (db_pt_in_rect(event.motion.x, event.motion.y, &up_rect)) { up_over = 1; break; } else { up_over = 0; } if (db_pt_in_rect(event.motion.x, event.motion.y, &dn_rect)) { dn_over = 1; break; } else { dn_over = 0; } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button != SDL_BUTTON_LEFT) { break; } if (db_pt_in_rect(event.button.x, event.button.y, &up_rect)) { text_src_rect.y -= DB_SCROLL_S; if (text_src_rect.y < 0) { text_src_rect.y = 0; } } else if (db_pt_in_rect(event.button.x, event.button.y, &dn_rect)) { text_src_rect.y += DB_SCROLL_S; if (text_src_rect.y > surface->h - text_src_rect.h) { text_src_rect.y = surface->h - text_src_rect.h; } } break; default: break; } if (_db_help_quit > 0) { break; } SDL_SetRenderDrawColor(renderer, DB_COLOR_BACK_R, DB_COLOR_BACK_G, DB_COLOR_BACK_B, DB_COLOR_BACK_A); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, &text_src_rect, &text_dst_rect); if (text_src_rect.y <= 0) { _db_help_triangle(renderer, DB_COLOR_DISA_R, DB_COLOR_DISA_G, DB_COLOR_DISA_B, DB_COLOR_DISA_A, DB_WINDOW_W - DB_WINDOW_P * 2, DB_WINDOW_P, -1); } else if (up_over == 1) { _db_help_triangle(renderer, DB_COLOR_ACTV_R, DB_COLOR_ACTV_G, DB_COLOR_ACTV_B, DB_COLOR_ACTV_A, DB_WINDOW_W - DB_WINDOW_P * 2, DB_WINDOW_P, -1); } else { _db_help_triangle(renderer, DB_COLOR_FORE_R, DB_COLOR_FORE_G, DB_COLOR_FORE_B, DB_COLOR_FORE_A, DB_WINDOW_W - DB_WINDOW_P * 2, DB_WINDOW_P, -1); } if (text_src_rect.y >= surface->h - text_src_rect.h) { _db_help_triangle(renderer, DB_COLOR_DISA_R, DB_COLOR_DISA_G, DB_COLOR_DISA_B, DB_COLOR_DISA_A, DB_WINDOW_W - DB_WINDOW_P * 2, DB_WINDOW_H - DB_WINDOW_P - DB_SCROLL_H, 1); } else if (dn_over == 1) { _db_help_triangle(renderer, DB_COLOR_ACTV_R, DB_COLOR_ACTV_G, DB_COLOR_ACTV_B, DB_COLOR_ACTV_A, DB_WINDOW_W - DB_WINDOW_P * 2, DB_WINDOW_H - DB_WINDOW_P - DB_SCROLL_H, 1); } else { _db_help_triangle(renderer, DB_COLOR_FORE_R, DB_COLOR_FORE_G, DB_COLOR_FORE_B, DB_COLOR_FORE_A, DB_WINDOW_W - DB_WINDOW_P * 2, DB_WINDOW_H - DB_WINDOW_P - DB_SCROLL_H, 1); } SDL_RenderPresent(renderer); } SDL_FreeSurface(surface); SDL_DestroyTexture(texture); return _db_help_quit - 1; }