source: abuse/branches/lol/src/endgame.cpp @ 732

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

build: SDL2 compilation fixes.

File size: 13.3 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2013 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 HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <math.h>
16
17#include "common.h"
18
19#include "lisp/lisp.h"
20#include "lisp/lisp_gc.h"
21
22#include "imlib/pmenu.h"
23#include "imlib/dprint.h"
24
25#include "menu.h"
26#include "game.h"
27#include "game.h"
28#include "id.h"
29#include "gui.h"
30#include "property.h"
31#include "dev.h"
32#include "clisp.h"
33#include "director.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(AImage *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)(lol::sqrt(0.5)*map_width/2.0);
75      else*/
76      if (x<=size/2)
77        *rem=(int)(lol::sqrt(x/(double)(size*2.0))*map_width/2.0);
78      else
79        *rem=map_width/2-(int)(lol::sqrt((size-x)/(double)(size*2.0))*map_width/2.0);
80
81//      (int)(mask->Size().x-(lol::sqrt((size-x)/(double)size)*map_width/2.0)+mask->Size().x/2);
82    }
83  }
84  return p;
85}
86
87
88void scan_map(AImage *screen, int sx, int sy, AImage *im1, AImage *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(u8vec3(r3 >> 3, g3 >> 3, b3 >> 3));
124
125      *sl=*(white_light+((*l)/2+28+rand(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(AImage *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      (AImage *im, AImage *screen, int x, int y, short new_width, short new_height);
147void scale_put_trans(AImage *im, AImage *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  AImage 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] =
189  {
190    g_palette->FindClosest(u8vec3(222, 222, 22)),
191    g_palette->FindClosest(u8vec3(200, 200, 200)),
192    g_palette->FindClosest(u8vec3(100, 100, 100)),
193    g_palette->FindClosest(u8vec3(64, 64, 64))
194  };
195  uint16_t sinfo[800*3],*si;
196
197  for (si=sinfo,i=0; i<800; i++)
198  {
199    *(si++)= rand(320);
200    *(si++)= rand(200);
201    *(si++)=c[rand(4)];
202    main_screen->PutPixel(ivec2(si[-3],si[-2]),si[-1]);
203  }
204  int32_t paddr[256];
205  if (old_pal)
206  {
207    for (i=0; i<256; i++)
208      paddr[i] = (old_pal->GetColor(i).r << 16)
209               | (old_pal->GetColor(i).g << 8)
210               | (old_pal->GetColor(i).b);
211  }
212  else
213  {
214    for (i=0; i<256; i++)
215      paddr[i] = (g_palette->GetColor(i).r << 16)
216               | (g_palette->GetColor(i).g << 8)
217               | (g_palette->GetColor(i).b);
218  }
219
220  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
221
222
223  scan_map(main_screen,ex,ey,cache.img(planet),cache.img(planet2),0,paddr,p,cache.img(mask)->Size().y,eoff,coff);
224  AImage *tcopy=cache.img(planet)->copy();
225  fade_in(NULL,32);
226
227  Timer t;
228
229
230  for (i=0; i<80; )
231  {
232    if (t.Poll() > 0.1)
233    {
234      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
235        cache.sfx(space_snd)->play(64);
236
237      t.Get();
238      main_screen->clear();
239      int j;
240      for (si=sinfo,j=0; j<800; j++,si+=3)
241        main_screen->PutPixel(ivec2(dx+si[0],dy+si[1]),si[2]);
242
243      if (i>=30 && i<=37)
244      {
245    tcopy->PutImage(cache.img(planet), ivec2(0, 0));
246    cache.fig(explo_frames1[i-30])->forward->PutImage(tcopy,ivec2(100,50));
247        scan_map(main_screen,ex,ey,tcopy,
248           cache.img(planet2),
249           0,paddr,
250           p,cache.img(mask)->Size().y,eoff,coff);
251      }
252      else
253        scan_map(main_screen,ex,ey,cache.img(planet),
254           cache.img(planet2),
255           0,paddr,
256           p,cache.img(mask)->Size().y,eoff,coff);
257      if (i>38)
258      {
259    int t=i-38;
260    AImage *s=cache.img(ship);
261    int nw=s->Size().x*(t+2)/16,
262        nh=s->Size().y*(t+2)/16;
263
264
265        scale_put_trans(s,main_screen,ex-(i-38)*5,ey+cache.img(mask)->Size().y/2+t*4,nw,nh);
266    if (i==77)
267      if (sound_avail&SFX_INITIALIZED)
268            cache.sfx(zip_snd)->play(127);
269      }
270
271      eoff+=2; if (eoff>=320) eoff-=320;
272      coff+=1; if (coff>=320) coff-=320;
273      wm->flush_screen();
274      i++;
275    }
276  }
277  delete tcopy;
278
279
280  ex_char *clist=NULL;
281  for (i=0; i<200; )
282  {
283    if (t.Poll() > 0.1)
284    {
285      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
286        cache.sfx(space_snd)->play(64);
287
288      t.Get();
289      main_screen->clear();
290      int j;
291      for (si=sinfo,j=0; j<800; j++,si+=3)
292        main_screen->PutPixel(ivec2(dx+si[0],dy+si[1]),si[2]);
293
294
295      scan_map(main_screen,ex,ey,cache.img(planet),
296           cache.img(planet2),i*256/200,paddr,p,cache.img(mask)->Size().y,eoff,coff);
297
298      eoff+=2; if (eoff>=320) eoff-=320;
299      coff+=1; if (coff>=320) coff-=320;
300
301      i++;
302      if (i<150 || (i<170 && ((i-149)%2)==0) || (i<180 && ((i-149)%4)==0) || (i<190 && ((i-149)%8)==0))
303      {
304        clist=new ex_char(ex+rand(cache.img(mask)->Size().x-cache.img(mask)->Size().x/3),
305            ey+rand(cache.img(mask)->Size().y-cache.img(mask)->Size().y/3),0,1,clist);
306    if (sound_avail&SFX_INITIALIZED)
307          cache.sfx(explo_snd)->play(127);
308      }
309
310//      clist=new ex_char(ex+rand(cache.img(mask)->Size().x,
311//            ey+rand(cache.img(mask)->Size().y,0,1,clist);
312
313      ex_char *c=clist,*last=NULL;
314      for (; c; )
315      {
316    c->frame++;
317    if (c->frame>6)
318    {
319      ex_char *d=c;
320      if (last) last->next=c->next;
321      else clist=c->next;
322      c=c->next;
323      delete d;
324    } else
325    {
326      last=c;
327      if (c->char_num)
328        cache.fig(explo_frames2[c->frame])->forward->PutImage(main_screen,ivec2(c->x,c->y));
329
330      c->x-=3;
331      c=c->next;
332    }
333      }
334
335      wm->flush_screen();
336
337    }
338
339
340  }
341  while (clist) { ex_char *p=clist; clist=clist->next; delete p; }
342
343  main_screen->clear();
344  int j;
345  for (si=sinfo,j=0; j<800; j++,si+=3)
346    main_screen->PutPixel(ivec2(si[0],si[1]),si[2]);
347
348  Event ev;
349  i=0;
350  do
351  {
352    if (t.Poll() > 0.1)
353    {
354      if ((i%10)==0 && (sound_avail&SFX_INITIALIZED))
355        cache.sfx(space_snd)->play(64);
356
357      t.Get();
358      scan_map(main_screen,ex,ey,cache.img(planet),
359           cache.img(planet2),
360           256,paddr,
361           p,cache.img(mask)->Size().y,eoff,coff);
362      eoff+=2; if (eoff>=320) eoff-=320;
363      coff+=1; if (coff>=320) coff-=320;
364      wm->flush_screen();
365      i++;
366    }
367
368    if (wm->IsPending())
369      wm->get_event(ev);
370
371  } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
372
373
374  uint8_t cmap[32];
375  for (i=0; i<32; i++)
376    cmap[i] = g_palette->FindClosest(u8vec3(i * 256 / 32, i * 256 / 32, i * 256 / 32));
377
378  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
379
380
381  t.Get();
382  ev.type=EV_SPURIOUS;
383  for (i=0; i<320 && ev.type!=EV_KEY; i++)
384  {
385    main_screen->clear();
386    int j;
387    for (si=sinfo,j=0; j<800; j++,si+=3)
388      main_screen->PutPixel(ivec2(dx+si[0],dy+si[1]),si[2]);
389
390    scan_map(main_screen,ex,ey,cache.img(planet),
391         cache.img(planet2),
392         256,paddr,
393         p,cache.img(mask)->Size().y,eoff,coff);
394    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
395    wm->flush_screen();
396    t.Wait(0.18);
397    t.Get();
398
399    while (wm->IsPending() && ev.type!=EV_KEY) wm->get_event(ev);
400  }
401
402
403
404  for (i=0; i<cache.img(mask)->Size().y; i++)
405  {
406    free(p[i].remap);
407    free(p[i].light);
408  }
409
410  free(p);
411
412
413  delete g_current_level;
414  g_current_level=NULL;
415
416  fade_out(16);
417  main_screen->clear();
418
419  wm->SetMouseShape(cache.img(c_normal)->copy(), ivec2(1, 1));
420  the_game->set_state(MENU_STATE);
421}
422
423void show_sell(int abortable);
424
425void share_end()
426{
427  fade_out(16);
428  AImage blank(ivec2(2, 2)); blank.clear();
429  wm->SetMouseShape(blank.copy(), ivec2(0, 0)); // don't show mouse
430  main_screen->clear();
431
432  AImage *im=cache.img(cache.reg("art/fore/endgame.spe","tbc",SPEC_IMAGE,1));
433
434  void *to_be = LSymbol::FindOrCreate("to_be_continued")->GetValue();
435  PtrRef r1(to_be);
436
437  void *mid_plot = LSymbol::FindOrCreate("plot_middle")->GetValue();
438  PtrRef r2(mid_plot);
439
440  int dx=(xres+1)/2-im->Size().x/2,dy=(yres+1)/2-im->Size().y/2;
441  main_screen->PutImage(im, ivec2(dx, dy));
442  console_font->PutString(main_screen, ivec2(xres / 2 + 35, yres / 2 + 100 - console_font->Size().y - 2),
443               lstring_value(to_be));
444  fade_in(NULL,32);
445
446  uint8_t cmap[32];
447  int i;
448  for (i=0; i<32; i++)
449    cmap[i] = g_palette->FindClosest(u8vec3(i * 256 / 32, i * 256 / 32, i * 256 / 32));
450
451  Event ev; ev.type=EV_SPURIOUS;
452  Timer t;
453  for (i=0; i<320 && ev.type!=EV_KEY; i++)
454  {
455    main_screen->PutImage(im, ivec2(dx, dy));
456    console_font->PutString(main_screen, ivec2(xres / 2 + 35, yres / 2 + 100 - console_font->Size().y - 2),
457               lstring_value(to_be));
458
459    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(mid_plot),wm->font(),cmap,wm->bright_color());
460    wm->flush_screen();
461    t.Wait(0.18);
462    t.Get();
463    while (wm->IsPending() && ev.type!=EV_KEY) wm->get_event(ev);
464  }
465
466  if (ev.type!=EV_KEY)
467  {
468    do
469    {
470      wm->flush_screen();
471      wm->get_event(ev);
472    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
473  }
474
475  fade_out(16);
476  wm->SetMouseShape(blank.copy(), ivec2(0, 0)); // don't show mouse
477  show_sell(1);
478  wm->Push(Event(ID_SHOW_SELL, NULL));
479}
480
481
482void show_end()
483{
484  fade_out(16);
485  AImage blank(ivec2(2, 2)); blank.clear();
486  wm->SetMouseShape(blank.copy(), ivec2(0, 0));      // don't show mouse
487  main_screen->clear();
488
489  AImage *im=cache.img(cache.reg("art/fore/endgame.spe","end.pcx",SPEC_IMAGE,1));
490
491  int dx=(xres+1)/2-320/2,dy=(yres+1)/2-200/2;
492
493  void *end_plot = LSymbol::FindOrCreate("plot_end")->GetValue();
494  PtrRef r2(end_plot);
495
496
497  fade_in(im,32);
498
499  uint8_t cmap[32];
500  int i;
501  for (i=0; i<32; i++)
502    cmap[i] = g_palette->FindClosest(u8vec3(i * 256 / 32, i * 256 / 32, i * 256 / 32));
503
504  Event ev; ev.type=EV_SPURIOUS;
505  Timer t;
506  for (i=0; i<320 && ev.type!=EV_KEY; i++)
507  {
508    main_screen->PutImage(im, ivec2(dx, dy));
509
510    text_draw(205-i,dx+10,dy,dx+319-10,dy+199,lstring_value(end_plot),wm->font(),cmap,wm->bright_color());
511    wm->flush_screen();
512    t.Wait(0.18);
513    t.Get();
514    while (wm->IsPending() && ev.type!=EV_KEY) wm->get_event(ev);
515  }
516
517  if (ev.type!=EV_KEY)
518  {
519    do
520    {
521      wm->flush_screen();
522      wm->get_event(ev);
523    } while (ev.type!=EV_KEY && ev.type!=EV_MOUSE_BUTTON);
524  }
525
526  delete g_current_level;
527  g_current_level=NULL;
528
529  fade_out(16);
530  main_screen->clear();
531
532  show_sell(1);
533
534  wm->SetMouseShape(cache.img(c_normal)->copy(), ivec2(1, 1));
535  the_game->set_state(MENU_STATE);
536}
537
Note: See TracBrowser for help on using the repository browser.