home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume20 / xboing / part01 < prev    next >
Encoding:
Text File  |  1993-09-03  |  53.2 KB  |  1,939 lines

  1. Newsgroups: comp.sources.x
  2. From: jck@kimba.catt.citri.edu.au (Justin Kibell)
  3. Subject: v20i108:  xboing - a simple blockout type game, Part01/26
  4. Message-ID: <csx-v20i108=xboing.072914@sparky.Sterling.COM>
  5. X-Md4-Signature: aaa648cddc692a02d2672273c7d79d93
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: CATT Centre at CITRI, Melbourne, Australia
  8. Date: Fri, 3 Sep 1993 12:30:00 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: jck@kimba.catt.citri.edu.au (Justin Kibell)
  12. Posting-number: Volume 20, Issue 108
  13. Archive-name: xboing/part01
  14. Environment: X11, xpm, color
  15.  
  16. XBoing is a simple blockout type game where you have a paddle which you use to
  17. bounce a ball around the game area blowing up blocks with the ball. You win by
  18. obtaining points for each block destroyed and each level completed. The person
  19. with the highest score wins.
  20.  
  21. XBoing was started like many other projects to learn Xlib better. I had the 
  22. XPM library and was already using it in a Motif application. I thought that it
  23. would be cool to have nice colour pictures/animations in an Xlib game. So I 
  24. did. Without the XPM library I would be still playing with the colours I think.
  25.  
  26. Please read the manual page as the manual has some important game play 
  27. information. Now I have warned you so don't complain if something doesn't 
  28. seem to be correct or that another breakout game did it like that or this. :-)
  29.  
  30. -------------------------------
  31. #! /bin/sh
  32. # This is a shell archive.  Remove anything before this line, then feed it
  33. # into a shell via "sh file" or similar.  To overwrite existing files,
  34. # type "sh file -c".
  35. # Contents:  README audio ball.c bitmaps levels sounds
  36. # Wrapped by chris@sparky on Fri Sep  3 07:14:40 1993
  37. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  38. echo If this archive is complete, you will see the following message:
  39. echo '          "shar: End of archive 1 (of 26)."'
  40. if test -f 'README' -a "${1}" != "-c" ; then 
  41.   echo shar: Will not clobber existing file \"'README'\"
  42. else
  43.   echo shar: Extracting \"'README'\" \(5657 characters\)
  44.   sed "s/^X//" >'README' <<'END_OF_FILE'
  45. X                    XBoing Version 1.6 - By Justin Kibell
  46. X                    -------------------------------------
  47. X
  48. X                              6th August 1993
  49. X
  50. XDescription
  51. X-----------
  52. X
  53. XXBoing is a simple blockout type game where you have a paddle which you use to
  54. Xbounce a ball around the game area blowing up blocks with the ball. You win by
  55. Xobtaining points for each block destroyed and each level completed. The person
  56. Xwith the highest score wins.
  57. X
  58. XXBoing was started like many other projects to learn Xlib better. I had the 
  59. XXPM library and was already using it in a Motif application. I thought that it
  60. Xwould be cool to have nice colour pictures/animations in an Xlib game. So I 
  61. Xdid. Without the XPM library I would be still playing with the colours I think.
  62. X
  63. XPlease read the manual page as the manual has some important game play 
  64. Xinformation. Now I have warned you so don't complain if something doesn't 
  65. Xseem to be correct or that another breakout game did it like that or this. :-)
  66. X
  67. X
  68. XRequirements
  69. X------------
  70. X
  71. XThe XPM library. Version 2.3 upwards tested. 3.2g is fine. Not tested below 2.3
  72. XSuggest you use 3.2g which is available everywhere now. 
  73. X
  74. XA COLOUR X display. I may fix it to use other visuals later. ie: grey. mono
  75. X
  76. XAn ansi or non-ansi compiler. Ansi is better, try gcc.
  77. XA decent GRUNT box to run XBoing. No network travel if possible! :-)
  78. X
  79. XAlso note that if you are on a Sun machine the xnews server is not the
  80. Xquickest and you may experience delays in the game due to its heavy use
  81. Xof pixmaps etc. I suggest playing it with the MIT X Server - hassle I know
  82. Xif you use other Sun software that requires news etc.
  83. X
  84. XNote: It will always be a bit slower on a network so playing on the host
  85. X      machine will give the best results. I have tuned the game for my
  86. X      SparcStation 2 and it runs very fast. I cannot test the game on
  87. X      other machines other the some Xterms and SGI Indigo's.  Disclamier.
  88. X
  89. X
  90. XWhere do I get it from
  91. X----------------------
  92. X
  93. XVia anonymous ftp from export.lcs.mit.edu.au in the contrib directory. 
  94. XThe most recent version is xboing1.6-tar.Z. It may appear on other mirrors
  95. Xthat mirror export or whatever.
  96. X
  97. XPlease do not try to obtain it from my own machine. export is quicker.
  98. XThe game is NOT kept in the ftp account on my machine so don't try please.
  99. X
  100. X
  101. XInstallation/Building game
  102. X--------------------------
  103. X
  104. XPlease read the file called INSTALL. It is important to read this file.
  105. XDon't forget to get the XPM library and compile it up first!
  106. X
  107. X
  108. XUsage
  109. X-----
  110. X
  111. XThe game does have command line options so check them out. 'xboing -help'
  112. X
  113. XThe colourmap is taken over as I need all the colours. Sorry but thats the
  114. Xproblem with only 256 colourmap entries. I cannot see a problem with this.
  115. X
  116. XThe colourmap is released afterwards and should return you to your lovely
  117. Xcolour scheme. If it doesn't please let me know.
  118. X
  119. X
  120. XDevelopement
  121. X------------
  122. X
  123. XXboing was developed on a SparcStation 2 with 48meg memory and a 19" colour
  124. Xdisplay using the MIT X11R5 X server, Motif Window Manager. I used x11ups
  125. Xfor debugging - excellent tool - well done. Sunos 4.1.2 sun4c. Compiled using
  126. Xgcc with warnings on and also tested using the Sun cc compiler (non ansi).
  127. X
  128. XReference books: All of O'Reilly Series, X & Motif Quick reference guide
  129. XGraphics: Titles done on Amiga using Deluxe Paint IV, converted using pbmplus
  130. X          tools and xpm image touch ups with "pixmap".
  131. XSounds:      Mainly from sounds.sdus.edu and also from other places.
  132. X
  133. X
  134. XSpecial Thanks
  135. X--------------
  136. X
  137. XReally Special thanks to Arnaud Le Hors (lehors@sophia.inria.fr) for the
  138. Xwonderful XPM library and for making it free :-).
  139. X
  140. XThanks for a some cool backgrounds found in Anthony's Icons V1.3 (new ones!)
  141. X    Anthony Thyssen - anthony@cit.gu.edu.au
  142. X
  143. XThe comp.windows.x newsgroup netters for help over the past few years. See
  144. Xthe CHANGES doco for inline lisitings of the helpers.
  145. X
  146. XThankyou to all those who have contributed. Especially the beta testers here
  147. Xat CATT. It's hard to do any work around here!
  148. X
  149. X    Michael Stone, Andrew Cassin, Iain Lim, Tim Liddelow, Peter Cupit
  150. X    Craig McNaughton, Chris Fu, David Kershaw, Geoff Lambourne
  151. X    Paul McGregor, my 3 cats ...
  152. X
  153. X
  154. XPatches to XBoing
  155. X-----------------
  156. X
  157. XPatches are great and welcomed. Please do as others have and either send them
  158. Xto me or post them to news. Please do NOT place them on export.lcs.mit.edu and
  159. Xmake it look like I put it there. I got heaps of mail saying a certain patch
  160. Xdidn't work and I didn't even know it existed. I think it is common courtesy
  161. Xto send me some email about what is going on etc.
  162. X
  163. XAlso - you can do whatever you like at your own site but don't send a patch
  164. Xthat changes the flag on the presentation screen. :-)
  165. X
  166. X
  167. XSuggestions/Bug fixes
  168. X---------------------
  169. X
  170. XI have had many suggestions and bug fixes. I cannot list all the names of the
  171. Xpeople who have helped as it would be a big list and I wouldn't want to
  172. Xleave anyone out. Thankyou to all those who have mailed - you know. ;-)
  173. X
  174. XSee the CHANGES doco for more info.
  175. X
  176. X
  177. XGrovel Bit
  178. X----------
  179. X
  180. XIf anyone is feeling really generous or kind they can send money, equipment,
  181. Xcars, travel vouchers or anything for that matter to my humble self and I 
  182. Xwill be very happy. ;-) If that's all a bit much then a friendly email will
  183. Xdo fine. Hope you have fun bouncing your balls. Stay cool.
  184. X
  185. XSurface Mail: 1/17 Albert Rd, North Warrandyte, Victoria, Australia, 3113
  186. X
  187. X--------------------------------------------------------------------------
  188. XJustin C. Kibell - email: jck@citri.edu.au     Phone: +61 3 282 2456
  189. XCITRI - CATT - Australia - Melbourne - Victoria - 723 Swanston St, Carlton
  190. XSystems Programmer - X11 Developer - Motif Head - Volunteer Rescuer - VICSES
  191. END_OF_FILE
  192.   if test 5657 -ne `wc -c <'README'`; then
  193.     echo shar: \"'README'\" unpacked with wrong size!
  194.   fi
  195.   # end of 'README'
  196. fi
  197. if test ! -d 'audio' ; then
  198.     echo shar: Creating directory \"'audio'\"
  199.     mkdir 'audio'
  200. fi
  201. if test -f 'ball.c' -a "${1}" != "-c" ; then 
  202.   echo shar: Will not clobber existing file \"'ball.c'\"
  203. else
  204.   echo shar: Extracting \"'ball.c'\" \(43006 characters\)
  205.   sed "s/^X//" >'ball.c' <<'END_OF_FILE'
  206. X#include "copyright.h"
  207. X
  208. X/*
  209. X *  Include file dependencies:
  210. X */
  211. X
  212. X#include <stdio.h>
  213. X#include <stdlib.h>
  214. X#include <math.h>
  215. X#include <xpm.h>
  216. X
  217. X#include "bitmaps/ball1.xpm"
  218. X#include "bitmaps/ball2.xpm"
  219. X#include "bitmaps/ball3.xpm"
  220. X#include "bitmaps/ball4.xpm"
  221. X#include "bitmaps/killer.xpm"
  222. X
  223. X#include "bitmaps/ballbirth1.xpm"
  224. X#include "bitmaps/ballbirth2.xpm"
  225. X#include "bitmaps/ballbirth3.xpm"
  226. X#include "bitmaps/ballbirth4.xpm"
  227. X#include "bitmaps/ballbirth5.xpm"
  228. X#include "bitmaps/ballbirth6.xpm"
  229. X#include "bitmaps/ballbirth7.xpm"
  230. X#include "bitmaps/ballbirth8.xpm"
  231. X
  232. X#include "audio.h"
  233. X#include "error.h"
  234. X#include "score.h"
  235. X#include "sfx.h"
  236. X#include "init.h"
  237. X#include "main.h"
  238. X#include "stage.h"
  239. X#include "blocks.h"
  240. X#include "paddle.h"
  241. X#include "misc.h"
  242. X#include "level.h"
  243. X#include "mess.h"
  244. X#include "special.h"
  245. X
  246. X#include "ball.h"
  247. X
  248. X/*
  249. X *  Internal macro definitions:
  250. X */
  251. X
  252. X#define X2COL(col, x) (col = x / colWidth)
  253. X#define Y2ROW(row, y) (row = y / rowHeight)
  254. X
  255. X#define COL2X(x, col) (x = col * colWidth)
  256. X#define ROW2Y(y, row) (y = row * rowHeight)
  257. X
  258. X/*
  259. X *  Internal type declarations:
  260. X */
  261. X
  262. X#if NeedFunctionPrototypes
  263. Xstatic void MoveBall(Display *display, Window window, int x, int y, int replace,
  264. X    int i);
  265. Xstatic void MoveBallBirth(Display *display, Window window, int x, int y, 
  266. X    int slide, int replace, int i);
  267. Xstatic void DoBoardTilt(Display *display, int i);
  268. Xstatic void TeleportBall(Display *display, Window window, int i);
  269. Xstatic int BallHitPaddle(Display *display, Window window, int *hit, int i,
  270. X    int *x, int *y);
  271. Xstatic void UpdateABall(Display *display, Window window, int i);
  272. Xstatic int CheckRegions(Display *display, Window window, int row, int col,
  273. X    int x, int y, int i);
  274. Xstatic int CheckForCollision(Display *display, Window window, int x, int y, 
  275. X    int *r, int *c, int i);
  276. Xstatic void updateBallVariables(int i);
  277. Xstatic void SetBallWait(int newMode, int waitFrame, int i);
  278. Xstatic void DoBallWait(int i);
  279. Xstatic void EraseTheBall(Display *display, Window window, int x, int y);
  280. X#else
  281. Xstatic void MoveBall();
  282. Xstatic void MoveBallBirth();
  283. Xstatic void DoBoardTilt();
  284. Xstatic void TeleportBall();
  285. Xstatic int BallHitPaddle();
  286. Xstatic void UpdateABall();
  287. Xstatic int CheckRegions();
  288. Xstatic int CheckForCollision();
  289. Xstatic void updateBallVariables();
  290. Xstatic void SetBallWait();
  291. Xstatic void DoBallWait();
  292. Xstatic void EraseTheBall();
  293. X#endif
  294. X
  295. X/*
  296. X *  Internal variable declarations:
  297. X */
  298. X
  299. Xstatic Pixmap ballsPixmap[BALL_SLIDES];
  300. Xstatic Pixmap ballsMask[BALL_SLIDES];
  301. Xstatic Pixmap ballBirthPixmap[BIRTH_SLIDES];
  302. Xstatic Pixmap ballBirthMask[BIRTH_SLIDES];
  303. XBALL balls[MAX_BALLS];
  304. X
  305. X#if NeedFunctionPrototypes
  306. Xvoid InitialiseBall(Display *display, Window window, Colormap colormap)
  307. X#else
  308. Xvoid InitialiseBall(display, window, colormap)
  309. X    Display     *display;
  310. X    Window         window;
  311. X    Colormap     colormap;
  312. X#endif
  313. X{
  314. X    XpmAttributes   attributes;
  315. X    int                XpmErrorStatus;
  316. X
  317. X    attributes.valuemask = XpmColormap;
  318. X    attributes.colormap = colormap;
  319. X
  320. X    /* Create the xpm pixmap ball frames */
  321. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball1_xpm,
  322. X        &ballsPixmap[0], &ballsMask[0], &attributes);
  323. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  324. X
  325. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball2_xpm,
  326. X        &ballsPixmap[1], &ballsMask[1], &attributes);
  327. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  328. X
  329. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball3_xpm,
  330. X        &ballsPixmap[2], &ballsMask[2], &attributes);
  331. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  332. X
  333. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball4_xpm,
  334. X        &ballsPixmap[3], &ballsMask[3], &attributes);
  335. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  336. X
  337. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, killer_xpm,
  338. X        &ballsPixmap[4], &ballsMask[4], &attributes);
  339. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  340. X
  341. X    /* Ball birth sequence */
  342. X
  343. X    /* Create the xpm pixmap ball birth frames */
  344. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth1_xpm,
  345. X        &ballBirthPixmap[0], &ballBirthMask[0], &attributes);
  346. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  347. X
  348. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth2_xpm,
  349. X        &ballBirthPixmap[1], &ballBirthMask[1], &attributes);
  350. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  351. X
  352. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth3_xpm,
  353. X        &ballBirthPixmap[2], &ballBirthMask[2], &attributes);
  354. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  355. X
  356. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth4_xpm,
  357. X        &ballBirthPixmap[3], &ballBirthMask[3], &attributes);
  358. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  359. X
  360. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth5_xpm,
  361. X        &ballBirthPixmap[4], &ballBirthMask[4], &attributes);
  362. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  363. X
  364. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth6_xpm,
  365. X        &ballBirthPixmap[5], &ballBirthMask[5], &attributes);
  366. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  367. X
  368. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth7_xpm,
  369. X        &ballBirthPixmap[6], &ballBirthMask[6], &attributes);
  370. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  371. X
  372. X    XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth8_xpm,
  373. X        &ballBirthPixmap[7], &ballBirthMask[7], &attributes);
  374. X    HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
  375. X
  376. X    /* Free the xpm pixmap attributes */
  377. X    XpmFreeAttributes(&attributes);
  378. X
  379. X    /* Make sure that all the balls are initialised */
  380. X    ClearAllBalls();
  381. X}
  382. X
  383. X#if NeedFunctionPrototypes
  384. Xvoid FreeBall(Display *display)
  385. X#else
  386. Xvoid FreeBall(display)
  387. X    Display *display;
  388. X#endif
  389. X{
  390. X    int i;
  391. X
  392. X    /* Free all animation frames for the ball */
  393. X    for (i = 0; i < BALL_SLIDES; i++)
  394. X    {
  395. X        if (ballsPixmap[i])     XFreePixmap(display, ballsPixmap[i]);
  396. X         if (ballsMask[i])         XFreePixmap(display, ballsMask[i]);
  397. X    }
  398. X
  399. X    /* Free all animation frames for the ball birth */
  400. X    for (i = 0; i < BIRTH_SLIDES; i++)
  401. X    {
  402. X        /* Free the ball birth animation pixmaps */
  403. X        if (ballBirthPixmap[i])     XFreePixmap(display, ballBirthPixmap[i]);
  404. X         if (ballBirthMask[i])         XFreePixmap(display, ballBirthMask[i]);
  405. X    }
  406. X}
  407. X
  408. X#if NeedFunctionPrototypes
  409. Xvoid RedrawBall(Display *display, Window window)
  410. X#else
  411. Xvoid RedrawBall(display, window)
  412. X    Display *display; 
  413. X    Window window;
  414. X#endif
  415. X{
  416. X    /* STILL TO BE IMPLEMENTED */
  417. X}
  418. X
  419. X#if NeedFunctionPrototypes
  420. Xstatic void EraseTheBall(Display *display, Window window, int x, int y)
  421. X#else
  422. Xstatic void EraseTheBall(display, window, x, y)
  423. X    Display *display;
  424. X    Window window;
  425. X    int x;
  426. X    int y;
  427. X#endif
  428. X{
  429. X    /* Clear the ball area! The x, y coordinates are the centre of ball */
  430. X    XClearArea(display, window, x - BALL_WC, y - BALL_HC, 
  431. X        BALL_WIDTH, BALL_HEIGHT, False);
  432. X}
  433. X
  434. X#if NeedFunctionPrototypes
  435. Xvoid DrawTheBall(Display *display, Window window, int x, int y, int slide)
  436. X#else
  437. Xvoid DrawTheBall(display, window, x, y, slide)
  438. X    Display *display;
  439. X    Window window;
  440. X    int x;
  441. X    int y; 
  442. X    int slide;
  443. X#endif
  444. X{
  445. X    /* Draw the ball using the slide variable as the index into the frames
  446. X     * of the ball animation. The x,y are the centre of the ball.
  447. X     */
  448. X    RenderShape(display, window, ballsPixmap[slide], ballsMask[slide],
  449. X        x - BALL_WC, y - BALL_HC, BALL_WIDTH, BALL_HEIGHT, False);
  450. X}
  451. X
  452. X#if NeedFunctionPrototypes
  453. Xvoid DrawTheBallBirth(Display *display, Window window, int x, int y, int slide)
  454. X#else
  455. Xvoid DrawTheBallBirth(display, window, x, y, slide)
  456. X    Display *display;
  457. X    Window window;
  458. X    int x;
  459. X    int y;
  460. X    int slide;
  461. X#endif
  462. X{
  463. X    /* Draw the ball using the slide variable as the index into the frames
  464. X     * of the ball animation. The x,y are the centre of the ball birth anim.
  465. X     */
  466. X    RenderShape(display, window, ballBirthPixmap[slide], ballBirthMask[slide],
  467. X        x - BALL_WC, y - BALL_HC, BALL_WIDTH, BALL_HEIGHT, False);
  468. X}
  469. X
  470. X#if NeedFunctionPrototypes
  471. Xstatic void MoveBallBirth(Display *display, Window window, int x, int y, 
  472. X    int slide, int replace, int i)
  473. X#else
  474. Xstatic void MoveBallBirth(display, window, x, y, slide, replace, i)
  475. X    Display *display;
  476. X    Window window;
  477. X    int x;
  478. X    int y; 
  479. X    int slide;
  480. X    int replace;
  481. X    int i;
  482. X#endif
  483. X{
  484. X    /* Remove any debris under ball first by clearing it */
  485. X    if (replace)
  486. X    {
  487. X        XClearArea(display, window, 
  488. X            balls[i].oldx - BALL_WC, balls[i].oldy - BALL_HC, 
  489. X            BALL_WIDTH, BALL_HEIGHT, False);
  490. X    }    
  491. X
  492. X    balls[i].oldx = x;
  493. X    balls[i].oldy = y;
  494. X
  495. X    /* If slide is -1 then clear the ball area */
  496. X    if (slide == -1)
  497. X        XClearArea(display, window, 
  498. X            x - BALL_WC, y - BALL_HC, BALL_WIDTH, BALL_HEIGHT, False);
  499. X    else
  500. X        DrawTheBallBirth(display, window, x, y, slide);
  501. X}
  502. X
  503. X#if NeedFunctionPrototypes
  504. Xstatic void MoveBall(Display *display, Window window, int x, int y, int replace,
  505. X    int i)
  506. X#else
  507. Xstatic void MoveBall(display, window, x, y, replace, i)
  508. X    Display *display; 
  509. X    Window window;
  510. X    int x;
  511. X    int y;
  512. X    int replace;
  513. X    int i;
  514. X#endif
  515. X{
  516. X    if (replace)
  517. X    {
  518. X        EraseTheBall(display, window, balls[i].oldx, balls[i].oldy);
  519. X    }
  520. X
  521. X    balls[i].oldx = x;
  522. X    balls[i].oldy = y;
  523. X
  524. X    if (Killer == True)
  525. X    {
  526. X        /* Render the killer ball now ie: red ball */
  527. X        DrawTheBall(display, window, x, y, BALL_SLIDES-1);
  528. X    }
  529. X    else
  530. X    {
  531. X        /* Render the ball now */
  532. X        DrawTheBall(display, window, x, y, balls[i].slide);
  533. X    }    
  534. X
  535. X    /* Change slide for ball every n frames of animation */
  536. X    if ((frame % BALL_ANIM_RATE) == 0)
  537. X        balls[i].slide++;
  538. X    
  539. X    /* wrap around slides */
  540. X    if (balls[i].slide == BALL_SLIDES-1) balls[i].slide = 0;
  541. X}
  542. X
  543. X#if NeedFunctionPrototypes
  544. Xstatic void DoBoardTilt(Display *display, int i)
  545. X#else
  546. Xstatic void DoBoardTilt(display, i)
  547. X    Display *display;
  548. X    int i;
  549. X#endif
  550. X{
  551. X    if (balls[i].ballState == BALL_ACTIVE)
  552. X    {
  553. X        /* Tilt the board to remove any endless loops */
  554. X        SetCurrentMessage(display, messWindow, 
  555. X            "Auto Tilt Activated", True);
  556. X    
  557. X        balls[i].dx = balls[i].dy = 0;
  558. X    
  559. X        /* Randomise the ball */
  560. X        while (balls[i].dx == 0)
  561. X        {
  562. X                balls[i].dx = (2 - (rand() % 4)) * 2;
  563. X                balls[i].dy = (abs(balls[i].dx)) * 2;
  564. X            balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  565. X        }
  566. X    }
  567. X}
  568. X
  569. X#if NeedFunctionPrototypes
  570. Xstatic void TeleportBall(Display *display, Window window, int i)
  571. X#else
  572. Xstatic void TeleportBall(display, window, i)
  573. X    Display *display;
  574. X     Window window;
  575. X    int i;
  576. X#endif
  577. X{
  578. X    /* This function will teleport the ball to some other space not occupied
  579. X     * and start off there.
  580. X     */
  581. X    int r1, c1, s1, r2, c2, s2, r3, c3, s3, r4, c4, s4;
  582. X    int r, c, x, y;
  583. X    struct aBlock *blockP, *bP;
  584. X    int done = False;
  585. X
  586. X    /* Loop until we find a block to move to */
  587. X    while (done == False)
  588. X    {
  589. X        /* Give me a new random block position */
  590. X        r = (rand() % (MAX_ROW - 5)) + 1;
  591. X        c = (rand() % MAX_COL) + 1;
  592. X
  593. X        if (r < 0 || r >= MAX_ROW) continue;
  594. X        if (c < 0 || c >= MAX_COL) continue;
  595. X
  596. X        /* Pointer to the correct block we need - speed things up */
  597. X        blockP = &blocks[r][c];
  598. X
  599. X        /* Check that the block is not occupied and not exploding */
  600. X        if ((blockP->occupied == False) && (blockP->exploding == False))
  601. X        {
  602. X            /* Check that the block is not a closed position */
  603. X
  604. X            r1 = r;     c1 = c - 1;  s1 = 0;
  605. X            if (r1 < 0 || r1 >= MAX_ROW) s1 = 1;
  606. X            if (c1 < 0 || c1 >= MAX_COL) s1 = 1;
  607. X            if (s1 == 0) 
  608. X            {
  609. X                bP = &blocks[r1][c1];
  610. X                if (bP->blockType == BLACK_BLK)
  611. X                s1 = 1;
  612. X            }
  613. X
  614. X            r2 = r - 1; c2 = c;      s2 = 0;
  615. X            if (r2 < 0 || r2 >= MAX_ROW) s2 = 1;
  616. X            if (c2 < 0 || c2 >= MAX_COL) s2 = 1;
  617. X            if (s2 == 0) 
  618. X            {
  619. X                bP = &blocks[r2][c2];
  620. X                if (bP->blockType == BLACK_BLK)
  621. X                    s2 = 1;
  622. X            }
  623. X
  624. X            r3 = r;     c3 = c + 1;  s3 = 0;
  625. X            if (r3 < 0 || r3 >= MAX_ROW) s3 = 1;
  626. X            if (c3 < 0 || c3 >= MAX_COL) s3 = 1;
  627. X            if (s3 == 0) 
  628. X            {
  629. X                bP = &blocks[r3][c3];
  630. X                if (bP->blockType == BLACK_BLK)
  631. X                    s3 = 1;
  632. X            }
  633. X
  634. X            r4 = r + 1; c4 = c;      s4 = 0;
  635. X            if (r4 < 0 || r4 >= MAX_ROW) s4 = 1;
  636. X            if (c4 < 0 || c4 >= MAX_COL) s4 = 1;
  637. X            if (s4 == 0) 
  638. X            {
  639. X                bP = &blocks[r4][c4];
  640. X                if (bP->blockType == BLACK_BLK)
  641. X                    s4 = 1;
  642. X            }
  643. X
  644. X            /* If it isn't ok to go here then keep searching */
  645. X            if ((s1 == 1) && (s2 == 1) && (s3 == 1) && (s4 == 1))
  646. X                continue;
  647. X
  648. X            /* Calculate the new ball coordinates */
  649. X            COL2X(x, c);
  650. X            ROW2Y(y, r);
  651. X
  652. X            balls[i].ballx = x;
  653. X            balls[i].bally = y;
  654. X
  655. X            /* Move the ball to the new position */
  656. X            MoveBall(display, window, x, y, True, i);
  657. X
  658. X            balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  659. X
  660. X            /* Ok jump out now thanks. */
  661. X            done = True;
  662. X        }
  663. X    }
  664. X}
  665. X
  666. X#if NeedFunctionPrototypes
  667. Xvoid SplitBallInTwo(Display *display, Window window)
  668. X#else
  669. Xvoid SplitBallInTwo(display, window)
  670. X    Display *display;
  671. X     Window window;
  672. X#endif
  673. X{
  674. X    int j;
  675. X
  676. X    if (livesLeft > 0)
  677. X    {
  678. X        j = AddANewBall(PLAY_WIDTH / 2, -BALL_HC, 3, 3);
  679. X        if (j > 0)
  680. X        {
  681. X            /* Make this new ball move straight away */
  682. X            ChangeBallMode(BALL_ACTIVE, j);
  683. X
  684. X            /* Take the life from player as the new ball is in play */
  685. X            DecExtraLife(display);
  686. X
  687. X            SetCurrentMessage(display, messWindow,
  688. X                "More balls!", True);
  689. X        }
  690. X    }
  691. X    else
  692. X        SetCurrentMessage(display, messWindow,
  693. X            "Cannot add ball!", True);
  694. X}
  695. X
  696. X#if NeedFunctionPrototypes
  697. Xvoid ClearBallNow(Display *display, Window window, int i)
  698. X#else
  699. Xvoid ClearBallNow(display, window, i)
  700. X    Display *display;
  701. X     Window window;
  702. X    int i;
  703. X#endif
  704. X{
  705. X    /* Kill the ball now, boy! */
  706. X    EraseTheBall(display, window, balls[i].ballx, balls[i].bally);
  707. X    ClearBall(i);
  708. X    DeadBall(display, window);
  709. X}
  710. X
  711. X#if NeedFunctionPrototypes
  712. Xvoid KillBallNow(Display *display, Window window, int i)
  713. X#else
  714. Xvoid KillBallNow(display, window, i)
  715. X    Display *display;
  716. X     Window window;
  717. X    int i;
  718. X#endif
  719. X{
  720. X    /* Kill the ball now, boy! */
  721. X    ChangeBallMode(BALL_POP, i);
  722. X}
  723. X
  724. X#if NeedFunctionPrototypes
  725. Xvoid GetBallPosition(int *ballX, int *ballY, int i)
  726. X#else
  727. Xvoid GetBallPosition(ballX, ballY, i)
  728. X    int *ballX;
  729. X    int *ballY;
  730. X    int i;
  731. X#endif
  732. X{
  733. X    /* Return ball i's position */
  734. X    *ballX = balls[i].ballx;
  735. X    *ballY = balls[i].bally;
  736. X}
  737. X
  738. X#if NeedFunctionPrototypes
  739. Xstatic int BallHitPaddle(Display *display, Window window, int *hit, int i,
  740. X    int *x, int *y)
  741. X#else
  742. Xstatic int BallHitPaddle(display, window, hit, i, x, y)
  743. X    Display *display;
  744. X    Window window;
  745. X    int *hit;
  746. X    int i;
  747. X    int *x, *y;
  748. X#endif
  749. X{
  750. X    float x1, x2, y1, y2, alpha, beta, xP1, xP2, xH, yH;
  751. X    int paddleLine;
  752. X
  753. X    /***********************************************************************
  754. X
  755. X                        A1 (x1,y1)
  756. X                        *
  757. X                       .
  758. X                      .
  759. X         P1 =========.=========== P2   <----   paddle (x, y pos is known )
  760. X        (xP1,yP1)   . H (xH, yH)    (xP2,yP2)
  761. X                   .
  762. X                  .
  763. X                 .
  764. X                .
  765. X               .
  766. X              *
  767. X             A2 (x2,y2)
  768. X
  769. X           Given the line A1A2, is the intersecting point H (xH, yH) in the paddle 
  770. X        segment ? (i.e xH in [xP1,xP2])
  771. X
  772. X           A1A2 is :  y = alpha * x + beta
  773. X
  774. X           A1 and A2 are in A1A2 than beta = [(y1 + y2) - alpha*(x1+x2)] / 2
  775. X
  776. X           yH = yP1 = yP2
  777. X
  778. X           so xH = (yP1 - beta) / alpha
  779. X
  780. X    **********************************************************************/
  781. X
  782. X    paddleLine = (PLAY_HEIGHT - DIST_BASE - 2);
  783. X
  784. X    if (balls[i].bally + BALL_HC > paddleLine)
  785. X       {
  786. X           xP1 = (float)(paddlePos - (GetPaddleSize() / 2) - BALL_WC/2);
  787. X           xP2 = (float)(paddlePos + (GetPaddleSize() / 2) + BALL_WC/2);
  788. X
  789. X           if (balls[i].dx == 0)
  790. X          {
  791. X            /* process the vertical moving balls */
  792. X              if (((float)balls[i].ballx > xP1) && ((float)balls[i].ballx < xP2))
  793. X             {
  794. X                 /* the ball hit the paddle */
  795. X                 *hit = balls[i].ballx - paddlePos;
  796. X                 *x      = balls[i].ballx;
  797. X                 *y      = paddleLine - BALL_HC;
  798. X
  799. X                 return True;
  800. X             }
  801. X              else
  802. X                return False;
  803. X          }
  804. X           else
  805. X          {
  806. X             /* compute the line coefficients of the ball */
  807. X
  808. X            alpha     = (float) balls[i].dy;
  809. X            x1         = (float) (balls[i].ballx - balls[i].dx);
  810. X            y1         = (float) (balls[i].bally - balls[i].dy);
  811. X            x2         = (float) (balls[i].ballx);
  812. X            y2         = (float) (balls[i].bally);
  813. X            beta     = ((y1 + y2) - alpha * (x1 + x2)) / 2.0;
  814. X
  815. X            yH = (float) paddleLine;
  816. X            xH = (yH - beta) / alpha;
  817. X
  818. X            if ((xH > xP1) && (xH < xP2))
  819. X            {
  820. X                /* the ball hit the paddle */
  821. X                *hit     = (int) (xH + 0.5) - paddlePos;
  822. X                *x         = (int) (xH + 0.5);
  823. X                *y         = paddleLine - BALL_HC;
  824. X
  825. X                return True;
  826. X            }
  827. X            else
  828. X                return False;
  829. X        }
  830. X    }
  831. X
  832. X       /* We didn't hit the paddle */
  833. X       return False;
  834. X}
  835. X
  836. X#if NeedFunctionPrototypes
  837. Xstatic int HandleTheBlocks(Display *display, Window window, int row, int col,
  838. X    int i)
  839. X#else
  840. Xstatic int HandleTheBlocks(display, window, row, col, i)
  841. X    int row;
  842. X    int col;
  843. X    int i;
  844. X#endif
  845. X{
  846. X    struct aBlock *blockP;
  847. X
  848. X    /* Pointer to the block the ball is in */
  849. X    blockP = &blocks[row][col];
  850. X
  851. X    /* There has been a collision so handle it */
  852. X    if (blockP->exploding == False)
  853. X    {
  854. X        if (blockP->blockType == COUNTER_BLK)
  855. X        {
  856. X            balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  857. X
  858. X            /* If in killer mode then don't bounce off block */
  859. X            if (Killer == True)
  860. X            {
  861. X                DrawBlock(display, window, row, col, KILL_BLK);
  862. X                return True;
  863. X            }
  864. X
  865. X            /* Special case for counter - reduce count on block */
  866. X            if (blockP->counterSlide == 0)
  867. X                DrawBlock(display, window, row, col, KILL_BLK);
  868. X            else
  869. X            {
  870. X                /* Draw the counter block minus one number */
  871. X                blockP->counterSlide--;
  872. X                DrawBlock(display, window, row, col, COUNTER_BLK);
  873. X            }
  874. X        }
  875. X        else
  876. X        {
  877. X            if (blockP->blockType == MGUN_BLK)
  878. X            {
  879. X                /* Turn the machine gun on */
  880. X                ToggleFastGun(display, True);
  881. X                DrawSpecials(display);
  882. X                SetCurrentMessage(display, messWindow,
  883. X                    "Machine Gun", True);
  884. X
  885. X                /* Not a wall so explode the block */
  886. X                DrawBlock(display, window, row, col, KILL_BLK);
  887. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  888. X
  889. X                /* If in killer mode then don't bounce off block */
  890. X                if (Killer == True)
  891. X                    return True;
  892. X
  893. X            } else if (blockP->blockType == DEATH_BLK)
  894. X            {
  895. X                /* Ha ha - hit death block so die */
  896. X
  897. X                /* Kill the ball now */
  898. X                ClearBallNow(display, window, i);
  899. X
  900. X                /* Not a wall so explode the block */
  901. X                DrawBlock(display, window, row, col, KILL_BLK);
  902. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  903. X
  904. X                /* If in killer mode then don't bounce off block */
  905. X                if (Killer == True)
  906. X                    return True;
  907. X
  908. X            } else if (blockP->blockType == HYPERSPACE_BLK)
  909. X            {
  910. X                /* Teleport to somewhere else */
  911. X                TeleportBall(display, window, i);
  912. X
  913. X                /* Redraw it just in case */
  914. X                DrawBlock(display, window, row, col, HYPERSPACE_BLK);
  915. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  916. X
  917. X                PlaySoundForBlock(HYPERSPACE_BLK);
  918. X
  919. X                return True;
  920. X
  921. X            } else if (blockP->blockType == WALLOFF_BLK)
  922. X            {
  923. X                /* Walls are now turned off */
  924. X                ToggleWallsOn(display, True);
  925. X                DrawSpecials(display);
  926. X                SetCurrentMessage(display, messWindow,
  927. X                    "Walls off", True);
  928. X
  929. X                /* Not a wall so explode the block */
  930. X                DrawBlock(display, window, row, col, KILL_BLK);
  931. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  932. X
  933. X                /* If in killer mode then don't bounce off block */
  934. X                if (Killer == True)
  935. X                    return True;
  936. X
  937. X            } else if (blockP->blockType == REVERSE_BLK)
  938. X            {
  939. X                /* Paddle control now reverse */
  940. X                ToggleReverse(display);
  941. X                SetCurrentMessage(display, messWindow,
  942. X                    "Reverse Control", True);
  943. X                DrawSpecials(display);
  944. X
  945. X                /* Not a wall so explode the block */
  946. X                DrawBlock(display, window, row, col, KILL_BLK);
  947. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  948. X
  949. X                /* If in killer mode then don't bounce off block */
  950. X                if (Killer == True)
  951. X                    return True;
  952. X
  953. X            } else if (blockP->blockType == PAD_SHRINK_BLK)
  954. X            {
  955. X                /* Paddle shrinking block */
  956. X                ChangePaddleSize(display, window, PAD_SHRINK_BLK);
  957. X                SetCurrentMessage(display, messWindow,
  958. X                    "Shrink Paddle", True);
  959. X
  960. X                /* Not a wall so explode the block */
  961. X                DrawBlock(display, window, row, col, KILL_BLK);
  962. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  963. X
  964. X                /* If in killer mode then don't bounce off block */
  965. X                if (Killer == True)
  966. X                    return True;
  967. X
  968. X            } else if (blockP->blockType == PAD_EXPAND_BLK)
  969. X            {
  970. X                /* Paddle expanding block */
  971. X                ChangePaddleSize(display, window, PAD_EXPAND_BLK);
  972. X                SetCurrentMessage(display, messWindow,
  973. X                    "Expand Paddle", True);
  974. X
  975. X                /* Not a wall so explode the block */
  976. X                DrawBlock(display, window, row, col, KILL_BLK);
  977. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  978. X
  979. X                /* If in killer mode then don't bounce off block */
  980. X                if (Killer == True)
  981. X                    return True;
  982. X
  983. X            } else if (blockP->blockType == EXTRABALL_BLK)
  984. X            {
  985. X                /* Extra ball */
  986. X                AddExtraLife(display);
  987. X                SetCurrentMessage(display, messWindow,
  988. X                    "Extra ball", True);
  989. X
  990. X                /* Not a wall so explode the block */
  991. X                DrawBlock(display, window, row, col, KILL_BLK);
  992. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  993. X
  994. X                /* If in killer mode then don't bounce off block */
  995. X                if (Killer == True)
  996. X                    return True;
  997. X
  998. X            } else if (blockP->blockType == STICKY_BLK)
  999. X            {
  1000. X                ToggleStickyBat(display, True);
  1001. X                DrawSpecials(display);
  1002. X                SetCurrentMessage(display, messWindow,
  1003. X                    "Sticky Bat", True);
  1004. X
  1005. X                /* Not a wall so explode the block */
  1006. X                DrawBlock(display, window, row, col, KILL_BLK);
  1007. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  1008. X
  1009. X                /* If in killer mode then don't bounce off block */
  1010. X                if (Killer == True)
  1011. X                    return True;
  1012. X
  1013. X            } else if (blockP->blockType == MULTIBALL_BLK)
  1014. X            {
  1015. X                ToggleMultiBall(display, True);
  1016. X                DrawSpecials(display);
  1017. X                SplitBallInTwo(display, window);
  1018. X
  1019. X                /* Not a wall so explode the block */
  1020. X                DrawBlock(display, window, row, col, KILL_BLK);
  1021. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  1022. X
  1023. X                /* If in killer mode then don't bounce off block */
  1024. X                if (Killer == True)
  1025. X                    return True;
  1026. X
  1027. X            } else if (blockP->blockType != BLACK_BLK)
  1028. X            {
  1029. X                /* Not a wall so explode the block */
  1030. X                DrawBlock(display, window, row, col, KILL_BLK);
  1031. X                balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  1032. X
  1033. X                /* If in killer mode then don't bounce off block */
  1034. X                if (Killer == True) return True;
  1035. X            }
  1036. X            else if (blockP->blockType == BLACK_BLK)
  1037. X            {
  1038. X                /* Redraw the solid wall block to make sure */
  1039. X                DrawBlock(display, window, row, col, BLACK_BLK);
  1040. X            }
  1041. X        }
  1042. X    }
  1043. X
  1044. X    /* Don't return after returning */
  1045. X    return False;
  1046. X}
  1047. X
  1048. X#if NeedFunctionPrototypes
  1049. Xstatic void UpdateABall(Display *display, Window window, int i)
  1050. X#else
  1051. Xstatic void UpdateABall(display, window, i)
  1052. X    Display *display;
  1053. X    Window window;
  1054. X    int i;
  1055. X#endif
  1056. X{
  1057. X    int row, col, hitPos, ret;
  1058. X    int cx, cy, step, j, r, ddx, ddy, Hx, Hy;
  1059. X    float incx, incy, x, y;
  1060. X    float Vs, Vx, Vy, alpha, beta, gamma, padSize;
  1061. X
  1062. X    /* Update ball position using dx and dy values */    
  1063. X    balls[i].ballx = balls[i].oldx + balls[i].dx;
  1064. X    balls[i].bally = balls[i].oldy + balls[i].dy;
  1065. X
  1066. X    /* Mark the ball to die as it is past the paddle */
  1067. X    if (balls[i].bally > (PLAY_HEIGHT - DIST_BASE))
  1068. X        ChangeBallMode(BALL_DIE, i);
  1069. X
  1070. X    /* Check if ball has hit left wall and bounce off */        
  1071. X    if (balls[i].ballx < BALL_WC && noWalls == False)
  1072. X    {
  1073. X        balls[i].dx = abs(balls[i].dx);
  1074. X        if (noSound == False) playSoundFile("boing", 20);
  1075. X
  1076. X    } else if (noWalls == True && balls[i].ballx < BALL_WC)
  1077. X    {
  1078. X        /* If the no walls mode is on then wrap around onto right wall */
  1079. X        balls[i].ballx = (PLAY_WIDTH - BALL_WC);
  1080. X
  1081. X        /* Move the ball to the new position */
  1082. X        MoveBall(display, window, balls[i].ballx, balls[i].bally, True, i);
  1083. X
  1084. X        return;
  1085. X    }
  1086. X
  1087. X    /* Check if ball has hit right wall and bounce off */        
  1088. X    if (balls[i].ballx > (PLAY_WIDTH - BALL_WC) && noWalls == False)
  1089. X    {
  1090. X        balls[i].dx = -(abs(balls[i].dx));
  1091. X        if (noSound == False) playSoundFile("boing", 20);
  1092. X
  1093. X    } else if (noWalls == True && balls[i].ballx > (PLAY_WIDTH - BALL_WC))
  1094. X    {
  1095. X        /* If the no walls mode is on then wrap around onto left wall */
  1096. X        balls[i].ballx = BALL_WC;
  1097. X
  1098. X        /* Move the ball to the new position */
  1099. X        MoveBall(display, window, balls[i].ballx, balls[i].bally, True, i);
  1100. X
  1101. X        return;
  1102. X    }
  1103. X
  1104. X    /* Check if ball has hit top wall and bounce off */        
  1105. X    if (balls[i].bally < BALL_HC) 
  1106. X    {
  1107. X        balls[i].dy = abs(balls[i].dy);
  1108. X        if (noSound == False) playSoundFile("boing", 20);
  1109. X    }
  1110. X
  1111. X    if (balls[i].ballState != BALL_DIE)
  1112. X    {
  1113. X        /* Check if the ball has hit the paddle */
  1114. X        if (BallHitPaddle(display, window, &hitPos, i, &Hx, &Hy) == True)
  1115. X        {
  1116. X            /* Keep track of how long it was since the last paddle hit */
  1117. X            balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
  1118. X            if (noSound == False) playSoundFile("boing", 20);
  1119. X
  1120. X            /* Add a paddle hit bonus score, I'm nice ;-) */
  1121. X            AddToScore((u_long) PADDLE_HIT_SCORE);
  1122. X            DisplayScore(display, scoreWindow, score);
  1123. X
  1124. X            /* speed vector of the ball */
  1125. X               Vx = (float) balls[i].dx;    
  1126. X               Vy = (float) balls[i].dy;
  1127. X
  1128. X            /* speed intensity of the ball */
  1129. X               Vs = sqrt( Vx*Vx + Vy*Vy );
  1130. X
  1131. X               alpha = atan(Vx/-Vy);
  1132. X
  1133. X               padSize = (float)(GetPaddleSize() + BALL_WC);
  1134. X               Vx = (float) hitPos;
  1135. X               Vy = (float) padSize/1.0;
  1136. X
  1137. X               beta = atan(Vx/Vy);
  1138. X               gamma = 2.0*beta - alpha;
  1139. X
  1140. X               Vx = Vs * sin(gamma);
  1141. X               Vy = -Vs * cos(gamma);
  1142. X
  1143. X            /* take in account the horizontal speed of the paddle: 
  1144. X             * vectorial summ 
  1145. X             */
  1146. X               Vx += (float) (paddleDx / 10.0);
  1147. X
  1148. X               if (Vx > 0.0)
  1149. X                balls[i].dx = (int) (Vx + 0.5);
  1150. X               else
  1151. X                 balls[i].dx = (int) (Vx - 0.5);
  1152. X
  1153. X               if (Vy < 0.0)
  1154. X                 balls[i].dy = (int) (Vy - 0.5);
  1155. X               else
  1156. X                 balls[i].dy = -MIN_DY_BALL;
  1157. X
  1158. X               if (balls[i].dy > -MIN_DY_BALL) 
  1159. X                balls[i].dy = -MIN_DY_BALL;
  1160. X
  1161. X               balls[i].ballx = Hx;
  1162. X               balls[i].bally = Hy;
  1163. X
  1164. X            /* handle the sticky paddle special by changing the ball mode
  1165. X             * to BALL_READY so it will need user to press space to start
  1166. X             * the ball moving again.
  1167. X             */
  1168. X            if (stickyBat == True)    
  1169. X            {
  1170. X                ChangeBallMode(BALL_READY, i);
  1171. X
  1172. X                /* Move the ball to the new position */
  1173. X                MoveBall(display, window, 
  1174. X                    balls[i].ballx, balls[i].bally, True, i);
  1175. X
  1176. X                /* So that it will auto shoot off if you wait too long */
  1177. X                balls[i].nextFrame = frame + BALL_AUTO_ACTIVE_DELAY;
  1178. X
  1179. X                return;
  1180. X            }
  1181. X        }
  1182. X        else
  1183. X        {
  1184. X            /* Ball didn't hit the paddle so check if it time to autotilt the
  1185. X             * board as it is in an infinite loop most likely.
  1186. X             */
  1187. X            if (balls[i].lastPaddleHitFrame == frame)
  1188. X                DoBoardTilt(display, i);
  1189. X        }
  1190. X
  1191. X           Vx = (float) balls[i].dx;
  1192. X           Vy = (float) balls[i].dy;
  1193. X           Vs = sqrt(Vx * Vx + Vy * Vy);
  1194. X
  1195. X           alpha = sqrt((float)MAX_X_VEL*(float)MAX_X_VEL + (float)MAX_Y_VEL*
  1196. X            (float)MAX_Y_VEL );
  1197. X           alpha /= 9.0; /* number of speed level */
  1198. X           alpha *= (float) speedLevel;
  1199. X           beta = alpha / Vs;
  1200. X           Vx *= beta;
  1201. X           Vy *= beta;
  1202. X
  1203. X           if (Vx > 0.0)
  1204. X             balls[i].dx = (int) (Vx + 0.5);
  1205. X           else
  1206. X             balls[i].dx = (int) (Vx - 0.5);
  1207. X
  1208. X           if (Vy > 0.0)
  1209. X             balls[i].dy = (int) (Vy + 0.5);
  1210. X           else
  1211. X             balls[i].dy = (int) (Vy - 0.5);
  1212. X
  1213. X           if (balls[i].dy == 0) 
  1214. X            balls[i].dy = MIN_DY_BALL;
  1215. X
  1216. X           if (balls[i].dx == 0) 
  1217. X            balls[i].dx = MIN_DX_BALL;
  1218. X    }
  1219. X
  1220. X    /* Has the player lost the ball of the bottom of the screen */
  1221. X    if (balls[i].bally > (PLAY_HEIGHT + BALL_HEIGHT))
  1222. X    {
  1223. X        /* Make ball start to die */
  1224. X        ClearBallNow(display, window, i);
  1225. X        return;
  1226. X    }
  1227. X
  1228. X    /* Convert the new ball positions to rows and cols for collision */
  1229. X    X2COL(col, balls[i].ballx);
  1230. X    Y2ROW(row, balls[i].bally);
  1231. X
  1232. X    x = balls[i].oldx;
  1233. X    y = balls[i].oldy;
  1234. X
  1235. X    cx = balls[i].dx > 0 ? 1 : -1;
  1236. X    cy = balls[i].dy > 0 ? 1 : -1;
  1237. X
  1238. X    if (abs(balls[i].dx) == abs(balls[i].dy))
  1239. X    {
  1240. X        incx = (float) cx;
  1241. X        incy = (float) cy;
  1242. X        step = abs(balls[i].dx);
  1243. X    } else if (abs(balls[i].dx) > abs(balls[i].dy))
  1244. X    {
  1245. X        incx = (float) cx;
  1246. X        incy = ((float) abs(balls[i].dy) / (float) abs(balls[i].dx)) * cy;
  1247. X        step = abs(balls[i].dx);
  1248. X    } 
  1249. X    else 
  1250. X    {
  1251. X        incy = (float) cy;
  1252. X        incx = ((float) abs(balls[i].dx) / (float) abs(balls[i].dy)) * cx;
  1253. X        step = abs(balls[i].dy);
  1254. X    }
  1255. X
  1256. X    for (j = 0; j < step; j++)
  1257. X    {
  1258. X        /* Check if the ball has hit a brick or something */
  1259. X        if ((ret = CheckForCollision(display, window, 
  1260. X            (int) x, (int) y, &row, &col, i)) != REGION_NONE)
  1261. X        {
  1262. X            if (HandleTheBlocks(display, window, row, col, i) == True)
  1263. X                return;
  1264. X
  1265. X            ddx = ddy = 0;
  1266. X            r = (rand() >> 16) % 4;
  1267. X
  1268. X            /* Find out which side the ball hit the brick */
  1269. X            switch (ret)
  1270. X            {
  1271. X                case REGION_LEFT:
  1272. X                    ddx = -r/4;
  1273. X                    balls[i].dx = -(abs(balls[i].dx));
  1274. X                    break;
  1275. X
  1276. X                case REGION_RIGHT:
  1277. X                    ddx = r/4;
  1278. X                    balls[i].dx = abs(balls[i].dx);
  1279. X                    break;
  1280. X
  1281. X                case REGION_TOP:
  1282. X                    ddy = -r/4;
  1283. X                    balls[i].dy = -(abs(balls[i].dy));
  1284. X                    break;
  1285. X
  1286. X                case REGION_BOTTOM:
  1287. X                    ddy = r/4;
  1288. X                    balls[i].dy = abs(balls[i].dy);
  1289. X                    break;
  1290. X
  1291. X                case (REGION_BOTTOM | REGION_RIGHT):
  1292. X                    ddy = r;
  1293. X                    ddx = r;
  1294. X                    balls[i].dy = abs(balls[i].dy);
  1295. X                    balls[i].dx = abs(balls[i].dx);
  1296. X                    break;
  1297. X
  1298. X                case (REGION_TOP | REGION_RIGHT):
  1299. X                    ddy = -r;
  1300. X                    ddx = r;
  1301. X                    balls[i].dy = -(abs(balls[i].dy));
  1302. X                    balls[i].dx = abs(balls[i].dx);
  1303. X                    break;
  1304. X
  1305. X                case (REGION_BOTTOM | REGION_LEFT):
  1306. X                    ddy = r;
  1307. X                    ddx = -r;
  1308. X                    balls[i].dx = -(abs(balls[i].dx));
  1309. X                    balls[i].dy = abs(balls[i].dy);
  1310. X                    break;
  1311. X
  1312. X                case (REGION_TOP | REGION_LEFT):
  1313. X                    ddy = -r;
  1314. X                    ddx = -r;
  1315. X                    balls[i].dx = -(abs(balls[i].dx));
  1316. X                    balls[i].dy = -(abs(balls[i].dy));
  1317. X                    break;
  1318. X            }
  1319. X
  1320. X            /* Update ball position using dx and dy values */    
  1321. X            balls[i].ballx = (int) x + balls[i].dx + ddx;
  1322. X            balls[i].bally = (int) y + balls[i].dy + ddy;
  1323. X
  1324. X            break;
  1325. X        }
  1326. X
  1327. X        x += incx;
  1328. X        y += incy;
  1329. X
  1330. X    }    /* for */
  1331. X
  1332. X    /* Move the ball to the new position */
  1333. X    MoveBall(display, window, balls[i].ballx, balls[i].bally, True, i);
  1334. X}
  1335. X
  1336. X#if NeedFunctionPrototypes
  1337. Xstatic int CheckRegions(Display *display, Window window, int row, int col,
  1338. X    int x, int y, int i)
  1339. X#else
  1340. Xstatic int CheckRegions(display, window, row, col, x, y, i)
  1341. X    Display *display;
  1342. X    Window window;
  1343. X    int row;
  1344. X    int col;
  1345. X    int x, y;
  1346. X    int i;
  1347. X#endif
  1348. X{
  1349. X    struct aBlock *blockP;
  1350. X    int region = REGION_NONE;
  1351. X
  1352. X    if (row < 0 || row >= MAX_ROW) return REGION_NONE;
  1353. X    if (col < 0 || col >= MAX_COL) return REGION_NONE;
  1354. X
  1355. X    blockP = &blocks[row][col];
  1356. X
  1357. X    /* If blocks is occupied then check for collision */
  1358. X    if (blockP->occupied == 1 && blockP->exploding == False)
  1359. X    {
  1360. X        /* Suss out if ball is moving more vertically than horizontally */
  1361. X        if (abs(balls[i].dx) > abs(balls[i].dy))
  1362. X        {
  1363. X            /* Check left and right first as ball is moving more horizontal */
  1364. X
  1365. X            /* See if the ball intersects with the block's left region */
  1366. X            if (XRectInRegion(blockP->regionLeft, x - BALL_WC, y - BALL_HC,
  1367. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1368. X                region |= REGION_LEFT;
  1369. X
  1370. X            /* See if the ball intersects with the block's right region */
  1371. X            if (XRectInRegion(blockP->regionRight, x - BALL_WC, y - BALL_HC,
  1372. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1373. X                region |= REGION_RIGHT;
  1374. X
  1375. X            /* See if the ball intersects with the block's bottom region */
  1376. X            if (XRectInRegion(blockP->regionBottom, x - BALL_WC, y - BALL_HC,
  1377. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1378. X                region |= REGION_BOTTOM;
  1379. X
  1380. X            /* See if the ball intersects with the block's top region */
  1381. X            if (XRectInRegion(blockP->regionTop, x - BALL_WC, y - BALL_HC,
  1382. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1383. X                region |= REGION_TOP;
  1384. X        }
  1385. X        else
  1386. X        {
  1387. X            /* Check top and bottom first as ball is moving more vertical */
  1388. X
  1389. X            /* See if the ball intersects with the block's bottom region */
  1390. X            if (XRectInRegion(blockP->regionBottom, x - BALL_WC, y - BALL_HC,
  1391. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1392. X                region |= REGION_BOTTOM;
  1393. X
  1394. X            /* See if the ball intersects with the block's top region */
  1395. X            if (XRectInRegion(blockP->regionTop, x - BALL_WC, y - BALL_HC,
  1396. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1397. X                region |= REGION_TOP;
  1398. X
  1399. X            /* See if the ball intersects with the block's left region */
  1400. X            if (XRectInRegion(blockP->regionLeft, x - BALL_WC, y - BALL_HC,
  1401. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1402. X                region |= REGION_LEFT;
  1403. X
  1404. X            /* See if the ball intersects with the block's right region */
  1405. X            if (XRectInRegion(blockP->regionRight, x - BALL_WC, y - BALL_HC,
  1406. X                BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
  1407. X                region |= REGION_RIGHT;
  1408. X        }
  1409. X    }
  1410. X
  1411. X    /* Return the region combination */
  1412. X    return region;
  1413. X}
  1414. X
  1415. X#if NeedFunctionPrototypes
  1416. Xstatic int CheckForCollision(Display *display, Window window, int x, int y, 
  1417. X    int *r, int *c, int i)
  1418. X#else
  1419. Xstatic int CheckForCollision(display, window, x, y, r, c, i)
  1420. X    Display *display;
  1421. X    Window window;
  1422. X    int x, y;
  1423. X    int *r, *c;
  1424. X    int i;
  1425. X#endif
  1426. X{
  1427. X    /* Check for ball to block collision */
  1428. X    int ret, row, col;
  1429. X
  1430. X    row = *r;
  1431. X    col = *c;
  1432. X
  1433. X    if ((ret = CheckRegions(display, window, row, col, x, y, i)) 
  1434. X        != REGION_NONE)    /*nothin*/;
  1435. X    else if ((ret = CheckRegions(display, window, row+1, col, x, y, i)) 
  1436. X        != REGION_NONE)    row++;
  1437. X    else if ((ret = CheckRegions(display, window, row-1, col, x, y, i)) 
  1438. X        != REGION_NONE)    row--;
  1439. X    else if ((ret = CheckRegions(display, window, row, col+1, x, y, i)) 
  1440. X        != REGION_NONE)    col++;
  1441. X    else if ((ret = CheckRegions(display, window, row, col-1, x, y, i)) 
  1442. X        != REGION_NONE)    col--;
  1443. X    else if ((ret = CheckRegions(display, window, row+1, col+1, x, y, i)) 
  1444. X        != REGION_NONE)    { row++; col++; }
  1445. X    else if ((ret = CheckRegions(display, window, row-1, col-1, x, y, i)) 
  1446. X        != REGION_NONE)    { row--; col--; }
  1447. X    else if ((ret = CheckRegions(display, window, row+1, col-1, x, y, i)) 
  1448. X        != REGION_NONE) { row++; col--; }
  1449. X    else if ((ret = CheckRegions(display, window, row-1, col+1, x, y, i)) 
  1450. X        != REGION_NONE)    
  1451. X    {
  1452. X        *r = row-1;
  1453. X        *c = col+1;
  1454. X        return REGION_NONE;
  1455. X    }
  1456. X
  1457. X    /* Return the row and column where the ball hit */
  1458. X    *r = row;
  1459. X    *c = col;
  1460. X
  1461. X    return ret;
  1462. X}
  1463. X
  1464. X#if NeedFunctionPrototypes
  1465. Xstatic void updateBallVariables(int i)
  1466. X#else
  1467. Xstatic void updateBallVariables(i)
  1468. X    int i;
  1469. X#endif
  1470. X{
  1471. X    balls[i].ballx     = paddlePos;
  1472. X    balls[i].bally     = PLAY_HEIGHT - DIST_BALL_OF_PADDLE;
  1473. X    balls[i].oldx     = balls[i].ballx;
  1474. X    balls[i].oldy     = balls[i].bally;
  1475. X}
  1476. X
  1477. X#if NeedFunctionPrototypes
  1478. Xint StartAnotherBall(Display *display, Window window)
  1479. X#else
  1480. Xint StartAnotherBall(display, window)
  1481. X    Display *display;
  1482. X    Window window;
  1483. X#endif
  1484. X{
  1485. X    int i;
  1486. X
  1487. X    i = AddANewBall(0, 0, 3, -3);
  1488. X    if (i >= 0)
  1489. X    {
  1490. X        /* Make sure that all variables are updated */
  1491. X        updateBallVariables(i);
  1492. X
  1493. X        /* Set up animation for ball creation */
  1494. X        SetBallWait(BALL_ACTIVE, frame + 1, i);
  1495. X        
  1496. X        return i;
  1497. X    }
  1498. X
  1499. X    return -1;
  1500. X}
  1501. X
  1502. X#if NeedFunctionPrototypes
  1503. Xint GetAnActiveBall(void)
  1504. X#else
  1505. Xint GetAnActiveBall()
  1506. X#endif
  1507. X{
  1508. X    int i;
  1509. X
  1510. X    /* Zap through the list of balls */
  1511. X    for (i = 0; i < MAX_BALLS; i++)
  1512. X    {
  1513. X        /* Return this ball */
  1514. X        if (balls[i].ballState == BALL_ACTIVE)
  1515. X            return i;
  1516. X    }
  1517. X
  1518. X    return -1;
  1519. X}
  1520. X
  1521. X#if NeedFunctionPrototypes
  1522. Xint IsBallWaiting(void)
  1523. X#else
  1524. Xint IsBallWaiting()
  1525. X#endif
  1526. X{
  1527. X    int i;
  1528. X
  1529. X    /* Zap through the list of balls */
  1530. X    for (i = 0; i < MAX_BALLS; i++)
  1531. X    {
  1532. X        /* Ok it must be on the paddle so shoot it off */
  1533. X        if (balls[i].ballState == BALL_READY)
  1534. X            return True;
  1535. X    }
  1536. X
  1537. X    return False;
  1538. X}
  1539. X
  1540. X#if NeedFunctionPrototypes
  1541. Xint ActivateWaitingBall(void)
  1542. X#else
  1543. Xint ActivateWaitingBall()
  1544. X#endif
  1545. X{
  1546. X    int i;
  1547. X
  1548. X    /* Zap through the list of balls */
  1549. X    for (i = 0; i < MAX_BALLS; i++)
  1550. X    {
  1551. X        /* Ok it must be on the paddle so shoot it off */
  1552. X        if (balls[i].ballState == BALL_READY)
  1553. X        {
  1554. X            /* Change the balls mode so that it shoots off */
  1555. X            ChangeBallMode(BALL_ACTIVE, i);
  1556. X            return True;
  1557. X        }
  1558. X    }
  1559. X
  1560. X    return False;
  1561. X}
  1562. X
  1563. X#if NeedFunctionPrototypes
  1564. Xvoid ResetBallStart(Display *display, Window window)
  1565. X#else
  1566. Xvoid ResetBallStart(display, window)
  1567. X    Display *display;
  1568. X    Window window;
  1569. X#endif
  1570. X{
  1571. X    int i;
  1572. X
  1573. X    i = AddANewBall(0, 0, 3, -3);
  1574. X    if (i >= 0)
  1575. X    {
  1576. X        /* Make sure that all variables are updated */
  1577. X        updateBallVariables(i);
  1578. X
  1579. X        /* Add 2 bullets every ball death or creation as it happens */
  1580. X        AddABullet(display);
  1581. X        AddABullet(display);
  1582. X
  1583. X        /* Set up animation for ball creation */
  1584. X        SetBallWait(BALL_CREATE, frame + 1, i);
  1585. X    }
  1586. X}
  1587. X
  1588. X#if NeedFunctionPrototypes
  1589. Xstatic void AnimateBallPop(Display *display, Window window, int i)
  1590. X#else
  1591. Xstatic void AnimateBallPop(display, window, i)
  1592. X    Display *display;
  1593. X    Window window;
  1594. X    int i;
  1595. X#endif
  1596. X{
  1597. X    static int slide = BIRTH_SLIDES + 1;
  1598. X
  1599. X    if (frame == balls[i].nextFrame)
  1600. X    {
  1601. X        /* We are imploding so go backwards through slides */
  1602. X        slide--;
  1603. X
  1604. X        /* Wait for the next frame */
  1605. X        balls[i].nextFrame += BIRTH_FRAME_RATE;
  1606. X
  1607. X        /* First frame is to clear the ball away */
  1608. X        if (slide == BIRTH_SLIDES)
  1609. X        {
  1610. X            /* Clear the ball area */
  1611. X            EraseTheBall(display, window, balls[i].oldx, balls[i].oldy);
  1612. X            slide--;
  1613. X        }
  1614. X
  1615. X        if (slide < 0)
  1616. X        {
  1617. X            /* Erase the ball birth image */
  1618. X            MoveBallBirth(display, window, 
  1619. X                balls[i].oldx, balls[i].oldy, -1, True, i);
  1620. X
  1621. X            slide = BIRTH_SLIDES + 1;
  1622. X
  1623. X            /* Stop the ball by killing it! */
  1624. X            ClearBall(i);
  1625. X            ResetBallStart(display, window);
  1626. X            DeadBall(display, window);
  1627. X        }
  1628. X        else
  1629. X            /* Draw ball birth - handles ball moving as well */
  1630. X            MoveBallBirth(display, window, 
  1631. X                balls[i].oldx, balls[i].oldy, slide, True, i);
  1632. X    }
  1633. X}
  1634. X
  1635. X#if NeedFunctionPrototypes
  1636. Xstatic void AnimateBallCreate(Display *display, Window window, int i)
  1637. X#else
  1638. Xstatic void AnimateBallCreate(display, window, i)
  1639. X    Display *display;
  1640. X    Window window;
  1641. X    int i;
  1642. X#endif
  1643. X{
  1644. X    static int slide = 0;
  1645. X
  1646. X    /* Draw the ball birth at the new position */
  1647. X    MoveBallBirth(display, window, paddlePos, 
  1648. X        PLAY_HEIGHT - DIST_BALL_OF_PADDLE, slide, True, i);
  1649. X
  1650. X    if (frame == balls[i].nextFrame)
  1651. X    {
  1652. X        /* Next slide thanks */
  1653. X        slide++;
  1654. X
  1655. X        /* Frame that will trigger the new slide */
  1656. X        balls[i].nextFrame += BIRTH_FRAME_RATE;
  1657. X
  1658. X        if (slide == BIRTH_SLIDES)
  1659. X        {
  1660. X            /* Erase the ball birth image */
  1661. X            MoveBallBirth(display, window, 
  1662. X                paddlePos, PLAY_HEIGHT - DIST_BALL_OF_PADDLE, -1, 
  1663. X                True, i);
  1664. X
  1665. X            slide = 0;
  1666. X
  1667. X            updateBallVariables(i);
  1668. X
  1669. X            MoveBall(display, window, paddlePos, 
  1670. X                PLAY_HEIGHT - DIST_BALL_OF_PADDLE, True, i);
  1671. X
  1672. X            ChangeBallMode(BALL_READY, i);
  1673. X
  1674. X            /* This frame will trigger the auto shoot off the ball if you
  1675. X             * don't press space within a specified time 
  1676. X             */
  1677. X            balls[i].nextFrame = frame + BALL_AUTO_ACTIVE_DELAY;
  1678. X        }
  1679. X        else
  1680. X            MoveBallBirth(display, window, 
  1681. X                paddlePos, PLAY_HEIGHT - DIST_BALL_OF_PADDLE, 
  1682. X                slide, True, i);
  1683. X
  1684. X        if (paddleIsMoving())
  1685. X            updateBallVariables(i);
  1686. X    }
  1687. X}
  1688. X
  1689. X#if NeedFunctionPrototypes
  1690. Xint GetBallMode(int i)
  1691. X#else
  1692. Xint GetBallMode(i)
  1693. X    int i;
  1694. X#endif
  1695. X{
  1696. X    /* Return the current state of the ball */
  1697. X    return balls[i].ballState;
  1698. X}
  1699. X
  1700. X#if NeedFunctionPrototypes
  1701. Xvoid ChangeBallMode(int newMode, int i)
  1702. X#else
  1703. Xvoid ChangeBallMode(newMode, i)
  1704. X    int newMode;
  1705. X    int i;
  1706. X#endif
  1707. X{
  1708. X    /* Change the ball mode */
  1709. X    balls[i].ballState = newMode;
  1710. X}
  1711. X
  1712. X#if NeedFunctionPrototypes
  1713. Xstatic void SetBallWait(int newMode, int waitFrame, int i)
  1714. X#else
  1715. Xstatic void SetBallWait(newMode, waitFrame, i)
  1716. X    int newMode;
  1717. X    int waitFrame;
  1718. X    int i;
  1719. X#endif
  1720. X{
  1721. X    /* Set up the ball waiting loop */
  1722. X    balls[i].waitingFrame    = waitFrame;
  1723. X    balls[i].waitMode         = newMode;
  1724. X    balls[i].ballState         = BALL_WAIT;
  1725. X}
  1726. X
  1727. X#if NeedFunctionPrototypes
  1728. Xstatic void DoBallWait(int i)
  1729. X#else
  1730. Xstatic void DoBallWait(i)
  1731. X    int i;
  1732. X#endif
  1733. X{
  1734. X    /* Once the waiting frame is reached then activate new state */
  1735. X    if (frame == balls[i].waitingFrame)
  1736. X    {
  1737. X        balls[i].nextFrame = frame + 10;
  1738. X        balls[i].ballState = balls[i].waitMode;
  1739. X    }
  1740. X}
  1741. X
  1742. X#if NeedFunctionPrototypes
  1743. Xint AddANewBall(int x, int y, int dx, int dy)
  1744. X#else
  1745. Xint AddANewBall(x, y, dx, dy)
  1746. X    int x;
  1747. X    int y;
  1748. X    int dx;
  1749. X    int dy;
  1750. X#endif
  1751. X{
  1752. X    int i;
  1753. X
  1754. X    /* Add a new ball to the balls array */
  1755. X    for (i = 0; i < MAX_BALLS; i++)
  1756. X    {
  1757. X        /* Is the ball free for us to use? */
  1758. X        if (balls[i].active == False)
  1759. X        {
  1760. X            /* Make sure that it is clear */
  1761. X            ClearBall(i);
  1762. X
  1763. X            /* We have found a new ball spot so setup the ball */
  1764. X            balls[i].active = True;
  1765. X            balls[i].ballx     = x;
  1766. X            balls[i].bally     = y;
  1767. X            balls[i].oldx     = balls[i].ballx;
  1768. X            balls[i].oldy     = balls[i].bally;
  1769. X            balls[i].dx     = dx;
  1770. X            balls[i].dy     = dy;
  1771. X            balls[i].ballState = BALL_CREATE;
  1772. X            balls[i].slide     = 0;
  1773. X            balls[i].nextFrame = frame + BIRTH_FRAME_RATE;
  1774. X
  1775. X            return i;
  1776. X        }
  1777. X    }
  1778. X
  1779. X    /* No more free balls available */
  1780. X    ErrorMessage("Warning: Cannot create a new ball - all active.");
  1781. X
  1782. X    return -1;
  1783. X}
  1784. X
  1785. X#if NeedFunctionPrototypes
  1786. Xvoid ClearBall(int i)
  1787. X#else
  1788. Xvoid ClearBall(i)
  1789. X    int i;
  1790. X#endif
  1791. X{
  1792. X    /* Clear out the ball structure */
  1793. X    balls[i].waitMode             = BALL_NONE;
  1794. X    balls[i].waitingFrame         = 0;
  1795. X    balls[i].lastPaddleHitFrame = 0;
  1796. X    balls[i].nextFrame             = 0;
  1797. X    balls[i].newMode             = BALL_NONE;
  1798. X    balls[i].active             = False;
  1799. X    balls[i].oldx                 = 0;
  1800. X    balls[i].oldy                 = 0;
  1801. X    balls[i].ballx                 = 0;
  1802. X    balls[i].bally                 = 0;
  1803. X    balls[i].dx                 = 0;
  1804. X    balls[i].dy                 = 0;
  1805. X    balls[i].slide                 = 0;
  1806. X    balls[i].ballState             = BALL_CREATE;
  1807. X}
  1808. X
  1809. X#if NeedFunctionPrototypes
  1810. Xvoid ClearAllBalls(void)
  1811. X#else
  1812. Xvoid ClearAllBalls()
  1813. X#endif
  1814. X{
  1815. X    int i;
  1816. X
  1817. X    /* Clear all the balls in the balls array */
  1818. X    for (i = 0; i < MAX_BALLS; i++)
  1819. X    {
  1820. X        /* "Clear the ball" - in an American accent */
  1821. X        ClearBall(i);
  1822. X    }
  1823. X}
  1824. X
  1825. X#if NeedFunctionPrototypes
  1826. Xvoid HandleBallMode(Display *display, Window window)
  1827. X#else
  1828. Xvoid HandleBallMode(display, window)
  1829. X    Display *display;
  1830. X    Window window;
  1831. X#endif
  1832. X{
  1833. X    int i;
  1834. X
  1835. X    /* Loop through all the balls */
  1836. X    for (i = 0; i < MAX_BALLS; i++)
  1837. X    {
  1838. X        /* Only handle active balls - sounds disgusting! :-) */
  1839. X        if (balls[i].active == True)
  1840. X        {
  1841. X            /* Switch on the state of the ball */
  1842. X            switch (balls[i].ballState)
  1843. X            {
  1844. X                case BALL_POP:        /* Ball pop animation */
  1845. X                    AnimateBallPop(display, window, i);
  1846. X                    break;
  1847. X
  1848. X                case BALL_ACTIVE:    /* Animate the ball normally */
  1849. X                    if ((frame % BALL_FRAME_RATE) == 0)
  1850. X                        UpdateABall(display, window, i);
  1851. X                    break;
  1852. X
  1853. X                case BALL_READY:    /* ball created and waiting to move */
  1854. X                    if (paddleIsMoving())
  1855. X                    {
  1856. X                        balls[i].ballx = paddlePos;
  1857. X                        balls[i].bally = PLAY_HEIGHT - DIST_BALL_OF_PADDLE;
  1858. X
  1859. X                        MoveBall(display, window, balls[i].ballx, 
  1860. X                            balls[i].bally, True, i);
  1861. X                    }
  1862. X
  1863. X                    /* After a certain number of seconds fire off anyway */
  1864. X                    if (frame == balls[i].nextFrame)
  1865. X                        ChangeBallMode(BALL_ACTIVE, i);
  1866. X                    break;
  1867. X
  1868. X                case BALL_STOP:        /* Ball dead and stopped */
  1869. X                    break;
  1870. X
  1871. X                case BALL_CREATE:    /* Create ball animation */
  1872. X                    AnimateBallCreate(display, window, i);
  1873. X                    break;
  1874. X
  1875. X                case BALL_WAIT:        /* In wait mode waiting to change state */
  1876. X                    DoBallWait(i);
  1877. X                    break;
  1878. X
  1879. X                case BALL_DIE:        /* Ball is going to die */
  1880. X                    if ((frame % BALL_FRAME_RATE) == 0)
  1881. X                        UpdateABall(display, window, i);
  1882. X                    break;
  1883. X
  1884. X                case BALL_NONE:        /* Really cool mode ;-) */
  1885. X                default:
  1886. X                    break;
  1887. X
  1888. X            }    /* Ball modes */
  1889. X        }    /* If active */    
  1890. X    }    /* For loop */
  1891. X}
  1892. END_OF_FILE
  1893.   if test 43006 -ne `wc -c <'ball.c'`; then
  1894.     echo shar: \"'ball.c'\" unpacked with wrong size!
  1895.   fi
  1896.   # end of 'ball.c'
  1897. fi
  1898. if test ! -d 'bitmaps' ; then
  1899.     echo shar: Creating directory \"'bitmaps'\"
  1900.     mkdir 'bitmaps'
  1901. fi
  1902. if test ! -d 'levels' ; then
  1903.     echo shar: Creating directory \"'levels'\"
  1904.     mkdir 'levels'
  1905. fi
  1906. if test ! -d 'sounds' ; then
  1907.     echo shar: Creating directory \"'sounds'\"
  1908.     mkdir 'sounds'
  1909. fi
  1910. echo shar: End of archive 1 \(of 26\).
  1911. cp /dev/null ark1isdone
  1912. MISSING=""
  1913. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ; do
  1914.     if test ! -f ark${I}isdone ; then
  1915.     MISSING="${MISSING} ${I}"
  1916.     fi
  1917. done
  1918. if test "${MISSING}" = "" ; then
  1919.     echo You have unpacked all 26 archives.
  1920.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1921.     echo "merging split files..."
  1922.     cat blocks.c[12] > blocks.c
  1923.     rm blocks.c[12]
  1924.     echo "blocks.c done"
  1925.     cat bitmaps/earth.xpm.Z.u.[ab] > bitmaps/earth.xpm.Z.uue
  1926.     rm bitmaps/earth.xpm.Z.u.[ab]
  1927.     echo "bitmaps/earth.xpm.Z.uue done"
  1928. else
  1929.     echo You still must unpack the following archives:
  1930.     echo "        " ${MISSING}
  1931. fi
  1932. exit 0
  1933. exit 0 # Just in case...
  1934. -- 
  1935.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1936. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1937.  "It's intuitively obvious to the |
  1938.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1939.