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

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

core: Get rid of mostly useless headers, move endianness handling to
common.h (and rewrite functions so that they do not need the SDL headers)
and move a few functions out of sdlport's video.cpp. These functions
were in the original video.cpp (which reappears) and shouldn't be part
of the SDL port.

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