Use alpha transparency to display ships
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 1 Jul 2014 10:50:49 +0000 (10:50 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 1 Jul 2014 10:50:49 +0000 (10:50 +0000)
mmsoftware/mystic_ships/client/src/main.c
mmsoftware/mystic_ships/client/src/screen.c
mmsoftware/mystic_ships/client/src/screen.h

index 07a80e7..b4ba80e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.11 2014/06/30 04:26:10 mmondor Exp $ */
+/* $Id: main.c,v 1.12 2014/07/01 10:50:49 mmondor Exp $ */
 
 /*
  * Copyright (c) 2006, Matthew Mondor
@@ -722,7 +722,6 @@ bmp_load_key(const uint8_t *data, size_t size)
 {
        SDL_RWops       *rwo;
        SDL_Surface     *s;
-       Uint32          c;
        uint8_t         *ndata;
        size_t          nsize;
 
@@ -734,8 +733,7 @@ bmp_load_key(const uint8_t *data, size_t size)
                goto err;
        SDL_FreeRW(rwo);
 
-       c = SDL_MapRGB(s->format, 0, 0, 0);
-       if (SDL_SetColorKey(s, SDL_SRCCOLORKEY | SDL_RLEACCEL, c) == -1)
+       if ((s = surface_alpha(s)) == NULL)
                goto err;
 
        return s;
index 23eefe7..5030704 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: screen.c,v 1.6 2014/06/30 03:07:39 mmondor Exp $ */
+/* $Id: screen.c,v 1.7 2014/07/01 10:50:49 mmondor Exp $ */
 
 /*
  * Copyright (c) 2006, 2014, Matthew Mondor
@@ -12,6 +12,7 @@
 
 
 #include <stdarg.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -39,15 +40,34 @@ static font_t       *error_font = NULL;
 void
 screen_init(void)
 {
+       Uint32  flags = SDL_DOUBLEBUF;
 
        if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
-               (void) fprintf(stderr, "main() - SDL_Init() - %s\n",
+               (void) fprintf(stderr, "screen_init() - SDL_Init() - %s\n",
                    SDL_GetError());
                exit(EXIT_FAILURE);
        }
+
+       /* Only useful for fullscreen mode
+       {
+               const SDL_VideoInfo     *vi;
+
+               if ((vi = SDL_GetVideoInfo()) == NULL) {
+                       (void) fprintf(stderr,
+                           "screen_init() - SDL_GetVideoInfo() - %s\n",
+                           SDL_GetError());
+                       exit(EXIT_FAILURE);
+               }
+               if (vi->hw_available)
+                       flags |= SDL_HWSURFACE | SDL_HWPALETTE |
+                           SDL_FULLSCREEN;
+       }
+       */
+
        if ((screen_surface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32,
-           SDL_DOUBLEBUF/* | SDL_FULLSCREEN*/)) == NULL) {
-               (void) fprintf(stderr, "main() - SDL_SetVideoMode() - %s\n",
+           flags)) == NULL) {
+               (void) fprintf(stderr,
+                   "screen_init() - SDL_SetVideoMode() - %s\n",
                    SDL_GetError());
                exit(EXIT_FAILURE);
        }
@@ -107,3 +127,77 @@ screen_error(const char *fmt, ...)
        exit(EXIT_FAILURE);
 }
 
+SDL_Surface *
+surface_alpha(SDL_Surface *surface1)
+{
+       SDL_Surface     *surface2 = NULL, *surface3 = NULL;
+       int             ok;
+
+       /* Convert loaded surface to screen_surface's depth into new surface. */
+       if ((surface2 = SDL_ConvertSurface(surface1, screen_surface->format,
+           SDL_SWSURFACE)) == NULL)
+               goto err;
+       SDL_FreeSurface(surface1);
+       surface1 = NULL;
+
+       /*
+        * Create new surface suitable for source alpha blending blitting.
+        * Using the converted surface directly to create an alpha blending
+        * enabled copy fails.  We thus explicitely create a new surface.
+        */
+       if ((surface1 = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
+           surface2->w, surface2->h, 32, 0, 0, 0, 0)) == NULL)
+               goto err;
+
+       /*
+        * Convert newly created surface to support per-pixel alpha blending
+        * with hardware support.  Resulting surface3 is the one we'll copy
+        * surface2 to.
+        */
+       (void) SDL_SetAlpha(surface1, SDL_SRCALPHA | SDL_RLEACCEL, 128);
+       if ((surface3 = SDL_DisplayFormatAlpha(surface1)) == NULL)
+               goto err;
+       SDL_FreeSurface(surface1);
+       surface1 = NULL;
+
+       /*
+        * We now have both our 32-bit depth font surface (surface2) and our
+        * destination alpha surface (surface3). Copy surface2 data to
+        * surface3, making sure to set the alpha color to 0x00 for pixels
+        * which originally were 0 bits, that is, now 0x00000000, and to
+        * 0xff for other pixels, that is, 0xffxxxxxx.
+        */
+       ok = -1;
+       if (SDL_LockSurface(surface2) == 0) {
+               if (SDL_LockSurface(surface3) == 0) {
+                       u_int32_t       *sptr, *dptr, *dtptr;
+
+                       for (sptr = (u_int32_t *)surface2->pixels,
+                            dptr = (u_int32_t *)surface3->pixels,
+                            dtptr = &dptr[surface3->w * surface3->h];
+                            dptr < dtptr;
+                            sptr++, dptr++)
+                               *dptr = (*sptr == 0 ? 0x00000000 :
+                                   *sptr | 0xff000000);
+                       ok = 0;
+                       SDL_UnlockSurface(surface3);
+               }
+               SDL_UnlockSurface(surface2);
+       }
+       SDL_FreeSurface(surface2);
+       surface2 = NULL;
+       if (ok == -1)
+               goto err;
+
+       return surface3;
+
+err:
+       if (surface1 != NULL)
+               SDL_FreeSurface(surface1);
+       if (surface2 != NULL)
+               SDL_FreeSurface(surface1);
+       if (surface3 != NULL)
+               SDL_FreeSurface(surface1);
+
+       return NULL;
+}
index 9691098..42f681b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: screen.h,v 1.3 2014/06/29 23:56:13 mmondor Exp $ */
+/* $Id: screen.h,v 1.4 2014/07/01 10:50:49 mmondor Exp $ */
 
 /*
  * Copyright (c) 2006, Matthew Mondor
@@ -42,6 +42,7 @@ void                  font_blit_string(font_t *, int, int, const char *,
                            uint8_t, uint8_t, uint8_t, uint8_t);
 void                   screen_error_setfont(font_t *);
 void                   screen_error(const char *, ...);
+SDL_Surface            *surface_alpha(SDL_Surface *);