|
|
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 c
Length: 6673 (0x1a11)
Types: TextFile
Names: »circles.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Sdi/circles.c«
/********************************* circles.c ************************/
#include <pixrect/pixrect_hs.h>
#include <stdio.h>
#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.
*/
/*
* Here be everything associated with drawing circles, especially
* all the different kinds of blasts (which are done by clipping
* different pixrects to different shapes of circles.) All the
* blast pixrects are precomputed for every size to save time during
* game display updating.
*/
static short default_laser_blast[] = {
#include "laser.h"
};
mpr_static(laser_blast_pr, 64, 64, 1, default_laser_blast);
static short default_laser_kill[] = {
#include "laserkill.h"
};
mpr_static(laser_kill_pr, 64, 64, 1, default_laser_kill);
static short default_city_blast[] = {
#include "mushroom.h"
};
mpr_static(city_blast_pr, 64, 64, 1, default_city_blast);
static short default_missile_kill[] = {
#include "missilekill.h"
};
mpr_static(missile_kill_pr, 64, 64, 1, default_missile_kill);
static short default_rocks[] = {
#include "rocks.h"
};
mpr_static(rocks_pr, 64, 64, 1, default_rocks);
struct pixrect *circles[MAX_NUM_CIRCLES];
struct pixrect *limited_circles[MAX_NUM_CIRCLES];
struct pixrect *rock_limited_circles[MAX_NUM_CIRCLES];
static struct {
int x, y;
} center = { 0, 0 };
static struct fill_line {
int left;
int right;
int y;
} scan_lines[MAX_LINES], *free_line;
static void circle_fill_pair(), circle_fill();
#define LIMIT(n) (((n) < 0) ? 0 : (((n) >= MAX_LINES) ? MAX_LINES-1 : (n)))
init_circles()
{
int i, size = 2*CIRCLE_SIZE_INC;
int limited_size = (MAX_NUM_CIRCLES-4)*CIRCLE_SIZE_INC + size;
int rock_limited_size = 2*CIRCLE_SIZE_INC + size;
for (i=0; i < MAX_NUM_CIRCLES; i++) {
if (size > MAX_CIRCLE)
size = MAX_CIRCLE;
circles[i] = make_circle(size);
limited_circles[i] = make_circle(size > limited_size ? limited_size : size);
rock_limited_circles[i] = make_circle(size > rock_limited_size ? rock_limited_size : size);
size += CIRCLE_SIZE_INC;
}
blankcircles = circles;
lasercircles = init_circ(3, circles);
laserkillcircles = init_circ(3, circles);
bigblastcircles = init_circ(MAX_NUM_CIRCLES, circles);
littleblastcircles = init_circ(MAX_NUM_CIRCLES-2, limited_circles);
blastkillcircles = init_circ(MAX_NUM_CIRCLES-3, circles);
citykillcircles = init_circ(MAX_NUM_CIRCLES, circles);
littlerockcircles = init_circ(4, rock_limited_circles);
bigrockcircles = init_circ(7, rock_limited_circles);
change_circ(lasercircles, &laser_blast_pr);
change_circ(laserkillcircles, &laser_kill_pr);
change_circ(citykillcircles, &city_blast_pr);
change_circ(blastkillcircles, &missile_kill_pr);
change_circ(littlerockcircles, &rocks_pr);
change_circ(bigrockcircles, &rocks_pr);
}
/*
* Create a new circ structure, and initialize it to contain the pixrect
* list 'c'.
*/
struct circ *
init_circ(n, c)
struct pixrect **c;
{
struct circ *r;
r = (struct circ *)calloc(sizeof(struct circ), 1);
r->masks = r->circles = c;
r->num_circles = n;
return r;
}
/*
* Routine to replace a list of pixrects in a circ structure with a new
* list. The new list is constructed by 'and'ing parameter p with
* circles of the diameter contained in the old list. This is the
* basic routine used to construct all the different kinds of blasts.
*
* Calling change_circ several times on the same circ structure
* will waste memory because the calloc from previous calls is
* never freed, nor are the pixrects. It is not much memory, and nothing will die from it.
*/
change_circ(c, p)
struct circ *c;
struct pixrect *p;
{
int i;
struct pixrect **newcircles;
int size, psize;
newcircles = (struct pixrect **)calloc(sizeof(struct pixrect *),c->num_circles);
psize = p->pr_size.x;
for (i = 0; i < c->num_circles; i++) {
size = c->masks[i]->pr_size.x;
newcircles[i] = mem_create(size, size, 1);
pr_rop(newcircles[i], 0, 0, size, size, PIX_SRC, c->masks[i],
0, 0);
pr_rop(newcircles[i], 0, 0, size, size, PIX_SRC & PIX_DST,
p, psize/2 - size/2, psize/2 - size/2);
}
c->circles = newcircles;
}
/*
* Build a black circle of the specified diameter, and return it in
* a pixrect of just the right size to hold it.
*/
struct pixrect *
make_circle(diameter)
int diameter;
{
struct pixrect *pr = mem_create(diameter, diameter, 1);
center.x = diameter/2;
center.y = diameter/2;
free_line = scan_lines;
circle_accept(pr, LIMIT((diameter/2)-2));
return pr;
}
/*
* The routines below borrow ideas from the Sun Bresenham
* circle code in iconedit.
*/
/*
* Draw a circle inside pr, with length as given here, and with center as
* set in global variable 'center'.
*/
circle_accept(pr, length)
struct pixrect *pr;
{
int d, x, y;
x = 0;
y = length;
d = 3 - 2*y;
while ( x < y ) {
circle_fill_pair(pr, x, y);
if (d < 0)
d += 4*x + 6;
else {
d += 4*(x-y) +10;
y -= 1;
}
x++;
}
if (x == y) {
circle_fill_pair(pr, x, y);
}
circle_fill(pr);
}
static void
circle_fill_pair(pr, x, y)
struct pixrect *pr;
register int x, y;
{
register struct fill_line *line_ptr = free_line;
free_line += 4;
line_ptr->left = LIMIT(center.x - x);
line_ptr->right = LIMIT(center.x + x);
line_ptr->y = LIMIT(center.y - y);
++line_ptr;
line_ptr->left = LIMIT(center.x - y);
line_ptr->right = LIMIT(center.x + y);
line_ptr->y = LIMIT(center.y - x);
++line_ptr;
line_ptr->left = LIMIT(center.x - y);
line_ptr->right = LIMIT(center.x + y);
line_ptr->y = LIMIT(center.y + x);
++line_ptr;
line_ptr->left = LIMIT(center.x - x);
line_ptr->right = LIMIT(center.x + x);
line_ptr->y = LIMIT(center.y + y);
}
static int
compare_lines(l1, l2)
register struct fill_line *l1, *l2;
{
if (l1->y < l2->y)
return -1;
else if (l1->y > l2->y)
return 1;
else if (l1->left < l2->left || l1->right > l2->right)
return -1;
else if (l1->left > l2->left || l1->right < l2->right)
return 1;
else return 0;
}
static void
circle_fill(pr)
struct pixrect *pr;
{
register struct fill_line *line_ptr = scan_lines;
register int len, y = -1;
qsort(scan_lines, free_line - scan_lines,
sizeof(struct fill_line), compare_lines);
while (line_ptr < free_line) {
register int x0;
if (line_ptr->y != y) {
x0 = line_ptr->left;
y = line_ptr->y;
len = line_ptr->right - x0 + 1;
pr_vector(pr, x0, y, x0+len, y, PIX_SET, 1);
}
line_ptr++;
}
}