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

Last change on this file since 674 was 674, checked in by Sam Hocevar, 9 years ago

game: convert a few View members to vec2i.

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, 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->m_aa.x,p->y-v->yoff()+v->m_aa.y,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 ScatterLine(vec2i p1, vec2i p2, int c, int s)
212{
213    vec2i caa, cbb;
214    main_screen->GetClip(caa, cbb);
215
216    int t = 1 + Max(abs(p2.x - p1.x), abs(p2.y - p1.y));
217    int xo = p1.x << 16,
218        yo = p1.y << 16,
219        dx = ((p2.x - p1.x) << 16) / t,
220        dy = ((p2.y - p1.y) << 16) / t;
221
222    int xm = (1 << s);
223    int ym = (1 << s);
224    s = (15 - s);
225
226    main_screen->Lock();
227    while(t--)
228    {
229        int x = (xo >> 16) + (jrand() >> s) - xm;
230        int y = (yo >> 16) + (jrand() >> s) - ym;
231        if(!(x < caa.x || y < caa.y || x >= cbb.x || y >= cbb.y))
232        {
233            *(main_screen->scan_line(y) + x) = c;
234        }
235        xo += dx;
236        yo += dy;
237    }
238    main_screen->Unlock();
239}
240
241void AScatterLine(vec2i p1, vec2i p2, int c1, int c2, int s)
242{
243    vec2i caa, cbb;
244    main_screen->GetClip(caa, cbb);
245
246    int t = 1 + Max(abs(p2.x - p1.x), abs(p2.y - p1.y));
247    int xo = p1.x << 16,
248        yo = p1.y << 16,
249        dx = ((p2.x - p1.x) << 16) / t,
250        dy = ((p2.y - p1.y) << 16) / t;
251
252    int xm = (1 << s);
253    int ym = (1 << s);
254    s = (15 - s);
255
256    main_screen->Lock();
257
258    int w = main_screen->Size().x;
259    uint8_t *addr;
260
261    while(t--)
262    {
263        int x = (xo >> 16) + (jrand() >> s) - xm;
264        int y = (yo >> 16) + (jrand() >> s) - ym;
265        // FIXME: these clip values seemed wrong to me before the GetClip
266        // refactoring.
267        if(!(x <= caa.x || y <= caa.y || x >= cbb.x - 1 || y >= cbb.y - 1))
268        {
269            addr = main_screen->scan_line(y) + x;
270            *addr = c1;
271            *(addr + w) = c2;
272            *(addr - w) = c2;
273            *(addr - 1) = c2;
274            *(addr + 1) = c2;
275        }
276        xo += dx;
277        yo += dy;
278    }
279
280    main_screen->Unlock();
281}
282
Note: See TracBrowser for help on using the repository browser.