source: abuse/trunk/src/endgame.cpp

Last change on this file was 682, checked in by Sam Hocevar, 8 years ago

core: rename vec2i to ivec2 and update matrix.h from Lol Engine.

File size: 13.4 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, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <math.h>
16
17#include "common.h"
18
19#include "menu.h"
20#include "lisp.h"
21#include "game.h"
22#include "timing.h"
23#include "game.h"
24#include "id.h"
25#include "pmenu.h"
26#include "gui.h"
27#include "property.h"
28#include "dev.h"
29#include "clisp.h"
30#include "dprint.h"
31#include "jrand.h"
32#include "director.h"
33#include "lisp_gc.h"
34
35extern palette *old_pal;
36
37struct mask_line
38{
39  int x,size;
40  uint16_t *remap;
41  uint8_t *light;
42} ;
43
44
45extern int text_draw(int y, int x1, int y1, int x2, int y2, char const *buf, JCFont *font, uint8_t *cmap, char color);
46
47static mask_line *make_mask_lines(image *mask, int map_width)
48{
49  mask_line *p=(mask_line *)malloc(mask->Size().y*sizeof(mask_line));
50  for (int y=0; y<mask->Size().y; y++)
51  {
52    // find the start of the run..
53    uint8_t *sl=mask->scan_line(y);
54    int x=0;
55    while (*sl==0) { sl++; x++; }
56    p[y].x=x;
57
58
59    // find the length of the run
60    int size=0;
61    uint8_t *sl_start=sl;
62    while (*sl!=0 && x<mask->Size().x) { sl++; x++; size++; }
63    p[y].size=size;
64
65    // now calculate remap for line
66    p[y].remap=(uint16_t *)malloc(size * 2);
67    p[y].light=(uint8_t *)malloc(size);
68    uint16_t *rem=p[y].remap;
69    uint8_t *lrem=p[y].light;
70    for (x=0; x<size; x++,rem++)
71    {
72      *(lrem++)=*(sl_start++);
73/*      if (x==size/2 || x==size/2-1 || x==size/2+1)
74        *rem=(int)(sqrt(0.5)*map_width/2.0);
75      else*/
76      if (x<=size/2)
77        *rem=(int)(sqrt(x/(double)(size*2.0))*map_width/2.0);
78      else
79        *rem=map_width/2-(int)(sqrt((size-x)/(double)(size*2.0))*map_width/2.0);
80
81//      (int)(mask->Size().x-(sqrt((size-x)/(double)size)*map_width/2.0)+mask->Size().x/2);
82    }
83  }
84  return p;
85}
86
87
88void scan_map(image *screen, int sx, int sy, image *im1, image *im2, int fade256, int32_t *paddr, mask_line *p, int mask_height,
89          int xoff, int coff)
90{
91  int x1=10000,x2=0;
92  int iw=im1->Size().x;
93  uint16_t r,off;
94  int y=0;
95  uint8_t *l;
96
97  for (; y<mask_height; y++)
98  {
99    mask_line *n=p+y;
100    uint8_t *sl=screen->scan_line(y+sy)+sx+n->x;
101    uint8_t *sl2=im1->scan_line(y);
102    uint8_t *sl3=im2->scan_line(y);
103    l=n->light;
104    uint16_t *rem=n->remap;
105    if (sx+n->x<x1) x1=sx+n->x;
106    int x=0;
107    for (; x<n->size; x++,sl++,rem++,l++)
108    {
109      r=*rem;
110
111      off=(r+xoff);
112      if (off>=iw) off-=iw;
113
114      int32_t p1=*(paddr+sl2[off]);
115      int32_t p2=*(paddr+sl3[off]);
116
117      int r1=p1>>16,g1=(p1>>8)&0xff,b1=p1&0xff;
118      int r2=p2>>16,g2=(p2>>8)&0xff,b2=p2&0xff;
119      int r3=r1+(r2-r1)*fade256/256,
120          g3=g1+(g2-g1)*fade256/256,
121          b3=b1+(b2-b1)*fade256/256;
122
123      uint8_t c=color_table->Lookup(r3>>3,g3>>3,b3>>3);
124
125      *sl=*(white_light+((*l)/2+28+jrand()%4)*256+c);
126
127    }
128    if (sx+n->x+x>x2) x2=sx+n->x+x;
129
130  }
131  screen->AddDirty(ivec2(x1, sy), ivec2(x2 + 1, sy + mask_height));
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/fore/endgame.spe","planet",SPEC_IMAGE,1);
153  int planet2=cache.reg("art/fore/endgame.spe","dead_planet",SPEC_IMAGE,1);
154  int mask=cache.reg("art/fore/endgame.spe","mask",SPEC_IMAGE,1);
155  int ship=cache.reg("art/fore/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(ivec2(2)); blank.clear();
184  wm->SetMouseShape(blank.copy(), ivec2(0, 0));      // don't show mouse
185
186
187  main_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    main_screen->PutPixel(ivec2(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(main_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      main_screen->clear();
234      int j;
235      for (si=sinfo,j=0; j<800; j++,si+=3)
236        main_screen->PutPixel(ivec2(dx+si[0],dy+si[1]),si[2]);
237
238      if (i>=30 && i<=37)
239      {
240    tcopy->PutImage(cache.img(planet), ivec2(0, 0));
241    cache.fig(explo_frames1[i-30])->forward->PutImage(tcopy,ivec2(100,50));
242        scan_map(main_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(main_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,main_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      main_screen->clear();
286      int j;
287      for (si=sinfo,j=0; j<800; j++,si+=3)
288        main_screen->PutPixel(ivec2(dx+si[0],dy+si[1]),si[2]);
289
290
291      scan_map(main_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->PutImage(main_screen,ivec2(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  main_screen->clear();
340  int j;
341  for (si=sinfo,j=0; j<800; j++,si+=3)
342    main_screen->PutPixel(ivec2(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(main_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->IsPending())
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    main_screen->clear();
384    int j;
385    for (si=sinfo,j=0; j<800; j++,si+=3)
386      main_screen->PutPixel(ivec2(dx+si[0],dy+si[1]),si[2]);
387
388    scan_map(main_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->IsPending() && 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  main_screen->clear();
415
416  wm->SetMouseShape(cache.img(c_normal)->copy(), ivec2(1, 1));
417  the_game->set_state(MENU_STATE);
418}
419
420void show_sell(int abortable);
421
422void share_end()
423{
424  fade_out(16);
425  image blank(ivec2(2, 2)); blank.clear();
426  wm->SetMouseShape(blank.copy(), ivec2(0, 0)); // don't show mouse
427  main_screen->clear();
428
429  image *im=cache.img(cache.reg("art/fore/endgame.spe","tbc",SPEC_IMAGE,1));
430
431  void *to_be = LSymbol::FindOrCreate("to_be_continued")->GetValue();
432  PtrRef r1(to_be);
433
434  void *mid_plot = LSymbol::FindOrCreate("plot_middle")->GetValue();
435  PtrRef r2(mid_plot);
436
437  int dx=(xres+1)/2-im->Size().x/2,dy=(yres+1)/2-im->Size().y/2;
438  main_screen->PutImage(im, ivec2(dx, dy));
439  console_font->PutString(main_screen, ivec2(xres / 2 + 35, yres / 2 + 100 - console_font->Size().y - 2),
440               lstring_value(to_be));
441  fade_in(NULL,32);
442
443  uint8_t cmap[32];
444  int i;
445  for (i=0; i<32; i++)
446    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
447
448  Event ev; ev.type=EV_SPURIOUS;
449  time_marker start;
450  for (i=0; i<320 && ev.type!=EV_KEY; i++)
451  {
452    main_screen->PutImage(im, ivec2(dx, dy));
453    console_font->PutString(main_screen, ivec2(xres / 2 + 35, yres / 2 + 100 - console_font->Size().y - 2),
454               lstring_value(to_be));
455
456    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(mid_plot),wm->font(),cmap,wm->bright_color());
457    wm->flush_screen();
458    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
459    while (wm->IsPending() && ev.type!=EV_KEY) wm->get_event(ev);
460  }
461
462  if (ev.type!=EV_KEY)
463  {
464    do
465    {
466      wm->flush_screen();
467      wm->get_event(ev);
468    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
469  }
470
471  fade_out(16);
472  wm->SetMouseShape(blank.copy(), ivec2(0, 0)); // don't show mouse
473  show_sell(1);
474  wm->Push(new Event(ID_SHOW_SELL,NULL));
475}
476
477
478void show_end()
479{
480  fade_out(16);
481  image blank(ivec2(2, 2)); blank.clear();
482  wm->SetMouseShape(blank.copy(), ivec2(0, 0));      // don't show mouse
483  main_screen->clear();
484
485  image *im=cache.img(cache.reg("art/fore/endgame.spe","end.pcx",SPEC_IMAGE,1));
486
487  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
488
489  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
490  PtrRef r2(end_plot);
491
492
493  fade_in(im,32);
494
495  uint8_t cmap[32];
496  int i;
497  for (i=0; i<32; i++)
498    cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
499
500  Event ev; ev.type=EV_SPURIOUS;
501  time_marker start;
502  for (i=0; i<320 && ev.type!=EV_KEY; i++)
503  {
504    main_screen->PutImage(im, ivec2(dx, dy));
505
506    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
507    wm->flush_screen();
508    time_marker now; while (now.diff_time(&start)<0.18) now.get_time(); start.get_time();
509    while (wm->IsPending() && ev.type!=EV_KEY) wm->get_event(ev);
510  }
511
512  if (ev.type!=EV_KEY)
513  {
514    do
515    {
516      wm->flush_screen();
517      wm->get_event(ev);
518    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
519  }
520
521  delete current_level;
522  current_level=NULL;
523
524  fade_out(16);
525  main_screen->clear();
526
527  show_sell(1);
528
529  wm->SetMouseShape(cache.img(c_normal)->copy(), ivec2(1, 1));
530  the_game->set_state(MENU_STATE);
531}
532
Note: See TracBrowser for help on using the repository browser.