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

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