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

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

imlib: refactor dirty_rect clipping coordiantes so that the upper
bound is no longer inclusive. It will make things easier in the future.

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