Logo Search packages:      
Sourcecode: abuse-sdl version File versions  Download package

particle.cpp

#include "macs.hpp"
#include "particle.hpp"
#include "view.hpp"
#include "lisp.hpp"
#include "cache.hpp"
#include "jrand.hpp"


static int total_pseqs=0;
static part_sequence **pseqs=NULL;
static part_animation *first_anim=NULL,*last_anim=NULL;

void free_pframes()
{
  for (int i=0;i<total_pseqs;i++)
    delete pseqs[i];
  if (total_pseqs)
    jfree(pseqs);
}

part_frame::~part_frame()
{
  jfree(data);
}

void add_panim(int id, long x, long y, int dir)
{
  CONDITION(id>=0 && id<total_pseqs,"bad id for particle animation");
  part_animation *pan=new part_animation(pseqs[id],x,y,dir,NULL);
  if (!first_anim)
    first_anim=last_anim=pan;
  else
  {
    last_anim->next=pan;
    last_anim=pan;
  }  
}

void delete_panims()
{
  while (first_anim)
  {
    last_anim=first_anim;
    first_anim=first_anim->next;
    delete last_anim;
  }
  last_anim=NULL;
}

int defun_pseq(void *args)
{
  lisp_symbol *sym=(lisp_symbol *)lcar(args);
  if (item_type(sym)!=L_SYMBOL)
  {
    lprint(args);
    printf("expecting first arg to def-particle to be a symbol!\n");
    exit(0);
  }
  int sp=current_space;
  current_space=PERM_SPACE;
  set_symbol_number(sym,total_pseqs);   // set the symbol value to the object number
  current_space=sp;
  pseqs=(part_sequence **)jrealloc(pseqs,sizeof(part_sequence *)*(total_pseqs+1),"particle seq array");

  args=lcdr(args);
  pseqs[total_pseqs]=new part_sequence(args);
  total_pseqs++;  
  return total_pseqs;
}

extern int total_files_open;

part_sequence::part_sequence(void *args)
{
  char *fn=lstring_value(lcar(args)); 
  bFILE *fp=open_file(fn,"rb");
  if (fp->open_failure())
  {
    delete fp;
    lprint(args);
    fprintf(stderr,"\nparticle sequence : Unable to open %s for reading\n",fn);
    fprintf(stderr,"total files open=%d\n",total_files_open);

    FILE *fp=fopen(fn,"rb");
    printf("convet = %d\n",fp!=NULL);
    exit(1);
  }

  // count how many frames are in the file
  spec_directory sd(fp);
  delete fp;
  tframes=0;
  int i=0;
  for (;i<sd.total;i++)
    if (sd.entries[i]->type==SPEC_PARTICLE) tframes++;
  frames=(int *)jmalloc(sizeof(int)*tframes,"part_frame id list\n");
 
  int on=0;
  for (i=0;i<sd.total;i++)
    if (sd.entries[i]->type==SPEC_PARTICLE)     
      frames[on++]=cash.reg(fn,sd.entries[i]->name,SPEC_PARTICLE,1);

}

part_frame::part_frame(bFILE *fp)
{
  t=fp->read_long();
  data=(part *)jmalloc(sizeof(part)*t,"particle frame");
  x1=y1=100000; x2=y2=-100000;
  for (int i=0;i<t;i++)
  {
    short x=fp->read_short();
    short y=fp->read_short();
    if (x<x1) x1=x;
    if (y<y1) y1=y;
    if (x>x2) x2=x;
    if (y>y2) y2=x;
    data[i].x=x;
    data[i].y=y;   
    data[i].color=fp->read_byte(); 
  }
}

void tick_panims()
{
  part_animation *last=NULL;
  for (part_animation *p=first_anim;p;)
  {
    p->frame++;
    if (p->frame>=p->seq->tframes)
    {
      if (last)
        last->next=p->next;
      else first_anim=first_anim->next;
      if (last_anim==p) last_anim=last;
      part_animation *d=p;
      p=p->next;
      delete d;
    } else 
    {
      last=p;
      p=p->next;
    }

  }
}

void draw_panims(view *v)
{
  for (part_animation *p=first_anim;p;p=p->next)      
  {
    cash.part(p->seq->frames[p->frame])->draw(screen,p->x-v->xoff()+v->cx1,p->y-v->yoff()+v->cy1,p->dir);
  }
}

void part_frame::draw(image *screen, int x, int y, int dir)
{
  short cx1,cy1,cx2,cy2;
  screen->get_clip(cx1,cy1,cx2,cy2);
  if (x+x1>cx2 || x+x2<cx1 || y+y1>cy2 || y+y2<cy1) return ;

  part *pon=data;
  cy1-=y;
  cy2-=y;

  int i=t;
  while (i && pon->y<cy1) { pon++; i--; }
  if (!i) return ;
  if (dir>0)
  {
    while (i && pon->y<=cy2)
    {
      long dx=x-pon->x;
      if (dx>=cx1 && dx<=cx2)
      *(screen->scan_line(pon->y+y)+dx)=pon->color;
      i--;
      pon++;
    }   
  } else
  {
    while (i && pon->y<=cy2)
    {
      long dx=pon->x+x;
      if (dx>=cx1 && dx<=cx2)
        *(screen->scan_line(pon->y+y)+dx)=pon->color;
      i--;
      pon++;
    }   
  }

}




void scatter_line(int x1, int y1, int x2, int y2, int c, int s)
{
      short cx1, cy1, cx2, cy2;
      screen->get_clip( cx1, cy1, cx2, cy2 );

      int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
      long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) << 16 ) / t, x, y;

      int xm = ( 1 << s );
      int ym = ( 1 << s );
      s = ( 15 - s );

      while( t-- )
      {
            x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
            y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
            if( !( x < cx1 || y < cy1 || x > cx2 || y > cy2 ) )
            {
                  *(screen->scan_line( y ) + x ) = c;
            }
            xo += dx;
            yo += dy;
      }
}



void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s)
{
      short cx1, cy1, cx2, cy2;
      screen->get_clip( cx1, cy1, cx2, cy2 );

      int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
      long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) <<16 ) / t, x, y;

      int xm = ( 1 << s );
      int ym = ( 1 << s );
      s = ( 15 - s );

      int w = screen->width();
      uchar *addr;

      while( t-- )
      {
            x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
            y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
            if( !( x <= cx1 || y <= cy1 || x >= cx2 || y >= cy2 ) )
            {
                  addr = screen->scan_line( y ) + x;
                  *addr = c1;
                  *(addr + w) = c2;
                  *(addr - w) = c2;
                  *(addr - 1) = c2;
                  *(addr + 1) = c2;
            }
            xo += dx;
            yo += dy;
      }
}

Generated by  Doxygen 1.6.0   Back to index