Agrego transparencia a las bolsas que desparecen.

master
Félix Arreola Rodríguez 2018-05-30 16:50:08 -05:00
parent 2db613871d
commit e0ab125eda
3 changed files with 305 additions and 20 deletions

View File

@ -379,6 +379,7 @@ 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);
/* Variables globales */ /* Variables globales */
SDL_Surface * screen; SDL_Surface * screen;
@ -526,11 +527,11 @@ int game_loop (void) {
Uint32 last_time, now_time; Uint32 last_time, now_time;
SDL_Rect rect; SDL_Rect rect;
int penguinx, handposx; int penguinx, handposx;
BeanBag *thisbag; BeanBag *thisbag, *nextbag;
int bags = 0; int bags = 0;
int penguin_frame = 0; int penguin_frame = 0;
int i; int i, j;
/* Predibujar todo */ /* Predibujar todo */
/*SDL_FillRect (screen, NULL, 0); /*SDL_FillRect (screen, NULL, 0);
@ -598,9 +599,17 @@ int game_loop (void) {
/* Procesar las bolsas */ /* Procesar las bolsas */
thisbag = first_bag; thisbag = first_bag;
while (thisbag != NULL) { while (thisbag != NULL) {
nextbag = thisbag->next;
thisbag->frame++; thisbag->frame++;
thisbag = thisbag->next; j = thisbag->frame - thisbag->throw_length;
if (j >= 35) {
/* Eliminar esta bolsa */
delete_bag (thisbag);
}
thisbag = nextbag;
} }
SDL_BlitSurface (images[IMG_BACKGROUND], NULL, screen, NULL); SDL_BlitSurface (images[IMG_BACKGROUND], NULL, screen, NULL);
@ -655,12 +664,17 @@ int game_loop (void) {
i = IMG_BAG_4; i = IMG_BAG_4;
rect.x = thisbag->bag_points[thisbag->throw_length][1]; rect.x = thisbag->bag_points[thisbag->throw_length][1];
rect.y = thisbag->bag_points[thisbag->throw_length][2]; rect.y = thisbag->bag_points[thisbag->throw_length][2];
j = thisbag->frame - thisbag->throw_length;
} }
rect.w = images[i]->w; rect.w = images[i]->w;
rect.h = images[i]->h; rect.h = images[i]->h;
if (i == IMG_BAG_4 && j > 25) {
SDL_gfxBlitRGBAWithAlpha (images[i], NULL, screen, &rect, 255 - SDL_ALPHA_OPAQUE * (j - 25) / 10);
} else {
SDL_BlitSurface (images[i], NULL, screen, &rect); SDL_BlitSurface (images[i], NULL, screen, &rect);
}
thisbag = thisbag->next; thisbag = thisbag->next;
} }
@ -989,3 +1003,20 @@ void add_bag (int tipo) {
} }
} }
void delete_bag (BeanBag *p) {
if (p == NULL) return;
if (p->prev == NULL) { /* El primero de la lista */
first_bag = p->next;
} else {
p->prev->next = p->next;
}
if (p->next == NULL) {
last_bag = p->prev;
} else {
p->next->prev = p->prev;
}
free (p);
}

View File

