/*************************************** blast.c ********************/ #include "sdi.h" #include "sdi_color.h" /* * Copyright 1987 by Mark Weiser. * Permission to reproduce and use in any manner whatsoever on Suns is granted * so long as this copyright and other identifying marks of authorship * in the code and the game remain intact and visible. Use of this code * in other products is reserved to me--I'm working on Mac and IBM versions. */ /* * Blast-related routines are here and in intersect.c. Also here is * the main dispatch point for display updating called, for historical * reasons, 'blast_timer'. */ static Notify_value blast_timer(); extern int draw_blast(), doto_missiles(), update_missile(); /* * Start the main dispatch timer. */ void init_blast() { static char *me = (char *)&me; struct itimerval timer; timer.it_interval.tv_usec = 0; timer.it_interval.tv_sec = 0; timer.it_value.tv_usec = 1; timer.it_value.tv_sec = 0; notify_set_itimer_func(me, blast_timer, ITIMER_REAL, &timer, NULL); } /* * Construct a new blast and put it on the display list. */ start_blast(x, y, xinc, yinc, pw, circle_type) int x, y; Xv_Window pw; struct circ *circle_type; { struct blast *bid = (struct blast *)malloc(sizeof(struct blast)); bid->pw = pw; bid->next = NULL; bid->circ = 0; bid->x = x; bid->orig_y = bid->y = y; bid->x_inc = xinc; bid->y_inc = yinc; bid->num_circles = circle_type->num_circles; bid->circles = circle_type->circles; bid->masks = circle_type->masks; bid->width = xv_get(bid->circles[0], XV_WIDTH); update_blast_rect(bid); add_blast(bid); draw_blast(bid); } #define INSCRIBING_FUDGE_FACTOR 0 /* * Construct a square which approximates the size of the current * blast circle. */ update_blast_rect(bid) struct blast *bid; { register int w = bid->width / 2 - INSCRIBING_FUDGE_FACTOR; register int h = bid->width - 2*INSCRIBING_FUDGE_FACTOR; bid->r.r_left = bid->x - w; bid->r.r_top = bid->y - w; bid->r.r_width = h; bid->r.r_height = h; } /* * The main dispatch routine. * 'blast_timer' is called at fixed intervals, queries routines * for launch, missiles, lasers, and blasts for their next update. */ static Notify_value blast_timer(me, which) int *me; int which; { extern Panel_item foe_ground_item; Xv_Window pw1 = citypw; struct itimerval timer; if (!running) return NOTIFY_DONE; if (suspended) { suspendor(blast_timer, me, which, 1); return NOTIFY_DONE; } if (missile_count <= 0 && blast_count <= 0 && xv_get(ballistic_item, PANEL_VALUE) <= 0 && xv_get(foe_ground_item, PANEL_VALUE) <= 0) finish_round(); /* checkinput(); */ timer.it_interval.tv_usec = 0; timer.it_interval.tv_sec = 0; timer.it_value.tv_usec = blast_delay; timer.it_value.tv_sec = 0; notify_set_itimer_func(pw1, blast_timer, ITIMER_REAL, &timer, NULL); if (need_a_bell != NULL) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 30000; /* this is the minimal reliable bell length */ /* How to do a bell in X? */ need_a_bell = NULL; } doto_missiles(update_missile); doto_lasers(); doto_blasts(draw_blast); doto_rocks(); doto_launch(); return NOTIFY_DONE; } /* * Helper routine passed into 'doto_blasts'. Updates the * blast circle, and frees the blast structure if done. */ draw_blast(bid) struct blast *bid; { int old_circ = bid->circ; if (bid->circ < 0 || bid->x_inc || bid->y_inc) { /* shrinking or moving, remove old blast */ pw_rop(bid->pw, B_OFFSET_X(bid), B_OFFSET_Y(bid), B_WIDTH(bid), B_HEIGHT(bid), /* use_color ? PIX_SRC : PIX_NOT(PIX_SRC), */ /* PIX_SRC ^ PIX_DST, */ PIX_SRC, bid->masks[ABS(bid->circ)], 0, 0); } /* Update the next blast circle. Positive values are growing, negative are shrinking */ bid->circ += 1; if (bid->circ >= bid->num_circles) { bid->circ = -(bid->num_circles) + 1; } if (bid->circ != 0) { /* Draw the new blast */ bid->x += bid->x_inc; bid->y += bid->y_inc; bid->width = xv_get(bid->circles[ABS((bid)->circ)], XV_WIDTH); pw_rop(bid->pw, B_OFFSET_X(bid), B_OFFSET_Y(bid), B_WIDTH(bid), B_HEIGHT(bid), /* use_color ? PIX_SRC : PIX_CLR, */ PIX_SRC, bid->circles[ABS(bid->circ)], 0, 0); } if (old_circ == -1) { remove_blast(bid); free(bid); } bid->width = xv_get(bid->circles[ABS((bid)->circ)], XV_WIDTH); update_blast_rect(bid); }