Agrego texto de siguiente nivel.
parent
b0e8f4f379
commit
e02282ec2c
|
@ -9,6 +9,7 @@ bean_counters_classic_SOURCES = beans.c \
|
|||
collider.c collider.h \
|
||||
sdl2_rect.c sdl2_rect.h \
|
||||
draw-text.c draw-text.h \
|
||||
zoom.c zoom.h \
|
||||
gettext.h
|
||||
|
||||
if MACOSX
|
||||
|
|
151
src/beans.c
151
src/beans.c
|
@ -44,6 +44,7 @@
|
|||
#include "gfx_blit_func.h"
|
||||
#include "collider.h"
|
||||
#include "draw-text.h"
|
||||
#include "zoom.h"
|
||||
|
||||
#define FPS (1000/24)
|
||||
#define RANDOM(x) ((int) (x ## .0 * rand () / (RAND_MAX + 1.0)))
|
||||
|
@ -477,6 +478,14 @@ enum {
|
|||
TEXT_LIVES,
|
||||
TEXT_TRUCKS,
|
||||
TEXT_SCORE,
|
||||
|
||||
TEXT_TRY_AGAIN,
|
||||
|
||||
TEXT_UNLOADED,
|
||||
TEXT_NEXT_TRUCK,
|
||||
|
||||
TEXT_GAME_OVER,
|
||||
|
||||
NUM_TEXTS
|
||||
};
|
||||
|
||||
|
@ -871,7 +880,14 @@ const int flower_offsets[32][2] = {
|
|||
const char *text_strings[NUM_TEXTS] = {
|
||||
gettext_noop ("LIVES:"),
|
||||
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 */
|
||||
|
@ -879,7 +895,7 @@ int game_intro (void);
|
|||
int game_loop (void);
|
||||
int game_finish (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 add_bag (int tipo);
|
||||
void delete_bag (BeanBag *p);
|
||||
|
@ -902,6 +918,7 @@ BeanBag *first_bag = NULL;
|
|||
BeanBag *last_bag = NULL;
|
||||
|
||||
TTF_Font *ttf24_klickclack;
|
||||
TTF_Font *ttf196_klickclack;
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
/* Recuperar las rutas del sistema */
|
||||
|
@ -1056,12 +1073,17 @@ int game_loop (void) {
|
|||
int score = 0;
|
||||
int bag_stack = 0;
|
||||
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.unused = 255;
|
||||
negro.r = negro.g = negro.b = 0;
|
||||
negro.unused = 255;
|
||||
amarillo.r = amarillo.g = 255;
|
||||
amarillo.b = 0;
|
||||
amarillo.unused = 255;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
do {
|
||||
|
@ -1211,7 +1246,8 @@ int game_loop (void) {
|
|||
|
||||
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 */
|
||||
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" */
|
||||
|
||||
if (bags >= 6 && (try_visible == FALSE || gameover_visible == FALSE)) {
|
||||
if (bags >= 6) {
|
||||
/* Esta bolsa crasheó al pingüino */
|
||||
printf ("Penguin Crash\n");
|
||||
if (vidas > 0) {
|
||||
|
@ -1252,38 +1288,39 @@ int game_loop (void) {
|
|||
thisbag = nextbag;
|
||||
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);
|
||||
|
||||
if (i == SDL_TRUE) {
|
||||
bags = 7;
|
||||
|
||||
/* TODO: Reproducir el sonido de golpe de yunque */
|
||||
/* TODO: Acomodar la animación de "Crash" */
|
||||
crash_anim = 0;
|
||||
|
||||
printf ("Penguin Crash by anvil\n");
|
||||
if (vidas > 0) {
|
||||
if (vidas > 0 && try_visible == FALSE) {
|
||||
try_visible = TRUE;
|
||||
printf ("Try again visible\n");
|
||||
animacion = 0;
|
||||
airbone = 1000; /* El airbone bloquea que salgan más objetos */
|
||||
printf ("Airbone: %i\n", airbone);
|
||||
vidas--;
|
||||
SDL_FreeSurface (vidas_p);
|
||||
snprintf (buffer, sizeof (buffer), "%d", vidas);
|
||||
vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro);
|
||||
} else {
|
||||
} else if (try_visible == FALSE) {
|
||||
gameover_visible = TRUE;
|
||||
printf ("Game Over visible\n");
|
||||
}
|
||||
|
||||
anvil_out = FALSE;
|
||||
airbone--;
|
||||
printf ("Airbone: %i\n", airbone);
|
||||
delete_bag (thisbag);
|
||||
thisbag = nextbag;
|
||||
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);
|
||||
|
||||
if (i == SDL_TRUE) {
|
||||
|
@ -1310,8 +1347,7 @@ int game_loop (void) {
|
|||
|
||||
/* TODO: Reproducir el sonido de golpe de pescado */
|
||||
crash_anim = 0;
|
||||
|
||||
if (vidas > 0) {
|
||||
if (vidas > 0 && try_visible == FALSE) {
|
||||
try_visible = TRUE;
|
||||
animacion = 0;
|
||||
airbone = 1000; /* El airbone bloquea que salgan más objetos */
|
||||
|
@ -1319,7 +1355,7 @@ int game_loop (void) {
|
|||
SDL_FreeSurface (vidas_p);
|
||||
snprintf (buffer, sizeof (buffer), "%d", vidas);
|
||||
vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro);
|
||||
} else {
|
||||
} else if (try_visible == FALSE) {
|
||||
gameover_visible = TRUE;
|
||||
}
|
||||
|
||||
|
@ -1339,7 +1375,7 @@ int game_loop (void) {
|
|||
/* TODO: Reproducir el sonido de golpe de florero */
|
||||
crash_anim = 0;
|
||||
|
||||
if (vidas > 0) {
|
||||
if (vidas > 0 && try_visible == FALSE) {
|
||||
try_visible = TRUE;
|
||||
animacion = 0;
|
||||
airbone = 1000; /* El airbone bloquea que salgan más objetos */
|
||||
|
@ -1347,7 +1383,7 @@ int game_loop (void) {
|
|||
SDL_FreeSurface (vidas_p);
|
||||
snprintf (buffer, sizeof (buffer), "%d", vidas);
|
||||
vidas_p = draw_text_with_shadow (ttf24_klickclack, 2, buffer, blanco, negro);
|
||||
} else {
|
||||
} else if (try_visible == FALSE) {
|
||||
gameover_visible = TRUE;
|
||||
}
|
||||
|
||||
|
@ -1445,6 +1481,16 @@ int game_loop (void) {
|
|||
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 */
|
||||
rect.x = 30;
|
||||
rect.y = 8;
|
||||
|
@ -1488,8 +1534,6 @@ int game_loop (void) {
|
|||
|
||||
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) {
|
||||
|
@ -1608,13 +1652,57 @@ int game_loop (void) {
|
|||
}
|
||||
|
||||
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++;
|
||||
|
||||
/* TODO: Dibujar el mensaje de "Intentar de nuevo" */
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
rect.x = 568 + (198 * animacion) / 36;
|
||||
} else if (animacion >= 36 && animacion < 60) {
|
||||
|
@ -1678,6 +1766,13 @@ int game_loop (void) {
|
|||
|
||||
} 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;
|
||||
}
|
||||
/* Set video mode: */
|
||||
|
@ -1697,6 +1792,7 @@ void setup (void) {
|
|||
char buffer_file[8192];
|
||||
char *systemdata_path = get_systemdata_path ();
|
||||
Collider *c;
|
||||
TTF_Font *ttf48_klickclack, *ttf52_klickclack;
|
||||
|
||||
/* Inicializar el Video SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
|
@ -1839,8 +1935,11 @@ void setup (void) {
|
|||
|
||||
sprintf (buffer_file, "%s%s", systemdata_path, "klickclack.ttf");
|
||||
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,
|
||||
_("Failed to load font file 'Klick Clack\n"
|
||||
"The error returned by SDL is:\n"
|
||||
|
@ -1856,9 +1955,17 @@ void setup (void) {
|
|||
blanco.r = blanco.g = blanco.b = 255;
|
||||
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[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) {
|
||||
|
|
|
@ -134,10 +134,10 @@ SDL_Surface *draw_text_with_shadow (TTF_Font *font, int outline, const char *tex
|
|||
}
|
||||
|
||||
TTF_SetFontOutline (font, outline);
|
||||
black_letters = TTF_RenderUTF8_Blended (font, text, background);
|
||||
black_letters = draw_text (font, text, &background);
|
||||
|
||||
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.x = rect.y = outline;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
Loading…
Reference in New Issue