aboutsummaryrefslogtreecommitdiff
path: root/effect-pad.c
diff options
context:
space:
mode:
Diffstat (limited to 'effect-pad.c')
-rw-r--r--effect-pad.c129
1 files changed, 126 insertions, 3 deletions
diff --git a/effect-pad.c b/effect-pad.c
index 61e0c79..702b372 100644
--- a/effect-pad.c
+++ b/effect-pad.c
@@ -3,6 +3,19 @@
#include <SDL.h>
+#define NARRAY(ARRAY) \
+ (sizeof(ARRAY) / sizeof(ARRAY[0]))
+
+#define SDL_MAYBE_LOCK(SURFACE) do { \
+ if (SDL_MUSTLOCK(SURFACE)) \
+ SDL_LockSurface(SURFACE); \
+} while (0)
+
+#define SDL_MAYBE_UNLOCK(SURFACE) do { \
+ if (SDL_MUSTLOCK(SURFACE)) \
+ SDL_UnlockSurface(SURFACE); \
+} while (0)
+
#define SDL_ERROR(FMT, ...) do { \
fprintf(stderr, "%s(%d): " FMT ": %s\n", \
__FILE__, __LINE__, ##__VA_ARGS__, SDL_GetError()); \
@@ -13,8 +26,107 @@
static SDL_Surface *screen;
+static inline SDL_Surface *
+effect_fire_init(void)
+{
+ SDL_Surface *surface;
+ static SDL_Color colors[256];
+
+ surface = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCCOLORKEY,
+ screen->w, screen->h, 8, 0, 0, 0, 0);
+ if (surface == NULL) {
+ SDL_ERROR("SDL_CreateRGBSurface");
+ exit(EXIT_FAILURE);
+ }
+
+ if (SDL_SetColorKey(surface, SDL_SRCCOLORKEY, 0)) {
+ SDL_ERROR("SDL_SetColorKey");
+ SDL_FreeSurface(surface);
+ exit(EXIT_FAILURE);
+ }
+
+ for (int i = 0; i < 32; i++) {
+ /* black to blue, 32 values */
+ colors[i].b = i << 1;
+
+ /* blue to red, 32 values */
+ colors[i + 32].r = i << 3;
+ colors[i + 32].b = 64 - (i << 1);
+
+ /*red to yellow, 32 values */
+ colors[i + 64].r = 255;
+ colors[i + 64].g = i << 3;
+
+ /* yellow to white, 162 */
+ colors[i + 96].r = 255;
+ colors[i + 96].g = 255;
+ colors[i + 96].b = i << 2;
+ colors[i + 128].r = 255;
+ colors[i + 128].g = 255;
+ colors[i + 128].b = 64 + (i << 2);
+ colors[i + 160].r = 255;
+ colors[i + 160].g = 255;
+ colors[i + 160].b = 128 + (i << 2);
+ colors[i + 192].r = 255;
+ colors[i + 192].g = 255;
+ colors[i + 192].b = 192 + i;
+ colors[i + 224].r = 255;
+ colors[i + 224].g = 255;
+ colors[i + 224].b = 224 + i;
+ }
+
+ SDL_SetPalette(surface, SDL_LOGPAL | SDL_PHYSPAL, colors,
+ 0, NARRAY(colors));
+
+ return surface;
+}
+
+static inline void
+effect_fire_update(SDL_Surface *surface)
+{
+ int mouse_x, mouse_y;
+
+ SDL_MAYBE_LOCK(surface);
+
+ if (SDL_GetMouseState(&mouse_x, &mouse_y) & SDL_BUTTON(1)) {
+ Uint8 *p = (Uint8 *)surface->pixels;
+ float r = (float)rand()/RAND_MAX;
+
+ p[mouse_y*surface->pitch + mouse_x] = r > .3 ? 255 : 0;
+ }
+
+ for (Uint8 *p = (Uint8 *)surface->pixels + surface->pitch*surface->h - 1;
+ p >= (Uint8 *)surface->pixels + surface->pitch;
+ p--) {
+ Uint16 acc;
+
+ if (!((p - (Uint8 *)surface->pixels) % surface->pitch)) {
+ /* left edge */
+ acc = (Uint16)p[0] + p[1];
+ if (acc/2 > p[-surface->pitch])
+ p[-surface->pitch] = (acc + p[-surface->pitch])/3;
+ } else if (!((p - (Uint8 *)surface->pixels + 1) % surface->pitch)) {
+ /* right edge */
+ acc = (Uint16)p[-1] + p[0];
+ if (acc/2 > p[-surface->pitch])
+ p[-surface->pitch] = (acc + p[-surface->pitch])/3;
+ } else {
+ /* somewhere inbetween */
+ acc = (Uint16)p[-1] + p[0] + p[1];
+ if (acc/3 > p[-surface->pitch])
+ p[-surface->pitch] = (acc + p[-surface->pitch])/4;
+ }
+
+ /* decay */
+ if (p[-surface->pitch] > 0)
+ p[-surface->pitch]--;
+ }
+
+ SDL_MAYBE_UNLOCK(surface);
+}
+
static inline void
-handle_events(void)
+process_events(void)
{
SDL_Event event;
@@ -53,6 +165,8 @@ handle_events(void)
int
main(int argc, char **argv)
{
+ SDL_Surface *fire_surface;
+
if (SDL_Init(SDL_INIT_VIDEO)) {
SDL_ERROR("SDL_Init");
return EXIT_FAILURE;
@@ -68,10 +182,19 @@ main(int argc, char **argv)
return EXIT_FAILURE;
}
+ fire_surface = effect_fire_init();
+
for (;;) {
- handle_events();
+ process_events();
+
+ SDL_FillRect(screen, NULL,
+ SDL_MapRGB(screen->format, 0, 0, 0));
+
+ effect_fire_update(fire_surface);
+ SDL_BlitSurface(fire_surface, NULL, screen, NULL);
- SDL_Delay(100);
+ SDL_Flip(screen);
+ SDL_Delay(50);
}
/* never reached */