source: abuse/trunk/src/scene.cpp @ 112

Last change on this file since 112 was 106, checked in by Sam Hocevar, 12 years ago
  • Rename the "eh" variable to "wm" because it's a window manager, not an event handler.
  • No longer pass the window manager to functions, there's only one.

Inspired by Win32 Abuse changelog for January 28, 2001:

  • Starting work on singleton code; will get rid of all

references to an arbitrary window_manager* because
there's only going to be one, and it's not ever
going to change.

File size: 14.7 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 <stdio.h>
13#include <stdlib.h>
14#include <ctype.h>
15#include <fcntl.h>
16
17#include "specs.hpp"
18#include "timage.hpp"
19#include "jwindow.hpp"
20#include "fonts.hpp"
21#include "timing.hpp"
22#include "scene.hpp"
23#include "game.hpp"
24#include "parse.hpp"
25#include "cache.hpp"
26
27
28class string_node
29{
30  string_node *l,*r;
31  char *n;
32public : 
33  string_node(char *Name, string_node *Left=NULL, string_node *Right=NULL)
34  { l=Left;
35    r=Right;
36    n=strcpy((char *)jmalloc(strlen(Name)+1,"string node"),Name);
37  }
38  ~string_node() { jfree(n); }               
39  char *name() { return n; }
40  string_node *left() { return l; }
41  string_node *right() { return r; }                               
42} ;
43
44
45/*class string_tree
46{
47  string_node *root;
48public :
49  string_tree() { root=NULL; }
50  void insert(char *name);
51     
52} ; */
53
54
55
56char scene_filename[100];
57
58class scene_frame
59{
60public :
61  int picture;
62  long time,xc,yc; 
63
64  scene_frame *next; 
65  scene_frame(char *&s);
66  ~scene_frame() { cash.unreg(picture); }
67} ;
68
69
70scene_frame::scene_frame(char *&s)
71{
72  char tmp_name[50];
73  expect(get_token(s,tmp_name),sWORD,s);
74
75  picture=cash.reg(scene_filename,tmp_name);
76  if (picture<0)
77  {
78    printf("Frame image not found (%s)\n",tmp_name);
79    exit(0);
80  }
81
82 
83  xc=yc=0;
84  time=-1; 
85  if (token_type(s)==sLEFT_PAREN)  // is a descriptor included?
86  {
87    next_token(s);
88   
89    xc=get_number(s);
90    if (token_type(s)!=sRIGHT_PAREN)
91    {     
92      yc=get_number(s);
93      if (token_type(s)!=sRIGHT_PAREN)
94        time=get_number(s);
95    }   
96    expect(get_token(s,tmp_name),sRIGHT_PAREN,s);   
97  }
98
99  next=NULL; 
100}
101
102
103
104class scene_sequence : public linked_node
105{
106public :   
107  char *n;
108  scene_frame *first;
109  scene_sequence *next; 
110  scene_sequence(char *&s);
111  ~scene_sequence();
112} ;
113
114
115
116scene_sequence::~scene_sequence()
117{ jfree(n);
118  while (first)
119  { scene_frame *p=first;
120    first=first->next;
121    delete p;
122  }
123}
124
125 
126scene_sequence::scene_sequence(char *&s)
127{
128  scene_frame *cur;
129  char tmp_name[50];
130  expect(token_type(s),sLEFT_PAREN,s);   
131  next_token(s);
132
133  expect(get_token(s,tmp_name),sWORD,s); 
134  n=strcpy((char *)jmalloc(strlen(tmp_name)+1,"sequence name"),tmp_name); 
135  cur=first=new scene_frame(s); 
136
137  while (token_type(s)!=sRIGHT_PAREN)   
138  {
139    cur->next=new scene_frame(s);
140    cur=cur->next;   
141
142    next=NULL; 
143  } 
144  next_token(s); 
145  next=NULL; 
146}
147
148
149class scene_sequence_list
150{
151public :
152  scene_sequence *first;
153  scene_sequence_list(char *&s); 
154  scene_sequence *get_seq(char *seq_name);
155  ~scene_sequence_list(); 
156} ;
157
158scene_sequence_list::~scene_sequence_list()
159{
160  scene_sequence *p;
161  while (first)
162  {
163    p=first;
164    first=first->next;
165    delete p;   
166  }
167
168
169scene_sequence_list::scene_sequence_list(char *&s)
170{
171  scene_sequence *cur; 
172  expect(token_type(s),sLEFT_PAREN,s);   
173  next_token(s);
174
175  cur=first=new scene_sequence(s);   
176  while (token_type(s)!=sRIGHT_PAREN)
177  {
178    cur->next=new scene_sequence(s);
179    cur=cur->next;   
180  }   
181  next_token(s); 
182}
183
184scene_sequence *scene_sequence_list::get_seq(char *seq_name)
185{
186  scene_sequence *s=first;
187  while (s && strcmp(s->n,seq_name)) s=s->next;
188  if (!s)
189  {
190    printf("No sequence named %s\n",seq_name);
191    exit(1);   
192  }
193  return s;       
194}
195
196
197class scene_character
198{
199  scene_sequence_list *seq_list;
200
201  game_object *me;
202 
203public :
204  char *n; 
205  scene_character *next;
206  scene_sequence *current_seq;   
207  scene_frame *current_frame;
208 
209  time_marker *last_frame;
210  void draw(); 
211  void area(int &x1, int &y1, int &x2, int &y2); 
212  scene_character(char *&s); 
213  void set_seq(char *seq_name)
214  { current_seq=seq_list->get_seq(seq_name); }
215  int x() { return the_game->screenx(me->x)-cash.fig(current_frame->picture)->xcfg; }       
216  int y() { return the_game->screeny(me->y)-cash.fig(current_frame->picture)->forward->height(); }
217  int next_frame();  // true if sequence is done
218  ~scene_character() { jfree(n); delete seq_list; if (last_frame) delete last_frame; }     
219} ;
220
221
222int scene_character::next_frame()
223{
224  me->x+=current_frame->xc;
225  me->y+=current_frame->yc;
226
227  current_frame=current_frame->next;        // advance the picture
228
229  if (last_frame)                           // save the time stamp, delete old one
230    delete last_frame;         
231  last_frame=new time_marker;           
232
233  if (!current_frame)                      // end of sequence?
234  {               
235    current_frame=current_seq->first;      // reset and return 1
236    return 1;
237  }
238  else return 0;
239}
240
241
242void scene_character::area(int &x1, int &y1, int &x2, int &y2)
243{
244   
245  x1=x();
246  y1=y();
247  y2=x2=0;
248 
249  scene_frame *p=current_seq->first;
250  while (p)
251  {   
252    if (x()+cash.fig(p->picture)->width()-1>x2)
253      x2=x()+cash.fig(p->picture)->width()-1;
254    if (y()+cash.fig(p->picture)->height()-1>y2)
255      y2=y()+cash.fig(p->picture)->height()-1;
256    p=p->next;
257  } 
258}
259
260
261void scene_character::draw()
262{
263  cash.fig(current_frame->picture)->forward->put_image(screen,x(),y());
264 
265}
266
267
268scene_character::scene_character(char *&s)
269{
270  char tmp[100]; 
271  expect(get_token(s,tmp),sLEFT_PAREN,s);       
272  expect(get_token(s,tmp),sWORD,s);             
273  n=strcpy((char *)jmalloc(strlen(tmp)+1,"scene character name"),tmp); 
274  expect(get_token(s,tmp),sNUMBER,s);   
275
276/*  if (atoi(tmp)==0) */
277
278  me=current_level->main_character();
279
280 
281  seq_list=new scene_sequence_list(s);         
282  current_seq=seq_list->first; 
283  current_frame=current_seq->first;
284  expect(get_token(s,tmp),sRIGHT_PAREN,s);         
285
286  last_frame=NULL;
287  next=NULL; 
288}
289
290
291class scene_character_list
292{
293public :
294  scene_character *first;
295  scene_character_list(char *&s); 
296  void inital_states(char *&s); 
297  scene_character *get(char *name);   
298 ~scene_character_list(); 
299} ;
300
301scene_character  *scene_character_list::get(char *name)
302{
303  scene_character *s=first;
304  while (s)
305  {
306    if (!strcmp(s->n,name)) return s;
307    s=s->next;
308  }
309  printf("Character %s not found!\n",name);
310  exit(1); 
311}
312
313
314scene_character_list::~scene_character_list()
315{
316  scene_character *p;
317  while (first)
318  {
319    p=first;
320    first=first->next;
321    delete p;   
322  }
323
324
325scene_character_list::scene_character_list(char *&s)
326{
327  scene_character *cur; 
328  expect(token_type(s),sLEFT_PAREN,s);   
329  next_token(s);
330
331  cur=first=new scene_character(s);
332   
333  while (token_type(s)!=sRIGHT_PAREN)
334  {
335    cur->next=new scene_character(s);
336    cur=cur->next;   
337  }   
338  next_token(s); 
339}
340
341
342void scene_character_list::inital_states(char *&s)
343{
344  char ch[50],seq[50];
345
346  do
347  {
348    expect(get_token(s,ch),sLEFT_PAREN,s); 
349    expect(get_token(s,ch),sWORD,s);     
350    expect(get_token(s,seq),sWORD,s);     
351    scene_character *c=first;
352    while (c && strcmp(c->n,ch)) c=c->next;
353    if (!c)
354    {
355      printf("No character named %s, at %s\n",ch,s);
356      exit(0);
357    } else c->set_seq(seq);       
358    expect(get_token(s,ch),sRIGHT_PAREN,s); 
359  } while (token_type(s)!=sRIGHT_PAREN);
360}
361
362class text_blocker
363{
364public : 
365  int x1,y1,x2,y2; 
366  text_blocker *next;
367  text_blocker(int X1, int Y1, int X2, int Y2, text_blocker *Next)
368  { x1=X1;
369    y1=Y1;
370    x2=X2;
371    y2=Y2;
372    next=Next;   
373  }     
374} ;
375
376
377int text_draw(int y, int x1, int y1, int x2, int y2, char const *buf,
378              text_blocker *first, JCFont *font)
379{
380  short cx1,cy1,cx2,cy2,word_size,word_len;
381  screen->get_clip(cx1,cy1,cx2,cy2);
382  screen->in_clip(x1,y1,x2,y2); 
383  int h=font->height()+2,w=font->width(),x=x1,dist;
384  y+=y1;
385  char const *word_start;
386
387  while (*buf)
388  {
389    do
390    { 
391      if (*buf=='\\' && buf[1]=='n')
392      {
393        x=x1;
394        y+=h*2;
395        buf+=2;
396      }
397     
398      // skip space
399      if (*buf==' ' || *buf=='\r' || *buf=='\n' || *buf=='\t')
400      {         
401        x+=w;
402        while (*buf==' ' || *buf=='\r' || *buf=='\n' || *buf=='\t')   // skip space until next word
403          buf++;
404      }
405
406      word_start=buf;
407      for (word_len=0,word_start=buf,word_size=0;*buf && *buf!=' ' && *buf!='\r' && *buf!='\n' &&
408           *buf!='\t' && (*buf!='\\' || buf[1]!='n');buf++,word_size+=w,word_len++);
409     
410      if (word_size<x2-x1) // make sure the word can fit on the screen
411      {
412        if (word_size+x>x2)    // does word not fit on line?
413        {
414          y+=h;                // go to next line
415          x=x1;     
416        }
417      }
418
419
420      if (y+h<y1)         // word on screen yet?
421        x+=word_size;
422
423    } while (y+h<y1);     // if not on screen yet, fetch next word
424
425/*    dist=100;
426    for (n=first;n;n=n->next)     
427    {
428      if (x<n->x1)
429        minx=(n->x1-x);
430      else if (x>n->x2)
431        minx=(x-n->x2);
432      else minx=0;
433
434      if (y<n->y1)
435        miny=(n->y1-y);
436      else if (y>n->y2)
437        miny=(y-n->y2);
438      else miny=0;
439     
440      dist=min(dist,max(minx,miny));
441    }
442     
443     
444    if (dist<=8) dist=8;
445    else if (dist>31) dist=31;      */
446
447    dist=31;
448    if (y-y1<dist)
449      if (y-y1<8) dist=8;
450      else dist=y-y1;
451    if (y2-y<dist)
452      if (y2-y<8) dist=8;
453      else dist=y2-y;         
454
455    if (y>y2) return 0;
456
457    while (word_len--)
458    {
459      font->put_char(screen,x+1,y+1,*word_start,0);
460      font->put_char(screen,x,y,*word_start,32-dist);
461      word_start++;
462      x+=w;     
463    }
464
465  }
466
467  screen->set_clip(cx1,cy1,cx2,cy2);
468  return (y<=y1); 
469}
470
471
472struct scene_data_struct       // define a name for the structure so that we can inspect in gdb
473{
474  int x1,y1,x2,y2,
475      pan_vx,pan_yv,pan_steps,
476      frame_speed,scroll_speed,pan_speed; 
477} scene_data;
478
479
480
481   
482
483void play_scene(char *script, char *filename, JCFont *font)
484{
485  char *s=script; 
486  char token[90];
487  text_blocker *text_blockers=NULL;
488
489  char *strng=(char *)jmalloc(MAX_SCROLL_DATA,"tmp token space"); 
490  strcpy(scene_filename,filename);
491 
492  int x1,y1,x2,y2,done,pan_xv=0,pan_yv=0,pan_steps=0,
493      text_loaded=0,frame_speed=100,scroll_speed=50,pan_speed=60,abort=0,text_step=-2;
494
495  short cx1,cy1,cx2,cy2; 
496
497  the_game->draw(1);
498
499  screen->get_clip(cx1,cy1,cx2,cy2);
500  screen->set_clip(the_game->viewx1,the_game->viewy1,
501                   the_game->viewx2,the_game->viewy2);
502 
503 
504 
505
506  expect(get_token(s,token),sLEFT_PAREN,s); 
507  scene_character_list cl(s);
508  int y;
509
510  do
511  {
512    expect(get_token(s,token),sLEFT_PAREN,s);   // list of transitions start
513    // ACTIONS   
514    time_marker *last_text_time=NULL;   
515    time_marker *last_pan_time=NULL;
516    do
517    {     
518      expect(get_token(s,token),sLEFT_PAREN,s);         
519      expect(get_token(s,token),sWORD,s);
520
521      if (!strcmp(token,"pan"))
522      {
523        pan_xv=get_number(s);
524        pan_yv=get_number(s);
525        pan_steps=get_number(s);
526      }
527      else if (!strcmp(token,"states"))
528        cl.inital_states(s);
529      else if (!strcmp(token,"scroll_speed"))
530        scroll_speed=get_number(s);
531      else if (!strcmp(token,"pan_speed"))
532        pan_speed=get_number(s);
533      else if (!strcmp(token,"frame_speed"))
534        frame_speed=get_number(s);     
535      else if (!strcmp(token,"text_region"))
536      {
537        x1=the_game->viewx1+get_number(s);
538        y1=the_game->viewy1+get_number(s);
539        x2=the_game->viewx1+get_number(s);
540        y2=the_game->viewy1+get_number(s);     
541        y=y2-y1;
542      } else if (!strcmp(token,"text_block"))
543      {
544        int sx1=get_number(s)+the_game->viewx1;
545        int sy1=get_number(s)+the_game->viewy1;
546        int sx2=get_number(s)+the_game->viewx1;
547        int sy2=get_number(s)+the_game->viewy1;
548        text_blockers=new text_blocker(sx1,sy1,sx2,sy2,text_blockers);
549      } else if (!strcmp(token,"block"))
550      {
551        int sx1,sy1,sx2,sy2;
552        expect(get_token(s,token),sWORD,s);     
553        cl.get(token)->area(sx1,sy1,sx2,sy2);
554        text_blockers=new text_blocker(sx1,sy1,sx2,sy2,text_blockers); 
555      }           
556      else if (!strcmp(token,"scroll"))
557      {
558        expect(get_token(s,strng),sSTRING,s);
559        text_loaded=1;
560        y=y2-y1;
561      } else if (!strcmp(token,"wait"))
562      {
563        expect(get_token(s,token),sWORD,s);
564        printf("waiting for %s\n",token);       
565        done=0;
566
567
568
569
570        int old_dev=dev;
571        dev=dev&(0xffff-DRAW_PEOPLE_LAYER);     
572
573
574        do
575        {       
576          the_game->draw_map();
577
578          time_marker cur_time;
579          if (pan_steps)
580          {
581            if (last_pan_time)
582            {
583              if ((int)(cur_time.diff_time(last_pan_time)*1000)>pan_speed)
584              {
585                the_game->pan(pan_xv,pan_yv);
586                pan_steps--;
587                delete last_pan_time;
588                if (pan_steps)
589                  last_pan_time=new time_marker;
590                else last_pan_time=NULL;
591              }
592            } else last_pan_time=new time_marker;
593          }
594
595          scene_character *first=cl.first;
596          while (first)
597          {
598            first->draw();
599           
600            if (!first->last_frame)
601              first->last_frame=new time_marker;
602            else
603            {
604              int time=first->current_frame->time,advance=0;
605              if (time>=0)
606              {                     
607                if ((int)(cur_time.diff_time(first->last_frame)*1000)>time)
608                  advance=1;
609              }
610              else
611              {
612                if ((int)(cur_time.diff_time(first->last_frame)*1000)>frame_speed)
613                  advance=1;           
614              }
615           
616              if (advance)
617              {
618                if (!strcmp(token,first->n))      // is this the character we are waiting on?
619                {
620                  if (first->next_frame())
621                    done=1;
622                } else first->next_frame();
623              }
624            }       
625            first=first->next;     
626          }
627          if (text_loaded)
628          {
629            text_loaded=(!text_draw(y,x1,y1,x2,y2,strng,text_blockers,font));
630            if (last_text_time)
631            {
632              if ((int)(cur_time.diff_time(last_text_time)*1000)>scroll_speed)
633              {       
634                y+=text_step;
635                delete last_text_time;
636                if (text_loaded)
637                  last_text_time=new time_marker;           
638                else
639                  last_text_time=NULL;
640              }
641            } else last_text_time=new time_marker;         
642          }
643
644         
645         
646          if (!strcmp(token,"pan"))       
647            if (pan_steps<=0) done=1;
648
649          if (!strcmp(token,"text"))
650            if (!text_loaded) done=1;
651           
652          wm->flush_screen();     
653          while (wm->event_waiting())
654          {     
655            event ev;       
656            wm->get_event(ev);
657            if (ev.type==EV_KEY)
658            {
659              switch (ev.key)
660              {
661                case JK_UP :
662                case JK_LEFT :
663                  if (scroll_speed>=20)
664                    scroll_speed-=20;
665                  else text_step--;
666                  break;
667                case JK_RIGHT :
668                case JK_DOWN :
669                  if (text_step<-2)
670                    text_step++;
671                  else if (scroll_speed<200) scroll_speed+=20;
672                  break;
673                case JK_ESC : abort=done=1; break;
674                case JK_ENTER : done=1; break;
675              }
676            }
677          }
678         
679         
680        } while (!done);
681        dev=old_dev;
682      }     
683           
684      expect(get_token(s,token),sRIGHT_PAREN,s);     
685     
686    } while (!abort && token_type(s)!=sRIGHT_PAREN);
687
688   
689    if (!abort)
690      next_token(s);
691
692    // free up memory allocated
693    while (text_blockers)
694    {
695      text_blocker *n=text_blockers->next;     
696      delete text_blockers;
697      text_blockers=n;     
698    }
699    if (last_text_time)
700      delete last_text_time;
701    if (last_pan_time)
702      delete last_pan_time;
703
704  } while (!abort && token_type(s)!=sRIGHT_PAREN); 
705  if (!abort)
706    next_token(s);
707
708  jfree(strng);
709  screen->set_clip(cx1,cy1,cx2,cy2); 
710
711  the_game->draw(0);
712}
713
714
715
Note: See TracBrowser for help on using the repository browser.