Agrego texto de siguiente nivel.

master
Félix Arreola Rodríguez 2019-11-15 16:52:13 -06:00
parent b0e8f4f379
commit e02282ec2c
5 changed files with 727 additions and 24 deletions

View File

@ -9,6 +9,7 @@ bean_counters_classic_SOURCES = beans.c \
collider.c collider.h \ collider.c collider.h \
sdl2_rect.c sdl2_rect.h \ sdl2_rect.c sdl2_rect.h \
draw-text.c draw-text.h \ draw-text.c draw-text.h \
zoom.c zoom.h \
gettext.h gettext.h
if MACOSX if MACOSX

View File

@ -44,6 +44,7 @@
#include "gfx_blit_func.h" #include "gfx_blit_func.h"
#include "collider.h" #include "collider.h"
#include "draw-text.h" #include "draw-text.h"
#include "zoom.h"
#define FPS (1000/24) #define FPS (1000/24)
#define RANDOM(x) ((int) (x ## .0 * rand () / (RAND_MAX + 1.0))) #define RANDOM(x) ((int) (x ## .0 * rand () / (RAND_MAX + 1.0)))
@ -477,6 +478,14 @@ enum {
TEXT_LIVES, TEXT_LIVES,
TEXT_TRUCKS, TEXT_TRUCKS,
TEXT_SCORE, TEXT_SCORE,
TEXT_TRY_AGAIN,
TEXT_UNLOADED,
TEXT_NEXT_TRUCK,
TEXT_GAME_OVER,
NUM_TEXTS NUM_TEXTS
}; };
@ -871,7 +880,14 @@ const int flower_offsets[32][2] = {
const char *text_strings[NUM_TEXTS] = { const char *text_strings[NUM_TEXTS] = {
gettext_noop ("LIVES:"), gettext_noop ("LIVES:"),
gettext_noop ("TRUCK:"), gettext_noop ("TRUCK:"),
gettext_noop ("SCORE:") gettext_noop ("SCORE:"),
gettext_noop ("TRY AGAIN..."),
gettext_noop ("TRUCK\nUNLOADED!!"),
gettext_noop ("NEXT TRUCK!!"),
gettext_noop ("Game Over!")
}; };
/* Prototipos de función */ /* Prototipos de función */
@ -879,7 +895,7 @@ int game_intro (void);
int game_loop (void); int game_loop (void);
int game_finish (void); int game_finish (void);
void setup (void); void setup (void);
SDL_Surface * set_video_mode(unsigned flags); SDL_Surface * set_video_mode (unsigned flags);
void setup_and_color_penguin (void); void setup_and_color_penguin (void);
void add_bag (int tipo); void add_bag (int tipo);
void delete_bag (BeanBag *p); void delete_bag (BeanBag *p);
@ -902,6 +918,7 @@ BeanBag *first_bag = NULL;
BeanBag *last_bag = NULL; BeanBag *last_bag = NULL;
TTF_Font *ttf24_klickclack; TTF_Font *ttf24_klickclack;
TTF_Font *ttf196_klickclack;
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {
/* Recuperar las rutas del sistema */ /* Recuperar las rutas del sistema */
@ -1056,12 +1073,17 @@ int game_loop (void) {
int score = 0; int score = 0;
int bag_stack = 0; int bag_stack = 0;
char buffer[20]; char buffer[20];
SDL_Surface *numbers[3][20];
double z;
SDL_Color negro, blanco; SDL_Color negro, blanco, amarillo;
blanco.r = blanco.g = blanco.b = 255; blanco.r = blanco.g = blanco.b = 255;
blanco.unused = 255; blanco.unused = 255;
negro.r = negro.g = negro.b = 0; negro.r = negro.g = negro.b = 0;
negro.unused = 255; negro.unused = 255;
amarillo.r = amarillo.g = 255;
amarillo.b = 0;
amarillo.unused = 255;
SDL_Surface *vidas_p, *nivel_p, *score_p; SDL_Surface *vidas_p, *nivel_p, *score_p;
@ -1069,6 +1091,19 @@ int game_loop (void) {
nivel_p = draw_text_with_shadow (ttf24_klickclack, 2, "1", 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); score_p = draw_text_with_shadow (ttf24_klickclack, 2, "0", blanco, negro);
/* Preparar los números en tamaño grande */
numbers[0][19] = draw_text_with_shadow (ttf196_klickclack, 3, "1", amarillo, negro);
numbers[1][19] = draw_text_with_shadow (ttf196_klickclack, 3, "2", amarillo, negro);
numbers[2][19] = draw_text_with_shadow (ttf196_klickclack, 3, "3", amarillo, negro);
z = 1.0;
for (i = 18; i >= 0; i--) {
z = z - 0.016118421;
numbers[0][i] = zoomSurface (numbers[0][19], z, z, 1);
numbers[1][i] = zoomSurface (numbers[1][19], z, z, 1);
numbers[2][i] = zoomSurface (numbers[2][19], z, z, 1);
}
SDL_EventState (SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState (SDL_MOUSEMOTION, SDL_IGNORE);
do { do {
@ -1211,7 +1246,8 @@ int game_loop (void) {
j = thisbag->frame - thisbag->throw_length; j = thisbag->frame - thisbag->throw_length;
if (j < 0 && next_level_visible == NO_NEXT_LEVEL && bags < 6 && thisbag->bag <= 3) { /* Nota, no entra a este if si el pinguino está crasheado */
if (j < 0 && next_level_visible == NO_NEXT_LEVEL && bags < 6 && thisbag->bag <= 3 && thisbag->frame > 6) {
/* Calcular aquí la colisión contra el pingüino */ /* Calcular aquí la colisión contra el pingüino */
i = collider_hittest (colliders[COLLIDER_BAG_3], thisbag->bag_points[thisbag->frame][1], thisbag->bag_points[thisbag->frame][2], colliders[k], penguinx - 120, 251); i = collider_hittest (colliders[COLLIDER_BAG_3], thisbag->bag_points[thisbag->frame][1], thisbag->bag_points[thisbag->frame][2], colliders[k], penguinx - 120, 251);
@ -1222,7 +1258,7 @@ int game_loop (void) {
/* Reproducir el sonido de "Agarrar bolsa" */ /* Reproducir el sonido de "Agarrar bolsa" */
if (bags >= 6 && (try_visible == FALSE || gameover_visible == FALSE)) { if (bags >= 6) {
/* Esta bolsa crasheó al pingüino */ /* Esta bolsa crasheó al pingüino */
printf ("Penguin Crash\n"); printf ("Penguin Crash\n");
if (vidas > 0) { if (vidas > 0) {
@ -1252,38 +1288,39 @@ int game_loop (void) {
thisbag = nextbag; thisbag = nextbag;
continue; continue;
} }
} else if (j < 0 && thisbag->bag == 5 && next_level_visible == NO_NEXT_LEVEL) { } else if (j < 0 && thisbag->bag == 5 && next_level_visible == NO_NEXT_LEVEL && thisbag->frame > 6) {
i = collider_hittest (colliders_hazard_block, anvil_collider_offsets[thisbag->frame][0], anvil_collider_offsets[thisbag->frame][1], colliders[k], penguinx - 120, 251); i = collider_hittest (colliders_hazard_block, anvil_collider_offsets[thisbag->frame][0], anvil_collider_offsets[thisbag->frame][1], colliders[k], penguinx - 120, 251);
if (i == SDL_TRUE) { if (i == SDL_TRUE) {
bags = 7; bags = 7;
/* TODO: Reproducir el sonido de golpe de yunque */ /* TODO: Reproducir el sonido de golpe de yunque */
/* TODO: Acomodar la animación de "Crash" */
crash_anim = 0; crash_anim = 0;
printf ("Penguin Crash by anvil\n"); printf ("Penguin Crash by anvil\n");
if (vidas > 0) { if (vidas > 0 && try_visible == FALSE) {
try_visible = TRUE; try_visible = TRUE;
printf ("Try again visible\n"); printf ("Try again visible\n");
animacion = 0; animacion = 0;
airbone = 1000; /* El airbone bloquea que salgan más objetos */ airbone = 1000; /* El airbone bloquea que salgan más objetos */
printf ("Airbone: %i\n", airbone);
vidas--; vidas--;
SDL_FreeSurface (vidas_p); SDL_FreeSurface (vidas_p);
snprintf (buffer, sizeof (buffer), "%d", vidas); snprintf (buffer, sizeof (buffer), "%d", vidas);
vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro);
} else { } else if (try_visible == FALSE) {
gameover_visible = TRUE; gameover_visible = TRUE;
printf ("Game Over visible\n"); printf ("Game Over visible\n");
} }
anvil_out = FALSE; anvil_out = FALSE;
airbone--; airbone--;
printf ("Airbone: %i\n", airbone);
delete_bag (thisbag); delete_bag (thisbag);
thisbag = nextbag; thisbag = nextbag;
continue; continue;
} }
} else if (j < 0 && thisbag->bag == 4 && next_level_visible == NO_NEXT_LEVEL) { } else if (j < 0 && thisbag->bag == 4 && next_level_visible == NO_NEXT_LEVEL && thisbag->frame > 6 && bags < 6) {
i = collider_hittest (colliders[COLLIDER_ONEUP], thisbag->object_points[thisbag->frame][0], thisbag->object_points[thisbag->frame][1], colliders[k], penguinx - 120, 251); i = collider_hittest (colliders[COLLIDER_ONEUP], thisbag->object_points[thisbag->frame][0], thisbag->object_points[thisbag->frame][1], colliders[k], penguinx - 120, 251);
if (i == SDL_TRUE) { if (i == SDL_TRUE) {
@ -1310,8 +1347,7 @@ int game_loop (void) {
/* TODO: Reproducir el sonido de golpe de pescado */ /* TODO: Reproducir el sonido de golpe de pescado */
crash_anim = 0; crash_anim = 0;
if (vidas > 0 && try_visible == FALSE) {
if (vidas > 0) {
try_visible = TRUE; try_visible = TRUE;
animacion = 0; animacion = 0;
airbone = 1000; /* El airbone bloquea que salgan más objetos */ airbone = 1000; /* El airbone bloquea que salgan más objetos */
@ -1319,7 +1355,7 @@ int game_loop (void) {
SDL_FreeSurface (vidas_p); SDL_FreeSurface (vidas_p);
snprintf (buffer, sizeof (buffer), "%d", vidas); snprintf (buffer, sizeof (buffer), "%d", vidas);
vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro);
} else { } else if (try_visible == FALSE) {
gameover_visible = TRUE; gameover_visible = TRUE;
} }
@ -1339,7 +1375,7 @@ int game_loop (void) {
/* TODO: Reproducir el sonido de golpe de florero */ /* TODO: Reproducir el sonido de golpe de florero */
crash_anim = 0; crash_anim = 0;
if (vidas > 0) { if (vidas > 0 && try_visible == FALSE) {
try_visible = TRUE; try_visible = TRUE;
animacion = 0; animacion = 0;
airbone = 1000; /* El airbone bloquea que salgan más objetos */ airbone = 1000; /* El airbone bloquea que salgan más objetos */
@ -1347,7 +1383,7 @@ int game_loop (void) {
SDL_FreeSurface (vidas_p); SDL_FreeSurface (vidas_p);
snprintf (buffer, sizeof (buffer), "%d", vidas); snprintf (buffer, sizeof (buffer), "%d", vidas);
vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro); vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro);
} else { } else if (try_visible == FALSE) {
gameover_visible = TRUE; gameover_visible = TRUE;
} }
@ -1445,6 +1481,16 @@ int game_loop (void) {
SDL_BlitSurface (images[i], NULL, screen, &rect); SDL_BlitSurface (images[i], NULL, screen, &rect);
} }
if (gameover_visible == TRUE) {
rect.w = texts[TEXT_GAME_OVER]->w;
rect.h = texts[TEXT_GAME_OVER]->h;
rect.x = 365 - (rect.w / 2);
rect.y = 145;
SDL_BlitSurface (texts[TEXT_GAME_OVER], NULL, screen, &rect);
}
/* Los mensajes de texto van antes de las bolsas */ /* Los mensajes de texto van antes de las bolsas */
rect.x = 30; rect.x = 30;
rect.y = 8; rect.y = 8;
@ -1488,8 +1534,6 @@ int game_loop (void) {
SDL_BlitSurface (score_p, NULL, screen, &rect); SDL_BlitSurface (score_p, NULL, screen, &rect);
/* TODO: Dibujar el mensaje de nivel completo */
/* Dibujar los objetos en pantalla */ /* Dibujar los objetos en pantalla */
thisbag = first_bag; thisbag = first_bag;
while (thisbag != NULL) { while (thisbag != NULL) {
@ -1608,13 +1652,57 @@ int game_loop (void) {
} }
if (try_visible == TRUE) { if (try_visible == TRUE) {
rect.w = texts[TEXT_TRY_AGAIN]->w;
rect.h = texts[TEXT_TRY_AGAIN]->h;
rect.x = 388 - (rect.w / 2);
rect.y = 126;
SDL_BlitSurface (texts[TEXT_TRY_AGAIN], NULL, screen, &rect);
/* Poner el número 3, 2, 1 */
i = -1;
if (animacion >= 20 && animacion < 40) {
j = animacion - 20;
i = 2;
} else if (animacion >= 44 && animacion < 64) {
j = animacion - 44;
i = 1;
} else if (animacion >= 68 && animacion < 88) {
j = animacion - 68;
i = 0;
}
if (i >= 0) {
rect.w = numbers[i][j]->w;
rect.h = numbers[i][j]->h;
rect.x = 371 - (rect.w / 2);
rect.y = 122 - j;
SDL_gfxBlitRGBAWithAlpha (numbers[i][j], NULL, screen, &rect, (255 - (12.75 * ((float) j))));
}
animacion++; animacion++;
/* TODO: Dibujar el mensaje de "Intentar de nuevo" */
} }
if (next_level_visible == NEXT_LEVEL) { if (next_level_visible == NEXT_LEVEL) {
if (animacion < 52) {
/* Presentar el texto del camión descargado */
rect.w = texts[TEXT_UNLOADED]->w;
rect.h = texts[TEXT_UNLOADED]->h;
rect.x = 388 - (rect.w / 2);
rect.y = 115;
SDL_BlitSurface (texts[TEXT_UNLOADED], NULL, screen, &rect);
} else if (animacion > 62) {
rect.w = texts[TEXT_NEXT_TRUCK]->w;
rect.h = texts[TEXT_NEXT_TRUCK]->h;
rect.x = 378 - (rect.w / 2);
rect.y = 121;
SDL_BlitSurface (texts[TEXT_NEXT_TRUCK], NULL, screen, &rect);
}
if (animacion < 36) { if (animacion < 36) {
rect.x = 568 + (198 * animacion) / 36; rect.x = 568 + (198 * animacion) / 36;
} else if (animacion >= 36 && animacion < 60) { } else if (animacion >= 36 && animacion < 60) {
@ -1678,6 +1766,13 @@ int game_loop (void) {
} while (!done); } while (!done);
/* Liberar los números usados */
for (i = 0; i < 3; i++) {
for (j = 0; j < 20; j++) {
SDL_FreeSurface (numbers[i][j]);
}
}
return done; return done;
} }
/* Set video mode: */ /* Set video mode: */
@ -1697,6 +1792,7 @@ void setup (void) {
char buffer_file[8192]; char buffer_file[8192];
char *systemdata_path = get_systemdata_path (); char *systemdata_path = get_systemdata_path ();
Collider *c; Collider *c;
TTF_Font *ttf48_klickclack, *ttf52_klickclack;
/* Inicializar el Video SDL */ /* Inicializar el Video SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) { if (SDL_Init(SDL_INIT_VIDEO) < 0) {
@ -1839,8 +1935,11 @@ void setup (void) {
sprintf (buffer_file, "%s%s", systemdata_path, "klickclack.ttf"); sprintf (buffer_file, "%s%s", systemdata_path, "klickclack.ttf");
ttf24_klickclack = TTF_OpenFont (buffer_file, 24); ttf24_klickclack = TTF_OpenFont (buffer_file, 24);
ttf196_klickclack = TTF_OpenFont (buffer_file, 196);
ttf48_klickclack = TTF_OpenFont (buffer_file, 48);
ttf52_klickclack = TTF_OpenFont (buffer_file, 52);
if (!ttf24_klickclack) { if (!ttf24_klickclack || !ttf196_klickclack || !ttf48_klickclack || !ttf52_klickclack) {
fprintf (stderr, fprintf (stderr,
_("Failed to load font file 'Klick Clack\n" _("Failed to load font file 'Klick Clack\n"
"The error returned by SDL is:\n" "The error returned by SDL is:\n"
@ -1856,9 +1955,17 @@ void setup (void) {
blanco.r = blanco.g = blanco.b = 255; blanco.r = blanco.g = blanco.b = 255;
negro.r = negro.g = negro.b = 0; negro.r = negro.g = negro.b = 0;
for (g = 0; g < NUM_TEXTS; g++) { for (g = TEXT_LIVES; g <= TEXT_SCORE; g++) {
texts[g] = draw_text_with_shadow (ttf24_klickclack, 2, _(text_strings[g]), blanco, negro); texts[g] = draw_text_with_shadow (ttf24_klickclack, 2, _(text_strings[g]), blanco, negro);
} }
texts[TEXT_TRY_AGAIN] = draw_text_with_shadow (ttf48_klickclack, 2, _(text_strings[TEXT_TRY_AGAIN]), blanco, negro);
texts[TEXT_UNLOADED] = draw_text_with_shadow (ttf48_klickclack, 2, _(text_strings[TEXT_UNLOADED]), blanco, negro);
texts[TEXT_NEXT_TRUCK] = draw_text_with_shadow (ttf48_klickclack, 2, _(text_strings[TEXT_NEXT_TRUCK]), blanco, negro);
texts[TEXT_GAME_OVER] = draw_text_with_shadow (ttf52_klickclack, 3, _(text_strings[TEXT_GAME_OVER]), blanco, negro);
TTF_CloseFont (ttf48_klickclack);
TTF_CloseFont (ttf52_klickclack);
} }
void setup_and_color_penguin (void) { void setup_and_color_penguin (void) {

View File

@ -134,10 +134,10 @@ SDL_Surface *draw_text_with_shadow (TTF_Font *font, int outline, const char *tex
} }
TTF_SetFontOutline (font, outline); TTF_SetFontOutline (font, outline);
black_letters = TTF_RenderUTF8_Blended (font, text, background); black_letters = draw_text (font, text, &background);
TTF_SetFontOutline (font, 0); TTF_SetFontOutline (font, 0);
white_letters = TTF_RenderUTF8_Blended (font, text, foreground); white_letters = draw_text (font, text, &foreground);
rect.w = white_letters->w; rect.h = white_letters->h; rect.w = white_letters->w; rect.h = white_letters->h;
rect.x = rect.y = outline; rect.x = rect.y = outline;

567
src/zoom.c 100644
View File

@ -0,0 +1,567 @@
/*
* zoom.c
* This file is part of Bean Counters Classic
*
* Copyright (C) 2018 - Félix Arreola Rodríguez
*
* Bean Counters Classic 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.
*
* Bean Counters Classic 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 Bean Counters Classic; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
/*
* Código tomado de la SDL_gfx
*/
/*
SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
Copyright (C) 2001-2012 Andreas Schiffler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Andreas Schiffler -- aschiffler at ferzkopp dot net
*/
#include <stdlib.h>
#include <math.h>
#include <SDL.h>
typedef struct tColorRGBA {
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
} tColorRGBA;
#define GUARD_ROWS (2)
#define VALUE_LIMIT 0.001
Uint32 _colorkey(SDL_Surface *src) {
Uint32 key = 0;
#if (SDL_MINOR_VERSION == 3)
SDL_GetColorKey(src, &key);
#else
if (src)
{
key = src->format->colorkey;
}
#endif
return key;
}
int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) {
int x, y;
Uint32 *sax, *say, *csax, *csay;
int csx, csy;
Uint8 *sp, *dp, *csp;
int dgap;
/*
* Allocate memory for row increments
*/
if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
return (-1);
}
if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
free(sax);
return (-1);
}
/*
* Pointer setup
*/
sp = csp = (Uint8 *) src->pixels;
dp = (Uint8 *) dst->pixels;
dgap = dst->pitch - dst->w;
if (flipx) csp += (src->w-1);
if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) );
/*
* Precalculate row increments
*/
csx = 0;
csax = sax;
for (x = 0; x < dst->w; x++) {
csx += src->w;
*csax = 0;
while (csx >= dst->w) {
csx -= dst->w;
(*csax)++;
}
(*csax) = (*csax) * (flipx ? -1 : 1);
csax++;
}
csy = 0;
csay = say;
for (y = 0; y < dst->h; y++) {
csy += src->h;
*csay = 0;
while (csy >= dst->h) {
csy -= dst->h;
(*csay)++;
}
(*csay) = (*csay) * (flipy ? -1 : 1);
csay++;
}
/*
* Draw
*/
csay = say;
for (y = 0; y < dst->h; y++) {
csax = sax;
sp = csp;
for (x = 0; x < dst->w; x++) {
/*
* Draw
*/
*dp = *sp;
/*
* Advance source pointers
*/
sp += (*csax);
csax++;
/*
* Advance destination pointer
*/
dp++;
}
/*
* Advance source pointer (for row)
*/
csp += ((*csay) * src->pitch);
csay++;
/*
* Advance destination pointers
*/
dp += dgap;
}
/*
* Remove temp arrays
*/
free(sax);
free(say);
return (0);
}
int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth) {
int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
tColorRGBA *c00, *c01, *c10, *c11;
tColorRGBA *sp, *csp, *dp;
int spixelgap, spixelw, spixelh, dgap, t1, t2;
/*
* Allocate memory for row/column increments
*/
if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
return (-1);
}
if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
free(sax);
return (-1);
}
/*
* Precalculate row increments
*/
spixelw = (src->w - 1);
spixelh = (src->h - 1);
if (smooth) {
sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
} else {
sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
}
/* Maximum scaled source size */
ssx = (src->w << 16) - 1;
ssy = (src->h << 16) - 1;
/* Precalculate horizontal row increments */
csx = 0;
csax = sax;
for (x = 0; x <= dst->w; x++) {
*csax = csx;
csax++;
csx += sx;
/* Guard from overflows */
if (csx > ssx) {
csx = ssx;
}
}
/* Precalculate vertical row increments */
csy = 0;
csay = say;
for (y = 0; y <= dst->h; y++) {
*csay = csy;
csay++;
csy += sy;
/* Guard from overflows */
if (csy > ssy) {
csy = ssy;
}
}
sp = (tColorRGBA *) src->pixels;
dp = (tColorRGBA *) dst->pixels;
dgap = dst->pitch - dst->w * 4;
spixelgap = src->pitch/4;
if (flipx) sp += spixelw;
if (flipy) sp += (spixelgap * spixelh);
/*
* Switch between interpolating and non-interpolating code
*/
if (smooth) {
/*
* Interpolating Zoom
*/
csay = say;
for (y = 0; y < dst->h; y++) {
csp = sp;
csax = sax;
for (x = 0; x < dst->w; x++) {
/*
* Setup color source pointers
*/
ex = (*csax & 0xffff);
ey = (*csay & 0xffff);
cx = (*csax >> 16);
cy = (*csay >> 16);
sstepx = cx < spixelw;
sstepy = cy < spixelh;
c00 = sp;
c01 = sp;
c10 = sp;
if (sstepy) {
if (flipy) {
c10 -= spixelgap;
} else {
c10 += spixelgap;
}
}
c11 = c10;
if (sstepx) {
if (flipx) {
c01--;
c11--;
} else {
c01++;
c11++;
}
}
/*
* Draw and interpolate colors
*/
t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
dp->r = (((t2 - t1) * ey) >> 16) + t1;
t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
dp->g = (((t2 - t1) * ey) >> 16) + t1;
t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
dp->b = (((t2 - t1) * ey) >> 16) + t1;
t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
dp->a = (((t2 - t1) * ey) >> 16) + t1;
/*
* Advance source pointer x
*/
salast = csax;
csax++;
sstep = (*csax >> 16) - (*salast >> 16);
if (flipx) {
sp -= sstep;
} else {
sp += sstep;
}
/*
* Advance destination pointer x
*/
dp++;
}
/*
* Advance source pointer y
*/
salast = csay;
csay++;
sstep = (*csay >> 16) - (*salast >> 16);
sstep *= spixelgap;
if (flipy) {
sp = csp - sstep;
} else {
sp = csp + sstep;
}
/*
* Advance destination pointer y
*/
dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
}
} else {
/*
* Non-Interpolating Zoom
*/
csay = say;
for (y = 0; y < dst->h; y++) {
csp = sp;
csax = sax;
for (x = 0; x < dst->w; x++) {
/*
* Draw
*/
*dp = *sp;
/*
* Advance source pointer x
*/
salast = csax;
csax++;
sstep = (*csax >> 16) - (*salast >> 16);
if (flipx) sstep = -sstep;
sp += sstep;
/*
* Advance destination pointer x
*/
dp++;
}
/*
* Advance source pointer y
*/
salast = csay;
csay++;
sstep = (*csay >> 16) - (*salast >> 16);
sstep *= spixelgap;
if (flipy) sstep = -sstep;
sp = csp + sstep;
/*
* Advance destination pointer y
*/
dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
}
}
/*
* Remove temp arrays
*/
free(sax);
free(say);
return (0);
}
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) {
/*
* Make zoom factors positive
*/
int flipx, flipy;
flipx = (zoomx<0.0);
if (flipx) zoomx = -zoomx;
flipy = (zoomy<0.0);
if (flipy) zoomy = -zoomy;
/*
* Sanity check zoom factors
*/
if (zoomx < VALUE_LIMIT) {
zoomx = VALUE_LIMIT;
}
if (zoomy < VALUE_LIMIT) {
zoomy = VALUE_LIMIT;
}
/*
* Calculate target size
*/
*dstwidth = (int) floor(((double) width * zoomx) + 0.5);
*dstheight = (int) floor(((double) height * zoomy) + 0.5);
if (*dstwidth < 1) {
*dstwidth = 1;
}
if (*dstheight < 1) {
*dstheight = 1;
}
}
SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) {
SDL_Surface *rz_src;
SDL_Surface *rz_dst;
int dstwidth, dstheight;
int is32bit;
int i, src_converted;
int flipx, flipy;
/*
* Sanity check
*/
if (src == NULL) return (NULL);
/*
* Determine if source surface is 32bit or 8bit
*/
is32bit = (src->format->BitsPerPixel == 32);
if ((is32bit) || (src->format->BitsPerPixel == 8)) {
/*
* Use source surface 'as is'
*/
rz_src = src;
src_converted = 0;
} else {
/*
* New source surface is 32bit with a defined RGBA ordering
*/
rz_src =
SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
#else
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
#endif
);
if (rz_src == NULL) {
return NULL;
}
SDL_BlitSurface(src, NULL, rz_src, NULL);
src_converted = 1;
is32bit = 1;
}
flipx = (zoomx<0.0);
if (flipx) zoomx = -zoomx;
flipy = (zoomy<0.0);
if (flipy) zoomy = -zoomy;
/* Get size if target */
zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
/*
* Alloc space to completely contain the zoomed surface
*/
rz_dst = NULL;
if (is32bit) {
/*
* Target surface is 32bit with source RGBA/ABGR ordering
*/
rz_dst =
SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
rz_src->format->Rmask, rz_src->format->Gmask,
rz_src->format->Bmask, rz_src->format->Amask);
} else {
/*
* Target surface is 8bit
*/
rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
}
/* Check target */
if (rz_dst == NULL) {
/*
* Cleanup temp surface
*/
if (src_converted) {
SDL_FreeSurface(rz_src);
}
return NULL;
}
/* Adjust for guard rows */
rz_dst->h = dstheight;
/*
* Lock source surface
*/
if (SDL_MUSTLOCK(rz_src)) {
SDL_LockSurface(rz_src);
}
/*
* Check which kind of surface we have
*/
if (is32bit) {
/*
* Call the 32bit transformation routine to do the zooming (using alpha)
*/
_zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
/*
* Turn on source-alpha support
*/
SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
} else {
/*
* Copy palette and colorkey info
*/
for (i = 0; i < rz_src->format->palette->ncolors; i++) {
rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
}
rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
/*
* Call the 8bit transformation routine to do the zooming
*/
_zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
}
/*
* Unlock source surface
*/
if (SDL_MUSTLOCK(rz_src)) {
SDL_UnlockSurface(rz_src);
}
/*
* Cleanup temp surface
*/
if (src_converted) {
SDL_FreeSurface(rz_src);
}
/*
* Return destination surface
*/
return (rz_dst);
}

28
src/zoom.h 100644
View File

@ -0,0 +1,28 @@
/*
* zoom.h
* This file is part of Bean Counters Classic
*
* Copyright (C) 2018 - Félix Arreola Rodríguez
*
* Bean Counters Classic 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.
*
* Bean Counters Classic 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 Bean Counters Classic; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef __ZOOM_H__
#define __ZOOM_H__
SDL_Surface *zoomSurface (SDL_Surface * src, double zoomx, double zoomy, int smooth);
#endif /* __ZOOM_H__ */