diff --git a/data/Makefile.am b/data/Makefile.am index e24d33b..ec37ea9 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -134,7 +134,8 @@ nobase_dist_gamedata_DATA = images/background.png \ images/crash_1.png \ images/crash_2.png \ images/crash_3.png \ - images/crash_4.png + images/crash_4.png \ + klickclack.ttf # Instalar los archivos .desktop e iconos applicationsdir = $(datadir)/applications diff --git a/data/klickclack.ttf b/data/klickclack.ttf new file mode 100644 index 0000000..0437808 Binary files /dev/null and b/data/klickclack.ttf differ diff --git a/po/bean-counters-classic.pot b/po/bean-counters-classic.pot new file mode 100644 index 0000000..3dc253e --- /dev/null +++ b/po/bean-counters-classic.pot @@ -0,0 +1,93 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the bean-counters-classic package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: bean-counters-classic 0.1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-13 13:45-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/beans.c:872 +msgid "LIVES:" +msgstr "" + +#: src/beans.c:873 +msgid "TRUCK:" +msgstr "" + +#: src/beans.c:874 +msgid "SCORE:" +msgstr "" + +#: src/beans.c:1732 +#, c-format +msgid "" +"Error: Can't initialize the video subsystem\n" +"The error returned by SDL is:\n" +"%s\n" +msgstr "" + +#: src/beans.c:1743 +msgid "Bean Counters Classic" +msgstr "" + +#: src/beans.c:1750 +#, c-format +msgid "" +"Error: Can't setup 760x480 video mode.\n" +"The error returned by SDL is:\n" +"%s\n" +msgstr "" + +#: src/beans.c:1759 +#, c-format +msgid "" +"Warning: Can't initialize the audio subsystem\n" +"Continuing...\n" +msgstr "" + +#: src/beans.c:1768 +#, c-format +msgid "Warning: Can't initialize the SDL Mixer library\n" +msgstr "" + +#: src/beans.c:1779 src/beans.c:1906 +#, c-format +msgid "" +"Failed to load data file:\n" +"%s\n" +"The error returned by SDL is:\n" +"%s\n" +msgstr "" + +#: src/beans.c:1806 +#, c-format +msgid "" +"Failed to load data file:\n" +"%s\n" +msgstr "" + +#: src/beans.c:1862 +#, c-format +msgid "" +"Error: Can't initialize the SDL TTF library\n" +"%s\n" +msgstr "" + +#: src/beans.c:1873 +#, c-format +msgid "" +"Failed to load font file 'Klick Clack\n" +"The error returned by SDL is:\n" +"%s\n" +msgstr "" diff --git a/src/Makefile.am b/src/Makefile.am index d07f93e..e87c19e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ bean_counters_classic_SOURCES = beans.c \ path.c path.h \ collider.c collider.h \ sdl2_rect.c sdl2_rect.h \ + draw-text.c draw-text.h \ gettext.h if MACOSX diff --git a/src/beans.c b/src/beans.c index 16f0294..86316ca 100644 --- a/src/beans.c +++ b/src/beans.c @@ -43,6 +43,7 @@ #include "gfx_blit_func.h" #include "collider.h" +#include "draw-text.h" #define FPS (1000/24) #define RANDOM(x) ((int) (x ## .0 * rand () / (RAND_MAX + 1.0))) @@ -472,6 +473,13 @@ enum { NUM_COLLIDERS }; +enum { + TEXT_LIVES, + TEXT_TRUCKS, + TEXT_SCORE, + NUM_TEXTS +}; + const char *collider_names[NUM_COLLIDERS] = { "collider/bag_3.col", @@ -860,6 +868,11 @@ const int flower_offsets[32][2] = { {334, 382} }; +const char *text_strings[NUM_TEXTS] = { + gettext_noop ("LIVES:"), + gettext_noop ("TRUCK:"), + gettext_noop ("SCORE:") +}; /* Prototipos de función */ int game_intro (void); @@ -874,6 +887,7 @@ void delete_bag (BeanBag *p); /* Variables globales */ SDL_Surface * screen; SDL_Surface * images[NUM_IMAGES]; +SDL_Surface * texts[NUM_TEXTS]; SDL_Surface * penguin_images[NUM_PENGUIN_FRAMES]; int use_sound; Collider *colliders[NUM_COLLIDERS]; @@ -887,6 +901,8 @@ Mix_Music * mus_carnie; BeanBag *first_bag = NULL; BeanBag *last_bag = NULL; +TTF_Font *ttf24_klickclack; + int main (int argc, char *argv[]) { /* Recuperar las rutas del sistema */ initSystemPaths (argv[0]); @@ -1037,8 +1053,21 @@ int game_loop (void) { int fish_max = 4; int fish_counter = 0; int crash_anim = -1; - + int score = 0; int bag_stack = 0; + char buffer[20]; + + SDL_Color negro, blanco; + blanco.r = blanco.g = blanco.b = 255; + blanco.unused = 255; + negro.r = negro.g = negro.b = 0; + negro.unused = 255; + + SDL_Surface *vidas_p, *nivel_p, *score_p; + + vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, "3", blanco, negro); + nivel_p = draw_text_with_shadow (ttf24_klickclack, 2, "1", blanco, negro); + score_p = draw_text_with_shadow (ttf24_klickclack, 2, "0", blanco, negro); SDL_EventState (SDL_MOUSEMOTION, SDL_IGNORE); @@ -1059,9 +1088,15 @@ int game_loop (void) { bags--; if (next_level_visible == NO_NEXT_LEVEL) { - /* TODO: Incrementar score = score + (nivel * 3) */ + score = score + (nivel * 3); + SDL_FreeSurface (score_p); + snprintf (buffer, sizeof (buffer), "%d", score); + score_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); } else if (next_level_visible == NEXT_LEVEL) { - /* TODO: Incrementar score = score + (nivel * 25) */ + score = score + (nivel * 25); + SDL_FreeSurface (score_p); + snprintf (buffer, sizeof (buffer), "%d", score); + score_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); } /* TODO: Sonido de poner bolsa */ @@ -1196,15 +1231,20 @@ int game_loop (void) { animacion = 0; airbone = 1000; /* El airbone bloquea que salgan más objetos */ vidas--; - + SDL_FreeSurface (vidas_p); + snprintf (buffer, sizeof (buffer), "%d", vidas); + vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); /* TODO: Reproducir aquí el sonido de golpe */ } else { gameover_visible = TRUE; printf ("Game Over visible\n"); } } else { - /* Sumar solo si no crasheó al pinguino - * score = score + (nivel * 2); */ + /* Sumar solo si no crasheó al pinguino */ + score = score + (nivel * 2); + SDL_FreeSurface (score_p); + snprintf (buffer, sizeof (buffer), "%d", score); + score_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); } airbone--; printf ("Airbone: %i\n", airbone); @@ -1229,6 +1269,9 @@ int game_loop (void) { animacion = 0; airbone = 1000; /* El airbone bloquea que salgan más objetos */ vidas--; + SDL_FreeSurface (vidas_p); + snprintf (buffer, sizeof (buffer), "%d", vidas); + vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); } else { gameover_visible = TRUE; printf ("Game Over visible\n"); @@ -1246,6 +1289,9 @@ int game_loop (void) { if (i == SDL_TRUE) { vidas++; + SDL_FreeSurface (vidas_p); + snprintf (buffer, sizeof (buffer), "%d", vidas); + vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); /* TODO: Reproducir sonido boing */ /* TODO: Mostrar la notificación de 1 vida */ @@ -1270,6 +1316,9 @@ int game_loop (void) { animacion = 0; airbone = 1000; /* El airbone bloquea que salgan más objetos */ vidas--; + SDL_FreeSurface (vidas_p); + snprintf (buffer, sizeof (buffer), "%d", vidas); + vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); } else { gameover_visible = TRUE; } @@ -1295,6 +1344,9 @@ int game_loop (void) { animacion = 0; airbone = 1000; /* El airbone bloquea que salgan más objetos */ vidas--; + SDL_FreeSurface (vidas_p); + snprintf (buffer, sizeof (buffer), "%d", vidas); + vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); } else { gameover_visible = TRUE; } @@ -1393,6 +1445,51 @@ int game_loop (void) { SDL_BlitSurface (images[i], NULL, screen, &rect); } + /* Los mensajes de texto van antes de las bolsas */ + rect.x = 30; + rect.y = 8; + rect.w = texts[TEXT_LIVES]->w; + rect.h = texts[TEXT_LIVES]->h; + + SDL_BlitSurface (texts[TEXT_LIVES], NULL, screen, &rect); + + rect.x = 30 + texts[TEXT_LIVES]->w + 2; + rect.y = 8; + rect.w = vidas_p->w; + rect.h = vidas_p->h; + + SDL_BlitSurface (vidas_p, NULL, screen, &rect); + + rect.x = 216; + rect.y = 8; + rect.w = texts[TEXT_TRUCKS]->w; + rect.h = texts[TEXT_TRUCKS]->h; + + SDL_BlitSurface (texts[TEXT_TRUCKS], NULL, screen, &rect); + + rect.x = 216 + texts[TEXT_TRUCKS]->w + 5; + rect.y = 8; + rect.w = nivel_p->w; + rect.h = nivel_p->h; + + SDL_BlitSurface (nivel_p, NULL, screen, &rect); + + rect.x = 390; + rect.y = 8; + rect.w = texts[TEXT_SCORE]->w; + rect.h = texts[TEXT_SCORE]->h; + + SDL_BlitSurface (texts[TEXT_SCORE], NULL, screen, &rect); + + rect.x = 390 + texts[TEXT_SCORE]->w + 5; + rect.h = 8; + rect.w = score_p->w; + rect.h = score_p->h; + + SDL_BlitSurface (score_p, NULL, screen, &rect); + + /* TODO: Dibujar el mensaje de nivel completo */ + /* Dibujar los objetos en pantalla */ thisbag = first_bag; while (thisbag != NULL) { @@ -1518,8 +1615,6 @@ int game_loop (void) { } if (next_level_visible == NEXT_LEVEL) { - - if (animacion < 36) { rect.x = 568 + (198 * animacion) / 36; } else if (animacion >= 36 && animacion < 60) { @@ -1566,6 +1661,9 @@ int game_loop (void) { nivel++; + SDL_FreeSurface (nivel_p); + snprintf (buffer, sizeof (buffer), "%d", nivel); + nivel_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); airbone = 0; bag_stack = 0; @@ -1739,8 +1837,28 @@ void setup (void) { exit (1); } + sprintf (buffer_file, "%s%s", systemdata_path, "klickclack.ttf"); + ttf24_klickclack = TTF_OpenFont (buffer_file, 24); + + if (!ttf24_klickclack) { + fprintf (stderr, + _("Failed to load font file 'Klick Clack\n" + "The error returned by SDL is:\n" + "%s\n"), TTF_GetError ()); + SDL_Quit (); + exit (1); + } + // TODO: Favor de manejar correctamente el bind_textdomain_codeset - //bind_textdomain_codeset (PACKAGE, "UTF-8"); + bind_textdomain_codeset (PACKAGE, "UTF-8"); + + SDL_Color negro, blanco; + blanco.r = blanco.g = blanco.b = 255; + negro.r = negro.g = negro.b = 0; + + for (g = 0; g < NUM_TEXTS; g++) { + texts[g] = draw_text_with_shadow (ttf24_klickclack, 2, _(text_strings[g]), blanco, negro); + } } void setup_and_color_penguin (void) { diff --git a/src/draw-text.c b/src/draw-text.c new file mode 100644 index 0000000..850dce8 --- /dev/null +++ b/src/draw-text.c @@ -0,0 +1,150 @@ +/* + * draw-text.c + * This file is part of Find Four + * + * Copyright (C) 2015 - Félix Arreola Rodríguez + * + * Find Four 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 2 of the License, or + * (at your option) any later version. + * + * Find Four 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 Find Four. If not, see . + */ + +#include +#include + +#include "gfx_blit_func.h" +#include "draw-text.h" + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define RMASK 0xff000000 +#define GMASK 0x00ff0000 +#define BMASK 0x0000ff00 +#define AMASK 0x000000ff +#else +#define RMASK 0x000000ff +#define GMASK 0x0000ff00 +#define BMASK 0x00ff0000 +#define AMASK 0xff000000 +#endif + +static char *l_strsep(char **from, const char *delim) { + char *s, *dp, *ret; + + if ((s = *from) == NULL) + return NULL; + + ret = s; + while (*s != '\0') { + /* loop until the end of s, checking against each delimiting character, + * if we find a delimiter set **s to '\0' and return our previous token + * to the user. */ + dp = (char *)delim; + while (*dp != '\0') { + if (*s == *dp) { + *s = '\0'; + *from = s + 1; + return ret; + } + dp++; + } + s++; + } + /* end of string case */ + *from = NULL; + return ret; +} + +SDL_Surface *draw_text (TTF_Font *font, const char *cadena, SDL_Color *color) { + SDL_Surface *final, **text; + SDL_Rect dest_rect; + int n_tokens; + int g, len, maxw; + char *dup, *str_token, *original; + + /* Si contiene saltos de linea, llamar a la otra función */ + if (strchr (cadena, '\n') != NULL) { + len = strlen (cadena); + for (g = 0, n_tokens = 1; g < len; g++) { + if (cadena[g] == '\n') n_tokens++; + } + len = TTF_FontLineSkip (font) * n_tokens; + + text = (SDL_Surface **) malloc (sizeof (SDL_Surface *) * n_tokens); + original = dup = strdup (cadena); + + str_token = l_strsep (&dup, "\n"); + g = 0; maxw = 0; + while (str_token != NULL) { + if (str_token[0] != '\0') { + text[g] = TTF_RenderUTF8_Blended (font, str_token, *color); + if (text[g]->w > maxw) maxw = text[g]->w; + } else { + text[g] = NULL; + } + g++; + str_token = l_strsep (&dup, "\n"); + }; + final = SDL_CreateRGBSurface (SDL_SWSURFACE, maxw, len, 32, RMASK, GMASK, BMASK, AMASK); + + SDL_FillRect (final, NULL, SDL_MapRGBA (final->format, 0, 0, 0, 0)); + /*SDL_SetAlpha(final, 0, SDL_ALPHA_OPAQUE);*/ + len = TTF_FontLineSkip (font); + for (g = 0; g < n_tokens; g++) { + if (text[g] == NULL) continue; + SDL_SetAlpha (text[g], 0, SDL_ALPHA_OPAQUE); + dest_rect.x = (maxw - text[g]->w) / 2; + dest_rect.y = len * g; + dest_rect.w = text[g]->w; + dest_rect.h = text[g]->h; + /*fprintf (stdout, "UMASK, R: %i, G: %i, B: %i, A: %i\n", text->format->Rmask, text->format->Gmask, text->format->Bmask, text->format->Amask);*/ + SDL_BlitSurface (text[g], NULL, final, &dest_rect); + SDL_FreeSurface (text[g]); + } + SDL_SetAlpha(final, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); + free (text); + free (original); + return final; + } else { + /* En caso contrario, renderizarla nosotros mismos */ + return TTF_RenderUTF8_Blended (font, cadena, *color); + } +} + +SDL_Surface *draw_text_with_shadow (TTF_Font *font, int outline, const char *text, SDL_Color foreground, SDL_Color background) { + SDL_Surface *black_letters, *white_letters; + SDL_Rect rect; + + /* Algunas validaciones */ + if (!font) { + return NULL; + } + + if (!text || text[0] == '\0') { + /* Texto vacio */ + return NULL; + } + + TTF_SetFontOutline (font, outline); + black_letters = TTF_RenderUTF8_Blended (font, text, background); + + TTF_SetFontOutline (font, 0); + white_letters = TTF_RenderUTF8_Blended (font, text, foreground); + + rect.w = white_letters->w; rect.h = white_letters->h; + rect.x = rect.y = outline; + + SDL_gfxBlitRGBA (white_letters, NULL, black_letters, &rect); + + SDL_FreeSurface (white_letters); + + return black_letters; +} diff --git a/src/draw-text.h b/src/draw-text.h new file mode 100644 index 0000000..a713acf --- /dev/null +++ b/src/draw-text.h @@ -0,0 +1,31 @@ +/* + * draw-text.h + * This file is part of Find Four + * + * Copyright (C) 2015 - Félix Arreola Rodríguez + * + * Find Four 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 2 of the License, or + * (at your option) any later version. + * + * Find Four 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 Find Four. If not, see . + */ + +#ifndef __DRAW_TEXT_H__ +#define __DRAW_TEXT_H__ + +#include +#include + +SDL_Surface *draw_text (TTF_Font *font, const char *cadena, SDL_Color *color); +SDL_Surface *draw_text_with_shadow (TTF_Font *font, int outline, const char *text, SDL_Color foreground, SDL_Color background); + +#endif /* __DRAW_TEXT_H__ */ +