source: abuse/trunk/src/particle.cpp @ 17

Last change on this file since 17 was 17, checked in by Sam Hocevar, 14 years ago
  • absolute shitloads of 64 bit fixes.
File size: 5.3 KB
Line 
1#include "macs.hpp"
2#include "particle.hpp"
3#include "view.hpp"
4#include "lisp.hpp"
5#include "cache.hpp"
6#include "jrand.hpp"
7
8
9static int total_pseqs=0;
10static part_sequence **pseqs=NULL;
11static part_animation *first_anim=NULL,*last_anim=NULL;
12
13void free_pframes()
14{
15  for (int i=0;i<total_pseqs;i++)
16    delete pseqs[i];
17  if (total_pseqs)
18    jfree(pseqs);
19}
20
21part_frame::~part_frame()
22{
23  jfree(data);
24}
25
26void add_panim(int id, long x, long y, int dir)
27{
28  CONDITION(id>=0 && id<total_pseqs,"bad id for particle animation");
29  part_animation *pan=new part_animation(pseqs[id],x,y,dir,NULL);
30  if (!first_anim)
31    first_anim=last_anim=pan;
32  else
33  {
34    last_anim->next=pan;
35    last_anim=pan;
36  } 
37}
38
39void delete_panims()
40{
41  while (first_anim)
42  {
43    last_anim=first_anim;
44    first_anim=first_anim->next;
45    delete last_anim;
46  }
47  last_anim=NULL;
48}
49
50int defun_pseq(void *args)
51{
52  lisp_symbol *sym=(lisp_symbol *)lcar(args);
53  if (item_type(sym)!=L_SYMBOL)
54  {
55    lprint(args);
56    printf("expecting first arg to def-particle to be a symbol!\n");
57    exit(0);
58  }
59  int sp=current_space;
60  current_space=PERM_SPACE;
61  set_symbol_number(sym,total_pseqs);   // set the symbol value to the object number
62  current_space=sp;
63  pseqs=(part_sequence **)jrealloc(pseqs,sizeof(part_sequence *)*(total_pseqs+1),"particle seq array");
64
65  args=lcdr(args);
66  pseqs[total_pseqs]=new part_sequence(args);
67  total_pseqs++; 
68  return total_pseqs;
69}
70
71extern int total_files_open;
72
73part_sequence::part_sequence(void *args)
74{
75  char *fn=lstring_value(lcar(args));
76  bFILE *fp=open_file(fn,"rb");
77  if (fp->open_failure())
78  {
79    delete fp;
80    lprint(args);
81    fprintf(stderr,"\nparticle sequence : Unable to open %s for reading\n",fn);
82    fprintf(stderr,"total files open=%d\n",total_files_open);
83
84    FILE *fp=fopen(fn,"rb");
85    printf("convet = %d\n",fp!=NULL);
86    exit(1);
87  }
88
89  // count how many frames are in the file
90  spec_directory sd(fp);
91  delete fp;
92  tframes=0;
93  int i=0;
94  for (;i<sd.total;i++)
95    if (sd.entries[i]->type==SPEC_PARTICLE) tframes++;
96  frames=(int *)jmalloc(sizeof(int)*tframes,"part_frame id list\n");
97 
98  int on=0;
99  for (i=0;i<sd.total;i++)
100    if (sd.entries[i]->type==SPEC_PARTICLE)     
101      frames[on++]=cash.reg(fn,sd.entries[i]->name,SPEC_PARTICLE,1);
102
103}
104
105part_frame::part_frame(bFILE *fp)
106{
107  t=fp->read_uint32();
108  data=(part *)jmalloc(sizeof(part)*t,"particle frame");
109  x1=y1=100000; x2=y2=-100000;
110  for (int i=0;i<t;i++)
111  {
112    int16_t x=fp->read_uint16();
113    int16_t y=fp->read_uint16();
114    if (x<x1) x1=x;
115    if (y<y1) y1=y;
116    if (x>x2) x2=x;
117    if (y>y2) y2=x;
118    data[i].x=x;
119    data[i].y=y;   
120    data[i].color=fp->read_uint8();
121  }
122}
123
124void tick_panims()
125{
126  part_animation *last=NULL;
127  for (part_animation *p=first_anim;p;)
128  {
129    p->frame++;
130    if (p->frame>=p->seq->tframes)
131    {
132      if (last)
133        last->next=p->next;
134      else first_anim=first_anim->next;
135      if (last_anim==p) last_anim=last;
136      part_animation *d=p;
137      p=p->next;
138      delete d;
139    } else
140    {
141      last=p;
142      p=p->next;
143    }
144
145  }
146}
147
148void draw_panims(view *v)
149{
150  for (part_animation *p=first_anim;p;p=p->next)     
151  {
152    cash.part(p->seq->frames[p->frame])->draw(screen,p->x-v->xoff()+v->cx1,p->y-v->yoff()+v->cy1,p->dir);
153  }
154}
155
156void part_frame::draw(image *screen, int x, int y, int dir)
157{
158  int16_t cx1,cy1,cx2,cy2;
159  screen->get_clip(cx1,cy1,cx2,cy2);
160  if (x+x1>cx2 || x+x2<cx1 || y+y1>cy2 || y+y2<cy1) return ;
161
162  part *pon=data;
163  cy1-=y;
164  cy2-=y;
165
166  int i=t;
167  while (i && pon->y<cy1) { pon++; i--; }
168  if (!i) return ;
169  if (dir>0)
170  {
171    while (i && pon->y<=cy2)
172    {
173      long dx=x-pon->x;
174      if (dx>=cx1 && dx<=cx2)
175      *(screen->scan_line(pon->y+y)+dx)=pon->color;
176      i--;
177      pon++;
178    }   
179  } else
180  {
181    while (i && pon->y<=cy2)
182    {
183      long dx=pon->x+x;
184      if (dx>=cx1 && dx<=cx2)
185        *(screen->scan_line(pon->y+y)+dx)=pon->color;
186      i--;
187      pon++;
188    }   
189  }
190
191}
192
193
194
195
196void scatter_line(int x1, int y1, int x2, int y2, int c, int s)
197{
198        int16_t cx1, cy1, cx2, cy2;
199        screen->get_clip( cx1, cy1, cx2, cy2 );
200
201        int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
202        long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) << 16 ) / t, x, y;
203
204        int xm = ( 1 << s );
205        int ym = ( 1 << s );
206        s = ( 15 - s );
207
208        while( t-- )
209        {
210                x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
211                y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
212                if( !( x < cx1 || y < cy1 || x > cx2 || y > cy2 ) )
213                {
214                        *(screen->scan_line( y ) + x ) = c;
215                }
216                xo += dx;
217                yo += dy;
218        }
219}
220
221
222
223void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s)
224{
225        int16_t cx1, cy1, cx2, cy2;
226        screen->get_clip( cx1, cy1, cx2, cy2 );
227
228        int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
229        long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) <<16 ) / t, x, y;
230
231        int xm = ( 1 << s );
232        int ym = ( 1 << s );
233        s = ( 15 - s );
234
235        int w = screen->width();
236        uint8_t *addr;
237
238        while( t-- )
239        {
240                x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
241                y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
242                if( !( x <= cx1 || y <= cy1 || x >= cx2 || y >= cy2 ) )
243                {
244                        addr = screen->scan_line( y ) + x;
245                        *addr = c1;
246                        *(addr + w) = c2;
247                        *(addr - w) = c2;
248                        *(addr - 1) = c2;
249                        *(addr + 1) = c2;
250                }
251                xo += dx;
252                yo += dy;
253        }
254}
Note: See TracBrowser for help on using the repository browser.