source: abuse/branches/lol/src/particle.cpp

Last change on this file was 737, checked in by Sam Hocevar, 7 years ago

build: sync with newer Lol Engine changes.

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