home *** CD-ROM | disk | FTP | other *** search
- 18-Jun-88 14:35:41-MDT,24983;000000000000
- Return-Path: <u-lchoqu%sunset@cs.utah.edu>
- Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:35:12 MDT
- Received: by cs.utah.edu (5.54/utah-2.0-cs)
- id AA22408; Sat, 18 Jun 88 14:35:09 MDT
- Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
- id AA24685; Sat, 18 Jun 88 14:35:04 MDT
- Date: Sat, 18 Jun 88 14:35:04 MDT
- From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
- Message-Id: <8806182035.AA24685@sunset.utah.edu>
- To: rthum@simtel20.arpa
- Subject: Maxwell.shar
-
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # 2 README
- # 1 ball.h
- # 10 damain.c
- # 5 movebits.c
- # 5 phys.c
- #
- echo 'Extracting README'
- if test -f README; then echo 'shar: will not overwrite README'; else
- sed 's/^X//' << '________This_Is_The_END________' > README
- XThis is the Maxwell desk accessory. It is written in version 2.? of
- XMegamax C. This is public domain.
- X
- XTo compile this, stick it on your Mac, and compile all the .c files.
- XLink the resulting objects, with damain.o being first. Make sure to
- Xtell the linker that you are makeing a DRVR, not CODE.
- X
- XNote that these files were edited with tabstops set every four.
- X
- XHere is a suggestion for decreasing the turnaround time
- Xif you are going to make changes to this:
- X
- X 1. Modify some random program that supports DAs to open
- X a resource file named TESTDA before it puts up the Apple
- X menu. The editor demo program from Megamax is a good
- X choice. Just change the place where it tries to open
- X "clock" to open "TESTDA" instead.
- X
- X 2. Have the linker put the DA in TESTDA. Be sure to use
- X the same resource ID each time, or things might get
- X confused.
- X
- X 3. Add an "Edit DA" item to the FILE menu.
- X
- X 4. The code for the "Edit DA" menu item should be something
- X like this:
- X
- X char *argv[] = {
- X "file1.c", "file2.c", "file3.c", 0
- X }; /* or whatever your source files are called */
- X
- X edit_da() {
- X execv( "editor", argv );
- X }
- X You might need to use the form "volume:name" for your file
- X names, or to get the editor, depending on how you set things
- X up.
- X
- XThis changes the test cycle from
- X
- X editor -> compiler -> linker -> resource editor -> finder -> editor
- X
- Xto
- X
- X editor -> compiler -> linker -> program -> editor
- X
- Xwhich can be faster.
- X
- X Tim Smith
- ________This_Is_The_END________
- if test `wc -l < README` -ne 49; then
- echo 'shar: README was damaged during transit'
- echo ' (should have been 49 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'Extracting ball.h'
- if test -f ball.h; then echo 'shar: will not overwrite ball.h'; else
- sed 's/^X//' << '________This_Is_The_END________' > ball.h
- Xtypedef struct particle {
- X long x,y; /* location */
- X long vx, vy; /* velocity */
- X int pict; /* which picture this ball is */
- X} ball;
- X
- X#define GRAD 6 /* radius for drawing (quickdraw units) */
- X#define CRAD 28 /* radius for collision (box units) */
- X#define SDIM (2*GRAD) /* diameter on screen */
- X
- X#define SLOW 225 /* max v squared for slow ball */
- ________This_Is_The_END________
- if test `wc -l < ball.h` -ne 11; then
- echo 'shar: ball.h was damaged during transit'
- echo ' (should have been 11 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'Extracting damain.c'
- if test -f damain.c; then echo 'shar: will not overwrite damain.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > damain.c
- X/*
- X * Maxwell: particles in box, with gate in middle. Inspired by the
- X * demo by the same name for the Teletype DMD 5620 terminal.
- X */
- X
- X#include <acc.h>
- X#include <desk.h>
- X#include <qd.h>
- X#include <qdvars.h>
- X#include <event.h>
- X#include <res.h>
- X#include <misc.h>
- X#include <mem.h>
- X#include <menu.h>
- X#include <te.h>
- X#include <font.h>
- X#include <file.h>
- X#include <win.h>
- X#include <control.h>
- X#include <device.h>
- X#include "ball.h"
- X
- X#define NULL 0
- X
- XACC( 0x2400, 2, 0xfffb, 0, 7, "Maxwell" )
- X
- X#define MAXBALLS 20 /* must be even */
- X
- Xball Balls[ MAXBALLS ];
- Xint nBalls;
- Xint GateState;
- XControlHandle help;
- X
- Xint wide = 300; /* initial size of box */
- Xint tall = 255;
- X
- Xaccopen( dctl, pb )
- X dctlentry *dctl;
- X paramblockrec *pb;
- X{
- X WindowPeek mywindow;
- X Rect bound; int i;
- X
- X if ( dctl->dCtlWindow == NULL )
- X {
- X GrafPtr saveport;
- X
- X GetPort( &saveport );
- X SetRect( &bound, 100, 40, 130 + wide, 80 + tall );
- X mywindow = NewWindow( 0L, &bound, "Maxwell", -1,
- X DocumentProc, -1L, -1, 0L );
- X mywindow->windowKind = dctl->dCtlRefNum;
- X dctl->dCtlWindow = mywindow;
- X initmove();
- X SetPort( mywindow );
- X helpControl( mywindow );
- X InitRandom( TickCount() );
- X SetupUniverse();
- X SetPort( saveport );
- X }
- X return 0;
- X}
- X
- Xaccclose( dctl, pb )
- X dctlentry *dctl;
- X paramblockrec *pb;
- X{
- X DisposeWindow( dctl->dCtlWindow );
- X dctl->dCtlWindow = NULL;
- X return 0;
- X}
- X
- Xaccctl( dctl, pb )
- X dctlentry *dctl;
- X paramblockrec *pb;
- X{
- X WindowPtr mywindow;
- X int code;
- X EventRecord *erp;
- X int infront, inmine;
- X
- X code = pb->paramunion.CntrlParam.CSCode;
- X mywindow = dctl->dCtlWindow;
- X
- X SetPort( mywindow );
- X
- X infront = mywindow == FrontWindow();
- X
- X switch ( code ) {
- Xcase accRun:
- X step( mywindow, infront );
- X break;
- Xcase accEvent:
- X erp = (EventRecord *)(pb->paramunion.CntrlParam.csParam.eventaddr);
- X switch ( erp->what ) {
- X case activateEvt:
- X case updateEvt:
- X setgate(0);
- X redraw( mywindow );
- X HiliteControl( help, infront ? 0 : 255 );
- X break;
- X case mouseDown:
- X /*
- X * Only mouse down events we care about are in the grow
- X * icon and in the help button. I tried FindWindow(),
- X * but it refused to distinguish between the grow icon
- X * and the rest of the content region, so instead, I
- X * will just do it directly with co-ordinates.
- X */
- X if ( infront ) {
- X GlobalToLocal( &erp->where );
- X /*
- X * check grow icon...
- X */
- X if ( 15+wide < erp->where.a.h
- X && erp->where.a.h < 30+wide
- X && 25+tall < erp->where.a.v &&
- X erp->where.a.v < 40+tall
- X ) {
- X LocalToGlobal( &erp->where );
- X resize( mywindow, &erp->where );
- X } else
- X /*
- X * see if there is any reason to check the help button...
- X */
- X if ( erp->where.a.v <= 25 )
- X /*
- X * yup, there is...
- X */
- X checkhelp( erp, mywindow );
- X }
- X break;
- X }
- X break;
- X }
- X}
- X
- Xaccprime() {}
- Xaccstatus() {}
- X
- X/*
- X * step() moves all the balls
- X */
- Xstatic int nslow;
- X
- Xstep(wp, infront)
- X GrafPtr wp;
- X{
- X register int i,j;
- X
- X nslow = 0;
- X sortballs();
- X for ( i = 0; i < nBalls; i++ ) {
- X for ( j = i+1; j < nBalls; j++ )
- X if ( bbump( Balls+i, Balls+j ) )
- X break;
- X wbump( Balls+i );
- X if ( infront )
- X setgate( Button() );
- X }
- X /*
- X * If we just draw the balls in order on the screen it will look
- X * bad, since we have them sorted by x.
- X */
- X for ( i = 0; i < 10; i++ )
- X for ( j = i; j < nBalls; j += 10 )
- X MoveBall( Balls + j, wp );
- X
- X if ( nslow < nBalls/3 )
- X walls( -1 );
- X else
- X if ( nslow >= (nBalls/3)<<1 )
- X walls( 1 );
- X else
- X walls( 0 );
- X}
- X
- XMoveBall( pA, wp )
- X register ball *pA;
- X GrafPtr wp;
- X{
- X Rect R;
- X register long v2;
- X ball before;
- X
- X before = *pA; /* save old ball */
- X mball( pA ); /* compute new ball */
- X
- X v2 = pA->vx * pA->vx + pA->vy * pA->vy;
- X
- X if ( v2 <= SLOW ) nslow++;
- X
- X pA->pict = (v2 <= SLOW ? 0 : 1);
- X
- X Draw( wp, &before, pA );
- X
- X return;
- X}
- X
- X
- X/*
- X * redraw() is called to deal with update events in our window
- X */
- Xredraw( wp )
- X GrafPtr wp;
- X{
- X Rect bound; int i;
- X
- X BeginUpdate( wp );
- X SetRect( &bound, 0, 0, wide+30, tall+40 );
- X EraseRect( &bound ); /* clear whole window */
- X SetRect( &bound, 15, 25, 15+wide, 25+tall );
- X FrameRect( &bound ); /* draw outer border */
- X SetRect( &bound, 13+wide/2, 25, 17+wide/2, 25+tall );
- X InvertRect( &bound ); /* draw barrier */
- X SetRect( &bound, 13+wide/2, 24+tall/3, 17+wide/2, 26+(tall+tall)/3 );
- X InvertRect( &bound ); /* remove gate + 1 pixel */
- X Toggle();
- X GateState = 0; /* gate is closed */
- X DrawControls( wp );
- X
- X /*
- X * Now draw the balls. This only works for an even number of balls,
- X * since Draw() wants two balls.
- X */
- X for ( i = 0; i < nBalls; i+=2 )
- X Draw( wp, Balls + i, Balls + i + 1 );
- X
- X EndUpdate( wp );
- X
- X /*
- X * now do the grow icon
- X */
- X SetRect( &bound, wide+15, tall+25, wide+30, tall+40 );
- X ClipRect( &bound );
- X DrawGrowIcon( wp );
- X SetRect( &bound, 0, 0, 31415, 27182 );
- X ClipRect( &bound );
- X}
- X
- X/*
- X * Draw() draws two balls in the window. It is used both to draw the
- X * initial balls, with the two balls being different balls, and to
- X * draw a ball that has moved. In the latter case, the two balls are
- X * the same ball, once at the old position and once at the new postion.
- X * This works since drawing is done in xor mode.
- X */
- XDraw( wp, pA, pB )
- X GrafPtr wp;
- X register ball *pA, *pB;
- X{
- X register long ax, ay, bx, by;
- X
- X ax = pA->x >> 2;
- X ay = pA->y >> 2;
- X
- X bx = pB->x >> 2;
- X by = pB->y >> 2;
- X
- X movebits( wp, bx-GRAD+15, by-GRAD+25, ax-GRAD+15,
- X ay-GRAD+25, (long)pB->pict, (long)pA->pict );
- X}
- X
- X/*
- X * set gate to a given state. bs != 0 means make sure the gate is
- X * open, and bs == 0 means make sure it is closed.
- X */
- Xsetgate( bs ) {
- X if ( !!bs != GateState ) {
- X GateState = !!bs;
- X Toggle();
- X }
- X}
- X
- X/*
- X * Change the state of the gate on the screen
- X */
- XToggle() {
- X Rect bound;
- X
- X SetRect( &bound, 13+wide/2, 25+tall/3, 17+wide/2, 25+(tall+tall)/3 );
- X InvertRect( &bound );
- X}
- X
- XInitRandom( seed )
- X long seed;
- X{
- X asm {
- X move.l (A5), A0
- X move.l seed(A6), 0xff82(A0)
- X }
- X}
- X
- X/*
- X * Generate a random integer in [low,high]. If "contract" is not zero,
- X * it skews the distribution to favor numbers nearer the center of
- X * the interval
- X */
- Xrani(low,high,contract)
- X int low, high;
- X{
- X register long r;
- X register int range;
- X
- X r = (Random()>>1) + 16384;
- X if ( !contract )
- X return r * (high-low) / 32768L + low;
- X
- X range = (high - low) >> 1;
- X
- X r = r * range;
- X r /= 32768;
- X r *= Random();
- X range = r / 32768;
- X
- X return ( (low + high) >> 1 ) + range;
- X}
- X
- X/*
- X * Set up balls.
- X */
- XSetupUniverse() {
- X int i; long nb;
- X
- X PenNormal();
- X PenMode( patXor );
- X
- X nb = (long)tall * (long)wide; nb >>= 13; nb <<= 1;
- X nBalls = nb + 4;
- X if ( nBalls > MAXBALLS )
- X nBalls = MAXBALLS;
- X
- X for ( i = 0; i < nBalls; i++ ) {
- X register long a,b;
- X
- X Balls[i].x = rani(CRAD, (wide<<2)-CRAD, 0);
- X Balls[i].y = rani(CRAD, (tall<<2)-CRAD, 0);
- X Balls[i].vx = a = rani(-40, 40, 1);
- X Balls[i].vy = b = rani(-40, 40, 1);
- X if ( a*a + b*b <= SLOW )
- X Balls[i].pict = 0;
- X else
- X Balls[i].pict = 1;
- X }
- X}
- X
- X/*
- X * resize the window
- X */
- Xresize( wp, mp )
- X WindowPtr wp;
- X Point *mp;
- X{
- X Rect sizerect; long result;
- X
- X SetRect( &sizerect, 150, 80, 2500, 402 );
- X result = GrowWindow( wp, mp, &sizerect );
- X if ( !result )
- X return;
- X tall = result >> 16; tall &= 0xffff;
- X wide = result & 0xffff;
- X
- X wide -= 29; wide -= wide % 2;
- X tall -= 38; tall -= tall % 3;
- X
- X DisposeControl( help );
- X
- X SizeWindow( wp, wide + 30, tall + 40, 0 );
- X
- X helpControl( wp );
- X
- X SetRect( &sizerect, 0, 0, wide + 30, tall + 40 );
- X InvalRect( &sizerect );
- X
- X SetupUniverse();
- X redraw( wp );
- X}
- X
- X/*
- X * Sort balls by x co-ordinate. The first time this is called, it has
- X * to do a lot of work, but on subsequent calls, the balls will for the
- X * most part be already in order. We shall use a bubble sort, since
- X * it is very fast for an already sorted list.
- X */
- Xsortballs() {
- X register int i, j, flag;
- X
- X flag = 1;
- X for ( i = 0; i < (nBalls - 1) && flag; i++ )
- X for ( flag = 0, j = nBalls-1; j > i; --j )
- X if ( Balls[j-1].x > Balls[j].x ) {
- X ball temp;
- X flag = 1;
- X temp = Balls[j-1]; Balls[j-1] = Balls[j];
- X Balls[j] = temp;
- X }
- X}
- X
- X/*
- X * repond to a click in the help button
- X */
- Xshowhelp() {
- X Rect bound;
- X WindowPtr wp;
- X char *h1, *h2, *h3, *h4;
- X char helptext[1024];
- X
- X SetRect( &bound, 91, 68, 421, 303 );
- X wp = NewWindow( 0L, &bound, "A", -1, DBoxProc, -1L, 0, 0L );
- X SetPort( wp );
- X
- X TextMode( srcXor );
- X TextSize( 9 );
- X
- X SetRect( &bound, 10, 10, 320, 225 );
- X
- X h1 = "\
- XMaxwell V2.1 from Mithral Engineering\r\r\
- XWhenever the Maxwell window is in front, holding down the\
- X mouse button opens the gate so that balls may go from one\
- X side to the other.\r\r";
- X h2 = "\
- XTry to get all the fast balls ( the black ones ) in the right\
- X half of the window, and all the slow ones in the left.\r\r\
- XDue to roundoff errors, at each collision there is a slight";
- X h3 = "\
- X net decrease in the total energy of the balls. To balance\
- X this, the right wall will become 'hot' if less than one third\
- X of the balls are fast balls. When a slow ball hits the hot right";
- X h4 = "\
- X wall, it will become a very fast ball. When more than one third\
- X of the balls are fast, the right wall will cool off.\r\r\
- XThis program and its source code are in the public domain";
- X
- X strcpy( helptext, h1 );
- X strcat( helptext, h2 );
- X strcat( helptext, h3 );
- X strcat( helptext, h4 );
- X
- X TextBox( helptext, (long)strlen( helptext ), &bound, teJustLeft );
- X
- X while ( !Button() )
- X ;
- X FlushEvents( mDownMask, 0 );
- X DisposeWindow( wp );
- X}
- X
- X/*
- X * put up the help button
- X */
- XhelpControl( wp )
- X WindowPtr wp;
- X{
- X Rect bound;
- X
- X SetRect( &bound, (wide>>1)-7, 4 , (wide>>1)+37, 22 );
- X
- X help = NewControl( wp, &bound, "Info...", -1,0,0,0, PushButProc, 0L );
- X}
- X
- X/*
- X * find out if the user wants help
- X */
- Xcheckhelp( erp, win )
- X EventRecord * erp;
- X WindowPtr win;
- X{
- X int part;
- X ControlHandle ch;
- X
- X part = FindControl( &erp->where, win, &ch );
- X
- X if ( part != inButton || ch != help )
- X return;
- X
- X part = TrackControl( ch, &erp->where, 0L );
- X
- X if ( part == inButton )
- X showhelp();
- X}
- ________This_Is_The_END________
- if test `wc -l < damain.c` -ne 480; then
- echo 'shar: damain.c was damaged during transit'
- echo ' (should have been 480 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'Extracting movebits.c'
- if test -f movebits.c; then echo 'shar: will not overwrite movebits.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > movebits.c
- X/*
- X * move or draw ball on screen
- X */
- X
- X#include <qd.h>
- X#include <qdvars.h>
- X#include "ball.h"
- X
- X/*
- X * There are three off-screen bitmaps. The first two hold the images of
- X * a slow ball and a fast ball. The third is used for combining the
- X * before and after pictures so that a screen update of a moving ball
- X * whose new postion overlaps its old position can be done in one
- X * screen operation. This is intended to reduce flicker, by cutting
- X * number of copybits calls to the screen from two to one per slow
- X * moving ball. However, it increases the total number of copybits
- X * calls, which makes things run slower.
- X *
- X * The use of this third bitmap is enabled by defining SMOOTH. It will
- X * run ~25% slower with SMOOTH defined.
- X */
- X
- Xchar sbits[ 2*(SDIM)*((SDIM+15)/16) ]; /* slow bits */
- Xchar fbits[ 2*(SDIM)*((SDIM+15)/16) ]; /* fast bits */
- X#ifdef SMOOTH
- Xchar dbits[ 2*(2*SDIM)*((2*SDIM+15)/16) ]; /* combined bits */
- X#endif
- X
- XBitMap sm, fm /* bitmaps for slow and fast bits */
- X#ifdef SMOOTH
- X ,dm /* and combined bits */
- X#endif
- X;
- X
- X/*
- X * movebits() draws two balls. The first is in the square with corner
- X * at Sx, Sy, and side SDIM. The second is at Dx and Dy, and has the
- X * same size. Which drawing to use for each is determined by op and np.
- X */
- Xmovebits( win, Sx, Sy, Dx, Dy, op, np )
- X GrafPtr win;
- X long Sx, Sy, Dx, Dy, op, np;
- X{
- X register int sx, sy, dx, dy;
- X int tx,ty;
- X int rt, rl;
- X Rect S,D;
- X
- X /*
- X * The pointers to the bits in the bitmaps may have changed if we
- X * have been moved on the heap since we were initialized, so we shall
- X * fix them.
- X */
- X sm.baseAddr = sbits;
- X fm.baseAddr = fbits;
- X#ifdef SMOOTH
- X dm.baseAddr = dbits;
- X#endif
- X
- X sx = Sx; sy = Sy; dx = Dx; dy = Dy; /* convert to integers */
- X tx = dx - sx; /* relative x positions */
- X ty = dy - sy; /* relative y positions */
- X
- X
- X#define pict(v) ((v) == 0 ? &sm : &fm )
- X
- X SetPort( win );
- X
- X/*
- X * If the balls do not overlap, or if SMOOTH is not defined, then we
- X * simply want to erase the first ball and draw the second.
- X */
- X#ifdef SMOOTH
- X /*
- X * If the balls can't possibly overlap, then just draw them directly
- X * on the screen
- X */
- X if ( tx < -GRAD || tx > GRAD || ty < -GRAD || ty > GRAD ) {
- X#endif
- X SetRect( &S, 0, 0, SDIM, SDIM );
- X SetRect( &D, sx, sy, sx + SDIM, sy + SDIM );
- X CopyBits( pict(op), &win->portBits, &S, &D, srcXor, 0L );
- X SetRect( &D, dx, dy, dx + SDIM, dy + SDIM );
- X CopyBits( pict(np), &win->portBits, &S, &D, srcXor, 0L );
- X return;
- X#ifdef SMOOTH
- X }
- X
- X /*
- X * The balls are close enough that we may combine their updates into
- X * one CopyBits to the screen.
- X */
- X
- X /*
- X * The rest of this is a pain to explain without a diagram,
- X * so figure it out for yourself!
- X */
- X if ( ty > 0 )
- X if ( tx > 0 ) { rt = 0; rl = 0; }
- X else { rt = 0; rl = SDIM; }
- X else
- X if ( tx > 0 ) { rt = SDIM; rl = 0; }
- X else { rt = SDIM; rl = SDIM; }
- X
- X SetRect( &D, 0, 0, 2*SDIM, 2*SDIM );
- X CopyBits( &dm, &dm, &D, &D, srcXor, 0L );
- X SetRect( &S, 0, 0, SDIM, SDIM );
- X SetRect( &D, rl, rt, rl+SDIM, rt+SDIM );
- X CopyBits( pict(op), &dm, &S, &D, srcCopy, 0L );
- X SetRect( &D, rl + tx, rt + ty, rl + tx + SDIM, rt + ty + SDIM );
- X CopyBits( pict(np), &dm, &S, &D, srcXor, 0L );
- X SetRect( &S, 0, 0, SDIM*2, SDIM*2 );
- X SetRect( &D, sx - rl, sy - rt, sx - rl + 2*SDIM, sy - rt + 2*SDIM );
- X CopyBits( &dm, &win->portBits, &S, &D, srcXor, 0L );
- X#endif
- X}
- X
- X/*
- X * Initialize the bitmaps
- X */
- Xinitmove() {
- X Rect S,D;
- X GrafPort port;
- X
- X /*
- X * get a grafport to do our thing in
- X */
- X OpenPort( &port );
- X PenNormal();
- X
- X /*
- X * bitmap for slow bits...
- X */
- X sm.baseAddr = sbits;
- X sm.rowBytes = 2*((SDIM+15)/16);
- X sm.bounds.a.top = 0;
- X sm.bounds.a.bottom = 2*SDIM;
- X sm.bounds.a.left = 0;
- X sm.bounds.a.right = 2*SDIM;
- X
- X /*
- X * bitmap for fast bits...
- X */
- X fm.baseAddr = fbits;
- X fm.rowBytes = 2*((SDIM+15)/16);
- X fm.bounds.a.top = 0;
- X fm.bounds.a.bottom = 2*SDIM;
- X fm.bounds.a.left = 0;
- X fm.bounds.a.right = 2*SDIM;
- X
- X SetPortBits( &sm ); /* prepare to draw slow ball */
- X
- X SetRect( &S, 0, 0, SDIM, SDIM );
- X FrameOval( &S );
- X MoveTo( 3, 7 ); LineTo( 4, 8 ); /* ...risking the taste-police */
- X LineTo( 7, 8 ); LineTo( 8, 7 );
- X MoveTo( 4, 4 ); LineTo( 4, 4 );
- X MoveTo( 7, 4 ); LineTo( 7, 4 );
- X
- X SetPortBits( &fm ); /* prepare to draw fast ball */
- X InvertOval( &S );
- X
- X#ifdef SMOOTH
- X /*
- X * bitmap for combined drawings...
- X */
- X dm.baseAddr = dbits;
- X dm.rowBytes = 2*((SDIM+SDIM+15)/16);
- X dm.bounds.a.top = 0;
- X dm.bounds.a.bottom = 2*SDIM;
- X dm.bounds.a.left = 0;
- X dm.bounds.a.right = 2*SDIM;
- X#endif
- X}
- ________This_Is_The_END________
- if test `wc -l < movebits.c` -ne 174; then
- echo 'shar: movebits.c was damaged during transit'
- echo ' (should have been 174 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'Extracting phys.c'
- if test -f phys.c; then echo 'shar: will not overwrite phys.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > phys.c
- X/*
- X * do collisions and movement
- X */
- X
- X#include "ball.h"
- X
- Xextern wide, tall; /* the size of the box we are in */
- Xextern GateState; /* != 0 iff gate is open */
- X
- X#define TWO(X) ((X)+(X))
- X#define THREE(X) (TWO(X)+(X))
- X
- X/*
- X * bbump() deals with a possible collision between two specific balls.
- X * The first ball will not be to the right of the second ball. Returns
- X * one if the second ball is far enough to the right so that no balls
- X * farther right could collide with the first ball, else returns zero
- X */
- Xbbump( pA, pB )
- X register ball *pA, *pB;
- X{
- X register long k;
- X long tAvx, tAvy;
- X register long tBx, tBy;
- X long tBvx, tBvy;
- X long WIDE, TALL;
- X
- X WIDE = wide<<2; /* scale from window to physical co-ords */
- X TALL = tall<<2;
- X
- X /*
- X * Deal with the barrier and the gate
- X */
- X if ( TWO(pA->x) <= WIDE && TWO(pB->x) >= WIDE )
- X /* gate closed means no collision */
- X if ( ! GateState )
- X return 0;
- X else
- X /* if either ball is below gate, no collision */
- X if ( THREE(pA->y) < TALL || THREE(pB->y) < TALL )
- X return 0;
- X else
- X /* if either ball is above gate, no collision */
- X if ( THREE(pA->y) > TWO(TALL) || THREE(pB->y) > TWO(TALL) )
- X return 0;
- X
- X /* shift to A's co-ordinate system */
- X tBx = pB->x - pA->x;
- X tBy = pB->y - pA->y;
- X tBvx = pB->vx - pA->vx; tAvx = 0;
- X tBvy = pB->vy - pA->vy; tAvy = 0;
- X
- X /*
- X * see if the balls are close enough to have collided
- X */
- X if ( tBx > TWO(CRAD) )
- X return 1;
- X if ( tBx * tBx + tBy * tBy > (CRAD*CRAD<<2) )
- X return 0;
- X
- X k = tBx * tBvx + tBy * tBvy;
- X
- X /*
- X * make sure they are going towards each other
- X */
- X if ( k > -1 )
- X return 0;
- X
- X k = ( tBy * tBvx - tBx * tBvy ) / k;
- X
- X tAvx = ( tBvx - k * tBvy ) / ( 1 + k*k );
- X tAvy = ( k * tBvx + tBvy ) / ( 1 + k*k );
- X
- X tBvx = k * tAvy;
- X tBvy = -k * tAvx;
- X
- X pB->vx = pA->vx + tBvx;
- X pB->vy = pA->vy + tBvy;
- X pA->vx += tAvx;
- X pA->vy += tAvy;
- X
- X return 0;
- X}
- X
- X/*
- X * Because the calculations above use longs instead of floats, we have a
- X * lot of round off error. This seems to manifest itself by causing the
- X * balls to slow down over time. We use the walls to correct this.
- X *
- X * If "we" is greater than zero, we are attempting to add energy to the
- X * system. We do this by looking for slow balls bouncing off the right
- X * wall. When we find such a ball, we give it a swift kick towards the
- X * left.
- X *
- X * If "we" is less than zero, then we are trying to remove energt from
- X * the system for some reason. In this case, the outer walls become
- X * slightly sticky, with the ball slowing down by abs(we) perpendicular
- X * to the wall.
- X *
- X * This stuff is done in wbump().
- X *
- X */
- X
- Xstatic int we = 0; /* wall energy factor */
- X
- Xwalls( i ) {
- X we = i;
- X}
- X
- X/*
- X * wump() checks for collisions between a ball walls or the gate
- X */
- Xwbump( pA )
- X register ball *pA;
- X{
- X register long WIDE, TALL;
- X
- X WIDE = wide<<2; TALL = tall<<2;
- X
- X if ( (pA->x <= CRAD && pA->vx < 0)
- X || (pA->x >= WIDE-CRAD && pA->vx > 0) ) {
- X pA->vx = -pA->vx;
- X if ( we > 0 ) {
- X if ( pA->vx < 0 && pA->pict == 0 && pA->x >= WIDE-CRAD)
- X pA->vx -= 30; /* swift kick */
- X } else {
- X if ( pA->vx > 0 )
- X pA->vx += we;
- X else
- X pA->vx -= we;
- X }
- X }
- X if ( (pA->y <= CRAD && pA->vy < 0)
- X || (pA->y >= TALL-CRAD && pA->vy > 0) ) {
- X pA->vy = -pA->vy;
- X if ( we < 0 ) {
- X if ( pA->vy > 0 )
- X pA->vy += we;
- X else
- X pA->vy -= we;
- X }
- X
- X }
- X
- X /*
- X * if the ball is on the same level as the gate, and the gate is open,
- X * there is nothing for the ball to hit on the barrier
- X */
- X if ( TALL < THREE(pA->y) && THREE(pA->y) < TWO(TALL) && GateState )
- X return;
- X
- X WIDE >>= 1; /* location of the barrier */
- X
- X /*
- X * see if the ball hits the barrier
- X */
- X if ( pA->x <= WIDE && pA->vx > 0 ) {
- X if ( pA->x + CRAD >= WIDE || pA->x + pA->vx > WIDE )
- X pA->vx = -pA->vx;
- X } else
- X if ( pA->x >= WIDE && pA->vx < 0 )
- X if ( pA->x - CRAD <= WIDE || pA->x + pA->vx < WIDE )
- X pA->vx = -pA->vx;
- X}
- X
- Xmball( pA )
- X ball *pA;
- X{
- X register long vx, vy;
- X pA->x += vx = pA->vx;
- X pA->y += vy = pA->vy;
- X
- X /*
- X * check for stalled balls, and offer them a chance to get going again
- X */
- X if ( vx == 0 && vy == 0 ) {
- X if ( Random() > 0 )
- X pA->vx = Random() > 0 ? 1 : -1;
- X if ( Random() > 0 )
- X pA->vy = Random() > 0 ? 1 : -1;
- X }
- X}
- ________This_Is_The_END________
- if test `wc -l < phys.c` -ne 182; then
- echo 'shar: phys.c was damaged during transit'
- echo ' (should have been 182 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
-