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

Last change on this file since 518 was 518, checked in by Sam Hocevar, 12 years ago

imlib: refactor dirty_rect clipping coordiantes so that the upper
bound is no longer inclusive. It will make things easier in the future.

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->AddDirty(x1, sy, x2 + 1, sy + mask_height);
130}
131
132
133void fade_in(image *im, int steps);
134void fade_out(int steps);
135
136class ex_char {
137  public :
138  uint8_t frame,char_num;
139  int x,y;
140  ex_char *next;
141  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; }
142} ;
143
144void scale_put      (image *im, image *screen, int x, int y, short new_width, short new_height);
145void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height);
146
147void show_end2()
148{
149  int i;
150  int planet=cache.reg("art/endgame.spe","planet",SPEC_IMAGE,1);
151  int planet2=cache.reg("art/endgame.spe","dead_planet",SPEC_IMAGE,1);
152  int mask=cache.reg("art/endgame.spe","mask",SPEC_IMAGE,1);
153  int ship=cache.reg("art/endgame.spe","ship",SPEC_IMAGE,1);
154
155
156  int explo_snd = lnumber_value(LSymbol::FindOrCreate("P_EXPLODE_SND")->GetValue());
157  int space_snd = lnumber_value(LSymbol::FindOrCreate("SPACE_SND")->GetValue());
158  int zip_snd = lnumber_value(LSymbol::FindOrCreate("SHIP_ZIP_SND")->GetValue());
159
160
161  mask_line *p=make_mask_lines(cache.img(mask),cache.img(planet)->Size().x);
162
163  int explo_frames1[8],explo_frames2[7];
164
165  for (i=0; i<8; i++)
166  { char nm[100]; sprintf(nm,"small_wite%04d.pcx",i+1);
167    explo_frames1[i]=cache.reg("art/exp1.spe",nm,SPEC_CHARACTER,1);
168  }
169
170  for (i=0; i<7; i++)
171  { char nm[100]; sprintf(nm,"small_fire%04d.pcx",i+1);
172    explo_frames2[i]=cache.reg("art/exp1.spe",nm,SPEC_CHARACTER,1);
173  }
174
175  int eoff=0,coff=0;
176
177  int ex=xres/2-cache.img(mask)->Size().x/2;
178  int ey=yres/2-cache.img(mask)->Size().y/2;
179  fade_out(16);
180
181  image blank(vec2i(2)); blank.clear();
182  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
183
184
185  screen->clear();
186  int c[4]={ pal->find_closest(222,222,22),
187        pal->find_closest(200,200,200),
188        pal->find_closest(100,100,100),
189        pal->find_closest(64,64,64)};
190  uint16_t sinfo[800*3],*si;
191
192  for (si=sinfo,i=0; i<800; i++)
193  {
194    *(si++)=jrand()%320;
195    *(si++)=jrand()%200;
196    *(si++)=c[jrand()%4];
197    screen->PutPixel(vec2i(si[-3],si[-2]),si[-1]);
198  }
199  int32_t paddr[256];
200  if (old_pal)
201  {
202    for (i=0; i<256; i++)
203      paddr[i]=(old_pal->red(i)<<16)|(old_pal->green(i)<<8)|(old_pal->blue(i));
204  }
205  else
206  {
207    for (i=0; i<256; i++)
208      paddr[i]=(pal->red(i)<<16)|(pal->green(i)<<8)|(pal->blue(i));
209  }
210
211  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
212
213
214  scan_map(screen,ex,ey,cache.img(planet),cache.img(planet2),0,paddr,p,cache.img(mask)->Size().y,eoff,coff);
215  image *tcopy=cache.img(planet)->copy();
216  fade_in(NULL,32);
217
218  time_marker old_time;
219
220
221
222  for (i=0; i<80; )
223  {
224    time_marker new_time;
225    if (new_time.diff_time(&old_time)>0.1)
226    {
227      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
228        cache.sfx(space_snd)->play(64);
229
230      old_time.get_time();
231      screen->clear();
232      int j;
233      for (si=sinfo,j=0; j<800; j++,si+=3)
234        screen->PutPixel(vec2i(dx+si[0],dy+si[1]),si[2]);
235
236      if (i>=30 && i<=37)
237      {
238    cache.img(planet)->put_image(tcopy,0,0);
239    cache.fig(explo_frames1[i-30])->forward->put_image(tcopy,100,50);
240        scan_map(screen,ex,ey,tcopy,
241           cache.img(planet2),
242           0,paddr,
243           p,cache.img(mask)->Size().y,eoff,coff);
244      }
245      else
246        scan_map(screen,ex,ey,cache.img(planet),
247           cache.img(planet2),
248           0,paddr,
249           p,cache.img(mask)->Size().y,eoff,coff);
250      if (i>38)
251      {
252    int t=i-38;
253    image *s=cache.img(ship);
254    int nw=s->Size().x*(t+2)/16,
255        nh=s->Size().y*(t+2)/16;
256
257
258        scale_put_trans(s,screen,ex-(i-38)*5,ey+cache.img(mask)->Size().y/2+t*4,nw,nh);
259    if (i==77)
260      if (sound_avail&SFX_INITIALIZED)
261            cache.sfx(zip_snd)->play(127);
262      }
263
264      eoff+=2; if (eoff>=320) eoff-=320;
265      coff+=1; if (coff>=320) coff-=320;
266      wm->flush_screen();
267      i++;
268    }
269  }
270  delete tcopy;
271
272
273  ex_char *clist=NULL;
274  for (i=0; i<200; )
275  {
276    time_marker new_time;
277    if (new_time.diff_time(&old_time)>0.1)
278    {
279      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
280        cache.sfx(space_snd)->play(64);
281
282      old_time.get_time();
283      screen->clear();
284      int j;
285      for (si=sinfo,j=0; j<800; j++,si+=3)
286        screen->PutPixel(vec2i(dx+si[0],dy+si[1]),si[2]);
287
288
289      scan_map(screen,ex,ey,cache.img(planet),
290           cache.img(planet2),i*256/200,paddr,p,cache.img(mask)->Size().y,eoff,coff);
291
292      eoff+=2; if (eoff>=320) eoff-=320;
293      coff+=1; if (coff>=320) coff-=320;
294
295      i++;
296      if (i<150 || (i<170 && ((i-149)%2)==0) || (i<180 && ((i-149)%4)==0) || (i<190 && ((i-149)%8)==0))
297      {
298        clist=new ex_char(ex+jrand()%(cache.img(mask)->Size().x-cache.img(mask)->Size().x/3),
299            ey+jrand()%(cache.img(mask)->Size().y-cache.img(mask)->Size().y/3),0,1,clist);
300    if (sound_avail&SFX_INITIALIZED)
301          cache.sfx(explo_snd)->play(127);
302      }
303
304//      clist=new ex_char(ex+jrand()%(cache.img(mask)->Size().x,
305//            ey+jrand()%(cache.img(mask)->Size().y,0,1,clist);
306
307      ex_char *c=clist,*last=NULL;
308      for (; c; )
309      {
310    c->frame++;
311    if (c->frame>6)
312    {
313      ex_char *d=c;
314      if (last) last->next=c->next;
315      else clist=c->next;
316      c=c->next;
317      delete d;
318    } else
319    {
320      last=c;
321      if (c->char_num)
322        cache.fig(explo_frames2[c->frame])->forward->put_image(screen,c->x,c->y);
323
324      c->x-=3;
325      c=c->next;
326    }
327      }
328
329      wm->flush_screen();
330
331    }
332
333
334  }
335  while (clist) { ex_char *p=clist; clist=clist->next; delete p; }
336
337  screen->clear();
338  int j;
339  for (si=sinfo,j=0; j<800; j++,si+=3)
340    screen->PutPixel(vec2i(si[0],si[1]),si[2]);
341
342  event ev;
343  i=0;
344  do
345  {
346    time_marker new_time;
347    if (new_time.diff_time(&old_time)>0.1)
348    {
349      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
350        cache.sfx(space_snd)->play(64);
351
352      old_time.get_time();
353      scan_map(screen,ex,ey,cache.img(planet),
354           cache.img(planet2),
355           256,paddr,
356           p,cache.img(mask)->Size().y,eoff,coff);
357      eoff+=2; if (eoff>=320) eoff-=320;
358      coff+=1; if (coff>=320) coff-=320;
359      wm->flush_screen();
360      i++;
361    }
362
363    if (wm->event_waiting())
364      wm->get_event(ev);
365
366  } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
367
368
369  uint8_t cmap[32];
370  for (i=0; i<32; i++)
371    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
372
373  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
374
375
376  time_marker start;
377
378  ev.type=EV_SPURIOUS;
379  for (i=0; i<320 && ev.type!=EV_KEY; i++)
380  {
381    screen->clear();
382    int j;
383    for (si=sinfo,j=0; j<800; j++,si+=3)
384      screen->PutPixel(vec2i(dx+si[0],dy+si[1]),si[2]);
385
386    scan_map(screen,ex,ey,cache.img(planet),
387         cache.img(planet2),
388         256,paddr,
389         p,cache.img(mask)->Size().y,eoff,coff);
390    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
391    wm->flush_screen();
392    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
393
394    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
395  }
396
397
398
399  for (i=0; i<cache.img(mask)->Size().y; i++)
400  {
401    free(p[i].remap);
402    free(p[i].light);
403  }
404
405  free(p);
406
407
408  delete current_level;
409  current_level=NULL;
410
411  fade_out(16);
412  screen->clear();
413
414
415  wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
416  the_game->set_state(MENU_STATE);
417}
418
419void show_sell(int abortable);
420
421void share_end()
422{
423  fade_out(16);
424  image blank(vec2i(2, 2)); blank.clear();
425  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
426  screen->clear();
427
428  image *im=cache.img(cache.reg("art/endgame.spe","tbc",SPEC_IMAGE,1));
429
430  void *to_be = LSymbol::FindOrCreate("to_be_continued")->GetValue();
431  PtrRef r1(to_be);
432
433  void *mid_plot = LSymbol::FindOrCreate("plot_middle")->GetValue();
434  PtrRef r2(mid_plot);
435
436  int dx=(xres+1)/2-im->Size().x/2,dy=(yres+1)/2-im->Size().y/2;
437  im->put_image(screen,dx,dy);
438  console_font->put_string(screen,xres/2+35,yres/2+100-console_font->height()-2,
439               lstring_value(to_be));
440  fade_in(NULL,32);
441
442  uint8_t cmap[32];
443  int i;
444  for (i=0; i<32; i++)
445    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
446
447  event ev; ev.type=EV_SPURIOUS;
448  time_marker start;
449  for (i=0; i<320 && ev.type!=EV_KEY; i++)
450  {
451    im->put_image(screen,dx,dy);
452    console_font->put_string(screen,xres/2+35,yres/2+100-console_font->height()-2,
453               lstring_value(to_be));
454
455    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(mid_plot),wm->font(),cmap,wm->bright_color());
456    wm->flush_screen();
457    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
458    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
459  }
460
461  if (ev.type!=EV_KEY)
462  {
463    do
464    {
465      wm->flush_screen();
466      wm->get_event(ev);
467    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
468  }
469
470  fade_out(16);
471  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
472  show_sell(1);
473  wm->push_event(new event(ID_SHOW_SELL,NULL));
474}
475
476
477void show_end()
478{
479  fade_out(16);
480  image blank(vec2i(2, 2)); blank.clear();
481  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
482  screen->clear();
483
484  image *im=cache.img(cache.reg("art/endgame.spe","end.pcx",SPEC_IMAGE,1));
485
486  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
487
488  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
489  PtrRef r2(end_plot);
490
491
492  fade_in(im,32);
493
494  uint8_t cmap[32];
495  int i;
496  for (i=0; i<32; i++)
497    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
498
499  event ev; ev.type=EV_SPURIOUS;
500  time_marker start;
501  for (i=0; i<320 && ev.type!=EV_KEY; i++)
502  {
503    im->put_image(screen,dx,dy);
504
505    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
506    wm->flush_screen();
507    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
508    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
509  }
510
511  if (ev.type!=EV_KEY)
512  {
513    do
514    {
515      wm->flush_screen();
516      wm->get_event(ev);
517    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
518  }
519
520  delete current_level;
521  current_level=NULL;
522
523  fade_out(16);
524  screen->clear();
525
526  show_sell(1);
527
528  wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
529  the_game->set_state(MENU_STATE);
530}
531
Note: See TracBrowser for help on using the repository browser.