|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 5338 (0x14da)
Types: TextFile
Names: »intersect.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Sdi/intersect.c«
/************************************ intersect.c ******************/
#include "sdi.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.
*/
/*
* The code to intersect blasts, missiles, and lasers is in here,
* as well as some blast-specific code.
*/
#define LINE_GRAIN 20
/* each 'line' is the head of a linked list of current blasts */
static struct blast *lines_launch[MAX_LINES/LINE_GRAIN + 1], *lines_city[MAX_LINES/LINE_GRAIN + 1];
static struct blast **init_line_from_bid(), **init_line_from_mid();
/*
* Clear out data structures which keep track of blasts.
*/
init_intersect()
{
int i;
for (i=0; i<(MAX_LINES/LINE_GRAIN +1); i++) {
lines_launch[i] = NULL;
lines_city[i] = NULL;
}
}
/*
* Register a blast for later display. After this call the blast will
* automatically be incremented and decremented in size, and will be checked
* for intersection with missiles.
*/
add_blast(bid)
register struct blast *bid;
{
/* for now don't sort, just stick at the head */
register int pos = bid->orig_y / LINE_GRAIN;
struct blast **lines;
if (pos < 0 || pos >= MAX_LINES/LINE_GRAIN + 1) {
return;
}
lines = init_line_from_bid(bid);
bid->next = lines[pos];
lines[pos] = bid;
blast_count++;
}
/*
* Remove a blast from the display list. The blast will no longer
* intersect missiles, change in size, or be displayed. The blast must
* have already been cleared from the display elsewhere. The storage
* is not freed here, in case the blast is statically allocated.
*/
remove_blast(bid)
register struct blast *bid;
{
struct blast **lines = init_line_from_bid(bid);
register struct blast *ptr = lines[bid->orig_y / LINE_GRAIN];
if (ptr == bid) {
/* head is special case */
lines[bid->orig_y / LINE_GRAIN] = bid->next;
} else {
while ( ptr != NULL && ptr->next != bid )
ptr = ptr->next;
if (ptr != NULL)
ptr->next = bid->next;
}
blast_count--;
}
/*
* See if the missile 'mid' has run into any blasts.
*/
intersect(mid)
struct missile *mid;
{
int start = max((mid->y - (MAX_CIRCLE >> 1) - 1) / LINE_GRAIN, 0);
int end = min((mid->y + (MAX_CIRCLE >> 1) + 1) / LINE_GRAIN, max_y);
register int i;
register struct blast *ptr;
struct blast **lines = init_line_from_mid(mid);
for (i=start; i <= end; i++) {
ptr = lines[i];
while (ptr != NULL) {
if (single_intersect(ptr, mid))
return TRUE;
ptr = ptr->next;
}
}
return FALSE;
}
/*
* See if the missile 'mid' is passing through blast 'bid'. This routine
* is also used for laser initialization, with a fake 'bid' to simulate
* the laser range. For purposes of computing intersection, the circular
* blast is considerd to be a rectangle with the same center and approximately
* the same area. An intersection has occured if the missile passed
* through the blast between its last update and now, even if both endpoints
* are outside the blast.
*/
single_intersect(bid,mid)
struct missile *mid;
struct blast *bid;
{
int x0 = mid->old_x, y0 = mid->old_y, x1 = mid->x, y1 = mid->y;
return rect_clipvector(&bid->r, &x0, &y0, &x1, &y1);
}
/*
* Procedure 'func' is called for every blast on the display lists.
*/
doto_blasts(func)
int (*func)();
{
int i;
struct blast *bid, *next;
struct blast **lines;
lines = lines_launch;
for (i=0; i< (MAX_LINES/LINE_GRAIN + 1); i++) {
bid = lines[i];
while (bid != NULL) {
next = bid->next; /* in case func destroys it */
(*func)(bid);
bid = next;
}
}
lines = lines_city;
for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
bid = lines[i];
while (bid != NULL) {
next = bid->next; /* in case func destroys it */
(*func)(bid);
bid = next;
}
}
}
/*
* Given a blast, return the proper display on which it will be found.
*/
static struct blast **
init_line_from_bid(bid)
struct blast *bid;
{
if (bid->pw == launchpw) {
return lines_launch;
} else {
return lines_city;
}
}
/*
* Given a missile, return the proper display list on which intersecting
* blasts will be found.
*/
static struct blast **
init_line_from_mid(mid)
struct missile *mid;
{
if (mid->pw == launchpw) {
return lines_launch;
} else {
return lines_city;
}
}
/*
* Remove all blasts from the display lists and free their storage.
* Nothing is done here about getting them off the display.
*/
static struct blast **line_list[] = {lines_launch, lines_city};
free_all_blasts()
{
int i, l;
struct blast *bid, *nextbid, **lines;
for (l=0; l < 2; l++) {
lines = line_list[l];
for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
bid = lines[i];
lines[i] = NULL;
while (bid != NULL) {
nextbid = bid->next;
free(bid);
bid = nextbid;
}
}
}
blast_count = 0;
}
/*
This is the old style, now commented out. It would let a fast
moving missile pass right through, but did consider blasts to
be real circles.
single_intersect(bid, mid)
struct blast *bid;
struct missile *mid;
{
register short offx = B_WIDTH(bid)/2;
register short x = bid->x - mid->x;
register short y = bid->y - mid->y;
return (x*x + y*y) < (offx*offx);
}
*/