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