1 /* -*- mode: C; tab-width: 2 -*-
2 * blaster, Copyright (c) 1999 Jonathan H. Lin <jonlin@tesuji.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
12 * Robots that move randomly and shoot lasers at each other. If the
13 * mothership is active, it will fly back and forth horizontally,
14 * firing 8 lasers in the 8 cardinal directions. The explosions are
15 * a 20 frame animation. Robots regenerate after the explosion is finished
16 * and all of its lasers have left the screen.
22 #include "screenhack.h"
26 static GC r_color0, r_color1, r_color2, r_color3, r_color4, r_color5, l_color0, l_color1;
32 static int NUM_ROBOTS=5;
33 static int NUM_LASERS=3;
35 static int MOTHER_SHIP=0;
36 static int MOTHER_SHIP_WIDTH=25;
37 static int MOTHER_SHIP_HEIGHT=7;
38 static int MOTHER_SHIP_LASER=15;
39 static int MOTHER_SHIP_PERIOD=150;
40 static int MOTHER_SHIP_HITS=10;
42 static int LINE_MOVE_STYLE=0;
43 static int RANDOM_MOVE_STYLE=1;
44 static int NUM_MOVE_STYLES=2;
46 static int EXPLODE_SIZE_1=27;
47 static int EXPLODE_SIZE_2=19;
48 static int EXPLODE_SIZE_3=7;
49 static GC EXPLODE_COLOR_1;
50 static GC EXPLODE_COLOR_2;
71 struct laser_state *lasers;
74 struct mother_ship_state {
81 struct laser_state *lasers;
86 static int MOVE_STARS;
87 static int MOVE_STARS_X;
88 static int MOVE_STARS_Y;
89 static int MOVE_STARS_RANDOM;
91 static struct mother_ship_state *mother;
93 static struct robot_state *robots;
95 XWindowAttributes xgwa;
100 /* creates a new robot. It starts out on one of the edges somewhere and
101 has no initial velocity. A target is randomly picked. */
102 static void make_new_robot(int index)
107 for(x=0;x<NUM_LASERS;x++) {
108 if(robots[index].lasers[x].active) {
114 robots[index].alive=1;
116 robots[index].radius = 7+(random()%7);
118 robots[index].move_style = random()%NUM_MOVE_STYLES;
120 robots[index].new_x=random()%(xgwa.width-robots[index].radius);
121 robots[index].old_x=robots[index].new_x;
123 robots[index].new_y=0;
124 robots[index].old_y=0;
127 robots[index].new_y=xgwa.height-robots[index].radius;
128 robots[index].old_y = robots[index].new_y;
132 robots[index].new_y=random()%(xgwa.height-robots[index].radius);
133 robots[index].old_y = robots[index].new_y;
135 robots[index].new_x=0;
136 robots[index].old_x=0;
139 robots[index].new_x=xgwa.width-robots[index].radius;
140 robots[index].old_x=robots[index].new_x;
146 robots[index].robot_color = r_color0;
149 robots[index].robot_color = r_color1;
152 robots[index].robot_color = r_color2;
155 robots[index].robot_color = r_color3;
158 robots[index].robot_color = r_color4;
161 robots[index].robot_color = r_color5;
165 robots[index].laser_color = l_color0;
168 robots[index].laser_color = l_color1;
172 robots[index].target = random()%NUM_ROBOTS;
173 while(robots[index].target==index) {
174 robots[index].target = random()%NUM_ROBOTS;
180 /* moves each robot, randomly changing its direction and velocity.
181 At random a laser is shot toward that robot's target. Also at random
182 the target can change. */
183 static void move_robots(void)
193 for(x=0;x<NUM_ROBOTS;x++) {
194 if(robots[x].alive) {
195 if((robots[x].new_x == robots[x].old_x) && (robots[x].new_y == robots[x].old_y)) {
196 if(robots[x].new_x==0) {
197 robots[x].old_x = -((random()%3)+1);
200 robots[x].old_x = robots[x].old_x + (random()%3)+1;
202 if(robots[x].new_y==0) {
203 robots[x].old_y = -((random()%3)+1);
206 robots[x].old_y = robots[x].old_y + (random()%3)+1;
209 if(robots[x].move_style==LINE_MOVE_STYLE) {
210 dx = robots[x].new_x - robots[x].old_x;
211 dy = robots[x].new_y - robots[x].old_y;
224 robots[x].old_x = robots[x].new_x;
225 robots[x].old_y = robots[x].new_y;
227 robots[x].new_x = robots[x].new_x + dx;
228 robots[x].new_y = robots[x].new_y + dy;
230 else if(robots[x].move_style==RANDOM_MOVE_STYLE) {
231 dx = robots[x].new_x - robots[x].old_x;
232 dy = robots[x].new_y - robots[x].old_y;
235 dx = dx - ((random()%7)+1);
238 dx = dx + ((random()%7)+1);
252 dy = dy - ((random()%7)+1);
255 dy = dy + ((random()%7)+1);
266 robots[x].old_x = robots[x].new_x;
267 robots[x].old_y = robots[x].new_y;
269 robots[x].new_x = robots[x].new_x + dx;
270 robots[x].new_y = robots[x].new_y + dy;
273 /* bounds corrections */
274 if(robots[x].new_x >= xgwa.width-robots[x].radius) {
275 robots[x].new_x = xgwa.width - robots[x].radius;
277 else if(robots[x].new_x < 0) {
280 if(robots[x].new_y >= xgwa.height-robots[x].radius) {
281 robots[x].new_y = xgwa.height - robots[x].radius;
283 else if(robots[x].new_y < 0) {
288 robots[x].move_style = 1;
291 robots[x].move_style = 0;
296 if(random()%200==0) {
297 robots[x].target = random()%NUM_ROBOTS;
298 while(robots[x].target==x) {
299 robots[x].target = random()%NUM_ROBOTS;
301 for(y=0;y<NUM_LASERS;y++) {
302 if(robots[x].lasers[y].active == 0) {
303 robots[x].lasers[y].active = 1;
306 robots[x].lasers[y].start_x = robots[x].new_x+robots[x].radius;
307 robots[x].lasers[y].start_y = robots[x].new_y+robots[x].radius;
308 robots[x].lasers[y].end_x = robots[x].lasers[y].start_x+7;
309 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y+7;
312 robots[x].lasers[y].start_x = robots[x].new_x-robots[x].radius;
313 robots[x].lasers[y].start_y = robots[x].new_y+robots[x].radius;
314 robots[x].lasers[y].end_x = robots[x].lasers[y].start_x-7;
315 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y+7;
320 robots[x].lasers[y].start_x = robots[x].new_x-robots[x].radius;
321 robots[x].lasers[y].start_y = robots[x].new_y-robots[x].radius;
322 robots[x].lasers[y].end_x = robots[x].lasers[y].start_x-7;
323 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y-7;
326 robots[x].lasers[y].start_x = robots[x].new_x+robots[x].radius;
327 robots[x].lasers[y].start_y = robots[x].new_y-robots[x].radius;
328 robots[x].lasers[y].end_x = robots[x].lasers[y].start_x+7;
329 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y-7;
337 for(y=0;y<NUM_LASERS;y++) {
338 if(robots[x].lasers[y].active==0) {
339 target_x = robots[robots[x].target].new_x;
340 target_y = robots[robots[x].target].new_y;
341 if((target_x-robots[x].new_x)!=0) {
342 slope = ((double)target_y-robots[x].new_y)/((double)(target_x-robots[x].new_x));
344 if((slope<1) && (slope>-1)) {
345 if(target_x>robots[x].new_x) {
346 robots[x].lasers[y].start_x = robots[x].radius;
347 robots[x].lasers[y].end_x = robots[x].lasers[y].start_x + 7;
350 robots[x].lasers[y].start_x = -robots[x].radius;
351 robots[x].lasers[y].end_x = robots[x].lasers[y].start_x - 7;
353 robots[x].lasers[y].start_y = (int)(robots[x].lasers[y].start_x * slope);
354 robots[x].lasers[y].end_y = (int)(robots[x].lasers[y].end_x * slope);
357 slope = (target_x-robots[x].new_x)/(target_y-robots[x].new_y);
358 if(target_y>robots[x].new_y) {
359 robots[x].lasers[y].start_y = robots[x].radius;
360 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y + 7;
363 robots[x].lasers[y].start_y = -robots[x].radius;
364 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y + 7;
366 robots[x].lasers[y].start_x = (int)(robots[x].lasers[y].start_y * slope);;
367 robots[x].lasers[y].start_x = (int)(robots[x].lasers[y].end_y * slope);
369 robots[x].lasers[y].start_x = robots[x].lasers[y].start_x + robots[x].new_x;
370 robots[x].lasers[y].start_y = robots[x].lasers[y].start_y + robots[x].new_y;
371 robots[x].lasers[y].end_x = robots[x].lasers[y].end_x + robots[x].new_x;
372 robots[x].lasers[y].end_y = robots[x].lasers[y].end_y + robots[x].new_y;
375 if(target_y > robots[x].new_y) {
376 robots[x].lasers[y].start_x = robots[x].new_x;
377 robots[x].lasers[y].start_y = robots[x].new_y+robots[x].radius;
378 robots[x].lasers[y].end_x = robots[x].new_x;
379 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y+7;
382 robots[x].lasers[y].start_x = robots[x].new_x;
383 robots[x].lasers[y].start_y = robots[x].new_y-robots[x].radius;
384 robots[x].lasers[y].end_x = robots[x].new_x;
385 robots[x].lasers[y].end_y = robots[x].lasers[y].start_y-7;
389 if((((robots[x].lasers[y].start_x - robots[x].lasers[y].end_x) > 7) ||
390 ((robots[x].lasers[y].end_x - robots[x].lasers[y].start_x) > 7)) &&
391 (((robots[x].lasers[y].start_y - robots[x].lasers[y].end_y) > 7) ||
392 ((robots[x].lasers[y].end_y - robots[x].lasers[y].start_y) > 7))) {
395 robots[x].lasers[y].active = 1;
405 if(robots[x].death==0) {
413 /* This moves a single laser one frame. collisions with other robots or
414 the mothership is checked. */
415 static void move_laser(int rindex, int index)
422 struct laser_state *laser;
424 laser = robots[rindex].lasers;
427 laser = mother->lasers;
429 if(laser[index].active) {
430 /* collision with other robots are checked here */
431 for(x=0;x<NUM_ROBOTS;x++) {
433 if(robots[x].alive) {
434 y = laser[index].start_x-robots[x].new_x;
436 y = robots[x].new_x-laser[index].start_x;
438 z = laser[index].start_y-robots[x].new_y;
440 z = robots[x].new_y-laser[index].start_y;
442 if((z<robots[x].radius-1)&&(y<robots[x].radius-1)) {
444 robots[x].death = 20;
445 XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
446 XFillArc(dpy, window, black, robots[x].new_x, robots[x].new_y, robots[x].radius, robots[x].radius, 0, 360*64);
447 laser[index].active = 0;
451 y = laser[index].end_x-robots[x].new_x;
453 y = robots[x].new_x-laser[index].end_x;
455 z = laser[index].end_y-robots[x].new_y;
457 z = robots[x].new_y-laser[index].end_y;
459 if((z<robots[x].radius-1)&&(y<robots[x].radius-1)) {
461 robots[x].death = 20;
462 XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
463 XFillArc(dpy, window, black, robots[x].new_x, robots[x].new_y, robots[x].radius, robots[x].radius, 0, 360*64);
464 laser[index].active = 0;
471 if((MOTHER_SHIP)&&(rindex!=-1)) {
472 if(laser[index].active) {
474 y = laser[index].start_x-mother->new_x;
476 y = mother->new_x-laser[index].start_x;
478 z = laser[index].start_y-mother->y;
480 z = mother->y-laser[index].start_y;
482 if((z<MOTHER_SHIP_HEIGHT-1)&&(y<MOTHER_SHIP_WIDTH-1)) {
483 laser[index].active = 0;
487 y = laser[index].end_x-mother->new_x;
489 y = mother->new_x-laser[index].end_x;
491 z = laser[index].end_y-mother->y;
493 z = mother->y-laser[index].end_y;
495 if((z<MOTHER_SHIP_HEIGHT-1)&&(y<MOTHER_SHIP_WIDTH-1)) {
496 laser[index].active = 0;
501 if(mother->active==0) {
508 if(laser[index].active) {
509 dx = laser[index].start_x - laser[index].end_x;
510 dy = laser[index].start_y - laser[index].end_y;
512 laser[index].start_x = laser[index].end_x;
513 laser[index].start_y = laser[index].end_y;
514 laser[index].end_x = laser[index].end_x-dx;
515 laser[index].end_y = laser[index].end_y-dy;
517 if((laser[index].end_x < 0) || (laser[index].end_x >= xgwa.width) ||
518 (laser[index].end_y < 0) || (laser[index].end_y >= xgwa.height)) {
519 laser[index].active = 0;
525 /* All the robots are drawn, including the mother ship and the explosions.
526 After all the robots have been drawn, their laser banks are check and
527 the active lasers are drawn. */
528 static void draw_robots(void)
533 for(x=0;x<NUM_ROBOTS;x++) {
534 if(robots[x].alive) {
535 XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
536 XFillArc(dpy, window, robots[x].robot_color, robots[x].new_x, robots[x].new_y, robots[x].radius, robots[x].radius, 0, 360*64);
539 XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
540 if(robots[x].death) {
541 if(robots[x].death==20) {
542 XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
544 else if(robots[x].death==18) {
545 XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
547 else if(robots[x].death==17) {
548 XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
550 else if(robots[x].death==15) {
551 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
553 else if(robots[x].death==14) {
554 XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
556 else if(robots[x].death==13) {
557 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
559 else if(robots[x].death==12) {
560 XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
562 else if(robots[x].death==11) {
563 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
565 else if(robots[x].death==10) {
566 XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
568 else if(robots[x].death==9) {
569 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
571 else if(robots[x].death==8) {
572 XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
574 else if(robots[x].death==7) {
575 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
577 else if(robots[x].death==6) {
578 XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
580 else if(robots[x].death==4) {
581 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
583 else if(robots[x].death==3) {
584 XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
586 else if(robots[x].death==2) {
587 XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
588 XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(1.7*robots[x].radius/2), robots[x].new_y+(1.7*robots[x].radius/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
590 else if(robots[x].death==1) {
591 XFillArc(dpy, window, black, robots[x].new_x+(1.7*robots[x].radius/2), robots[x].new_y+(1.7*robots[x].radius/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
598 for(x=0;x<NUM_ROBOTS;x++) {
599 for(y=0;y<NUM_LASERS;y++) {
600 if(robots[x].lasers[y].active) {
601 XDrawLine(dpy, window, black, robots[x].lasers[y].start_x,
602 robots[x].lasers[y].start_y,
603 robots[x].lasers[y].end_x,
604 robots[x].lasers[y].end_y);
606 if(robots[x].lasers[y].active) {
607 XDrawLine(dpy, window, robots[x].laser_color, robots[x].lasers[y].start_x,
608 robots[x].lasers[y].start_y,
609 robots[x].lasers[y].end_x,
610 robots[x].lasers[y].end_y);
613 XDrawLine(dpy, window, black, robots[x].lasers[y].start_x,
614 robots[x].lasers[y].start_y,
615 robots[x].lasers[y].end_x,
616 robots[x].lasers[y].end_y);
624 XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
625 XFillArc(dpy, window, mother->ship_color, mother->new_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
629 XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
630 if(mother->death==20) {
631 XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
633 else if(mother->death==18) {
634 XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
636 else if(mother->death==17) {
637 XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
639 else if(mother->death==15) {
640 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
642 else if(mother->death==14) {
643 XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
645 else if(mother->death==13) {
646 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
648 else if(mother->death==12) {
649 XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
651 else if(mother->death==11) {
652 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
654 else if(mother->death==10) {
655 XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
657 else if(mother->death==9) {
658 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
660 else if(mother->death==8) {
661 XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
663 else if(mother->death==7) {
664 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
666 else if(mother->death==6) {
667 XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
669 else if(mother->death==4) {
670 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
672 else if(mother->death==3) {
673 XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
675 else if(mother->death==2) {
676 XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
677 XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+(1.7*MOTHER_SHIP_WIDTH/2), mother->y+(1.7*MOTHER_SHIP_HEIGHT/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
679 else if(mother->death==1) {
680 XFillArc(dpy, window, black, mother->new_x+(1.7*MOTHER_SHIP_WIDTH/2), mother->y+(1.7*MOTHER_SHIP_HEIGHT/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
686 if(mother->lasers[y].active) {
687 XDrawLine(dpy, window, black, mother->lasers[y].start_x,
688 mother->lasers[y].start_y,
689 mother->lasers[y].end_x,
690 mother->lasers[y].end_y);
692 if(mother->lasers[y].active) {
693 XDrawLine(dpy, window, mother->laser_color, mother->lasers[y].start_x,
694 mother->lasers[y].start_y,
695 mother->lasers[y].end_x,
696 mother->lasers[y].end_y);
699 XDrawLine(dpy, window, black, mother->lasers[y].start_x,
700 mother->lasers[y].start_y,
701 mother->lasers[y].end_x,
702 mother->lasers[y].end_y);
709 /* This is the main loop. The mothership movement and laser firing happens inside
717 robots = (struct robot_state *) malloc(NUM_ROBOTS * sizeof (struct robot_state));
718 for(x=0;x<NUM_ROBOTS;x++) {
721 robots[x].lasers = (struct laser_state *) malloc (NUM_LASERS * sizeof(struct laser_state));
722 for(y=0;y<NUM_LASERS;y++) {
723 robots[x].lasers[y].active = 0;
728 stars = (XArc *) malloc (NUM_STARS * sizeof(XArc));
729 for(x=0;x<NUM_STARS;x++) {
730 stars[x].x = random()%xgwa.width;
731 stars[x].y = random()%xgwa.height;
732 stars[x].width = random()%4 + 1;
733 stars[x].height = stars[x].width;
735 stars[x].angle2 = 360 * 64;
742 XFillArcs(dpy,window,black,stars,NUM_STARS);
743 if(MOVE_STARS_RANDOM) {
746 if(random()%167==0) {
749 if(random()%173==0) {
755 if(y>MOVE_STARS_RANDOM) {
756 y = MOVE_STARS_RANDOM;
761 if(y < -(MOVE_STARS_RANDOM)) {
762 y = -(MOVE_STARS_RANDOM);
769 if(z>MOVE_STARS_RANDOM) {
770 z = MOVE_STARS_RANDOM;
775 if(z < -MOVE_STARS_RANDOM) {
776 z = -MOVE_STARS_RANDOM;
782 for(x=0;x<NUM_STARS;x++) {
783 stars[x].x = stars[x].x + y;
784 stars[x].y = stars[x].y + z;
786 stars[x].x = stars[x].x + xgwa.width;
788 else if(stars[x].x>xgwa.width) {
789 stars[x].x = stars[x].x - xgwa.width;
792 stars[x].y = stars[x].y + xgwa.height;
794 else if(stars[x].y>xgwa.height) {
795 stars[x].y = stars[x].y - xgwa.height;
800 for(x=0;x<NUM_STARS;x++) {
801 stars[x].x = stars[x].x + MOVE_STARS_X;
802 stars[x].y = stars[x].y + MOVE_STARS_Y;
804 stars[x].x = stars[x].x + xgwa.width;
806 else if(stars[x].x>xgwa.width) {
807 stars[x].x = stars[x].x - xgwa.width;
810 stars[x].y = stars[x].y + xgwa.height;
812 else if(stars[x].y>xgwa.height) {
813 stars[x].y = stars[x].y - xgwa.height;
817 XFillArcs(dpy,window,s_color,stars,NUM_STARS);
820 XFillArcs(dpy,window,s_color,stars,NUM_STARS);
825 if(random()%MOTHER_SHIP_PERIOD==0) {
826 if((mother->active==0)&&(mother->death==0)) {
827 mother->active = MOTHER_SHIP_HITS;
828 mother->y = random()%(xgwa.height-7);
834 mother->old_x=xgwa.width-25;
835 mother->new_x=xgwa.width-25;
843 if(mother->old_x==mother->new_x) {
844 if(mother->old_x==0) {
848 mother->new_x=mother->new_x-3;
852 if(mother->old_x>mother->new_x) {
853 mother->old_x = mother->new_x;
854 mother->new_x = mother->new_x-3;
855 if(mother->new_x<0) {
857 XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
858 XFillArc(dpy, window, black, mother->new_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
862 mother->old_x = mother->new_x;
863 mother->new_x = mother->new_x+3;
864 if(mother->new_x>xgwa.width) {
866 XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
867 XFillArc(dpy, window, black, mother->new_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
873 if(mother->lasers[x].active) {
880 mother->lasers[x].active = 1;
881 mother->lasers[x].start_x=mother->new_x+(MOTHER_SHIP_WIDTH/2);
882 mother->lasers[x].start_y=mother->y+(MOTHER_SHIP_HEIGHT/2);
884 y = (int)(MOTHER_SHIP_LASER/1.5);
885 mother->lasers[0].end_x=mother->lasers[0].start_x-MOTHER_SHIP_LASER;
886 mother->lasers[0].end_y=mother->lasers[0].start_y;
887 mother->lasers[1].end_x=mother->lasers[1].start_x-y;
888 mother->lasers[1].end_y=mother->lasers[1].start_y-y;
889 mother->lasers[2].end_x=mother->lasers[2].start_x;
890 mother->lasers[2].end_y=mother->lasers[2].start_y-MOTHER_SHIP_LASER;
891 mother->lasers[3].end_x=mother->lasers[3].start_x+y;
892 mother->lasers[3].end_y=mother->lasers[3].start_y-y;
893 mother->lasers[4].end_x=mother->lasers[4].start_x+MOTHER_SHIP_LASER;
894 mother->lasers[4].end_y=mother->lasers[4].start_y;
895 mother->lasers[5].end_x=mother->lasers[5].start_x+y;
896 mother->lasers[5].end_y=mother->lasers[5].start_y+y;
897 mother->lasers[6].end_x=mother->lasers[6].start_x;
898 mother->lasers[6].end_y=mother->lasers[6].start_y+MOTHER_SHIP_LASER;
899 mother->lasers[7].end_x=mother->lasers[7].start_x-y;
900 mother->lasers[7].end_y=mother->lasers[7].start_y+y;
907 screenhack_handle_events(dpy);
908 if(delay) usleep(delay);
919 char *progclass = "Blaster";
921 char *defaults [] = {
922 ".background: black",
923 ".foreground: white",
924 "*r_color0: magenta",
932 "*mother_ship_color0: darkblue",
933 "*mother_ship_color1: white",
934 "*explode_color_1: yellow",
935 "*explode_color_2: orange",
939 "*mother_ship: false",
940 "*mother_ship_width: 25",
941 "*mother_ship_height: 7",
942 "*mother_ship_laser: 15",
943 "*mother_ship_period: 150",
944 "*mother_ship_hits: 10",
945 "*explode_size_1: 27",
946 "*explode_size_2: 19",
947 "*explode_size_3: 7",
949 "*star_color: white",
953 "*move_stars_random: 0",
957 XrmOptionDescRec options [] = {
958 /* These are the 6 robot colors */
959 { "-r_color0", ".r_color0", XrmoptionSepArg, 0 },
960 { "-r_color1", ".r_color1", XrmoptionSepArg, 0 },
961 { "-r_color2", ".r_color2", XrmoptionSepArg, 0 },
962 { "-r_color3", ".r_color3", XrmoptionSepArg, 0 },
963 { "-r_color4", ".r_color4", XrmoptionSepArg, 0 },
964 { "-r_color5", ".r_color5", XrmoptionSepArg, 0 },
965 /* These are the 2 laser colors that robots have */
966 { "-l_color0", ".l_color0", XrmoptionSepArg, 0 },
967 { "-l_color1", ".l_color1", XrmoptionSepArg, 0 },
968 /* These are the colors for the mothership and the mothership lasers */
969 { "-mother_ship_color0", ".mother_ship_color0", XrmoptionSepArg, 0},
970 { "-mother_ship_color1", ".mother_ship_color1", XrmoptionSepArg, 0},
971 /* These are the two colors of the animated explosion */
972 { "-explode_color_1", ".explode_color_1", XrmoptionSepArg, 0 },
973 { "-explode_color_2", ".explode_color_2", XrmoptionSepArg, 0 },
974 /* This is the delay in the main loop */
975 { "-delay", ".delay", XrmoptionSepArg, 0 },
976 /* The number of robots and the number of lasers each robot has */
977 { "-num_robots", ".num_robots", XrmoptionSepArg, 0},
978 { "-num_lasers", ".num_lasers", XrmoptionSepArg, 0},
979 /* If this is set, a mothership will appear, otherwise no mothership */
980 { "-mother_ship", ".mother_ship", XrmoptionNoArg, "true"},
981 { "-no_mother_ship", ".mother_ship", XrmoptionNoArg, "false"},
982 /* This is the width, height, and laser length of the mothership */
983 { "-mother_ship_width", ".mother_ship_width", XrmoptionSepArg, 0},
984 { "-mother_ship_height", ".mother_ship_height", XrmoptionSepArg, 0},
985 { "-mother_ship_laser", ".mother_ship_laser", XrmoptionSepArg, 0},
986 /* This is the period which the mothership comes out, higher period==less often */
987 { "-mother_ship_period", ".mother_ship_period", XrmoptionSepArg, 0},
988 /* This is the number of hits it takes to destroy the mothership */
989 { "-mother_ship_hits", ".mother_ship_hits", XrmoptionSepArg, 0},
990 /* These are the size of the radius of the animated explosions */
991 { "-explode_size_1", ".explode_size_1", XrmoptionSepArg, 0},
992 { "-explode_size_2", ".explode_size_2", XrmoptionSepArg, 0},
993 { "-explode_size_3", ".explode_size_3", XrmoptionSepArg, 0},
994 /* This sets the number of stars in the star field, if this is set to 0, there will be no stars */
995 { "-num_stars", ".num_stars", XrmoptionSepArg, 0},
996 /* This is the color of the stars */
997 { "-star_color", ".star_color", XrmoptionSepArg, 0},
998 /* If this is true, the stars will move */
999 { "-move_stars", ".move_stars", XrmoptionNoArg, "true"},
1000 /* This is the amount the stars will move in the x and y direction */
1001 { "-move_stars_x", ".move_stars_x", XrmoptionSepArg, 0},
1002 { "-move_stars_y", ".move_stars_y", XrmoptionSepArg, 0},
1003 /* If this is non-zero, the stars will move randomly, but will not move more than this number in
1004 either the x or y direction */
1005 { "-move_stars_random", ".move_stars_random", XrmoptionSepArg, 0},
1011 void screenhack(Display *d, Window w)
1019 XGetWindowAttributes(dpy, window, &xgwa);
1020 cmap = xgwa.colormap;
1022 delay = get_integer_resource("delay", "Integer");
1026 NUM_ROBOTS = get_integer_resource("num_robots","Integer");
1030 NUM_LASERS = get_integer_resource("num_lasers","Integer");
1031 EXPLODE_SIZE_1 = get_integer_resource("explode_size_1","Integer");
1032 EXPLODE_SIZE_2 = get_integer_resource("explode_size_2","Integer");
1033 EXPLODE_SIZE_3 = get_integer_resource("explode_size_3","Integer");
1035 NUM_STARS = get_integer_resource("num_stars","Integer");
1036 if(get_boolean_resource("move_stars","Boolean")) {
1038 MOVE_STARS_X = get_integer_resource("move_stars_x","Integer");
1039 MOVE_STARS_Y = get_integer_resource("move_stars_y","Integer");
1040 MOVE_STARS_RANDOM = get_integer_resource("move_stars_random","Integer");
1047 bg = get_pixel_resource("background","Background", dpy, cmap);
1048 gcv.function = GXcopy;
1050 #define make_gc(color,name) \
1051 gcv.foreground = bg ^ get_pixel_resource ((name), "Foreground", \
1053 color = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv)
1056 gcv.foreground = bg;
1057 black = XCreateGC(dpy, window, GCForeground|GCFunction, &gcv);
1058 gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, cmap);
1059 r_color0 = r_color1 = r_color2 = r_color3 = r_color4 = r_color5 = l_color0 = l_color1 = s_color=
1060 XCreateGC(dpy, window, GCForeground|GCFunction, &gcv);
1061 if(get_boolean_resource("mother_ship","Boolean")) {
1062 MOTHER_SHIP_WIDTH=get_integer_resource("mother_ship_width","Integer");
1063 MOTHER_SHIP_HEIGHT=get_integer_resource("mother_ship_height","Integer");
1064 MOTHER_SHIP_LASER=get_integer_resource("mother_ship_laser","Integer");
1065 MOTHER_SHIP_PERIOD=get_integer_resource("mother_ship_period","Integer");
1066 MOTHER_SHIP_HITS=get_integer_resource("mother_ship_hits","Integer");
1068 mother = (struct mother_ship_state *) malloc(sizeof(struct mother_ship_state));
1069 mother->lasers = (struct laser_state *) malloc(8*sizeof(struct laser_state));
1072 mother->ship_color = r_color0;
1073 mother->laser_color = r_color0;
1077 if(get_boolean_resource("mother_ship","Boolean")) {
1078 MOTHER_SHIP_WIDTH=get_integer_resource("mother_ship_width","Integer");
1079 MOTHER_SHIP_HEIGHT=get_integer_resource("mother_ship_height","Integer");
1080 MOTHER_SHIP_LASER=get_integer_resource("mother_ship_laser","Integer");
1081 MOTHER_SHIP_PERIOD=get_integer_resource("mother_ship_period","Integer");
1082 MOTHER_SHIP_HITS=get_integer_resource("mother_ship_hits","Integer");
1084 mother = (struct mother_ship_state *) malloc(sizeof(struct mother_ship_state));
1085 mother->lasers = (struct laser_state *) malloc(8*sizeof(struct laser_state));
1088 make_gc(mother->ship_color,"mother_ship_color0");
1089 make_gc(mother->laser_color,"mother_ship_color1");
1092 make_gc (s_color,"star_color");
1094 make_gc (EXPLODE_COLOR_1,"explode_color_1");
1095 make_gc (EXPLODE_COLOR_2,"explode_color_2");
1097 make_gc (r_color0,"r_color0");
1098 make_gc (r_color1,"r_color1");
1099 make_gc (r_color2,"r_color2");
1100 make_gc (r_color3,"r_color3");
1101 make_gc (r_color4,"r_color4");
1102 make_gc (r_color5,"r_color5");
1103 make_gc (l_color0,"l_color0");
1104 make_gc (l_color1,"l_color1");
1105 make_gc (black,"background");