Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

drops.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou 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.
 *
 *  lebiniou 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 lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "context.h"


u_long id = 1075754710;
u_long options = BE_GFX;
u_long mode = OVERLAY;
char desc[] = "Falling drops";


#define FACTOR 0.0005     /* empirical value, as usual */
#define NDROPS (u_long)((float)BUFFSIZE * FACTOR)

#define MIN_X_SPEED -1
#define MAX_X_SPEED 1
#define MIN_Y_SPEED 4
#define MAX_Y_SPEED 10

#define DELTA_X 1


00040 typedef struct Drop_s {
  int active;
  Point2d_t pos, speed;
  u_char height;
} Drop_t;


static Drop_t *drops = NULL;
static u_char drops_mode = 0;
static u_long active_drops = 0;


void
create(__attribute__ ((unused)) Context_t *ctx)
{
  u_long d;
  assert(NDROPS > 0);

  drops = xcalloc(NDROPS, sizeof(Drop_t));
  
  for (d = 0; d < NDROPS; d++)
    drops[d].active = 0;

  active_drops = 0;
}


void
destroy(__attribute__ ((unused)) Context_t *ctx)
{
  xfree(drops);  
}


static void
do_drops(Context_t *ctx)
{
  const Buffer8_t *src = active_buffer(ctx);
  Buffer8_t *dst = passive_buffer(ctx);
  u_long d;
  short m;

  Buffer8_clear(dst);

  for (d = 0; d < NDROPS; d++) {
    if (!drops[d].active)
      continue;
            
    for (m = 0; m < -drops[d].speed.y; m++) {
      u_char z;
      Point2d_t C;
      Pixel_t Cz;

      drops[d].pos.x += drops[d].speed.x;
      if (drops[d].pos.x < 0)
      drops[d].pos.x = 0;
      else if (drops[d].pos.x > MAXX)
      drops[d].pos.x = MAXX;
                  
      /* drops[d].pos = p2d_add (&drops[d].pos, &drops[d].speed); */
      drops[d].pos.y--;
                  
      if (!drops[d].pos.y)
      continue;
                  
      z = drops[d].height;
                  
      /* now, move and set new height */
      /* go to center first */
      C.x = drops[d].pos.x;
      C.y = drops[d].pos.y - 1; /* is >= 0 */
                  
      Cz = get_pixel /*_nc*/ (src, C.x, C.y);
                  
      /* ceci est un commentaire ANSI C */
      if ((!drops_mode && (Cz < z)) || (drops_mode && (Cz > z))) {
      drops[d].speed.y++;
      drops[d].height--;
      } else if (Cz == z) {
      /* drops[d].speed.y++; */
      drops[d].height--;
      } else {
      Point2d_t L, R;
      Pixel_t Lz, Rz;
            
      /* if (!drops[d].height++)
         drops[d].height = 255; */
                        
      drops[d].height--;
                        
      L.x = drops[d].pos.x-1;
      if (L.x < 0)
        L.x = 0;
      else if (L.x > MAXX)
        L.x = MAXX;
      L.y = C.y;
                        
      R.x = drops[d].pos.x+1;
      if (R.x < 0)
        R.x = 0;
      else if (R.x > MAXX)
        R.x = MAXX;
      R.y = C.y;
                        
      Lz = get_pixel/*_nc*/(src, L.x, L.y);
      Rz = get_pixel/*_nc*/(src, R.x, R.y);
                        
      /* choose either LCR or RCL */
      if (b_rand_boolean()) {
        /* LCR */
        if (Lz <= z) {
          /* drops[d].speed.x--; */
          drops[d].pos.x -= DELTA_X;
        } else {
          /* drops[d].speed.x++; */
          drops[d].pos.x += DELTA_X;
        }
      } else {
        /* RCL */
        if (Rz <= z) {
          /* drops[d].speed.x++; */
          drops[d].pos.x += DELTA_X;
        } else {
          /* drops[d].speed.x--; */
          drops[d].pos.x -= DELTA_X;
        }
      }
      }
                  
      /* if (drops[d].height)
       drops[d].height--; */
                  
      /* clamp speed */
      if (drops[d].speed.x < MIN_X_SPEED)
      drops[d].speed.x = MIN_X_SPEED;
      else if (drops[d].speed.x > MAX_X_SPEED)
      drops[d].speed.x = MAX_X_SPEED;
                  
      /* ok this one is tricky, i admit ;) */
      if (drops[d].speed.y > -MIN_Y_SPEED)
      drops[d].speed.y = -MIN_Y_SPEED;
      else if (drops[d].speed.y < -MAX_Y_SPEED)
      drops[d].speed.y = -MAX_Y_SPEED;
    }
            
    if (drops[d].pos.y)
      set_pixel/*_nc*/(dst, drops[d].pos.x, drops[d].pos.y, drops[d].height);
  }
}


static void
decay_drops()
{
  u_long d;
  for (d = 0; d < NDROPS; d++)
    if (drops[d].active)
      if ((drops[d].pos.y <= 0) || !drops[d].height) {
      drops[d].active = 0;
      active_drops--;
      }
}


void
run(Context_t *ctx)
{
  u_short nd;
  u_long idx;

  if (ctx->input == NULL)
    return;

  pthread_mutex_lock(&ctx->input->mutex);

  for (nd = 0, idx = 0;
       (nd < ctx->input->size) && (idx < NDROPS)
       && (active_drops < NDROPS);
       idx++) {
    if (drops[idx].active)
      continue;

    /* create a new drop */
    drops[idx].pos.x = b_rand_int() % WIDTH;
    drops[idx].pos.y = b_rand_int() % (MAXY - HHEIGHT) + HHEIGHT;
    drops[idx].speed.x = 0;
    drops[idx].speed.y = -(Input_random_u_u_float(ctx->input) * (MAX_Y_SPEED - MIN_Y_SPEED) + MIN_Y_SPEED);
    drops[idx].active = 1;
    drops[idx].height = 255; /* Input_random_u_float () * 128 + 127; */
    active_drops++;
    nd++;
    assert(active_drops <= NDROPS);
  }

  pthread_mutex_unlock(&ctx->input->mutex);

  decay_drops();
  do_drops(ctx);

  /* printf ("%li active drops\n", active_drops); */
}

#ifndef EVT_DAWA
#ifdef HAVE_SDL_H
u_char
on_SDL_Event(Context_t *ctx, const SDL_Event *e)
{
  if (key(e, SDLK_m)) {
    drops_mode = !drops_mode;
    printf("[d] drops mode switched to %s\n", (drops_mode ? "normal" : "special"));
    return 1;
  }

  return 0;
}
#endif /* HAVE_SDL_H */
#endif

Generated by  Doxygen 1.6.0   Back to index