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 "common.h"
16 
17 #include "director.h"
18 #include "game.h"
19 #include "lisp.h"
20 #include "fonts.h"
21 
22 director scene_director;
23 
scroll_text(char * Text)24 void director::scroll_text(char *Text)
25 { text=Text;
26   text_y=the_game->first_view->cy2-the_game->first_view->cy1+1;
27 }
28 
director()29 director::director()
30 {
31   tleft=ttop=tright=tbottom=pan_xv=pan_yv=0;
32   text_step=-2;
33   frame_speed=100;
34   scroll_speed=60;
35   pan_speed=60;
36   scene_abort=0;
37 }
38 
39 extern unsigned char *white_light;
40 
41 
42 
text_draw(int y,int x1,int y1,int x2,int y2,char const * buf,JCFont * font,uint8_t * cmap,char color)43 int text_draw(int y, int x1, int y1, int x2, int y2, char const *buf, JCFont *font, uint8_t *cmap, char color)
44 {
45   int cx1, cy1, cx2, cy2, word_size, word_len;
46   screen->GetClip(cx1, cy1, cx2, cy2);
47   screen->InClip(x1,y1,x2+1,y2+1);
48   int h=font->height()+2,w=font->width(),x=x1,dist;
49   y+=y1;
50   char const *word_start;
51 
52   while (buf && *buf)
53   {
54     do
55     {
56       if (*buf=='\\' && buf[1]=='n')
57       {
58     x=x1;
59     y+=h*2;
60     buf+=2;
61       }
62 
63       // skip space
64       if (*buf==' ' || *buf=='\r' || *buf=='\n' || *buf=='\t')
65       {
66     x+=w;
67     while (*buf==' ' || *buf=='\r' || *buf=='\n' || *buf=='\t')   // skip space until next word
68           buf++;
69       }
70 
71       word_start=buf;
72       for (word_len=0,word_start=buf,word_size=0; *buf && *buf!=' ' && *buf!='\r' && *buf!='\n' &&
73        *buf!='\t' && (*buf!='\\' || buf[1]!='n'); buf++,word_size+=w,word_len++);
74 
75       if (word_size<x2-x1) // make sure the word can fit on the screen
76       {
77     if (word_size+x>x2)    // does word not fit on line?
78     {
79       y+=h;                // go to next line
80       x=x1;
81     }
82       }
83 
84 
85       if (y+h<y1)         // word on screen yet?
86     x+=word_size;
87 
88     } while (*buf && y+h<y1);     // if not on screen yet, fetch next word
89 
90     dist=31;
91     if (y-y1<dist)
92     {
93       if (y-y1<1) dist=0;
94       else dist=y-y1;
95     }
96 
97     if (y2-y<dist)
98     {
99       if (y2-y<1) dist=0;
100       else dist=y2-y;
101     }
102 
103     int c=cmap[dist];
104     if (y>y2) { buf=NULL; }
105     else
106     {
107       while (word_len--)
108       {
109     font->put_char(screen,x+1,y+1,*word_start,0);
110     font->put_char(screen,x,y,*word_start,c);
111     word_start++;
112     x+=w;
113       }
114     }
115 
116   }
117   screen->SetClip(cx1,cy1,cx2,cy2);
118   return (y<=y1);
119 }
120 
wait(void * arg)121 void director::wait(void *arg)
122 {
123   if (scene_abort) return ;
124   pan_time=frame_time=text_time=NULL;
125   int done=0;
126   LSymbol *pan_symbol = LSymbol::FindOrCreate("pan"),
127              *text_symbol = LSymbol::FindOrCreate("text");
128 
129   JCFont *font=wm->font();
130 
131   do
132   {
133     the_game->draw_map(the_game->first_view);
134     time_marker cur_time;
135 
136     if (pan_steps)
137     {
138       if (pan_time)
139       {
140     if ((int)(cur_time.diff_time(pan_time)*1000)>pan_speed)
141     {
142       the_game->pan(pan_xv,pan_yv);
143       pan_steps--;
144       delete pan_time;
145       if (pan_steps)
146           pan_time=new time_marker;
147       else pan_time=NULL;
148     }
149       } else pan_time=new time_marker;
150     } else if (arg==pan_symbol) done=1;
151 
152     if (text)
153     {
154       if (text_draw(text_y,
155             the_game->first_view->cx1+tleft,
156             the_game->first_view->cy1+ttop,
157             the_game->first_view->cx2-tright,
158             the_game->first_view->cy2-tbottom,text,font,
159             white_light+32*256,
160             wm->bright_color()
161 
162             ))
163         text=NULL;
164       if (text_time)
165       {
166     if ((int)(cur_time.diff_time(text_time)*1000)>scroll_speed)
167     {
168       text_y+=text_step;
169       delete text_time;
170       if (text)
171         text_time=new time_marker;
172       else
173         text_time=NULL;
174     }
175       } else text_time=new time_marker;
176     } else if (arg==text_symbol) done=1;
177 
178     wm->flush_screen();
179     while (wm->event_waiting())
180     {
181       event ev;
182       wm->get_event(ev);
183       if (ev.type==EV_KEY)
184       {
185     switch (ev.key)
186     {
187       case JK_UP :
188       case JK_LEFT :
189       {
190         if (scroll_speed>=20)
191         scroll_speed-=20;
192           else text_step--;
193       }
194       break;
195       case JK_RIGHT :
196       case JK_DOWN :
197       {
198         if (text_step<-2)
199         text_step++;
200         else if (scroll_speed<200) scroll_speed+=20;
201         break;
202         case JK_ESC : set_abort(1); done=1; break;
203         case JK_ENTER : done=1; break;
204       }
205     }
206       }
207     }
208   } while (!done);
209   if (pan_time) delete pan_time;
210   if (frame_time) delete frame_time;
211   if (text_time) delete text_time;
212 }
213 
214