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

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

ps3: make everything compile on the PS3. Of course, nothing links yet
because so much support is missing.

File size: 6.0 KB
RevLine 
[56]1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
[494]4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
[56]5 *
6 *  This software was released into the Public Domain. As with most public
[555]7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
[56]9 */
10
[555]11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
[56]14
[512]15#include "common.h"
16
[481]17#include "particle.h"
18#include "view.h"
19#include "lisp.h"
20#include "cache.h"
21#include "jrand.h"
[2]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{
[494]30  for (int i=0; i<total_pseqs; i++)
[2]31    delete pseqs[i];
32  if (total_pseqs)
[129]33    free(pseqs);
[2]34}
35
36part_frame::~part_frame()
37{
[129]38  free(data);
[2]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;
[115]51  }
[2]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{
[492]67  LSymbol *sym=(LSymbol *)lcar(args);
[2]68  if (item_type(sym)!=L_SYMBOL)
69  {
[493]70    ((LObject *)args)->Print();
[2]71    printf("expecting first arg to def-particle to be a symbol!\n");
72    exit(0);
73  }
74  int sp=current_space;
75  current_space=PERM_SPACE;
[484]76  sym->SetNumber(total_pseqs); // set the symbol value to the object number
[2]77  current_space=sp;
[129]78  pseqs=(part_sequence **)realloc(pseqs,sizeof(part_sequence *)*(total_pseqs+1));
[2]79
80  args=lcdr(args);
81  pseqs[total_pseqs]=new part_sequence(args);
[115]82  total_pseqs++;
[2]83  return total_pseqs;
84}
85
86extern int total_files_open;
87
88part_sequence::part_sequence(void *args)
89{
[115]90  char *fn=lstring_value(lcar(args));
[2]91  bFILE *fp=open_file(fn,"rb");
92  if (fp->open_failure())
93  {
94    delete fp;
[493]95    ((LObject *)args)->Print();
[2]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;
[494]109  for (; i<sd.total; i++)
[2]110    if (sd.entries[i]->type==SPEC_PARTICLE) tframes++;
[129]111  frames=(int *)malloc(sizeof(int)*tframes);
[115]112
[2]113  int on=0;
[494]114  for (i=0; i<sd.total; i++)
[115]115    if (sd.entries[i]->type==SPEC_PARTICLE)
[123]116      frames[on++]=cache.reg(fn,sd.entries[i]->name,SPEC_PARTICLE,1);
[2]117
118}
119
120part_frame::part_frame(bFILE *fp)
121{
[17]122  t=fp->read_uint32();
[129]123  data=(part *)malloc(sizeof(part)*t);
[2]124  x1=y1=100000; x2=y2=-100000;
[494]125  for (int i=0; i<t; i++)
[2]126  {
[17]127    int16_t x=fp->read_uint16();
128    int16_t y=fp->read_uint16();
[2]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;
[115]134    data[i].y=y;
135    data[i].color=fp->read_uint8();
[2]136  }
137}
138
139void tick_panims()
140{
141  part_animation *last=NULL;
[494]142  for (part_animation *p=first_anim; p; )
[2]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;
[115]154    } else
[2]155    {
156      last=p;
157      p=p->next;
158    }
159
160  }
161}
162
163void draw_panims(view *v)
164{
[494]165  for (part_animation *p=first_anim; p; p=p->next)
[2]166  {
[123]167    cache.part(p->seq->frames[p->frame])->draw(screen,p->x-v->xoff()+v->cx1,p->y-v->yoff()+v->cy1,p->dir);
[2]168  }
169}
170
171void part_frame::draw(image *screen, int x, int y, int dir)
172{
[518]173  int cx1, cy1, cx2, cy2;
174  screen->GetClip(cx1, cy1, cx2, cy2);
175  if (x + x1 >= cx2 || x + x2 < cx1 || y + y1 >= cy2 || y + y2 < cy1) return;
[2]176
177  part *pon=data;
[518]178  cy1 -= y;
179  cy2 -= y;
[2]180
181  int i=t;
182  while (i && pon->y<cy1) { pon++; i--; }
183  if (!i) return ;
[515]184  screen->Lock();
[2]185  if (dir>0)
186  {
[518]187    while (i && pon->y < cy2)
[2]188    {
189      long dx=x-pon->x;
[518]190      if (dx >= cx1 && dx < cx2)
[2]191      *(screen->scan_line(pon->y+y)+dx)=pon->color;
192      i--;
193      pon++;
[115]194    }
[2]195  } else
196  {
[518]197    while (i && pon->y < cy2)
[2]198    {
199      long dx=pon->x+x;
[518]200      if (dx >= cx1 && dx < cx2)
[2]201        *(screen->scan_line(pon->y+y)+dx)=pon->color;
202      i--;
203      pon++;
[115]204    }
[2]205  }
[515]206  screen->Unlock();
[2]207}
208
209void scatter_line(int x1, int y1, int x2, int y2, int c, int s)
210{
[518]211    int cx1, cy1, cx2, cy2;
212    screen->GetClip(cx1, cy1, cx2, cy2);
[2]213
[115]214    int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
215    long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) << 16 ) / t, x, y;
[2]216
[115]217    int xm = ( 1 << s );
218    int ym = ( 1 << s );
219    s = ( 15 - s );
[2]220
[515]221    screen->Lock();
[115]222    while( t-- )
223    {
224        x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
225        y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
[518]226        if( !( x < cx1 || y < cy1 || x >= cx2 || y >= cy2 ) )
[115]227        {
228            *(screen->scan_line( y ) + x ) = c;
229        }
230        xo += dx;
231        yo += dy;
232    }
[515]233    screen->Unlock();
[2]234}
235
236
237
238void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s)
239{
[518]240    int cx1, cy1, cx2, cy2;
241    screen->GetClip(cx1, cy1, cx2, cy2);
[2]242
[115]243    int t = abs( x2 - x1 ) > abs( y2 - y1 ) ? abs( x2 - x1 ) + 1 : abs( y2 - y1 ) + 1;
244    long xo = x1 << 16, yo = y1 << 16, dx = ( ( x2 - x1 ) << 16 ) / t, dy = ( ( y2 - y1 ) <<16 ) / t, x, y;
[2]245
[115]246    int xm = ( 1 << s );
247    int ym = ( 1 << s );
248    s = ( 15 - s );
[2]249
[515]250    screen->Lock();
[2]251
[512]252    int w = screen->Size().x;
[115]253    uint8_t *addr;
254
255    while( t-- )
256    {
257        x = ( xo >> 16 ) + ( jrand() >> s ) - xm;
258        y = ( yo >> 16 ) + ( jrand() >> s ) - ym;
[518]259        // FIXME: these clip values seemed wrong to me before the GetClip
260        // refactoring.
261        if( !( x <= cx1 || y <= cy1 || x >= cx2 - 1 || y >= cy2 - 1) )
[115]262        {
263            addr = screen->scan_line( y ) + x;
264            *addr = c1;
265            *(addr + w) = c2;
266            *(addr - w) = c2;
267            *(addr - 1) = c2;
268            *(addr + 1) = c2;
269        }
270        xo += dx;
271        yo += dy;
272    }
273
[515]274    screen->Unlock();
[2]275}
[115]276
Note: See TracBrowser for help on using the repository browser.