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

Last change on this file since 115 was 115, checked in by Sam Hocevar, 11 years ago
  • Add lock() and unlock() methods to jimage objects. They're no-ops, but the Win32/DirectX version uses them all over the place because it uses DirectDraw? surfaces. One day we may wish to merge Abuse Win32's video output, or to use the SDL blending functions. You never know.
File size: 5.8 KB
RevLine 
[56]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
[2]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;
[115]47  }
[2]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);
[115]78  total_pseqs++;
[2]79  return total_pseqs;
80}
81
82extern int total_files_open;
83
84part_sequence::part_sequence(void *args)
85{
[115]86  char *fn=lstring_value(lcar(args));
[2]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");
[115]108
[2]109  int on=0;
110  for (i=0;i<sd.total;i++)
[115]111    if (sd.entries[i]->type==SPEC_PARTICLE)
[2]112      frames[on++]=cash.reg(fn,sd.entries[i]->name,SPEC_PARTICLE,1);
113
114}
115
116part_frame::part_frame(bFILE *fp)
117{
[17]118  t=fp->read_uint32();
[2]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  {
[17]123    int16_t x=fp->read_uint16();
124    int16_t y=fp->read_uint16();
[2]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;
[115]130    data[i].y=y;
131    data[i].color=fp->read_uint8();
[2]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;
[115]150    } else
[2]151    {
152      last=p;
153      p=p->next;
154    }
155
156  }
157}
158
159void draw_panims(view *v)
160{
[115]161  for (part_animation *p=first_anim;p;p=p->next)
[2]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{
[17]169  int16_t cx1,cy1,cx2,cy2;
[2]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 ;
[115]180  screen->lock();
[2]181  if (dir>0)
182  {
183    while (i && pon->y<=cy2)
184    {
185      long dx=x-pon->x;
186      if (dx>=cx1 && dx<=cx2)
187      *(screen->scan_line(pon->y+y)+dx)=pon->color;
188      i--;
189      pon++;
[115]190    }
[2]191  } else
192  {
193    while (i && pon->y<=cy2)
194    {
195      long dx=pon->x+x;
196      if (dx>=cx1 && dx<=cx2)
197        *(screen->scan_line(pon->y+y)+dx)=pon->color;
198      i--;
199      pon++;
[115]200    }
[2]201  }
[115]202  screen->unlock();
[2]203}
204
205void scatter_line(int x1, int y1, int x2, int y2, int c, int s)
206{
[115]207    int16_t cx1, cy1, cx2, cy2;
208    screen->get_clip( cx1, cy1, cx2, cy2 );
[2]209
[115]210    int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
211    long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) << 16 ) / t, x, y;
[2]212
[115]213    int xm = ( 1 << s );
214    int ym = ( 1 << s );
215    s = ( 15 - s );
[2]216
[115]217    screen->lock();
218    while( t-- )
219    {
220        x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
221        y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
222        if( !( x < cx1 || y < cy1 || x > cx2 || y > cy2 ) )
223        {
224            *(screen->scan_line( y ) + x ) = c;
225        }
226        xo += dx;
227        yo += dy;
228    }
229    screen->unlock();
[2]230}
231
232
233
234void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s)
235{
[115]236    int16_t cx1, cy1, cx2, cy2;
237    screen->get_clip( cx1, cy1, cx2, cy2 );
[2]238
[115]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;
[2]241
[115]242    int xm = ( 1 << s );
243    int ym = ( 1 << s );
244    s = ( 15 - s );
[2]245
[115]246    screen->lock();
[2]247
[115]248    int w = screen->width();
249    uint8_t *addr;
250
251    while( t-- )
252    {
253        x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
254        y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
255        if( !( x <= cx1 || y <= cy1 || x >= cx2 || y >= cy2 ) )
256        {
257            addr = 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    screen->unlock();
[2]269}
[115]270
Note: See TracBrowser for help on using the repository browser.