source: abuse/tags/pd/abuse/src/scene.c

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