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

Last change on this file since 60 was 60, checked in by Sam Hocevar, 12 years ago
  • Make a few symbols static (Ref #7).
File size: 12.9 KB
RevLine 
[56]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
[2]14#include "menu.hpp"
15#include "lisp.hpp"
16#include "game.hpp"
17#include "timing.hpp"
18#include "game.hpp"
19#include "id.hpp"
20#include "pmenu.hpp"
21#include "gui.hpp"
22#include "property.hpp"
23#include "dev.hpp"
24#include "clisp.hpp"
25#include "dprint.hpp"
26#include "jrand.hpp"
27#include "director.hpp"
28#include "lisp_gc.hpp"
29
30extern palette *old_pal;
31
32struct mask_line
33{
34  int x,size;
[17]35  uint16_t *remap;
36  uint8_t *light;
[2]37} ;
38
39
[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);
[2]41
[60]42static mask_line *make_mask_lines(image *mask, int map_width)
[2]43{
44  mask_line *p=(mask_line *)jmalloc(mask->height()*sizeof(mask_line),"mask_line");
45  for (int y=0;y<mask->height();y++)
46  {
47    // find the start of the run..
[17]48    uint8_t *sl=mask->scan_line(y);   
[2]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;
[17]56    uint8_t *sl_start=sl;
[2]57    while (*sl!=0 && x<mask->width()) { sl++; x++; size++; }
58    p[y].size=size;
59
60    // now calculate remap for line
[17]61    p[y].remap=(uint16_t *)jmalloc(size*2,"mask remap");
62    p[y].light=(uint8_t *)jmalloc(size,"mask light");
63    uint16_t *rem=p[y].remap;
64    uint8_t *lrem=p[y].light;
[2]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
[17]83void scan_map(image *screen, int sx, int sy, image *im1, image *im2, int fade256, int32_t *paddr, mask_line *p, int mask_height,
[2]84              int xoff, int coff)
85
86  int x1=10000,x2=0;
87  int iw=im1->width(); 
[17]88  uint16_t r,off;
[2]89  int y=0;
[17]90  uint8_t *l;
[2]91
92  for (;y<mask_height;y++)
93  {
94    mask_line *n=p+y;
[17]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);
[2]98    l=n->light;
[17]99    uint16_t *rem=n->remap;
[2]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
[17]109      int32_t p1=*(paddr+sl2[off]);
110      int32_t p2=*(paddr+sl3[off]);
[2]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
[17]118      uint8_t c=color_table->lookup_color(r3>>3,g3>>3,b3>>3);
[2]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 :
[17]137  uint8_t frame,char_num;
[2]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=cash.reg("art/endgame.spe","planet",SPEC_IMAGE,1);
150  int planet2=cash.reg("art/endgame.spe","dead_planet",SPEC_IMAGE,1);
151  int mask=cash.reg("art/endgame.spe","mask",SPEC_IMAGE,1);
152  int ship=cash.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(cash.img(mask),cash.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]=cash.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]=cash.reg("art/exp1.spe",nm,SPEC_CHARACTER,1);
172  }
173
174  int eoff=0,coff=0;
175
176  int ex=xres/2-cash.img(mask)->width()/2;
177  int ey=yres/2-cash.img(mask)->height()/2;
178  fade_out(16);
179
180  image blank(2,2); blank.clear();
181  eh->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)};
[17]189  uint16_t sinfo[800*3],*si;
[2]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  }
[17]198  int32_t paddr[256];
[2]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,cash.img(planet),cash.img(planet2),0,paddr,p,cash.img(mask)->height(),eoff,coff);     
214  image *tcopy=cash.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        cash.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        cash.img(planet)->put_image(tcopy,0,0);
238        cash.fig(explo_frames1[i-30])->forward->put_image(tcopy,100,50);
239        scan_map(screen,ex,ey,tcopy,
240               cash.img(planet2),
241               0,paddr,
242               p,cash.img(mask)->height(),eoff,coff);     
243      }
244      else
245        scan_map(screen,ex,ey,cash.img(planet),
246               cash.img(planet2),
247               0,paddr,
248               p,cash.img(mask)->height(),eoff,coff);     
249      if (i>38)
250      {
251        int t=i-38;
252        image *s=cash.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+cash.img(mask)->height()/2+t*4,nw,nh);
258        if (i==77)
259          if (sound_avail&SFX_INITIALIZED)
260            cash.sfx(zip_snd)->play(127);
261      }
262       
263      eoff+=2; if (eoff>=320) eoff-=320;
264      coff+=1; if (coff>=320) coff-=320;     
265      eh->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        cash.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,cash.img(planet),
289               cash.img(planet2),i*256/200,paddr,p,cash.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()%(cash.img(mask)->width()-cash.img(mask)->width()/3),
298                        ey+jrand()%(cash.img(mask)->height()-cash.img(mask)->height()/3),0,1,clist);
299        if (sound_avail&SFX_INITIALIZED)
300          cash.sfx(explo_snd)->play(127);
301      }
302
303//      clist=new ex_char(ex+jrand()%(cash.img(mask)->width(),
304//                      ey+jrand()%(cash.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            cash.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      eh->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        cash.sfx(space_snd)->play(64);
350
351      old_time.get_time();
352      scan_map(screen,ex,ey,cash.img(planet),
353               cash.img(planet2),
354               256,paddr,
355               p,cash.img(mask)->height(),eoff,coff);     
356      eoff+=2; if (eoff>=320) eoff-=320;
357      coff+=1; if (coff>=320) coff-=320;     
358      eh->flush_screen();
359      i++;
360    }
361   
362    if (eh->event_waiting())
363      eh->get_event(ev);
364
365  } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
366
367
[17]368  uint8_t cmap[32];
[2]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,cash.img(planet),
386             cash.img(planet2),
387             256,paddr,
388             p,cash.img(mask)->height(),eoff,coff);     
389    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),eh->font(),cmap,eh->bright_color());
390    eh->flush_screen();
391    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
392
393    while (eh->event_waiting() && ev.type!=EV_KEY) eh->get_event(ev);
394  }
395
396
397
398  for (i=0;i<cash.img(mask)->height();i++)
399  {
400    jfree(p[i].remap);
401    jfree(p[i].light);
402  }
403
404  jfree(p);
405
406
407  delete current_level;
408  current_level=NULL;
409
410  fade_out(16);
411  screen->clear();
412
413
414  eh->set_mouse_shape(cash.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  eh->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
425  screen->clear();
426
427  image *im=cash.img(cash.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
[17]442  uint8_t cmap[32];
[2]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),eh->font(),cmap,eh->bright_color());
456    eh->flush_screen();
457    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
458    while (eh->event_waiting() && ev.type!=EV_KEY) eh->get_event(ev);
459  }
460
461  if (ev.type!=EV_KEY)
462  {
463    do
464    {
465      eh->flush_screen();
466      eh->get_event(ev);   
467    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
468  }
469
470  fade_out(16);
471  eh->set_mouse_shape(blank.copy(),0,0);      // don't show mouse 
472  show_sell(1);
473  eh->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  eh->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
482  screen->clear();
483
484  image *im=cash.img(cash.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
[17]494  uint8_t cmap[32];
[2]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),eh->font(),cmap,eh->bright_color());
506    eh->flush_screen();
507    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
508    while (eh->event_waiting() && ev.type!=EV_KEY) eh->get_event(ev);
509  }
510
511  if (ev.type!=EV_KEY)
512  {
513    do
514    {
515      eh->flush_screen();
516      eh->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  eh->set_mouse_shape(cash.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.