@ -41,6 +41,13 @@ b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \
a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \ a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \
} }
#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b) \
{ \
r = (((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); \
g = (((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); \
b = (((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); \
}
/*! /*!
\brief Disassemble buffer pointer into a pixel and separate RGBA values. \brief Disassemble buffer pointer into a pixel and separate RGBA values.
*/ */
@ -51,6 +58,34 @@ GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \
pixel &= ~fmt->Amask; \ pixel &= ~fmt->Amask; \
} while(0) } while(0)
#define GFX_DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b) \
do { \
switch (bpp) { \
case 2: \
Pixel = *((Uint16 *)(buf)); \
break; \
\
case 3: { \
Uint8 *B = (Uint8 *)buf; \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
} else { \
Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
} \
} \
break; \
\
case 4: \
Pixel = *((Uint32 *)(buf)); \
break; \
\
default: \
Pixel = 0; /* prevent gcc from complaining */ \
break; \
} \
RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \
} while(0)
/*! /*!
\brief Wrap a pixel from RGBA values using mask, shift and loss for surface. \brief Wrap a pixel from RGBA values using mask, shift and loss for surface.
*/ */
@ -67,10 +102,36 @@ pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \
*/ */
#define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ #define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \
{ \ { \
Uint32 pixel; \ switch (bpp) { \
case 2: { \
Uint16 Pixel; \
\ \
GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ GFX_PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a); \
*((Uint32 *)(buf)) = pixel; \ *((Uint16 *)(buf)) = Pixel; \
} \
break; \
\
case 3: { /* FIXME: broken code (no alpha) */ \
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
*((buf)+fmt->Rshift/8) = r; \
*((buf)+fmt->Gshift/8) = g; \
*((buf)+fmt->Bshift/8) = b; \
} else { \
*((buf)+2-fmt->Rshift/8) = r; \
*((buf)+2-fmt->Gshift/8) = g; \
*((buf)+2-fmt->Bshift/8) = b; \
} \
} \
break; \
\
case 4: { \
Uint32 Pixel; \
\
GFX_PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a); \
*((Uint32 *)(buf)) = Pixel; \
} \
break; \
} \
} }
/*! /*!
@ -83,18 +144,6 @@ dG = (((sG-dG)*(A))/255)+dG; \
dB = (((sB-dB)*(A))/255)+dB; \ dB = (((sB-dB)*(A))/255)+dB; \
} while(0) } while(0)
#define PERFECT_ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \
do { \
dR = ((sR * sA) + (dR * dA * (255 - sA))); \
dG = ((sG * sA) + (dG * dA * (255 - sA))); \
dB = ((sB * sA) + (dB * dA * (255 - sA))); \
dA = (sA + (dA * (255 - sA))); \
dR = dR / dA; \
dG = dG / dA; \
dB = dB / dA; \
dA = (dA / 255); \
} while (0)
/*! /*!
\brief 4-times unrolled DUFFs loop. \brief 4-times unrolled DUFFs loop.
@ -124,6 +173,7 @@ typedef struct {
SDL_PixelFormat *src; SDL_PixelFormat *src;
Uint8 *table; Uint8 *table;
SDL_PixelFormat *dst; SDL_PixelFormat *dst;
Uint8 alpha;
} SDL_gfxBlitInfo; } SDL_gfxBlitInfo;
/*! /*!
@ -607,3 +657,206 @@ int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SD
return 0; return 0;
} }
/* Funciones escritas por Gatuno para hacer Blit con superficies transparentes más un alpha general */
/* General (slow) N->N blending with per-surface alpha */
static void _SDL_gfxBlitBlitterRGBAWithAlpha(SDL_gfxBlitInfo *info)
{
int width = info->d_width;
int height = info->d_height;
Uint8 *src = info->s_pixels;
int srcskip = info->s_skip;
Uint8 *dst = info->d_pixels;
int dstskip = info->d_skip;
SDL_PixelFormat *srcfmt = info->src;
SDL_PixelFormat *dstfmt = info->dst;
int srcbpp = srcfmt->BytesPerPixel;
int dstbpp = dstfmt->BytesPerPixel;
unsigned sAlpha = info->alpha;
unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0;
if(sAlpha) {
while ( height-- ) {
GFX_DUFFS_LOOP4( {
Uint32 Pixel;
unsigned sR;
unsigned sG;
unsigned sB;
unsigned dR;
unsigned dG;
unsigned dB;
unsigned sA;
GFX_DISASSEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA);
GFX_DISEMBLE_RGB(dst, dstbpp, dstfmt, Pixel, dR, dG, dB);
sA = sA * sAlpha / 255;
GFX_ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);
GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
src += srcbpp;
dst += dstbpp;
},
width);
src += srcskip;
dst += dstskip;
}
}
}
int _SDL_gfxBlitRGBACallWithAlpha(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, Uint8 alpha)
{
/*
* Set up source and destination buffer pointers, then blit
*/
if (srcrect->w && srcrect->h) {
SDL_gfxBlitInfo info;
/*
* Set up the blit information
*/
#if (SDL_MINOR_VERSION == 3)
info.s_pixels = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
#else
info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
#endif
info.s_width = srcrect->w;
info.s_height = srcrect->h;
info.s_skip = (int)(src->pitch - info.s_width * src->format->BytesPerPixel);
#if (SDL_MINOR_VERSION == 3)
info.d_pixels = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
#else
info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
#endif
info.d_width = dstrect->w;
info.d_height = dstrect->h;
info.d_skip = (int)(dst->pitch - info.d_width * dst->format->BytesPerPixel);
info.aux_data = NULL;
info.src = src->format;
info.table = NULL;
info.dst = dst->format;
info.alpha = alpha;
/*
* Run the actual software blitter
*/
_SDL_gfxBlitBlitterRGBAWithAlpha(&info);
return 1;
}
return (0);
}
/*!
\brief Blitter for RGBA->RGBA blits with alpha per surface.
Verifies the input 'src' and 'dst' surfaces and rectangles and performs blit.
The destination clip rectangle is honored.
\param src The source surface.
\param srcrect The source rectangle.
\param dst The destination surface.
\param dstrect The destination rectangle.
\returns Returns 1 if blit was performed, 0 otherwise, or -1 if an error occured.
*/
int SDL_gfxBlitRGBAWithAlpha(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, Uint8 alpha)
{
SDL_Rect sr, dr;
int srcx, srcy, w, h;
/*
* Make sure the surfaces aren't locked
*/
if (!src || !dst) {
SDL_SetError("SDL_UpperBlit: passed a NULL surface");
return (-1);
}
if ((src->locked) || (dst->locked)) {
SDL_SetError("Surfaces must not be locked during blit");
return (-1);
}
if (alpha == 0) {
return 0;
}
/*
* If the destination rectangle is NULL, use the entire dest surface
*/
if (dstrect == NULL) {
dr.x = dr.y = 0;
dr.w = dst->w;
dr.h = dst->h;
} else {
dr = *dstrect;
}
/*
* Clip the source rectangle to the source surface
*/
if (srcrect) {
int maxw, maxh;
srcx = srcrect->x;
w = srcrect->w;
if (srcx < 0) {
w += srcx;
dr.x -= srcx;
srcx = 0;
}
maxw = src->w - srcx;
if (maxw < w)
w = maxw;
srcy = srcrect->y;
h = srcrect->h;
if (srcy < 0) {
h += srcy;
dr.y -= srcy;
srcy = 0;
}
maxh = src->h - srcy;
if (maxh < h)
h = maxh;
} else {
srcx = srcy = 0;
w = src->w;
h = src->h;
}
/*
* Clip the destination rectangle against the clip rectangle
*/
{
SDL_Rect *clip = &dst->clip_rect;
int dx, dy;
dx = clip->x - dr.x;
if (dx > 0) {
w -= dx;
dr.x += dx;
srcx += dx;
}
dx = dr.x + w - clip->x - clip->w;
if (dx > 0)
w -= dx;
dy = clip->y - dr.y;
if (dy > 0) {
h -= dy;
dr.y += dy;
srcy += dy;
}
dy = dr.y + h - clip->y - clip->h;
if (dy > 0)
h -= dy;
}
if (w > 0 && h > 0) {
sr.x = srcx;
sr.y = srcy;
sr.w = dr.w = w;
sr.h = dr.h = h;
return (_SDL_gfxBlitRGBACallWithAlpha(src, &sr, dst, &dr, alpha));
}
return 0;
}

View File

@ -24,6 +24,7 @@
#define __GFX_BLIT_FUNC_H__ #define __GFX_BLIT_FUNC_H__
int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect);
int SDL_gfxBlitRGBAWithAlpha(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect, Uint8 alpha);
#endif /* __GFX_BLIT_FUNC_H__ */ #endif /* __GFX_BLIT_FUNC_H__ */