home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / code / shar_max.sit < prev    next >
Text File  |  1988-06-20  |  24KB  |  972 lines

  1. 18-Jun-88 14:35:41-MDT,24983;000000000000
  2. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  3. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:35:12 MDT
  4. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  5.     id AA22408; Sat, 18 Jun 88 14:35:09 MDT
  6. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  7.     id AA24685; Sat, 18 Jun 88 14:35:04 MDT
  8. Date: Sat, 18 Jun 88 14:35:04 MDT
  9. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  10. Message-Id: <8806182035.AA24685@sunset.utah.edu>
  11. To: rthum@simtel20.arpa
  12. Subject: Maxwell.shar
  13.  
  14. #! /bin/sh
  15. #
  16. # This is a shell archive.  Save this into a file, edit it
  17. # and delete all lines above this comment.  Then give this
  18. # file to sh by executing the command "sh file".  The files
  19. # will be extracted into the current directory owned by
  20. # you with default permissions.
  21. #
  22. # The files contained herein are:
  23. #
  24. #    2 README
  25. #    1 ball.h
  26. #   10 damain.c
  27. #    5 movebits.c
  28. #    5 phys.c
  29. #
  30. echo 'Extracting README'
  31. if test -f README; then echo 'shar: will not overwrite README'; else
  32. sed 's/^X//' << '________This_Is_The_END________' > README
  33. XThis is the Maxwell desk accessory.  It is written in version 2.? of
  34. XMegamax C.  This is public domain.
  35. X
  36. XTo compile this, stick it on your Mac, and compile all the .c files.
  37. XLink the resulting objects, with damain.o being first.  Make sure to
  38. Xtell the linker that you are makeing a DRVR, not CODE.
  39. X
  40. XNote that these files were edited with tabstops set every four.
  41. X
  42. XHere is a suggestion for decreasing the turnaround time
  43. Xif you are going to make changes to this:
  44. X
  45. X    1. Modify some random program that supports DAs to open
  46. X    a resource file named TESTDA before it puts up the Apple
  47. X    menu.  The editor demo program from Megamax is a good
  48. X    choice.  Just change the place where it tries to open
  49. X    "clock" to open "TESTDA" instead.
  50. X
  51. X    2. Have the linker put the DA in TESTDA.  Be sure to use
  52. X    the same resource ID each time, or things might get
  53. X    confused.
  54. X
  55. X    3. Add an "Edit DA" item to the FILE menu.
  56. X
  57. X    4. The code for the "Edit DA" menu item should be something
  58. X    like this:
  59. X
  60. X        char *argv[] = {
  61. X            "file1.c", "file2.c", "file3.c", 0
  62. X        };      /* or whatever your source files are called */
  63. X
  64. X        edit_da() {
  65. X            execv( "editor", argv );
  66. X        }
  67. X    You might need to use the form "volume:name" for your file
  68. X    names, or to get the editor, depending on how you set things
  69. X    up.
  70. X
  71. XThis changes the test cycle from
  72. X
  73. X    editor -> compiler -> linker -> resource editor -> finder -> editor
  74. X
  75. Xto
  76. X
  77. X    editor -> compiler -> linker -> program -> editor
  78. X
  79. Xwhich can be faster.
  80. X
  81. X                            Tim Smith
  82. ________This_Is_The_END________
  83. if test `wc -l < README` -ne 49; then
  84.     echo 'shar: README was damaged during transit'
  85.   echo '      (should have been 49 bytes)'
  86. fi
  87. fi        ; : end of overwriting check
  88. echo 'Extracting ball.h'
  89. if test -f ball.h; then echo 'shar: will not overwrite ball.h'; else
  90. sed 's/^X//' << '________This_Is_The_END________' > ball.h
  91. Xtypedef struct particle {
  92. X    long x,y;                /* location */
  93. X    long vx, vy;            /* velocity */
  94. X    int    pict;                /* which picture this ball is */
  95. X} ball;
  96. X
  97. X#define    GRAD    6            /* radius for drawing (quickdraw units) */
  98. X#define    CRAD    28            /* radius for collision (box units) */
  99. X#define    SDIM    (2*GRAD)    /* diameter on screen */
  100. X
  101. X#define    SLOW    225            /* max v squared for slow ball */
  102. ________This_Is_The_END________
  103. if test `wc -l < ball.h` -ne 11; then
  104.     echo 'shar: ball.h was damaged during transit'
  105.   echo '      (should have been 11 bytes)'
  106. fi
  107. fi        ; : end of overwriting check
  108. echo 'Extracting damain.c'
  109. if test -f damain.c; then echo 'shar: will not overwrite damain.c'; else
  110. sed 's/^X//' << '________This_Is_The_END________' > damain.c
  111. X/*
  112. X * Maxwell: particles in box, with gate in middle.  Inspired by the
  113. X * demo by the same name for the Teletype DMD 5620 terminal.
  114. X */
  115. X
  116. X#include <acc.h>
  117. X#include <desk.h>
  118. X#include <qd.h>
  119. X#include <qdvars.h>
  120. X#include <event.h>
  121. X#include <res.h>
  122. X#include <misc.h>
  123. X#include <mem.h>
  124. X#include <menu.h>
  125. X#include <te.h>
  126. X#include <font.h>
  127. X#include <file.h>
  128. X#include <win.h>
  129. X#include <control.h>
  130. X#include <device.h>
  131. X#include "ball.h"
  132. X
  133. X#define    NULL    0
  134. X
  135. XACC( 0x2400, 2, 0xfffb, 0, 7, "Maxwell" )
  136. X
  137. X#define MAXBALLS    20                /* must be even */
  138. X
  139. Xball Balls[ MAXBALLS ];
  140. Xint nBalls;
  141. Xint GateState;
  142. XControlHandle help;
  143. X
  144. Xint wide = 300;                        /* initial size of box */
  145. Xint tall = 255;
  146. X
  147. Xaccopen( dctl, pb )
  148. X    dctlentry *dctl;
  149. X    paramblockrec *pb;
  150. X{
  151. X    WindowPeek mywindow;
  152. X    Rect bound; int i;
  153. X            
  154. X    if ( dctl->dCtlWindow == NULL )
  155. X    {
  156. X        GrafPtr saveport;
  157. X        
  158. X        GetPort( &saveport );
  159. X        SetRect( &bound, 100, 40, 130 + wide, 80 + tall );
  160. X        mywindow = NewWindow( 0L, &bound, "Maxwell", -1,
  161. X            DocumentProc, -1L, -1, 0L );
  162. X        mywindow->windowKind = dctl->dCtlRefNum;
  163. X        dctl->dCtlWindow = mywindow;
  164. X        initmove();
  165. X        SetPort( mywindow );
  166. X        helpControl( mywindow );
  167. X        InitRandom( TickCount() );
  168. X        SetupUniverse();
  169. X        SetPort( saveport );
  170. X    }
  171. X    return 0;
  172. X}
  173. X
  174. Xaccclose( dctl, pb )
  175. X    dctlentry *dctl;
  176. X    paramblockrec *pb;
  177. X{
  178. X    DisposeWindow( dctl->dCtlWindow );
  179. X    dctl->dCtlWindow = NULL;
  180. X    return 0;
  181. X}
  182. X
  183. Xaccctl( dctl, pb )
  184. X    dctlentry *dctl;
  185. X    paramblockrec *pb;
  186. X{
  187. X    WindowPtr mywindow;
  188. X    int code;
  189. X    EventRecord *erp;
  190. X    int infront, inmine;
  191. X    
  192. X    code = pb->paramunion.CntrlParam.CSCode;
  193. X    mywindow = dctl->dCtlWindow;
  194. X    
  195. X    SetPort( mywindow );
  196. X
  197. X    infront = mywindow == FrontWindow();
  198. X    
  199. X    switch ( code ) {
  200. Xcase accRun:
  201. X        step( mywindow, infront );
  202. X        break;
  203. Xcase accEvent:
  204. X        erp = (EventRecord *)(pb->paramunion.CntrlParam.csParam.eventaddr);
  205. X        switch ( erp->what ) {
  206. X    case activateEvt:
  207. X    case updateEvt:
  208. X            setgate(0);
  209. X            redraw( mywindow );
  210. X            HiliteControl( help, infront ? 0 : 255 );
  211. X            break;
  212. X    case mouseDown:
  213. X            /*
  214. X             * Only mouse down events we care about are in the grow
  215. X             * icon and in the help button.  I tried FindWindow(),
  216. X             * but it refused to distinguish between the grow icon
  217. X             * and the rest of the content region, so instead, I
  218. X             * will just do it directly with co-ordinates.
  219. X             */
  220. X            if ( infront ) {
  221. X                GlobalToLocal( &erp->where );
  222. X                /*
  223. X                 * check grow icon...
  224. X                 */
  225. X                if ( 15+wide < erp->where.a.h
  226. X                  && erp->where.a.h < 30+wide
  227. X                  && 25+tall < erp->where.a.v &&
  228. X                  erp->where.a.v < 40+tall
  229. X                ) {
  230. X                    LocalToGlobal( &erp->where );
  231. X                    resize( mywindow, &erp->where );
  232. X                } else
  233. X                /*
  234. X                 * see if there is any reason to check the help button...
  235. X                 */
  236. X                if ( erp->where.a.v <= 25 )
  237. X                    /*
  238. X                     * yup, there is...
  239. X                     */
  240. X                    checkhelp( erp, mywindow );
  241. X            }
  242. X            break;
  243. X        }
  244. X        break;
  245. X    }
  246. X}
  247. X
  248. Xaccprime() {}
  249. Xaccstatus() {}
  250. X
  251. X/*
  252. X * step() moves all the balls
  253. X */
  254. Xstatic int nslow;
  255. X
  256. Xstep(wp, infront)
  257. X    GrafPtr wp;
  258. X{
  259. X    register int i,j;
  260. X
  261. X    nslow = 0;
  262. X    sortballs();
  263. X    for ( i = 0; i < nBalls; i++ ) {
  264. X        for ( j = i+1; j < nBalls; j++ )
  265. X            if ( bbump( Balls+i, Balls+j ) )
  266. X                break;
  267. X        wbump( Balls+i );
  268. X        if ( infront )
  269. X            setgate( Button() );
  270. X    }
  271. X    /*
  272. X     * If we just draw the balls in order on the screen it will look
  273. X     * bad, since we have them sorted by x.
  274. X     */
  275. X    for ( i = 0; i < 10; i++ )
  276. X    for ( j = i; j < nBalls; j += 10 )
  277. X        MoveBall( Balls + j, wp );
  278. X
  279. X    if ( nslow < nBalls/3 )
  280. X        walls( -1 );
  281. X    else
  282. X    if ( nslow >= (nBalls/3)<<1 )
  283. X        walls( 1 );
  284. X    else
  285. X        walls( 0 );
  286. X}
  287. X
  288. XMoveBall( pA, wp )
  289. X    register ball *pA;
  290. X    GrafPtr wp;
  291. X{
  292. X    Rect R;
  293. X    register long v2;
  294. X    ball before;
  295. X    
  296. X    before = *pA;        /* save old ball */
  297. X    mball( pA );        /* compute new ball */
  298. X    
  299. X    v2 = pA->vx * pA->vx + pA->vy * pA->vy;
  300. X    
  301. X    if ( v2 <= SLOW ) nslow++;
  302. X    
  303. X    pA->pict = (v2 <= SLOW ? 0 : 1);
  304. X    
  305. X    Draw( wp, &before, pA );
  306. X    
  307. X    return;
  308. X}
  309. X
  310. X
  311. X/*
  312. X * redraw() is called to deal with update events in our window
  313. X */
  314. Xredraw( wp )
  315. X    GrafPtr wp;
  316. X{
  317. X    Rect bound; int i;
  318. X
  319. X    BeginUpdate( wp );
  320. X    SetRect( &bound, 0, 0, wide+30, tall+40 );
  321. X    EraseRect( &bound );                /* clear whole window */
  322. X    SetRect( &bound, 15, 25, 15+wide, 25+tall );
  323. X    FrameRect( &bound );                /* draw outer border */
  324. X    SetRect( &bound, 13+wide/2, 25, 17+wide/2, 25+tall );
  325. X    InvertRect( &bound );                /* draw barrier */
  326. X    SetRect( &bound, 13+wide/2, 24+tall/3, 17+wide/2, 26+(tall+tall)/3 );
  327. X    InvertRect( &bound );                /* remove gate + 1 pixel */
  328. X    Toggle();
  329. X    GateState = 0;                        /* gate is closed */
  330. X    DrawControls( wp );
  331. X    
  332. X    /*
  333. X     * Now draw the balls.  This only works for an even number of balls,
  334. X     * since Draw() wants two balls.
  335. X     */
  336. X    for ( i = 0; i < nBalls; i+=2 )
  337. X        Draw( wp, Balls + i, Balls + i + 1 );
  338. X
  339. X    EndUpdate( wp );
  340. X
  341. X    /*
  342. X     * now do the grow icon
  343. X     */
  344. X    SetRect( &bound, wide+15, tall+25, wide+30, tall+40 );
  345. X    ClipRect( &bound );
  346. X    DrawGrowIcon( wp );
  347. X    SetRect( &bound, 0, 0, 31415, 27182 );
  348. X    ClipRect( &bound );
  349. X}
  350. X
  351. X/*
  352. X * Draw() draws two balls in the window.  It is used both to draw the
  353. X * initial balls, with the two balls being different balls, and to
  354. X * draw a ball that has moved.  In the latter case, the two balls are
  355. X * the same ball, once at the old position and once at the new postion.
  356. X * This works since drawing is done in xor mode.
  357. X */
  358. XDraw( wp, pA, pB )
  359. X    GrafPtr wp;
  360. X    register ball *pA, *pB;
  361. X{
  362. X    register long ax, ay, bx, by;
  363. X    
  364. X    ax = pA->x >> 2;
  365. X    ay = pA->y >> 2;
  366. X    
  367. X    bx = pB->x >> 2;
  368. X    by = pB->y >> 2;
  369. X    
  370. X    movebits( wp, bx-GRAD+15, by-GRAD+25, ax-GRAD+15,
  371. X        ay-GRAD+25, (long)pB->pict, (long)pA->pict );
  372. X}
  373. X
  374. X/*
  375. X * set gate to a given state.  bs != 0 means make sure the gate is
  376. X * open, and bs == 0 means make sure it is closed.
  377. X */
  378. Xsetgate( bs ) {
  379. X    if ( !!bs != GateState ) {
  380. X        GateState = !!bs;
  381. X        Toggle();
  382. X    }
  383. X}
  384. X
  385. X/*
  386. X * Change the state of the gate on the screen
  387. X */
  388. XToggle() {
  389. X    Rect bound;
  390. X
  391. X    SetRect( &bound, 13+wide/2, 25+tall/3, 17+wide/2, 25+(tall+tall)/3 );
  392. X    InvertRect( &bound );
  393. X}
  394. X
  395. XInitRandom( seed )
  396. X    long seed;
  397. X{
  398. X    asm {
  399. X        move.l    (A5), A0
  400. X        move.l    seed(A6), 0xff82(A0)
  401. X    }
  402. X}
  403. X
  404. X/*
  405. X * Generate a random integer in [low,high].  If "contract" is not zero,
  406. X * it skews the distribution to favor numbers nearer the center of
  407. X * the interval
  408. X */
  409. Xrani(low,high,contract)
  410. X    int low, high;
  411. X{
  412. X    register long r;
  413. X    register int range;
  414. X    
  415. X    r = (Random()>>1) + 16384;
  416. X    if ( !contract )
  417. X        return r * (high-low) / 32768L + low;
  418. X    
  419. X    range = (high - low) >> 1;
  420. X    
  421. X    r = r * range;
  422. X    r /= 32768;
  423. X    r *= Random();
  424. X    range = r / 32768;
  425. X    
  426. X    return ( (low + high) >> 1 ) + range;
  427. X}
  428. X
  429. X/*
  430. X * Set up balls.
  431. X */
  432. XSetupUniverse() {
  433. X    int i; long nb;
  434. X    
  435. X    PenNormal();
  436. X    PenMode( patXor );
  437. X    
  438. X    nb = (long)tall * (long)wide; nb >>= 13; nb <<= 1;
  439. X    nBalls = nb + 4;
  440. X    if ( nBalls > MAXBALLS )
  441. X        nBalls = MAXBALLS;
  442. X
  443. X    for ( i = 0; i < nBalls; i++ ) {
  444. X        register long a,b;
  445. X        
  446. X        Balls[i].x  = rani(CRAD, (wide<<2)-CRAD, 0);
  447. X        Balls[i].y  = rani(CRAD, (tall<<2)-CRAD, 0);
  448. X        Balls[i].vx = a = rani(-40, 40, 1);
  449. X        Balls[i].vy = b = rani(-40, 40, 1);
  450. X        if ( a*a + b*b <= SLOW )
  451. X            Balls[i].pict = 0;
  452. X        else
  453. X            Balls[i].pict = 1;
  454. X    }
  455. X}
  456. X
  457. X/*
  458. X * resize the window
  459. X */
  460. Xresize( wp, mp )
  461. X    WindowPtr wp;
  462. X    Point *mp;
  463. X{
  464. X    Rect sizerect; long result;
  465. X    
  466. X    SetRect( &sizerect, 150, 80, 2500, 402 );
  467. X    result = GrowWindow( wp, mp, &sizerect );
  468. X    if ( !result )
  469. X        return;
  470. X    tall = result >> 16; tall &= 0xffff;
  471. X    wide = result & 0xffff;
  472. X    
  473. X    wide -= 29; wide -= wide % 2;
  474. X    tall -= 38; tall -= tall % 3;
  475. X    
  476. X    DisposeControl( help );
  477. X    
  478. X    SizeWindow( wp, wide + 30, tall + 40, 0 );
  479. X    
  480. X    helpControl( wp );
  481. X    
  482. X    SetRect( &sizerect, 0, 0, wide + 30, tall + 40 );
  483. X    InvalRect( &sizerect );
  484. X    
  485. X    SetupUniverse();
  486. X    redraw( wp );
  487. X}
  488. X
  489. X/*
  490. X * Sort balls by x co-ordinate.  The first time this is called, it has
  491. X * to do a lot of work, but on subsequent calls, the balls will for the
  492. X * most part be already in order.  We shall use a bubble sort, since
  493. X * it is very fast for an already sorted list.
  494. X */
  495. Xsortballs() {
  496. X    register int i, j, flag;
  497. X    
  498. X    flag = 1;
  499. X    for ( i = 0; i < (nBalls - 1) && flag; i++ )
  500. X        for ( flag = 0, j = nBalls-1; j > i; --j )
  501. X            if ( Balls[j-1].x > Balls[j].x ) {
  502. X                ball temp;
  503. X                flag = 1;
  504. X                temp = Balls[j-1]; Balls[j-1] = Balls[j];
  505. X                Balls[j] = temp;
  506. X            }
  507. X}
  508. X
  509. X/*
  510. X * repond to a click in the help button
  511. X */
  512. Xshowhelp() {
  513. X    Rect bound;
  514. X    WindowPtr wp;
  515. X    char *h1, *h2, *h3, *h4;
  516. X    char helptext[1024];
  517. X    
  518. X    SetRect( &bound, 91, 68, 421, 303 );
  519. X    wp = NewWindow( 0L, &bound, "A", -1, DBoxProc, -1L, 0, 0L );
  520. X    SetPort( wp );
  521. X
  522. X    TextMode( srcXor );
  523. X    TextSize( 9 );
  524. X    
  525. X    SetRect( &bound, 10, 10, 320, 225 );
  526. X
  527. X    h1 = "\
  528. XMaxwell V2.1 from Mithral Engineering\r\r\
  529. XWhenever the Maxwell window is in front, holding down the\
  530. X mouse button opens the gate so that balls may go from one\
  531. X side to the other.\r\r";
  532. X     h2 = "\
  533. XTry to get all the fast balls ( the black ones ) in the right\
  534. X half of the window, and all the slow ones in the left.\r\r\
  535. XDue to roundoff errors, at each collision there is a slight";
  536. X    h3 = "\
  537. X net decrease in the total energy of the balls.  To balance\
  538. X this, the right wall will become 'hot' if less than one third\
  539. X of the balls are fast balls.  When a slow ball hits the hot right";
  540. X     h4 = "\
  541. X wall, it will become a very fast ball.  When more than one third\
  542. X of the balls are fast, the right wall will cool off.\r\r\
  543. XThis program and its source code are in the public domain";
  544. X
  545. X    strcpy( helptext, h1 );
  546. X    strcat( helptext, h2 );
  547. X    strcat( helptext, h3 );
  548. X    strcat( helptext, h4 );
  549. X
  550. X    TextBox( helptext, (long)strlen( helptext ), &bound, teJustLeft );
  551. X    
  552. X    while ( !Button() )
  553. X        ;
  554. X    FlushEvents( mDownMask, 0 );
  555. X    DisposeWindow( wp );
  556. X}
  557. X
  558. X/*
  559. X * put up the help button
  560. X */
  561. XhelpControl( wp )
  562. X    WindowPtr wp;
  563. X{
  564. X    Rect bound;
  565. X    
  566. X    SetRect( &bound, (wide>>1)-7, 4 , (wide>>1)+37, 22 );
  567. X    
  568. X    help = NewControl( wp, &bound, "Info...", -1,0,0,0, PushButProc, 0L );
  569. X}
  570. X
  571. X/*
  572. X * find out if the user wants help
  573. X */
  574. Xcheckhelp( erp, win )
  575. X    EventRecord * erp;
  576. X    WindowPtr win;
  577. X{
  578. X    int part;
  579. X    ControlHandle ch;
  580. X    
  581. X    part = FindControl( &erp->where, win, &ch );
  582. X    
  583. X    if ( part != inButton || ch != help )
  584. X        return;
  585. X        
  586. X     part = TrackControl( ch, &erp->where, 0L );
  587. X    
  588. X     if ( part == inButton )
  589. X         showhelp();
  590. X}
  591. ________This_Is_The_END________
  592. if test `wc -l < damain.c` -ne 480; then
  593.     echo 'shar: damain.c was damaged during transit'
  594.   echo '      (should have been 480 bytes)'
  595. fi
  596. fi        ; : end of overwriting check
  597. echo 'Extracting movebits.c'
  598. if test -f movebits.c; then echo 'shar: will not overwrite movebits.c'; else
  599. sed 's/^X//' << '________This_Is_The_END________' > movebits.c
  600. X/*
  601. X * move or draw ball on screen
  602. X */
  603. X
  604. X#include <qd.h>
  605. X#include <qdvars.h>
  606. X#include "ball.h"
  607. X
  608. X/*
  609. X * There are three off-screen bitmaps.  The first two hold the images of
  610. X * a slow ball and a fast ball.  The third is used for combining the
  611. X * before and after pictures so that a screen update of a moving ball
  612. X * whose new postion overlaps its old position can be done in one
  613. X * screen operation.  This is intended to reduce flicker, by cutting
  614. X * number of copybits calls to the screen from two to one per slow
  615. X * moving ball.  However, it increases the total number of copybits
  616. X * calls, which makes things run slower.
  617. X *
  618. X * The use of this third bitmap is enabled by defining SMOOTH.  It will
  619. X * run ~25% slower with SMOOTH defined.
  620. X */
  621. X
  622. Xchar sbits[ 2*(SDIM)*((SDIM+15)/16) ];        /* slow bits */
  623. Xchar fbits[ 2*(SDIM)*((SDIM+15)/16) ];        /* fast bits */
  624. X#ifdef SMOOTH
  625. Xchar dbits[ 2*(2*SDIM)*((2*SDIM+15)/16) ];    /* combined bits */
  626. X#endif
  627. X
  628. XBitMap sm, fm                            /* bitmaps for slow and fast bits */
  629. X#ifdef SMOOTH
  630. X    ,dm                                    /* and combined bits */
  631. X#endif
  632. X;
  633. X
  634. X/*
  635. X * movebits() draws two balls.  The first is in the square with corner
  636. X * at Sx, Sy, and side SDIM.  The second is at Dx and Dy, and has the
  637. X * same size.  Which drawing to use for each is determined by op and np.
  638. X */
  639. Xmovebits( win, Sx, Sy, Dx, Dy, op, np )
  640. X    GrafPtr win;
  641. X    long Sx, Sy, Dx, Dy, op, np;
  642. X{
  643. X    register int sx, sy, dx, dy;
  644. X    int tx,ty;
  645. X    int rt, rl;
  646. X    Rect S,D;
  647. X
  648. X    /*
  649. X     * The pointers to the bits in the bitmaps may have changed if we
  650. X     * have been moved on the heap since we were initialized, so we shall
  651. X     * fix them.
  652. X     */
  653. X    sm.baseAddr = sbits;
  654. X    fm.baseAddr = fbits;
  655. X#ifdef SMOOTH
  656. X    dm.baseAddr = dbits;
  657. X#endif
  658. X    
  659. X    sx = Sx; sy = Sy; dx = Dx; dy = Dy; /* convert to integers */
  660. X    tx = dx - sx;                        /* relative x positions */
  661. X    ty = dy - sy;                        /* relative y positions */
  662. X    
  663. X    
  664. X#define pict(v) ((v) == 0 ? &sm : &fm )
  665. X
  666. X    SetPort( win );
  667. X
  668. X/*
  669. X * If the balls do not overlap, or if SMOOTH is not defined, then we
  670. X * simply want to erase the first ball and draw the second.
  671. X */
  672. X#ifdef SMOOTH
  673. X    /*
  674. X     * If the balls can't possibly overlap, then just draw them directly
  675. X     * on the screen
  676. X     */
  677. X    if ( tx < -GRAD || tx > GRAD || ty < -GRAD || ty > GRAD ) {
  678. X#endif
  679. X        SetRect( &S, 0, 0, SDIM, SDIM );
  680. X        SetRect( &D, sx, sy, sx + SDIM, sy + SDIM );
  681. X        CopyBits( pict(op), &win->portBits, &S, &D, srcXor, 0L );
  682. X        SetRect( &D, dx, dy, dx + SDIM, dy + SDIM );
  683. X        CopyBits( pict(np), &win->portBits, &S, &D, srcXor, 0L );
  684. X        return;
  685. X#ifdef SMOOTH
  686. X    }
  687. X    
  688. X    /*
  689. X     * The balls are close enough that we may combine their updates into
  690. X     * one CopyBits to the screen.
  691. X     */
  692. X    
  693. X    /*
  694. X     * The rest of this is a pain to explain without a diagram,
  695. X     * so figure it out for yourself!
  696. X     */
  697. X    if ( ty > 0 )
  698. X        if ( tx > 0 )    { rt = 0;    rl = 0; }
  699. X        else            { rt = 0;    rl = SDIM; }
  700. X    else
  701. X        if ( tx > 0 )    { rt = SDIM; rl = 0; }
  702. X        else            { rt = SDIM; rl = SDIM; }
  703. X        
  704. X    SetRect( &D, 0, 0, 2*SDIM, 2*SDIM );
  705. X    CopyBits( &dm, &dm, &D, &D, srcXor, 0L );
  706. X    SetRect( &S, 0, 0, SDIM, SDIM );
  707. X    SetRect( &D, rl, rt, rl+SDIM, rt+SDIM );
  708. X    CopyBits( pict(op), &dm, &S, &D, srcCopy, 0L );
  709. X    SetRect( &D, rl + tx, rt + ty, rl + tx + SDIM, rt + ty + SDIM );
  710. X    CopyBits( pict(np), &dm, &S, &D, srcXor, 0L );
  711. X    SetRect( &S, 0, 0, SDIM*2, SDIM*2 );
  712. X    SetRect( &D, sx - rl, sy - rt, sx - rl + 2*SDIM, sy - rt + 2*SDIM );
  713. X    CopyBits( &dm, &win->portBits, &S, &D, srcXor, 0L );
  714. X#endif
  715. X}
  716. X
  717. X/*
  718. X * Initialize the bitmaps
  719. X */    
  720. Xinitmove() {        
  721. X    Rect S,D;
  722. X    GrafPort port;
  723. X
  724. X    /*
  725. X     * get a grafport to do our thing in
  726. X     */
  727. X    OpenPort( &port );
  728. X    PenNormal();
  729. X    
  730. X    /*
  731. X     * bitmap for slow bits...
  732. X     */
  733. X    sm.baseAddr = sbits;
  734. X    sm.rowBytes = 2*((SDIM+15)/16);
  735. X    sm.bounds.a.top = 0;
  736. X    sm.bounds.a.bottom = 2*SDIM;
  737. X    sm.bounds.a.left = 0;
  738. X    sm.bounds.a.right = 2*SDIM;
  739. X    
  740. X    /*
  741. X     * bitmap for fast bits...
  742. X     */
  743. X    fm.baseAddr = fbits;
  744. X    fm.rowBytes = 2*((SDIM+15)/16);
  745. X    fm.bounds.a.top = 0;
  746. X    fm.bounds.a.bottom = 2*SDIM;
  747. X    fm.bounds.a.left = 0;
  748. X    fm.bounds.a.right = 2*SDIM;
  749. X    
  750. X    SetPortBits( &sm );                /* prepare to draw slow ball */
  751. X    
  752. X    SetRect( &S, 0, 0, SDIM, SDIM );
  753. X    FrameOval( &S );
  754. X    MoveTo( 3, 7 ); LineTo( 4, 8 );    /* ...risking the taste-police */
  755. X    LineTo( 7, 8 ); LineTo( 8, 7 );
  756. X    MoveTo( 4, 4 ); LineTo( 4, 4 );
  757. X    MoveTo( 7, 4 ); LineTo( 7, 4 );
  758. X
  759. X    SetPortBits( &fm );                /* prepare to draw fast ball */
  760. X    InvertOval( &S );
  761. X    
  762. X#ifdef SMOOTH
  763. X    /*
  764. X     * bitmap for combined drawings...
  765. X     */
  766. X    dm.baseAddr = dbits;
  767. X    dm.rowBytes = 2*((SDIM+SDIM+15)/16);
  768. X    dm.bounds.a.top = 0;
  769. X    dm.bounds.a.bottom = 2*SDIM;
  770. X    dm.bounds.a.left = 0;
  771. X    dm.bounds.a.right = 2*SDIM;
  772. X#endif    
  773. X}
  774. ________This_Is_The_END________
  775. if test `wc -l < movebits.c` -ne 174; then
  776.     echo 'shar: movebits.c was damaged during transit'
  777.   echo '      (should have been 174 bytes)'
  778. fi
  779. fi        ; : end of overwriting check
  780. echo 'Extracting phys.c'
  781. if test -f phys.c; then echo 'shar: will not overwrite phys.c'; else
  782. sed 's/^X//' << '________This_Is_The_END________' > phys.c
  783. X/*
  784. X * do collisions and movement
  785. X */
  786. X
  787. X#include "ball.h"
  788. X
  789. Xextern wide, tall;            /* the size of the box we are in */
  790. Xextern GateState;            /* != 0 iff gate is open */
  791. X
  792. X#define TWO(X) ((X)+(X))
  793. X#define THREE(X) (TWO(X)+(X))
  794. X
  795. X/*
  796. X * bbump() deals with a possible collision between two specific balls.
  797. X * The first ball will not be to the right of the second ball.  Returns
  798. X * one if the second ball is far enough to the right so that no balls
  799. X * farther right could collide with the first ball, else returns zero
  800. X */
  801. Xbbump( pA, pB )
  802. X    register ball *pA, *pB;
  803. X{
  804. X    register long k;
  805. X    long tAvx, tAvy;
  806. X    register long tBx, tBy;
  807. X    long tBvx, tBvy;
  808. X    long WIDE, TALL;
  809. X    
  810. X    WIDE = wide<<2;            /* scale from window to physical co-ords */
  811. X    TALL = tall<<2;
  812. X    
  813. X    /*
  814. X     * Deal with the barrier and the gate
  815. X     */
  816. X    if ( TWO(pA->x) <= WIDE && TWO(pB->x) >= WIDE )
  817. X        /* gate closed means no collision */
  818. X        if ( ! GateState )
  819. X            return 0;
  820. X        else
  821. X        /* if either ball is below gate, no collision */
  822. X        if ( THREE(pA->y) < TALL || THREE(pB->y) < TALL )
  823. X            return 0;
  824. X        else
  825. X        /* if either ball is above gate, no collision */
  826. X        if ( THREE(pA->y) > TWO(TALL) || THREE(pB->y) > TWO(TALL) )
  827. X            return 0;
  828. X
  829. X    /* shift to A's co-ordinate system */
  830. X    tBx = pB->x - pA->x;
  831. X    tBy = pB->y - pA->y;
  832. X    tBvx = pB->vx - pA->vx;    tAvx = 0;
  833. X    tBvy = pB->vy - pA->vy;    tAvy = 0;
  834. X    
  835. X    /*
  836. X     * see if the balls are close enough to have collided
  837. X     */
  838. X    if ( tBx > TWO(CRAD) )
  839. X        return 1;
  840. X    if ( tBx * tBx + tBy * tBy > (CRAD*CRAD<<2) )
  841. X        return 0;
  842. X    
  843. X    k = tBx * tBvx + tBy * tBvy;
  844. X    
  845. X    /*
  846. X     * make sure they are going towards each other
  847. X     */    
  848. X    if ( k > -1 )
  849. X        return 0;
  850. X        
  851. X    k = ( tBy * tBvx - tBx * tBvy ) / k;
  852. X    
  853. X    tAvx = ( tBvx - k * tBvy ) / ( 1 + k*k );
  854. X    tAvy = ( k * tBvx + tBvy ) / ( 1 + k*k );
  855. X    
  856. X    tBvx =  k * tAvy;
  857. X    tBvy = -k * tAvx;
  858. X    
  859. X    pB->vx = pA->vx + tBvx;
  860. X    pB->vy = pA->vy + tBvy;
  861. X    pA->vx += tAvx;
  862. X    pA->vy += tAvy;
  863. X    
  864. X    return 0;
  865. X}
  866. X
  867. X/*
  868. X * Because the calculations above use longs instead of floats, we have a
  869. X * lot of round off error.  This seems to manifest itself by causing the
  870. X * balls to slow down over time.  We use the walls to correct this.
  871. X *
  872. X * If "we" is greater than zero, we are attempting to add energy to the
  873. X * system.  We do this by looking for slow balls bouncing off the right
  874. X * wall.  When we find such a ball, we give it a swift kick towards the
  875. X * left.
  876. X *
  877. X * If "we" is less than zero, then we are trying to remove energt from
  878. X * the system for some reason.  In this case, the outer walls become
  879. X * slightly sticky, with the ball slowing down by abs(we) perpendicular
  880. X * to the wall.
  881. X *
  882. X * This stuff is done in wbump().
  883. X *
  884. X */
  885. X
  886. Xstatic int we = 0;            /* wall energy factor */
  887. X
  888. Xwalls( i ) {
  889. X    we = i;
  890. X}
  891. X
  892. X/*
  893. X * wump() checks for collisions between a ball walls or the gate
  894. X */
  895. Xwbump( pA )
  896. X    register ball *pA;
  897. X{
  898. X    register long WIDE, TALL;
  899. X    
  900. X    WIDE = wide<<2; TALL = tall<<2;
  901. X    
  902. X    if ( (pA->x <= CRAD && pA->vx < 0)
  903. X      || (pA->x >= WIDE-CRAD && pA->vx > 0) ) {
  904. X        pA->vx = -pA->vx;
  905. X        if ( we > 0 ) {
  906. X            if ( pA->vx < 0 && pA->pict == 0 && pA->x >= WIDE-CRAD)
  907. X                pA->vx -= 30;                /* swift kick */
  908. X        } else {
  909. X            if ( pA->vx > 0 )
  910. X                pA->vx += we;
  911. X            else
  912. X                pA->vx -= we;
  913. X        }
  914. X    }
  915. X    if ( (pA->y <= CRAD && pA->vy < 0)
  916. X      || (pA->y >= TALL-CRAD && pA->vy > 0) ) {
  917. X        pA->vy = -pA->vy;
  918. X        if ( we < 0 ) {
  919. X            if ( pA->vy > 0 )
  920. X                pA->vy += we;
  921. X            else
  922. X                pA->vy -= we;
  923. X        }
  924. X
  925. X    }
  926. X    
  927. X    /*
  928. X     * if the ball is on the same level as the gate, and the gate is open,
  929. X     * there is nothing for the ball to hit on the barrier
  930. X     */
  931. X    if ( TALL < THREE(pA->y) && THREE(pA->y) < TWO(TALL) && GateState )
  932. X        return;
  933. X        
  934. X    WIDE >>= 1;            /* location of the barrier */
  935. X
  936. X    /*
  937. X     * see if the ball hits the barrier
  938. X     */
  939. X    if ( pA->x <= WIDE && pA->vx > 0 ) {
  940. X        if ( pA->x + CRAD >= WIDE || pA->x + pA->vx > WIDE )
  941. X            pA->vx = -pA->vx;
  942. X    } else
  943. X    if ( pA->x >= WIDE &&  pA->vx < 0 )
  944. X        if ( pA->x - CRAD <= WIDE || pA->x + pA->vx < WIDE )
  945. X            pA->vx = -pA->vx;
  946. X}
  947. X
  948. Xmball( pA )
  949. X    ball *pA;
  950. X{
  951. X    register long vx, vy;
  952. X    pA->x += vx = pA->vx;
  953. X    pA->y += vy = pA->vy;
  954. X
  955. X    /*
  956. X     * check for stalled balls, and offer them a chance to get going again
  957. X     */
  958. X    if ( vx == 0 && vy == 0 ) {
  959. X        if ( Random() > 0 )
  960. X            pA->vx = Random() > 0 ? 1 : -1;
  961. X        if ( Random() > 0 )
  962. X            pA->vy = Random() > 0 ? 1 : -1;
  963. X    }
  964. X}
  965. ________This_Is_The_END________
  966. if test `wc -l < phys.c` -ne 182; then
  967.     echo 'shar: phys.c was damaged during transit'
  968.   echo '      (should have been 182 bytes)'
  969. fi
  970. fi        ; : end of overwriting check
  971. exit 0
  972.