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

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

lisp: miscellaneous work on type safety.

File size: 13.0 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(LispSymbol::FindOrCreate("P_EXPLODE_SND")->GetValue());
156  int space_snd = lnumber_value(LispSymbol::FindOrCreate("SPACE_SND")->GetValue());
157  int zip_snd = lnumber_value(LispSymbol::FindOrCreate("SHIP_ZIP_SND")->GetValue());
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 = LispSymbol::FindOrCreate("plot_end")->GetValue();
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 = LispSymbol::FindOrCreate("to_be_continued")->GetValue();
430  PtrRef r1(to_be);
431
432  void *mid_plot = LispSymbol::FindOrCreate("plot_middle")->GetValue();
433  PtrRef r2(mid_plot);
434
435  int dx=(xres+1)/2-im->width()/2,dy=(yres+1)/2-im->height()/2;
436  im->put_image(screen,dx,dy);
437  console_font->put_string(screen,xres/2+35,yres/2+100-console_font->height()-2,
438               lstring_value(to_be));
439  fade_in(NULL,32);
440
441  uint8_t cmap[32];
442  int i;
443  for (i=0;i<32;i++)
444    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
445
446  event ev; ev.type=EV_SPURIOUS;
447  time_marker start;
448  for (i=0;i<320 && ev.type!=EV_KEY;i++)
449  {
450    im->put_image(screen,dx,dy);
451    console_font->put_string(screen,xres/2+35,yres/2+100-console_font->height()-2,
452               lstring_value(to_be));
453
454    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(mid_plot),wm->font(),cmap,wm->bright_color());
455    wm->flush_screen();
456    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
457    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
458  }
459
460  if (ev.type!=EV_KEY)
461  {
462    do
463    {
464      wm->flush_screen();
465      wm->get_event(ev);
466    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
467  }
468
469  fade_out(16);
470  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
471  show_sell(1);
472  wm->push_event(new event(ID_SHOW_SELL,NULL));
473}
474
475
476void show_end()
477{
478  fade_out(16);
479  image blank(2,2); blank.clear();
480  wm->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
481  screen->clear();
482
483  image *im=cache.img(cache.reg("art/endgame.spe","end.pcx",SPEC_IMAGE,1));
484
485  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
486
487  void *end_plot = LispSymbol::FindOrCreate("plot_end")->GetValue();
488  PtrRef r2(end_plot);
489
490
491  fade_in(im,32);
492
493  uint8_t cmap[32];
494  int i;
495  for (i=0;i<32;i++)
496    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
497
498  event ev; ev.type=EV_SPURIOUS;
499  time_marker start;
500  for (i=0;i<320 && ev.type!=EV_KEY;i++)
501  {
502    im->put_image(screen,dx,dy);
503
504    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
505    wm->flush_screen();
506    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
507    while (wm->event_waiting() && ev.type!=EV_KEY) wm->get_event(ev);
508  }
509
510  if (ev.type!=EV_KEY)
511  {
512    do
513    {
514      wm->flush_screen();
515      wm->get_event(ev);
516    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
517  }
518
519  delete current_level;
520  current_level=NULL;
521
522  fade_out(16);
523  screen->clear();
524
525  show_sell(1);
526
527  wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
528  the_game->set_state(MENU_STATE);
529}
530
Note: See TracBrowser for help on using the repository browser.