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

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

imlib: refactor Event and EventHandler?.

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