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

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

imlib: refactor GetClip?, SetClip? etc. to use vec2i.

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    vec2i caa, cbb;
174    screen->GetClip(caa, cbb);
175
176    if (x + x1 >= cbb.x || x + x2 < caa.x || y + y1 >= cbb.y || y + y2 < caa.y)
177       return;
178
179  part *pon=data;
180  caa.y -= y;
181  cbb.y -= y;
182
183  int i=t;
184  while (i && pon->y<caa.y) { pon++; i--; }
185  if (!i) return ;
186  screen->Lock();
187  if (dir>0)
188  {
189    while (i && pon->y < cbb.y)
190    {
191      long dx=x-pon->x;
192      if (dx >= caa.x && dx < cbb.x)
193      *(screen->scan_line(pon->y+y)+dx)=pon->color;
194      i--;
195      pon++;
196    }
197  } else
198  {
199    while (i && pon->y < cbb.y)
200    {
201      long dx=pon->x+x;
202      if (dx >= caa.x && dx < cbb.x)
203        *(screen->scan_line(pon->y+y)+dx)=pon->color;
204      i--;
205      pon++;
206    }
207  }
208  screen->Unlock();
209}
210
211void scatter_line(int x1, int y1, int x2, int y2, int c, int s)
212{
213    vec2i caa, cbb;
214    main_screen->GetClip(caa, cbb);
215
216    int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
217    long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) << 16 ) / t, x, y;
218
219    int xm = ( 1 << s );
220    int ym = ( 1 << s );
221    s = ( 15 - s );
222
223    main_screen->Lock();
224    while( t-- )
225    {
226        x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
227        y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
228        if( !( x < caa.x || y < caa.y || x >= cbb.x || y >= cbb.y ) )
229        {
230            *(main_screen->scan_line( y ) + x ) = c;
231        }
232        xo += dx;
233        yo += dy;
234    }
235    main_screen->Unlock();
236}
237
238
239
240void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s)
241{
242    vec2i caa, cbb;
243    main_screen->GetClip(caa, cbb);
244
245    int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
246    long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) <<16 ) / t, x, y;
247
248    int xm = ( 1 << s );
249    int ym = ( 1 << s );
250    s = ( 15 - s );
251
252    main_screen->Lock();
253
254    int w = main_screen->Size().x;
255    uint8_t *addr;
256
257    while( t-- )
258    {
259        x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
260        y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
261        // FIXME: these clip values seemed wrong to me before the GetClip
262        // refactoring.
263        if( !( x <= caa.x || y <= caa.y || x >= cbb.x - 1 || y >= cbb.y - 1) )
264        {
265            addr = main_screen->scan_line( y ) + x;
266            *addr = c1;
267            *(addr + w) = c2;
268            *(addr - w) = c2;
269            *(addr - 1) = c2;
270            *(addr + 1) = c2;
271        }
272        xo += dx;
273        yo += dy;
274    }
275
276    main_screen->Unlock();
277}
278
Note: See TracBrowser for help on using the repository browser.