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

Last change on this file since 732 was 732, checked in by Sam Hocevar, 8 years ago

build: SDL2 compilation fixes.

File size: 5.9 KB
RevLine 
[56]1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
[724]4 *  Copyright (c) 2005-2013 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
[732]11#if HAVE_CONFIG_H
[555]12#   include "config.h"
13#endif
[56]14
[512]15#include "common.h"
16
[724]17#include "lisp/lisp.h"
18
[481]19#include "particle.h"
20#include "view.h"
21#include "cache.h"
[2]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{
[494]29  for (int i=0; i<total_pseqs; i++)
[2]30    delete pseqs[i];
31  if (total_pseqs)
[129]32    free(pseqs);
[2]33}
34
35part_frame::~part_frame()
36{
[129]37  free(data);
[2]38}
39
40void add_panim(int id, long x, long y, int dir)
41{
[687]42  ASSERT(id >= 0 && id < total_pseqs, "bad id for particle animation");
[2]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;
[115]50  }
[2]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{
[492]66  LSymbol *sym=(LSymbol *)lcar(args);
[2]67  if (item_type(sym)!=L_SYMBOL)
68  {
[493]69    ((LObject *)args)->Print();
[2]70    printf("expecting first arg to def-particle to be a symbol!\n");
71    exit(0);
72  }
[635]73  LSpace *sp = LSpace::Current;
74  LSpace::Current = &LSpace::Perm;
[484]75  sym->SetNumber(total_pseqs); // set the symbol value to the object number
[635]76  LSpace::Current = sp;
[129]77  pseqs=(part_sequence **)realloc(pseqs,sizeof(part_sequence *)*(total_pseqs+1));
[2]78
79  args=lcdr(args);
80  pseqs[total_pseqs]=new part_sequence(args);
[115]81  total_pseqs++;
[2]82  return total_pseqs;
83}
84
85extern int total_files_open;
86
87part_sequence::part_sequence(void *args)
88{
[115]89  char *fn=lstring_value(lcar(args));
[2]90  bFILE *fp=open_file(fn,"rb");
91  if (fp->open_failure())
92  {
93    delete fp;
[493]94    ((LObject *)args)->Print();
[2]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
[689]104  SpecDir sd(fp);
[2]105  delete fp;
[698]106  tframes = sd.type_total(SPEC_PARTICLE);
[129]107  frames=(int *)malloc(sizeof(int)*tframes);
[115]108
[698]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);
[2]112}
113
114part_frame::part_frame(bFILE *fp)
115{
[17]116  t=fp->read_uint32();
[129]117  data=(part *)malloc(sizeof(part)*t);
[2]118  x1=y1=100000; x2=y2=-100000;
[494]119  for (int i=0; i<t; i++)
[2]120  {
[17]121    int16_t x=fp->read_uint16();
122    int16_t y=fp->read_uint16();
[2]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;
[115]128    data[i].y=y;
129    data[i].color=fp->read_uint8();
[2]130  }
131}
132
133void tick_panims()
134{
135  part_animation *last=NULL;
[494]136  for (part_animation *p=first_anim; p; )
[2]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;
[115]148    } else
[2]149    {
150      last=p;
151      p=p->next;
152    }
153
154  }
155}
156
157void draw_panims(view *v)
158{
[494]159  for (part_animation *p=first_anim; p; p=p->next)
[2]160  {
[674]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);
[2]162  }
163}
164
[709]165void part_frame::draw(AImage *screen, int x, int y, int dir)
[2]166{
[682]167    ivec2 caa, cbb;
[665]168    screen->GetClip(caa, cbb);
[2]169
[665]170    if (x + x1 >= cbb.x || x + x2 < caa.x || y + y1 >= cbb.y || y + y2 < caa.y)
171       return;
172
[2]173  part *pon=data;
[665]174  caa.y -= y;
175  cbb.y -= y;
[2]176
177  int i=t;
[665]178  while (i && pon->y<caa.y) { pon++; i--; }
[2]179  if (!i) return ;
180  if (dir>0)
181  {
[665]182    while (i && pon->y < cbb.y)
[2]183    {
184      long dx=x-pon->x;
[665]185      if (dx >= caa.x && dx < cbb.x)
[2]186      *(screen->scan_line(pon->y+y)+dx)=pon->color;
187      i--;
188      pon++;
[115]189    }
[2]190  } else
191  {
[665]192    while (i && pon->y < cbb.y)
[2]193    {
194      long dx=pon->x+x;
[665]195      if (dx >= caa.x && dx < cbb.x)
[2]196        *(screen->scan_line(pon->y+y)+dx)=pon->color;
197      i--;
198      pon++;
[115]199    }
[2]200  }
201}
202
[682]203void ScatterLine(ivec2 p1, ivec2 p2, int c, int s)
[2]204{
[682]205    ivec2 caa, cbb;
[665]206    main_screen->GetClip(caa, cbb);
[2]207
[687]208    int t = 1 + lol::max(lol::abs(p2.x - p1.x), lol::abs(p2.y - p1.y));
[672]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;
[2]213
[672]214    int xm = (1 << s);
215    int ym = (1 << s);
216    s = (15 - s);
[2]217
[672]218    while(t--)
[115]219    {
[693]220        int x = (xo >> 16) + (rand(0x10000) >> s) - xm;
221        int y = (yo >> 16) + (rand(0x10000) >> s) - ym;
[672]222        if(!(x < caa.x || y < caa.y || x >= cbb.x || y >= cbb.y))
[115]223        {
[672]224            *(main_screen->scan_line(y) + x) = c;
[115]225        }
226        xo += dx;
227        yo += dy;
228    }
[2]229}
230
[682]231void AScatterLine(ivec2 p1, ivec2 p2, int c1, int c2, int s)
[2]232{
[682]233    ivec2 caa, cbb;
[665]234    main_screen->GetClip(caa, cbb);
[2]235
[687]236    int t = 1 + lol::max(lol::abs(p2.x - p1.x), lol::abs(p2.y - p1.y));
[672]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;
[2]241
[672]242    int xm = (1 << s);
243    int ym = (1 << s);
244    s = (15 - s);
[2]245
[643]246    int w = main_screen->Size().x;
[115]247    uint8_t *addr;
248
[672]249    while(t--)
[115]250    {
[693]251        int x = (xo >> 16) + (rand(0x10000) >> s) - xm;
252        int y = (yo >> 16) + (rand(0x10000) >> s) - ym;
[518]253        // FIXME: these clip values seemed wrong to me before the GetClip
254        // refactoring.
[672]255        if(!(x <= caa.x || y <= caa.y || x >= cbb.x - 1 || y >= cbb.y - 1))
[115]256        {
[672]257            addr = main_screen->scan_line(y) + x;
[115]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    }
[2]267}
[115]268
Note: See TracBrowser for help on using the repository browser.