1 /*
2  * graphics.c  --  xrobots
3  *
4  * Copyright 1989 Brian Warkentine
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the author's name not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  The author makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
18  * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
19  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * The author's current employer has no connection with this software, as it
24  * was written before being employed at Sun.  The following address is for
25  * contacting the author only and does not imply any responsibility on the
26  * behalf of Sun Microsystems.
27  *
28  * Contact the author at:
29  * 	Brian Warkentine  (brianw@Sun.COM)
30  * 	Sun Microsystems
31  * 	2550 Garcia Avenue
32  * 	Mountain View, Ca 94043-1100
33  *
34  */
35 
36 #include <X11/X.h>
37 #include <X11/Intrinsic.h>
38 #include <X11/Shell.h>
39 #include "xrobots.h"
40 #include "bitmaps.h"
41 #include "icon.h"
42 
43 static Pixmap playerP, dead_playerP, robotP, heapP, iconP;
44 static Cursor upC, up_rightC, rightC, down_rightC, downC,
45               down_leftC, leftC, up_leftC, stayC, cant_goC, thumbsC;
46 
47 #define NUM_TMP_CURSOR_PIXMAPS 11
48 static Pixmap tmp_pixmap[NUM_TMP_CURSOR_PIXMAPS];
49 
50 /*----------------------------------------------------------------------*/
51 
52 void
init_pixmaps(top_shell)53 init_pixmaps(top_shell)
54   Widget top_shell;
55 {
56 /*
57  * Let's make some pixmaps and some cursors.
58  * And then let's set the iconpixmap.
59  */
60   Pixmap tmpP;
61   XColor fgcolor,bgcolor;
62   Arg arg;
63 
64   playerP = XCreateBitmapFromData(display,playfield,
65 		Image_player_bits, Image_player_width, Image_player_height);
66 
67   dead_playerP = XCreateBitmapFromData(display,playfield,
68 		Image_player_dead_bits, Image_player_dead_width,
69 		Image_player_dead_height);
70 
71   iconP   = XCreateBitmapFromData(display,playfield,
72 		icon_bits, icon_width, icon_height);
73 
74   robotP  = XCreateBitmapFromData(display,playfield,
75 		Image_robot_bits, Image_robot_width, Image_robot_height);
76 
77   heapP   = XCreateBitmapFromData(display,playfield,
78 		Image_heap_bits, Image_heap_width, Image_heap_height);
79 
80 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
81 
82   fgcolor.pixel = app_data.fg;
83   bgcolor.pixel = app_data.bg;
84   fgcolor.flags =  DoRed | DoGreen | DoBlue;
85   bgcolor.flags =  DoRed | DoGreen | DoBlue;
86   XQueryColor(display,DefaultColormapOfScreen(XtScreen(playfield_widget)), &fgcolor);
87   XQueryColor(display,DefaultColormapOfScreen(XtScreen(playfield_widget)), &bgcolor);
88 
89 
90   tmp_pixmap[0] =
91   tmpP = XCreateBitmapFromData(display,playfield, up_bits,
92                                   up_width, up_height);
93   upC  = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
94 
95   tmp_pixmap[1] =
96   tmpP = XCreateBitmapFromData(display,playfield, up_right_bits,
97                                   up_right_width, up_right_height);
98   up_rightC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
99 
100   tmp_pixmap[2] =
101   tmpP = XCreateBitmapFromData(display,playfield, right_bits,
102                                   right_width, right_height);
103   rightC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
104 
105   tmp_pixmap[3] =
106   tmpP = XCreateBitmapFromData(display,playfield, down_right_bits,
107                                   down_right_width, down_right_height);
108   down_rightC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
109 
110   tmp_pixmap[4] =
111   tmpP = XCreateBitmapFromData(display,playfield, down_bits,
112                                   down_width, down_height);
113   downC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
114 
115   tmp_pixmap[5] =
116   tmpP = XCreateBitmapFromData(display,playfield, down_left_bits,
117                                   down_left_width, down_left_height);
118   down_leftC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
119 
120   tmp_pixmap[6] =
121   tmpP = XCreateBitmapFromData(display,playfield, left_bits,
122                                   left_width, left_height);
123   leftC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
124 
125   tmp_pixmap[7] =
126   tmpP = XCreateBitmapFromData(display,playfield, up_left_bits,
127                                   up_left_width, up_left_height);
128   up_leftC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
129 
130   tmp_pixmap[8] =
131   tmpP = XCreateBitmapFromData(display,playfield, stay_bits,
132                                   stay_width, stay_height);
133   stayC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
134 
135   tmp_pixmap[9] =
136   tmpP = XCreateBitmapFromData(display,playfield, cant_go_bits,
137                                   cant_go_width, cant_go_height);
138   cant_goC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,8,8);
139 
140   tmp_pixmap[10] =
141   tmpP = XCreateBitmapFromData(display,playfield, thumbs_down_bits,
142                                   thumbs_down_width, thumbs_down_height);
143   thumbsC = XCreatePixmapCursor(display, tmpP, tmpP, &fgcolor,&bgcolor,
144  				thumbs_down_x_hot,thumbs_down_y_hot);
145 
146   XtSetArg(arg,XtNiconPixmap,iconP);
147   XtSetValues(top_shell,&arg,1);
148 }
149 
150 /*----------------------------------------------------------------------*/
151 
152 static int cant_move;  /* set as a side effect of checking possible moves */
153 
154 void
auto_teleport()155 auto_teleport()
156 {
157   if(!cant_move)
158 	return;
159   if(app_data.autoteleport && sonic_used) {
160 	teleport();
161 	return;
162   }
163   if(app_data.autoteleportalways)
164 	teleport();
165 }
166 
167 static void
display_ok_move(x,y)168 display_ok_move(x,y)
169   int x,y;
170 {
171 
172   if(can_go(x,y)) {
173     cant_move = 0;
174     if(!app_data.spiffy) return;
175 			/* show the icon for a good move */
176     XDrawPoint(display, playfield, gc,
177                pos_to_coord(x)+CELLSIZE/2,pos_to_coord(y)+CELLSIZE/2);
178   } else {
179     if(!app_data.spiffy) return;
180 			/* or erase any previous dross */
181     if( INXRANGE(x) && INYRANGE(y) && (robot_array[x][y] == EMPTY))
182       XClearArea(display, playfield,
183                  pos_to_coord(x), pos_to_coord(y),
184                  CELLSIZE, CELLSIZE, False);
185   }
186 }
187 
188 void
display_possible_moves()189 display_possible_moves()
190 {
191   cant_move = 1;
192 
193   display_ok_move( human_x-1,human_y-1 );
194   display_ok_move( human_x  ,human_y-1 );
195   display_ok_move( human_x+1,human_y-1 );
196   display_ok_move( human_x-1,human_y   );
197 
198   display_ok_move( human_x+1,human_y   );
199   display_ok_move( human_x-1,human_y+1 );
200   display_ok_move( human_x  ,human_y+1 );
201   display_ok_move( human_x+1,human_y+1 );
202 
203 }
204 
205 
206 void
display_level()207 display_level()
208 {
209 /* Naive refresh algorithm.... */
210   int x,y;
211 
212   XClearWindow(display,playfield);
213   if(game_active)
214     XCopyPlane(display,playerP,playfield,gc,0,0,
215  	Image_player_width,Image_player_height,
216  	pos_to_coord(human_x),pos_to_coord(human_y),1);
217   else
218     XCopyPlane(display,dead_playerP,playfield,gc,0,0,
219  	Image_player_dead_width,Image_player_dead_height,
220  	pos_to_coord(human_x),pos_to_coord(human_y),1);
221 
222   for(y=0;y<MAXY;y++)
223   {
224     for(x=0;x<MAXX;x++)
225         switch (robot_array[x][y])
226         {
227           case ROBOT:
228             XCopyPlane(display,robotP,playfield,gc,0,0,
229                        Image_robot_width,Image_robot_height,
230                        pos_to_coord(x),pos_to_coord(y),1);
231             break;
232 
233           case HEAP:
234             XCopyPlane(display,heapP,playfield,gc,0,0,
235                        Image_heap_width,Image_heap_height,
236                        pos_to_coord(x),pos_to_coord(y),1);
237             break;
238     }
239   }
240 }
241 
242 
243 void
show_movement()244 show_movement()
245 {
246 /*
247  * draw just the changes.
248  */
249   int x,y;
250 
251   /* force a redraw of the area surrounding last position */
252   for(x=last_human_x-1;x<last_human_x+2;x++)
253     for(y=last_human_y-1;y<last_human_y+2;y++)
254       if( INXRANGE(x) && INYRANGE(y) )
255         robot_array_bak[x][y] = REDRAW;
256 
257   /*
258    * This is a little hacked up because the player isn't really in the
259    * robot array.  Assigning the backup array to EMPTY avoids
260    * drawing over the player.
261    */
262   robot_array_bak[human_x][human_y] = EMPTY;
263 
264   XCopyPlane(display,playerP,playfield,gc,0,0,
265         Image_player_width,Image_player_height,
266         pos_to_coord(human_x),pos_to_coord(human_y),1);
267 
268   for(y=0;y<MAXY;y++)
269   {
270     for(x=0;x<MAXX;x++)
271       if(robot_array[x][y] != robot_array_bak[x][y])
272         switch (robot_array[x][y])
273         {
274           case ROBOT:
275             XCopyPlane(display,robotP,playfield,gc,0,0,
276                        Image_robot_width,Image_robot_height,
277                        pos_to_coord(x),pos_to_coord(y),1);
278             break;
279 
280           case HEAP:
281             XCopyPlane(display,heapP,playfield,gc,0,0,
282                        Image_heap_width,Image_heap_height,
283                        pos_to_coord(x),pos_to_coord(y),1);
284             break;
285           default:
286             XClearArea(display, playfield,
287                        pos_to_coord(x), pos_to_coord(y),
288                        CELLSIZE, CELLSIZE, False);
289     }
290   }
291 }
292 
293 
294 
295 /*ARGSUSED*/
296 XtEventHandler
redisplay_level(w,closure,event)297 redisplay_level(w, closure, event)
298   Widget w;
299   caddr_t closure;
300   XExposeEvent *event;
301 {
302 /* refresh entire screen -- e.g. expose events.  Just a little naive. */
303   display_level();
304   display_possible_moves();
305   XFlush(display);
306 }
307 
308 
309 void
update_pointer(direction)310 update_pointer(direction)
311   int direction;
312 {
313 /*
314  * set the cursor to the appropriate one.
315  */
316   int tmp_human_x = human_x, tmp_human_y = human_y;
317 
318   if(direction & UP)    tmp_human_y--;
319   if(direction & DOWN)  tmp_human_y++;
320   if(direction & LEFT)  tmp_human_x--;
321   if(direction & RIGHT) tmp_human_x++;
322 
323   if(!can_go(tmp_human_x,tmp_human_y)) {
324     XDefineCursor(display,playfield,cant_goC);
325     return;
326     }
327   if(direction&LEFT)
328     if(direction&UP)
329       XDefineCursor(display,playfield,up_leftC);
330     else
331       if(direction&DOWN)
332           XDefineCursor(display,playfield,down_leftC);
333       else
334         XDefineCursor(display,playfield,leftC);
335 
336    if(direction&RIGHT)
337     if(direction&UP)
338       XDefineCursor(display,playfield,up_rightC);
339     else
340       if(direction&DOWN)
341           XDefineCursor(display,playfield,down_rightC);
342       else
343         XDefineCursor(display,playfield,rightC);
344 
345   if(direction == UP)
346         XDefineCursor(display,playfield,upC);
347   if(direction == DOWN)
348         XDefineCursor(display,playfield,downC);
349   if(direction == STILL)
350         XDefineCursor(display,playfield,stayC);
351 
352 
353 }
354 
355 
356 /*----------------------------------------------------------------------*/
357 
free_pixmaps()358 void free_pixmaps()
359 {
360   int i;
361 
362   XFreeCursor(display,upC);
363   XFreeCursor(display,up_rightC);
364   XFreeCursor(display,rightC);
365   XFreeCursor(display,down_rightC);
366   XFreeCursor(display,downC);
367   XFreeCursor(display,down_leftC);
368   XFreeCursor(display,leftC);
369   XFreeCursor(display,up_leftC);
370   XFreeCursor(display,stayC);
371   XFreeCursor(display,thumbsC);
372   XFreeCursor(display,cant_goC);
373   for(i=0;i<NUM_TMP_CURSOR_PIXMAPS;i++)
374     XFreePixmap(display,tmp_pixmap[i]);
375 
376   XFreePixmap(display,playerP);
377   XFreePixmap(display,dead_playerP);
378   XFreePixmap(display,robotP);
379   XFreePixmap(display,iconP);
380   XFreePixmap(display,heapP);
381 
382 }
383 
384 
385 
386 /*----------------------------------------------------------------------*/
387 
388 void
do_death()389 do_death()
390 {
391   XDefineCursor(display,playfield,thumbsC);
392   XCopyPlane(display,dead_playerP,playfield,gc,0,0,
393  	Image_player_dead_width,Image_player_dead_height,
394  	pos_to_coord(human_x),pos_to_coord(human_y),1);
395   XFlush(display);
396 }
397 
398 /*----------------------------------------------------------------------*/
399 
400 void
show_teleport()401 show_teleport()
402 {
403 /*
404  * Cheap animation... but it needs a fast server
405  */
406 unsigned int i;
407 
408   if(!app_data.spiffy) return;
409 
410   for(i=100;i>0;i-=10) {
411     XDrawArc(display,playfield,gc,
412       pos_to_coord(human_x)+(CELLSIZE/2)-(i/2)-2,
413       pos_to_coord(human_y)+(CELLSIZE/2)-(i/2)-2,
414       i,i,0,64*360);
415     XFlush(display);
416   }
417 }
418 
419 /*----------------------------------------------------------------------*/
420 
421 static void
do_sonic(agc)422 do_sonic(agc)
423 GC agc;
424 {
425 /*
426  * do some effects for the sonic screwdriver...
427  */
428 #define SPACING 3
429 int center_x = pos_to_coord(human_x)+(CELLSIZE/2)-2,
430     center_y = pos_to_coord(human_y)+(CELLSIZE/2)-2;
431 int i;
432 
433   if(!app_data.spiffy) return;
434 
435   for(i=pos_to_coord(human_x-1);i<pos_to_coord(human_x+2);i+=SPACING) {
436     XDrawLine(display,playfield,agc,center_x,center_y,i,pos_to_coord(human_y-1));
437     XCopyPlane(display,playerP,playfield,gc,0,0,
438  	Image_player_width,Image_player_height,
439  	pos_to_coord(human_x),pos_to_coord(human_y),1);
440   }
441 
442   for(i=pos_to_coord(human_y-1);i<pos_to_coord(human_y+2);i+=SPACING) {
443     XDrawLine(display,playfield,agc,center_x,center_y,pos_to_coord(human_x+2),i);
444     XCopyPlane(display,playerP,playfield,gc,0,0,
445  	Image_player_width,Image_player_height,
446  	pos_to_coord(human_x),pos_to_coord(human_y),1);
447   }
448 
449   for(i=pos_to_coord(human_x+2);i>pos_to_coord(human_x-1);i-=SPACING) {
450     XDrawLine(display,playfield,agc,center_x,center_y,i,pos_to_coord(human_y+2));
451     XCopyPlane(display,playerP,playfield,gc,0,0,
452  	Image_player_width,Image_player_height,
453  	pos_to_coord(human_x),pos_to_coord(human_y),1);
454   }
455 
456   for(i=pos_to_coord(human_y+2);i>pos_to_coord(human_y-1);i-=SPACING) {
457     XDrawLine(display,playfield,agc,center_x,center_y,pos_to_coord(human_x-1),i);
458     XCopyPlane(display,playerP,playfield,gc,0,0,
459  	Image_player_width,Image_player_height,
460  	pos_to_coord(human_x),pos_to_coord(human_y),1);
461   }
462   XFlush(display);
463 }
464 
465 
466 void
show_sonic()467 show_sonic()
468 {
469   do_sonic(gc);		/* do it, */
470   do_sonic(cleargc);	/* then erase it. */
471 }
472 
473