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

Last change on this file since 494 was 494, checked in by Sam Hocevar, 11 years ago

style: remove trailing spaces, fix copyright statements.

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