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

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

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

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