source: abuse/trunk/src/endgame.cpp @ 512

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

imlib: use vec2i for image::size and unroll all necessary changes
everywhere else in the code.

File size: 13.1 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 or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include <math.h>
14
15#include "common.h"
16
17#include "menu.h"
18#include "lisp.h"
19#include "game.h"
20#include "timing.h"
21#include "game.h"
22#include "id.h"
23#include "pmenu.h"
24#include "gui.h"
25#include "property.h"
26#include "dev.h"
27#include "clisp.h"
28#include "dprint.h"
29#include "jrand.h"
30#include "director.h"
31#include "lisp_gc.h"
32
33extern palette *old_pal;
34
35struct mask_line
36{
37  int x,size;
38  uint16_t *remap;
39  uint8_t *light;
40} ;
41
42
43extern int text_draw(int y, int x1, int y1, int x2, int y2, char const *buf, JCFont *font, uint8_t *cmap, char color);
44
45static mask_line *make_mask_lines(image *mask, int map_width)
46{
47  mask_line *p=(mask_line *)malloc(mask->Size().y*sizeof(mask_line));
48  for (int y=0; y<mask->Size().y; y++)
49  {
50    // find the start of the run..
51    uint8_t *sl=mask->scan_line(y);
52    int x=0;
53    while (*sl==0) { sl++; x++; }
54    p[y].x=x;
55
56
57    // find the length of the run
58    int size=0;
59    uint8_t *sl_start=sl;
60    while (*sl!=0 && x<mask->Size().x) { sl++; x++; size++; }
61    p[y].size=size;
62
63    // now calculate remap for line
64    p[y].remap=(uint16_t *)malloc(size * 2);
65    p[y].light=(uint8_t *)malloc(size);
66    uint16_t *rem=p[y].remap;
67    uint8_t *lrem=p[y].light;
68    for (x=0; x<size; x++,rem++)
69    {
70      *(lrem++)=*(sl_start++);
71/*      if (x==size/2 || x==size/2-1 || x==size/2+1)
72        *rem=(int)(sqrt(0.5)*map_width/2.0);
73      else*/
74      if (x<=size/2)
75        *rem=(int)(sqrt(x/(double)(size*2.0))*map_width/2.0);
76      else
77        *rem=map_width/2-(int)(sqrt((size-x)/(double)(size*2.0))*map_width/2.0);
78
79//      (int)(mask->Size().x-(sqrt((size-x)/(double)size)*map_width/2.0)+mask->Size().x/2);
80    }
81  }
82  return p;
83}
84
85
86void scan_map(image *screen, int sx, int sy, image *im1, image *im2, int fade256, int32_t *paddr, mask_line *p, int mask_height,
87          int xoff, int coff)
88{
89  int x1=10000,x2=0;
90  int iw=im1->Size().x;
91  uint16_t r,off;
92  int y=0;
93  uint8_t *l;
94
95  for (; y<mask_height; y++)
96  {
97    mask_line *n=p+y;
98    uint8_t *sl=screen->scan_line(y+sy)+sx+n->x;
99    uint8_t *sl2=im1->scan_line(y);
100    uint8_t *sl3=im2->scan_line(y);
101    l=n->light;
102    uint16_t *rem=n->remap;
103    if (sx+n->x<x1) x1=sx+n->x;
104    int x=0;
105    for (; x<n->size; x++,sl++,rem++,l++)
106    {
107      r=*rem;
108
109      off=(r+xoff);
110      if (off>=iw) off-=iw;
111
112      int32_t p1=*(paddr+sl2[off]);
113      int32_t p2=*(paddr+sl3[off]);
114
115      int r1=p1>>16,g1=(p1>>8)&0xff,b1=p1&0xff;
116      int r2=p2>>16,g2=(p2>>8)&0xff,b2=p2&0xff;
117      int r3=r1+(r2-r1)*fade256/256,
118          g3=g1+(g2-g1)*fade256/256,
119          b3=b1+(b2-b1)*fade256/256;
120
121      uint8_t c=color_table->lookup_color(r3>>3,g3>>3,b3>>3);
122
123      *sl=*(white_light+((*l)/2+28+jrand()%4)*256+c);
124
125    }
126    if (sx+n->x+x>x2) x2=sx+n->x+x;
127
128  }
129  screen->add_dirty(x1,sy,x2,sy+mask_height-1);
130
131}
132
133
134
135void fade_in(image *im, int steps);
136void fade_out(int steps);
137
138class ex_char {
139  public :
140  uint8_t frame,char_num;
141  int x,y;
142  ex_char *next;
143  ex_char (int X, int Y, int Frame, int Char_num, ex_char *Next) { x=X; y=Y; frame=Frame; char_num=Char_num; next=Next; }
144} ;
145
146void scale_put      (image *im, image *screen, int x, int y, short new_width, short new_height);
147void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height);
148
149void show_end2()
150{
151  int i;
152  int planet=cache.reg("art/endgame.spe","planet",SPEC_IMAGE,1);
153  int planet2=cache.reg("art/endgame.spe","dead_planet",SPEC_IMAGE,1);
154  int mask=cache.reg("art/endgame.spe","mask",SPEC_IMAGE,1);
155  int ship=cache.reg("art/endgame.spe","ship",SPEC_IMAGE,1);
156
157
158  int explo_snd = lnumber_value(LSymbol::FindOrCreate("P_EXPLODE_SND")->GetValue());
159  int space_snd = lnumber_value(LSymbol::FindOrCreate("SPACE_SND")->GetValue());
160  int zip_snd = lnumber_value(LSymbol::FindOrCreate("SHIP_ZIP_SND")->GetValue());
161
162
163  mask_line *p=make_mask_lines(cache.img(mask),cache.img(planet)->Size().x);
164
165  int explo_frames1[8],explo_frames2[7];
166
167  for (i=0; i<8; i++)
168  { char nm[100]; sprintf(nm,"small_wite%04d.pcx",i+1);
169    explo_frames1[i]=cache.reg("art/exp1.spe",nm,SPEC_CHARACTER,1);
170  }
171
172  for (i=0; i<7; i++)
173  { char nm[100]; sprintf(nm,"small_fire%04d.pcx",i+1);
174    explo_frames2[i]=cache.reg("art/exp1.spe",nm,SPEC_CHARACTER,1);
175  }
176
177  int eoff=0,coff=0;
178
179  int ex=xres/2-cache.img(mask)->Size().x/2;
180  int ey=yres/2-cache.img(mask)->Size().y/2;
181  fade_out(16);
182
183  image blank(2,2); blank.clear();
184  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
185
186
187  screen->clear();
188  int c[4]={ pal->find_closest(222,222,22),
189        pal->find_closest(200,200,200),
190        pal->find_closest(100,100,100),
191        pal->find_closest(64,64,64)};
192  uint16_t sinfo[800*3],*si;
193
194  for (si=sinfo,i=0; i<800; i++)
195  {
196    *(si++)=jrand()%320;
197    *(si++)=jrand()%200;
198    *(si++)=c[jrand()%4];
199    screen->putpixel(si[-3],si[-2],si[-1]);
200  }
201  int32_t paddr[256];
202  if (old_pal)
203  {
204    for (i=0; i<256; i++)
205      paddr[i]=(old_pal->red(i)<<16)|(old_pal->green(i)<<8)|(old_pal->blue(i));
206  }
207  else
208  {
209    for (i=0; i<256; i++)
210      paddr[i]=(pal->red(i)<<16)|(pal->green(i)<<8)|(pal->blue(i));
211  }
212
213  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
214
215
216  scan_map(screen,ex,ey,cache.img(planet),cache.img(planet2),0,paddr,p,cache.img(mask)->Size().y,eoff,coff);
217  image *tcopy=cache.img(planet)->copy();
218  fade_in(NULL,32);
219
220  time_marker old_time;
221
222
223
224  for (i=0; i<80; )
225  {
226    time_marker new_time;
227    if (new_time.diff_time(&old_time)>0.1)
228    {
229      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
230        cache.sfx(space_snd)->play(64);
231
232      old_time.get_time();
233      screen->clear();
234      int j;
235      for (si=sinfo,j=0; j<800; j++,si+=3)
236        screen->putpixel(dx+si[0],dy+si[1],si[2]);
237
238      if (i>=30 && i<=37)
239      {
240    cache.img(planet)->put_image(tcopy,0,0);
241    cache.fig(explo_frames1[i-30])->forward->put_image(tcopy,100,50);
242        scan_map(screen,ex,ey,tcopy,
243           cache.img(planet2),
244           0,paddr,
245           p,cache.img(mask)->Size().y,eoff,coff);
246      }
247      else
248        scan_map(screen,ex,ey,cache.img(planet),
249           cache.img(planet2),
250           0,paddr,
251           p,cache.img(mask)->Size().y,eoff,coff);
252      if (i>38)
253      {
254    int t=i-38;
255    image *s=cache.img(ship);
256    int nw=s->Size().x*(t+2)/16,
257        nh=s->Size().y*(t+2)/16;
258
259
260        scale_put_trans(s,screen,ex-(i-38)*5,ey+cache.img(mask)->Size().y/2+t*4,nw,nh);
261    if (i==77)
262      if (sound_avail&SFX_INITIALIZED)
263            cache.sfx(zip_snd)->play(127);
264      }
265
266      eoff+=2; if (eoff>=320) eoff-=320;
267      coff+=1; if (coff>=320) coff-=320;
268      wm->flush_screen();
269      i++;
270    }
271  }
272  delete tcopy;
273
274
275  ex_char *clist=NULL;
276  for (i=0; i<200; )
277  {
278    time_marker new_time;
279    if (new_time.diff_time(&old_time)>0.1)
280    {
281      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
282        cache.sfx(space_snd)->play(64);
283
284      old_time.get_time();
285      screen->clear();
286      int j;
287      for (si=sinfo,j=0; j<800; j++,si+=3)
288        screen->putpixel(dx+si[0],dy+si[1],si[2]);
289
290
291      scan_map(screen,ex,ey,cache.img(planet),
292           cache.img(planet2),i*256/200,paddr,p,cache.img(mask)->Size().y,eoff,coff);
293
294      eoff+=2; if (eoff>=320) eoff-=320;
295      coff+=1; if (coff>=320) coff-=320;
296
297      i++;
298      if (i<150 || (i<170 && ((i-149)%2)==0) || (i<180 && ((i-149)%4)==0) || (i<190 && ((i-149)%8)==0))
299      {
300        clist=new ex_char(ex+jrand()%(cache.img(mask)->Size().x-cache.img(mask)->Size().x/3),
301            ey+jrand()%(cache.img(mask)->Size().y-cache.img(mask)->Size().y/3),0,1,clist);
302    if (sound_avail&SFX_INITIALIZED)
303          cache.sfx(explo_snd)->play(127);
304      }
305
306//      clist=new ex_char(ex+jrand()%(cache.img(mask)->Size().x,
307//            ey+jrand()%(cache.img(mask)->Size().y,0,1,clist);
308
309      ex_char *c=clist,*last=NULL;
310      for (; c; )
311      {
312    c->frame++;
313    if (c->frame>6)
314    {
315      ex_char *d=c;
316      if (last) last->next=c->next;
317      else clist=c->next;
318      c=c->next;
319      delete d;
320    } else
321    {
322      last=c;
323      if (c->char_num)
324        cache.fig(explo_frames2[c->frame])->forward->put_image(screen,c->x,c->y);
325
326      c->x-=3;
327      c=c->next;
328    }
329      }
330
331      wm->flush_screen();
332
333    }
334
335
336  }
337  while (clist) { ex_char *p=clist; clist=clist->next; delete p; }
338
339  screen->clear();
340  int j;
341  for (si=sinfo,j=0; j<800; j++,si+=3)
342    screen->putpixel(si[0],si[1],si[2]);
343
344  event ev;
345  i=0;
346  do
347  {
348    time_marker new_time;
349    if (new_time.diff_time(&old_time)>0.1)
350    {
351      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
352        cache.sfx(space_snd)->play(64);
353
354      old_time.get_time();
355      scan_map(screen,ex,ey,cache.img(planet),
356           cache.img(planet2),
357           256,paddr,
358           p,cache.img(mask)->Size().y,eoff,coff);
359      eoff+=2; if (eoff>=320) eoff-=320;
360      coff+=1; if (coff>=320) coff-=320;
361      wm->flush_screen();
362      i++;
363    }
364
365    if (wm->event_waiting())
366      wm->get_event(ev);
367
368  } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
369
370
371  uint8_t cmap[32];
372  for (i=0; i<32; i++)
373    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
374
375  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
376
377
378  time_marker start;
379
380  ev.type=EV_SPURIOUS;
381  for (i=0; i<320 && ev.type!=EV_KEY; i++)
382  {
383    screen->clear();
384    int j;
385    for (si=sinfo,j=0; j<800; j++,si+=3)
386      screen->putpixel(dx+si[0],dy+si[1],si[2]);
387
388    scan_map(screen,ex,ey,cache.img(planet),
389         cache.img(planet2),
390         256,paddr,
391         p,cache.img(mask)->Size().y,eoff,coff);
392    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
393    wm->flush_screen();
394    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
395
396    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
397  }
398
399
400
401  for (i=0; i<cache.img(mask)->Size().y; i++)
402  {
403    free(p[i].remap);
404    free(p[i].light);
405  }
406
407  free(p);
408
409
410  delete current_level;
411  current_level=NULL;
412
413  fade_out(16);
414  screen->clear();
415
416
417  wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
418  the_game->set_state(MENU_STATE);
419}
420
421void show_sell(int abortable);
422
423void share_end()
424{
425  fade_out(16);
426  image blank(2,2); blank.clear();
427  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
428  screen->clear();
429
430  image *im=cache.img(cache.reg("art/endgame.spe","tbc",SPEC_IMAGE,1));
431
432  void *to_be = LSymbol::FindOrCreate("to_be_continued")->GetValue();
433  PtrRef r1(to_be);
434
435  void *mid_plot = LSymbol::FindOrCreate("plot_middle")->GetValue();
436  PtrRef r2(mid_plot);
437
438  int dx=(xres+1)/2-im->Size().x/2,dy=(yres+1)/2-im->Size().y/2;
439  im->put_image(screen,dx,dy);
440  console_font->put_string(screen,xres/2+35,yres/2+100-console_font->height()-2,
441               lstring_value(to_be));
442  fade_in(NULL,32);
443
444  uint8_t cmap[32];
445  int i;
446  for (i=0; i<32; i++)
447    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
448
449  event ev; ev.type=EV_SPURIOUS;
450  time_marker start;
451  for (i=0; i<320 && ev.type!=EV_KEY; i++)
452  {
453    im->put_image(screen,dx,dy);
454    console_font->put_string(screen,xres/2+35,yres/2+100-console_font->height()-2,
455               lstring_value(to_be));
456
457    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(mid_plot),wm->font(),cmap,wm->bright_color());
458    wm->flush_screen();
459    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
460    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
461  }
462
463  if (ev.type!=EV_KEY)
464  {
465    do
466    {
467      wm->flush_screen();
468      wm->get_event(ev);
469    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
470  }
471
472  fade_out(16);
473  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
474  show_sell(1);
475  wm->push_event(new event(ID_SHOW_SELL,NULL));
476}
477
478
479void show_end()
480{
481  fade_out(16);
482  image blank(2,2); blank.clear();
483  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
484  screen->clear();
485
486  image *im=cache.img(cache.reg("art/endgame.spe","end.pcx",SPEC_IMAGE,1));
487
488  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
489
490  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
491  PtrRef r2(end_plot);
492
493
494  fade_in(im,32);
495
496  uint8_t cmap[32];
497  int i;
498  for (i=0; i<32; i++)
499    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
500
501  event ev; ev.type=EV_SPURIOUS;
502  time_marker start;
503  for (i=0; i<320 && ev.type!=EV_KEY; i++)
504  {
505    im->put_image(screen,dx,dy);
506
507    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
508    wm->flush_screen();
509    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
510    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
511  }
512
513  if (ev.type!=EV_KEY)
514  {
515    do
516    {
517      wm->flush_screen();
518      wm->get_event(ev);
519    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
520  }
521
522  delete current_level;
523  current_level=NULL;
524
525  fade_out(16);
526  screen->clear();
527
528  show_sell(1);
529
530  wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
531  the_game->set_state(MENU_STATE);
532}
533
Note: See TracBrowser for help on using the repository browser.