home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-03 | 53.2 KB | 1,939 lines |
- Newsgroups: comp.sources.x
- From: jck@kimba.catt.citri.edu.au (Justin Kibell)
- Subject: v20i108: xboing - a simple blockout type game, Part01/26
- Message-ID: <csx-v20i108=xboing.072914@sparky.Sterling.COM>
- X-Md4-Signature: aaa648cddc692a02d2672273c7d79d93
- Sender: chris@sparky.sterling.com (Chris Olson)
- Organization: CATT Centre at CITRI, Melbourne, Australia
- Date: Fri, 3 Sep 1993 12:30:00 GMT
- Approved: chris@sterling.com
-
- Submitted-by: jck@kimba.catt.citri.edu.au (Justin Kibell)
- Posting-number: Volume 20, Issue 108
- Archive-name: xboing/part01
- Environment: X11, xpm, color
-
- XBoing is a simple blockout type game where you have a paddle which you use to
- bounce a ball around the game area blowing up blocks with the ball. You win by
- obtaining points for each block destroyed and each level completed. The person
- with the highest score wins.
-
- XBoing was started like many other projects to learn Xlib better. I had the
- XPM library and was already using it in a Motif application. I thought that it
- would be cool to have nice colour pictures/animations in an Xlib game. So I
- did. Without the XPM library I would be still playing with the colours I think.
-
- Please read the manual page as the manual has some important game play
- information. Now I have warned you so don't complain if something doesn't
- seem to be correct or that another breakout game did it like that or this. :-)
-
- -------------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: README audio ball.c bitmaps levels sounds
- # Wrapped by chris@sparky on Fri Sep 3 07:14:40 1993
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 26)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(5657 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X XBoing Version 1.6 - By Justin Kibell
- X -------------------------------------
- X
- X 6th August 1993
- X
- XDescription
- X-----------
- X
- XXBoing is a simple blockout type game where you have a paddle which you use to
- Xbounce a ball around the game area blowing up blocks with the ball. You win by
- Xobtaining points for each block destroyed and each level completed. The person
- Xwith the highest score wins.
- X
- XXBoing was started like many other projects to learn Xlib better. I had the
- XXPM library and was already using it in a Motif application. I thought that it
- Xwould be cool to have nice colour pictures/animations in an Xlib game. So I
- Xdid. Without the XPM library I would be still playing with the colours I think.
- X
- XPlease read the manual page as the manual has some important game play
- Xinformation. Now I have warned you so don't complain if something doesn't
- Xseem to be correct or that another breakout game did it like that or this. :-)
- X
- X
- XRequirements
- X------------
- X
- XThe XPM library. Version 2.3 upwards tested. 3.2g is fine. Not tested below 2.3
- XSuggest you use 3.2g which is available everywhere now.
- X
- XA COLOUR X display. I may fix it to use other visuals later. ie: grey. mono
- X
- XAn ansi or non-ansi compiler. Ansi is better, try gcc.
- XA decent GRUNT box to run XBoing. No network travel if possible! :-)
- X
- XAlso note that if you are on a Sun machine the xnews server is not the
- Xquickest and you may experience delays in the game due to its heavy use
- Xof pixmaps etc. I suggest playing it with the MIT X Server - hassle I know
- Xif you use other Sun software that requires news etc.
- X
- XNote: It will always be a bit slower on a network so playing on the host
- X machine will give the best results. I have tuned the game for my
- X SparcStation 2 and it runs very fast. I cannot test the game on
- X other machines other the some Xterms and SGI Indigo's. Disclamier.
- X
- X
- XWhere do I get it from
- X----------------------
- X
- XVia anonymous ftp from export.lcs.mit.edu.au in the contrib directory.
- XThe most recent version is xboing1.6-tar.Z. It may appear on other mirrors
- Xthat mirror export or whatever.
- X
- XPlease do not try to obtain it from my own machine. export is quicker.
- XThe game is NOT kept in the ftp account on my machine so don't try please.
- X
- X
- XInstallation/Building game
- X--------------------------
- X
- XPlease read the file called INSTALL. It is important to read this file.
- XDon't forget to get the XPM library and compile it up first!
- X
- X
- XUsage
- X-----
- X
- XThe game does have command line options so check them out. 'xboing -help'
- X
- XThe colourmap is taken over as I need all the colours. Sorry but thats the
- Xproblem with only 256 colourmap entries. I cannot see a problem with this.
- X
- XThe colourmap is released afterwards and should return you to your lovely
- Xcolour scheme. If it doesn't please let me know.
- X
- X
- XDevelopement
- X------------
- X
- XXboing was developed on a SparcStation 2 with 48meg memory and a 19" colour
- Xdisplay using the MIT X11R5 X server, Motif Window Manager. I used x11ups
- Xfor debugging - excellent tool - well done. Sunos 4.1.2 sun4c. Compiled using
- Xgcc with warnings on and also tested using the Sun cc compiler (non ansi).
- X
- XReference books: All of O'Reilly Series, X & Motif Quick reference guide
- XGraphics: Titles done on Amiga using Deluxe Paint IV, converted using pbmplus
- X tools and xpm image touch ups with "pixmap".
- XSounds: Mainly from sounds.sdus.edu and also from other places.
- X
- X
- XSpecial Thanks
- X--------------
- X
- XReally Special thanks to Arnaud Le Hors (lehors@sophia.inria.fr) for the
- Xwonderful XPM library and for making it free :-).
- X
- XThanks for a some cool backgrounds found in Anthony's Icons V1.3 (new ones!)
- X Anthony Thyssen - anthony@cit.gu.edu.au
- X
- XThe comp.windows.x newsgroup netters for help over the past few years. See
- Xthe CHANGES doco for inline lisitings of the helpers.
- X
- XThankyou to all those who have contributed. Especially the beta testers here
- Xat CATT. It's hard to do any work around here!
- X
- X Michael Stone, Andrew Cassin, Iain Lim, Tim Liddelow, Peter Cupit
- X Craig McNaughton, Chris Fu, David Kershaw, Geoff Lambourne
- X Paul McGregor, my 3 cats ...
- X
- X
- XPatches to XBoing
- X-----------------
- X
- XPatches are great and welcomed. Please do as others have and either send them
- Xto me or post them to news. Please do NOT place them on export.lcs.mit.edu and
- Xmake it look like I put it there. I got heaps of mail saying a certain patch
- Xdidn't work and I didn't even know it existed. I think it is common courtesy
- Xto send me some email about what is going on etc.
- X
- XAlso - you can do whatever you like at your own site but don't send a patch
- Xthat changes the flag on the presentation screen. :-)
- X
- X
- XSuggestions/Bug fixes
- X---------------------
- X
- XI have had many suggestions and bug fixes. I cannot list all the names of the
- Xpeople who have helped as it would be a big list and I wouldn't want to
- Xleave anyone out. Thankyou to all those who have mailed - you know. ;-)
- X
- XSee the CHANGES doco for more info.
- X
- X
- XGrovel Bit
- X----------
- X
- XIf anyone is feeling really generous or kind they can send money, equipment,
- Xcars, travel vouchers or anything for that matter to my humble self and I
- Xwill be very happy. ;-) If that's all a bit much then a friendly email will
- Xdo fine. Hope you have fun bouncing your balls. Stay cool.
- X
- XSurface Mail: 1/17 Albert Rd, North Warrandyte, Victoria, Australia, 3113
- X
- X--------------------------------------------------------------------------
- XJustin C. Kibell - email: jck@citri.edu.au Phone: +61 3 282 2456
- XCITRI - CATT - Australia - Melbourne - Victoria - 723 Swanston St, Carlton
- XSystems Programmer - X11 Developer - Motif Head - Volunteer Rescuer - VICSES
- END_OF_FILE
- if test 5657 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test ! -d 'audio' ; then
- echo shar: Creating directory \"'audio'\"
- mkdir 'audio'
- fi
- if test -f 'ball.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ball.c'\"
- else
- echo shar: Extracting \"'ball.c'\" \(43006 characters\)
- sed "s/^X//" >'ball.c' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X/*
- X * Include file dependencies:
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <math.h>
- X#include <xpm.h>
- X
- X#include "bitmaps/ball1.xpm"
- X#include "bitmaps/ball2.xpm"
- X#include "bitmaps/ball3.xpm"
- X#include "bitmaps/ball4.xpm"
- X#include "bitmaps/killer.xpm"
- X
- X#include "bitmaps/ballbirth1.xpm"
- X#include "bitmaps/ballbirth2.xpm"
- X#include "bitmaps/ballbirth3.xpm"
- X#include "bitmaps/ballbirth4.xpm"
- X#include "bitmaps/ballbirth5.xpm"
- X#include "bitmaps/ballbirth6.xpm"
- X#include "bitmaps/ballbirth7.xpm"
- X#include "bitmaps/ballbirth8.xpm"
- X
- X#include "audio.h"
- X#include "error.h"
- X#include "score.h"
- X#include "sfx.h"
- X#include "init.h"
- X#include "main.h"
- X#include "stage.h"
- X#include "blocks.h"
- X#include "paddle.h"
- X#include "misc.h"
- X#include "level.h"
- X#include "mess.h"
- X#include "special.h"
- X
- X#include "ball.h"
- X
- X/*
- X * Internal macro definitions:
- X */
- X
- X#define X2COL(col, x) (col = x / colWidth)
- X#define Y2ROW(row, y) (row = y / rowHeight)
- X
- X#define COL2X(x, col) (x = col * colWidth)
- X#define ROW2Y(y, row) (y = row * rowHeight)
- X
- X/*
- X * Internal type declarations:
- X */
- X
- X#if NeedFunctionPrototypes
- Xstatic void MoveBall(Display *display, Window window, int x, int y, int replace,
- X int i);
- Xstatic void MoveBallBirth(Display *display, Window window, int x, int y,
- X int slide, int replace, int i);
- Xstatic void DoBoardTilt(Display *display, int i);
- Xstatic void TeleportBall(Display *display, Window window, int i);
- Xstatic int BallHitPaddle(Display *display, Window window, int *hit, int i,
- X int *x, int *y);
- Xstatic void UpdateABall(Display *display, Window window, int i);
- Xstatic int CheckRegions(Display *display, Window window, int row, int col,
- X int x, int y, int i);
- Xstatic int CheckForCollision(Display *display, Window window, int x, int y,
- X int *r, int *c, int i);
- Xstatic void updateBallVariables(int i);
- Xstatic void SetBallWait(int newMode, int waitFrame, int i);
- Xstatic void DoBallWait(int i);
- Xstatic void EraseTheBall(Display *display, Window window, int x, int y);
- X#else
- Xstatic void MoveBall();
- Xstatic void MoveBallBirth();
- Xstatic void DoBoardTilt();
- Xstatic void TeleportBall();
- Xstatic int BallHitPaddle();
- Xstatic void UpdateABall();
- Xstatic int CheckRegions();
- Xstatic int CheckForCollision();
- Xstatic void updateBallVariables();
- Xstatic void SetBallWait();
- Xstatic void DoBallWait();
- Xstatic void EraseTheBall();
- X#endif
- X
- X/*
- X * Internal variable declarations:
- X */
- X
- Xstatic Pixmap ballsPixmap[BALL_SLIDES];
- Xstatic Pixmap ballsMask[BALL_SLIDES];
- Xstatic Pixmap ballBirthPixmap[BIRTH_SLIDES];
- Xstatic Pixmap ballBirthMask[BIRTH_SLIDES];
- XBALL balls[MAX_BALLS];
- X
- X#if NeedFunctionPrototypes
- Xvoid InitialiseBall(Display *display, Window window, Colormap colormap)
- X#else
- Xvoid InitialiseBall(display, window, colormap)
- X Display *display;
- X Window window;
- X Colormap colormap;
- X#endif
- X{
- X XpmAttributes attributes;
- X int XpmErrorStatus;
- X
- X attributes.valuemask = XpmColormap;
- X attributes.colormap = colormap;
- X
- X /* Create the xpm pixmap ball frames */
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball1_xpm,
- X &ballsPixmap[0], &ballsMask[0], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball2_xpm,
- X &ballsPixmap[1], &ballsMask[1], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball3_xpm,
- X &ballsPixmap[2], &ballsMask[2], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ball4_xpm,
- X &ballsPixmap[3], &ballsMask[3], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, killer_xpm,
- X &ballsPixmap[4], &ballsMask[4], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X /* Ball birth sequence */
- X
- X /* Create the xpm pixmap ball birth frames */
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth1_xpm,
- X &ballBirthPixmap[0], &ballBirthMask[0], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth2_xpm,
- X &ballBirthPixmap[1], &ballBirthMask[1], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth3_xpm,
- X &ballBirthPixmap[2], &ballBirthMask[2], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth4_xpm,
- X &ballBirthPixmap[3], &ballBirthMask[3], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth5_xpm,
- X &ballBirthPixmap[4], &ballBirthMask[4], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth6_xpm,
- X &ballBirthPixmap[5], &ballBirthMask[5], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth7_xpm,
- X &ballBirthPixmap[6], &ballBirthMask[6], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X XpmErrorStatus = XpmCreatePixmapFromData(display, window, ballbirth8_xpm,
- X &ballBirthPixmap[7], &ballBirthMask[7], &attributes);
- X HandleXPMError(display, XpmErrorStatus, "InitialiseBall()");
- X
- X /* Free the xpm pixmap attributes */
- X XpmFreeAttributes(&attributes);
- X
- X /* Make sure that all the balls are initialised */
- X ClearAllBalls();
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid FreeBall(Display *display)
- X#else
- Xvoid FreeBall(display)
- X Display *display;
- X#endif
- X{
- X int i;
- X
- X /* Free all animation frames for the ball */
- X for (i = 0; i < BALL_SLIDES; i++)
- X {
- X if (ballsPixmap[i]) XFreePixmap(display, ballsPixmap[i]);
- X if (ballsMask[i]) XFreePixmap(display, ballsMask[i]);
- X }
- X
- X /* Free all animation frames for the ball birth */
- X for (i = 0; i < BIRTH_SLIDES; i++)
- X {
- X /* Free the ball birth animation pixmaps */
- X if (ballBirthPixmap[i]) XFreePixmap(display, ballBirthPixmap[i]);
- X if (ballBirthMask[i]) XFreePixmap(display, ballBirthMask[i]);
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid RedrawBall(Display *display, Window window)
- X#else
- Xvoid RedrawBall(display, window)
- X Display *display;
- X Window window;
- X#endif
- X{
- X /* STILL TO BE IMPLEMENTED */
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void EraseTheBall(Display *display, Window window, int x, int y)
- X#else
- Xstatic void EraseTheBall(display, window, x, y)
- X Display *display;
- X Window window;
- X int x;
- X int y;
- X#endif
- X{
- X /* Clear the ball area! The x, y coordinates are the centre of ball */
- X XClearArea(display, window, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT, False);
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid DrawTheBall(Display *display, Window window, int x, int y, int slide)
- X#else
- Xvoid DrawTheBall(display, window, x, y, slide)
- X Display *display;
- X Window window;
- X int x;
- X int y;
- X int slide;
- X#endif
- X{
- X /* Draw the ball using the slide variable as the index into the frames
- X * of the ball animation. The x,y are the centre of the ball.
- X */
- X RenderShape(display, window, ballsPixmap[slide], ballsMask[slide],
- X x - BALL_WC, y - BALL_HC, BALL_WIDTH, BALL_HEIGHT, False);
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid DrawTheBallBirth(Display *display, Window window, int x, int y, int slide)
- X#else
- Xvoid DrawTheBallBirth(display, window, x, y, slide)
- X Display *display;
- X Window window;
- X int x;
- X int y;
- X int slide;
- X#endif
- X{
- X /* Draw the ball using the slide variable as the index into the frames
- X * of the ball animation. The x,y are the centre of the ball birth anim.
- X */
- X RenderShape(display, window, ballBirthPixmap[slide], ballBirthMask[slide],
- X x - BALL_WC, y - BALL_HC, BALL_WIDTH, BALL_HEIGHT, False);
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void MoveBallBirth(Display *display, Window window, int x, int y,
- X int slide, int replace, int i)
- X#else
- Xstatic void MoveBallBirth(display, window, x, y, slide, replace, i)
- X Display *display;
- X Window window;
- X int x;
- X int y;
- X int slide;
- X int replace;
- X int i;
- X#endif
- X{
- X /* Remove any debris under ball first by clearing it */
- X if (replace)
- X {
- X XClearArea(display, window,
- X balls[i].oldx - BALL_WC, balls[i].oldy - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT, False);
- X }
- X
- X balls[i].oldx = x;
- X balls[i].oldy = y;
- X
- X /* If slide is -1 then clear the ball area */
- X if (slide == -1)
- X XClearArea(display, window,
- X x - BALL_WC, y - BALL_HC, BALL_WIDTH, BALL_HEIGHT, False);
- X else
- X DrawTheBallBirth(display, window, x, y, slide);
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void MoveBall(Display *display, Window window, int x, int y, int replace,
- X int i)
- X#else
- Xstatic void MoveBall(display, window, x, y, replace, i)
- X Display *display;
- X Window window;
- X int x;
- X int y;
- X int replace;
- X int i;
- X#endif
- X{
- X if (replace)
- X {
- X EraseTheBall(display, window, balls[i].oldx, balls[i].oldy);
- X }
- X
- X balls[i].oldx = x;
- X balls[i].oldy = y;
- X
- X if (Killer == True)
- X {
- X /* Render the killer ball now ie: red ball */
- X DrawTheBall(display, window, x, y, BALL_SLIDES-1);
- X }
- X else
- X {
- X /* Render the ball now */
- X DrawTheBall(display, window, x, y, balls[i].slide);
- X }
- X
- X /* Change slide for ball every n frames of animation */
- X if ((frame % BALL_ANIM_RATE) == 0)
- X balls[i].slide++;
- X
- X /* wrap around slides */
- X if (balls[i].slide == BALL_SLIDES-1) balls[i].slide = 0;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void DoBoardTilt(Display *display, int i)
- X#else
- Xstatic void DoBoardTilt(display, i)
- X Display *display;
- X int i;
- X#endif
- X{
- X if (balls[i].ballState == BALL_ACTIVE)
- X {
- X /* Tilt the board to remove any endless loops */
- X SetCurrentMessage(display, messWindow,
- X "Auto Tilt Activated", True);
- X
- X balls[i].dx = balls[i].dy = 0;
- X
- X /* Randomise the ball */
- X while (balls[i].dx == 0)
- X {
- X balls[i].dx = (2 - (rand() % 4)) * 2;
- X balls[i].dy = (abs(balls[i].dx)) * 2;
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X }
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void TeleportBall(Display *display, Window window, int i)
- X#else
- Xstatic void TeleportBall(display, window, i)
- X Display *display;
- X Window window;
- X int i;
- X#endif
- X{
- X /* This function will teleport the ball to some other space not occupied
- X * and start off there.
- X */
- X int r1, c1, s1, r2, c2, s2, r3, c3, s3, r4, c4, s4;
- X int r, c, x, y;
- X struct aBlock *blockP, *bP;
- X int done = False;
- X
- X /* Loop until we find a block to move to */
- X while (done == False)
- X {
- X /* Give me a new random block position */
- X r = (rand() % (MAX_ROW - 5)) + 1;
- X c = (rand() % MAX_COL) + 1;
- X
- X if (r < 0 || r >= MAX_ROW) continue;
- X if (c < 0 || c >= MAX_COL) continue;
- X
- X /* Pointer to the correct block we need - speed things up */
- X blockP = &blocks[r][c];
- X
- X /* Check that the block is not occupied and not exploding */
- X if ((blockP->occupied == False) && (blockP->exploding == False))
- X {
- X /* Check that the block is not a closed position */
- X
- X r1 = r; c1 = c - 1; s1 = 0;
- X if (r1 < 0 || r1 >= MAX_ROW) s1 = 1;
- X if (c1 < 0 || c1 >= MAX_COL) s1 = 1;
- X if (s1 == 0)
- X {
- X bP = &blocks[r1][c1];
- X if (bP->blockType == BLACK_BLK)
- X s1 = 1;
- X }
- X
- X r2 = r - 1; c2 = c; s2 = 0;
- X if (r2 < 0 || r2 >= MAX_ROW) s2 = 1;
- X if (c2 < 0 || c2 >= MAX_COL) s2 = 1;
- X if (s2 == 0)
- X {
- X bP = &blocks[r2][c2];
- X if (bP->blockType == BLACK_BLK)
- X s2 = 1;
- X }
- X
- X r3 = r; c3 = c + 1; s3 = 0;
- X if (r3 < 0 || r3 >= MAX_ROW) s3 = 1;
- X if (c3 < 0 || c3 >= MAX_COL) s3 = 1;
- X if (s3 == 0)
- X {
- X bP = &blocks[r3][c3];
- X if (bP->blockType == BLACK_BLK)
- X s3 = 1;
- X }
- X
- X r4 = r + 1; c4 = c; s4 = 0;
- X if (r4 < 0 || r4 >= MAX_ROW) s4 = 1;
- X if (c4 < 0 || c4 >= MAX_COL) s4 = 1;
- X if (s4 == 0)
- X {
- X bP = &blocks[r4][c4];
- X if (bP->blockType == BLACK_BLK)
- X s4 = 1;
- X }
- X
- X /* If it isn't ok to go here then keep searching */
- X if ((s1 == 1) && (s2 == 1) && (s3 == 1) && (s4 == 1))
- X continue;
- X
- X /* Calculate the new ball coordinates */
- X COL2X(x, c);
- X ROW2Y(y, r);
- X
- X balls[i].ballx = x;
- X balls[i].bally = y;
- X
- X /* Move the ball to the new position */
- X MoveBall(display, window, x, y, True, i);
- X
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* Ok jump out now thanks. */
- X done = True;
- X }
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid SplitBallInTwo(Display *display, Window window)
- X#else
- Xvoid SplitBallInTwo(display, window)
- X Display *display;
- X Window window;
- X#endif
- X{
- X int j;
- X
- X if (livesLeft > 0)
- X {
- X j = AddANewBall(PLAY_WIDTH / 2, -BALL_HC, 3, 3);
- X if (j > 0)
- X {
- X /* Make this new ball move straight away */
- X ChangeBallMode(BALL_ACTIVE, j);
- X
- X /* Take the life from player as the new ball is in play */
- X DecExtraLife(display);
- X
- X SetCurrentMessage(display, messWindow,
- X "More balls!", True);
- X }
- X }
- X else
- X SetCurrentMessage(display, messWindow,
- X "Cannot add ball!", True);
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid ClearBallNow(Display *display, Window window, int i)
- X#else
- Xvoid ClearBallNow(display, window, i)
- X Display *display;
- X Window window;
- X int i;
- X#endif
- X{
- X /* Kill the ball now, boy! */
- X EraseTheBall(display, window, balls[i].ballx, balls[i].bally);
- X ClearBall(i);
- X DeadBall(display, window);
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid KillBallNow(Display *display, Window window, int i)
- X#else
- Xvoid KillBallNow(display, window, i)
- X Display *display;
- X Window window;
- X int i;
- X#endif
- X{
- X /* Kill the ball now, boy! */
- X ChangeBallMode(BALL_POP, i);
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid GetBallPosition(int *ballX, int *ballY, int i)
- X#else
- Xvoid GetBallPosition(ballX, ballY, i)
- X int *ballX;
- X int *ballY;
- X int i;
- X#endif
- X{
- X /* Return ball i's position */
- X *ballX = balls[i].ballx;
- X *ballY = balls[i].bally;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic int BallHitPaddle(Display *display, Window window, int *hit, int i,
- X int *x, int *y)
- X#else
- Xstatic int BallHitPaddle(display, window, hit, i, x, y)
- X Display *display;
- X Window window;
- X int *hit;
- X int i;
- X int *x, *y;
- X#endif
- X{
- X float x1, x2, y1, y2, alpha, beta, xP1, xP2, xH, yH;
- X int paddleLine;
- X
- X /***********************************************************************
- X
- X A1 (x1,y1)
- X *
- X .
- X .
- X P1 =========.=========== P2 <---- paddle (x, y pos is known )
- X (xP1,yP1) . H (xH, yH) (xP2,yP2)
- X .
- X .
- X .
- X .
- X .
- X *
- X A2 (x2,y2)
- X
- X Given the line A1A2, is the intersecting point H (xH, yH) in the paddle
- X segment ? (i.e xH in [xP1,xP2])
- X
- X A1A2 is : y = alpha * x + beta
- X
- X A1 and A2 are in A1A2 than beta = [(y1 + y2) - alpha*(x1+x2)] / 2
- X
- X yH = yP1 = yP2
- X
- X so xH = (yP1 - beta) / alpha
- X
- X **********************************************************************/
- X
- X paddleLine = (PLAY_HEIGHT - DIST_BASE - 2);
- X
- X if (balls[i].bally + BALL_HC > paddleLine)
- X {
- X xP1 = (float)(paddlePos - (GetPaddleSize() / 2) - BALL_WC/2);
- X xP2 = (float)(paddlePos + (GetPaddleSize() / 2) + BALL_WC/2);
- X
- X if (balls[i].dx == 0)
- X {
- X /* process the vertical moving balls */
- X if (((float)balls[i].ballx > xP1) && ((float)balls[i].ballx < xP2))
- X {
- X /* the ball hit the paddle */
- X *hit = balls[i].ballx - paddlePos;
- X *x = balls[i].ballx;
- X *y = paddleLine - BALL_HC;
- X
- X return True;
- X }
- X else
- X return False;
- X }
- X else
- X {
- X /* compute the line coefficients of the ball */
- X
- X alpha = (float) balls[i].dy;
- X x1 = (float) (balls[i].ballx - balls[i].dx);
- X y1 = (float) (balls[i].bally - balls[i].dy);
- X x2 = (float) (balls[i].ballx);
- X y2 = (float) (balls[i].bally);
- X beta = ((y1 + y2) - alpha * (x1 + x2)) / 2.0;
- X
- X yH = (float) paddleLine;
- X xH = (yH - beta) / alpha;
- X
- X if ((xH > xP1) && (xH < xP2))
- X {
- X /* the ball hit the paddle */
- X *hit = (int) (xH + 0.5) - paddlePos;
- X *x = (int) (xH + 0.5);
- X *y = paddleLine - BALL_HC;
- X
- X return True;
- X }
- X else
- X return False;
- X }
- X }
- X
- X /* We didn't hit the paddle */
- X return False;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic int HandleTheBlocks(Display *display, Window window, int row, int col,
- X int i)
- X#else
- Xstatic int HandleTheBlocks(display, window, row, col, i)
- X int row;
- X int col;
- X int i;
- X#endif
- X{
- X struct aBlock *blockP;
- X
- X /* Pointer to the block the ball is in */
- X blockP = &blocks[row][col];
- X
- X /* There has been a collision so handle it */
- X if (blockP->exploding == False)
- X {
- X if (blockP->blockType == COUNTER_BLK)
- X {
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X {
- X DrawBlock(display, window, row, col, KILL_BLK);
- X return True;
- X }
- X
- X /* Special case for counter - reduce count on block */
- X if (blockP->counterSlide == 0)
- X DrawBlock(display, window, row, col, KILL_BLK);
- X else
- X {
- X /* Draw the counter block minus one number */
- X blockP->counterSlide--;
- X DrawBlock(display, window, row, col, COUNTER_BLK);
- X }
- X }
- X else
- X {
- X if (blockP->blockType == MGUN_BLK)
- X {
- X /* Turn the machine gun on */
- X ToggleFastGun(display, True);
- X DrawSpecials(display);
- X SetCurrentMessage(display, messWindow,
- X "Machine Gun", True);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == DEATH_BLK)
- X {
- X /* Ha ha - hit death block so die */
- X
- X /* Kill the ball now */
- X ClearBallNow(display, window, i);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == HYPERSPACE_BLK)
- X {
- X /* Teleport to somewhere else */
- X TeleportBall(display, window, i);
- X
- X /* Redraw it just in case */
- X DrawBlock(display, window, row, col, HYPERSPACE_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X PlaySoundForBlock(HYPERSPACE_BLK);
- X
- X return True;
- X
- X } else if (blockP->blockType == WALLOFF_BLK)
- X {
- X /* Walls are now turned off */
- X ToggleWallsOn(display, True);
- X DrawSpecials(display);
- X SetCurrentMessage(display, messWindow,
- X "Walls off", True);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == REVERSE_BLK)
- X {
- X /* Paddle control now reverse */
- X ToggleReverse(display);
- X SetCurrentMessage(display, messWindow,
- X "Reverse Control", True);
- X DrawSpecials(display);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == PAD_SHRINK_BLK)
- X {
- X /* Paddle shrinking block */
- X ChangePaddleSize(display, window, PAD_SHRINK_BLK);
- X SetCurrentMessage(display, messWindow,
- X "Shrink Paddle", True);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == PAD_EXPAND_BLK)
- X {
- X /* Paddle expanding block */
- X ChangePaddleSize(display, window, PAD_EXPAND_BLK);
- X SetCurrentMessage(display, messWindow,
- X "Expand Paddle", True);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == EXTRABALL_BLK)
- X {
- X /* Extra ball */
- X AddExtraLife(display);
- X SetCurrentMessage(display, messWindow,
- X "Extra ball", True);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == STICKY_BLK)
- X {
- X ToggleStickyBat(display, True);
- X DrawSpecials(display);
- X SetCurrentMessage(display, messWindow,
- X "Sticky Bat", True);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType == MULTIBALL_BLK)
- X {
- X ToggleMultiBall(display, True);
- X DrawSpecials(display);
- X SplitBallInTwo(display, window);
- X
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True)
- X return True;
- X
- X } else if (blockP->blockType != BLACK_BLK)
- X {
- X /* Not a wall so explode the block */
- X DrawBlock(display, window, row, col, KILL_BLK);
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X
- X /* If in killer mode then don't bounce off block */
- X if (Killer == True) return True;
- X }
- X else if (blockP->blockType == BLACK_BLK)
- X {
- X /* Redraw the solid wall block to make sure */
- X DrawBlock(display, window, row, col, BLACK_BLK);
- X }
- X }
- X }
- X
- X /* Don't return after returning */
- X return False;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void UpdateABall(Display *display, Window window, int i)
- X#else
- Xstatic void UpdateABall(display, window, i)
- X Display *display;
- X Window window;
- X int i;
- X#endif
- X{
- X int row, col, hitPos, ret;
- X int cx, cy, step, j, r, ddx, ddy, Hx, Hy;
- X float incx, incy, x, y;
- X float Vs, Vx, Vy, alpha, beta, gamma, padSize;
- X
- X /* Update ball position using dx and dy values */
- X balls[i].ballx = balls[i].oldx + balls[i].dx;
- X balls[i].bally = balls[i].oldy + balls[i].dy;
- X
- X /* Mark the ball to die as it is past the paddle */
- X if (balls[i].bally > (PLAY_HEIGHT - DIST_BASE))
- X ChangeBallMode(BALL_DIE, i);
- X
- X /* Check if ball has hit left wall and bounce off */
- X if (balls[i].ballx < BALL_WC && noWalls == False)
- X {
- X balls[i].dx = abs(balls[i].dx);
- X if (noSound == False) playSoundFile("boing", 20);
- X
- X } else if (noWalls == True && balls[i].ballx < BALL_WC)
- X {
- X /* If the no walls mode is on then wrap around onto right wall */
- X balls[i].ballx = (PLAY_WIDTH - BALL_WC);
- X
- X /* Move the ball to the new position */
- X MoveBall(display, window, balls[i].ballx, balls[i].bally, True, i);
- X
- X return;
- X }
- X
- X /* Check if ball has hit right wall and bounce off */
- X if (balls[i].ballx > (PLAY_WIDTH - BALL_WC) && noWalls == False)
- X {
- X balls[i].dx = -(abs(balls[i].dx));
- X if (noSound == False) playSoundFile("boing", 20);
- X
- X } else if (noWalls == True && balls[i].ballx > (PLAY_WIDTH - BALL_WC))
- X {
- X /* If the no walls mode is on then wrap around onto left wall */
- X balls[i].ballx = BALL_WC;
- X
- X /* Move the ball to the new position */
- X MoveBall(display, window, balls[i].ballx, balls[i].bally, True, i);
- X
- X return;
- X }
- X
- X /* Check if ball has hit top wall and bounce off */
- X if (balls[i].bally < BALL_HC)
- X {
- X balls[i].dy = abs(balls[i].dy);
- X if (noSound == False) playSoundFile("boing", 20);
- X }
- X
- X if (balls[i].ballState != BALL_DIE)
- X {
- X /* Check if the ball has hit the paddle */
- X if (BallHitPaddle(display, window, &hitPos, i, &Hx, &Hy) == True)
- X {
- X /* Keep track of how long it was since the last paddle hit */
- X balls[i].lastPaddleHitFrame = frame + PADDLE_BALL_FRAME_TILT;
- X if (noSound == False) playSoundFile("boing", 20);
- X
- X /* Add a paddle hit bonus score, I'm nice ;-) */
- X AddToScore((u_long) PADDLE_HIT_SCORE);
- X DisplayScore(display, scoreWindow, score);
- X
- X /* speed vector of the ball */
- X Vx = (float) balls[i].dx;
- X Vy = (float) balls[i].dy;
- X
- X /* speed intensity of the ball */
- X Vs = sqrt( Vx*Vx + Vy*Vy );
- X
- X alpha = atan(Vx/-Vy);
- X
- X padSize = (float)(GetPaddleSize() + BALL_WC);
- X Vx = (float) hitPos;
- X Vy = (float) padSize/1.0;
- X
- X beta = atan(Vx/Vy);
- X gamma = 2.0*beta - alpha;
- X
- X Vx = Vs * sin(gamma);
- X Vy = -Vs * cos(gamma);
- X
- X /* take in account the horizontal speed of the paddle:
- X * vectorial summ
- X */
- X Vx += (float) (paddleDx / 10.0);
- X
- X if (Vx > 0.0)
- X balls[i].dx = (int) (Vx + 0.5);
- X else
- X balls[i].dx = (int) (Vx - 0.5);
- X
- X if (Vy < 0.0)
- X balls[i].dy = (int) (Vy - 0.5);
- X else
- X balls[i].dy = -MIN_DY_BALL;
- X
- X if (balls[i].dy > -MIN_DY_BALL)
- X balls[i].dy = -MIN_DY_BALL;
- X
- X balls[i].ballx = Hx;
- X balls[i].bally = Hy;
- X
- X /* handle the sticky paddle special by changing the ball mode
- X * to BALL_READY so it will need user to press space to start
- X * the ball moving again.
- X */
- X if (stickyBat == True)
- X {
- X ChangeBallMode(BALL_READY, i);
- X
- X /* Move the ball to the new position */
- X MoveBall(display, window,
- X balls[i].ballx, balls[i].bally, True, i);
- X
- X /* So that it will auto shoot off if you wait too long */
- X balls[i].nextFrame = frame + BALL_AUTO_ACTIVE_DELAY;
- X
- X return;
- X }
- X }
- X else
- X {
- X /* Ball didn't hit the paddle so check if it time to autotilt the
- X * board as it is in an infinite loop most likely.
- X */
- X if (balls[i].lastPaddleHitFrame == frame)
- X DoBoardTilt(display, i);
- X }
- X
- X Vx = (float) balls[i].dx;
- X Vy = (float) balls[i].dy;
- X Vs = sqrt(Vx * Vx + Vy * Vy);
- X
- X alpha = sqrt((float)MAX_X_VEL*(float)MAX_X_VEL + (float)MAX_Y_VEL*
- X (float)MAX_Y_VEL );
- X alpha /= 9.0; /* number of speed level */
- X alpha *= (float) speedLevel;
- X beta = alpha / Vs;
- X Vx *= beta;
- X Vy *= beta;
- X
- X if (Vx > 0.0)
- X balls[i].dx = (int) (Vx + 0.5);
- X else
- X balls[i].dx = (int) (Vx - 0.5);
- X
- X if (Vy > 0.0)
- X balls[i].dy = (int) (Vy + 0.5);
- X else
- X balls[i].dy = (int) (Vy - 0.5);
- X
- X if (balls[i].dy == 0)
- X balls[i].dy = MIN_DY_BALL;
- X
- X if (balls[i].dx == 0)
- X balls[i].dx = MIN_DX_BALL;
- X }
- X
- X /* Has the player lost the ball of the bottom of the screen */
- X if (balls[i].bally > (PLAY_HEIGHT + BALL_HEIGHT))
- X {
- X /* Make ball start to die */
- X ClearBallNow(display, window, i);
- X return;
- X }
- X
- X /* Convert the new ball positions to rows and cols for collision */
- X X2COL(col, balls[i].ballx);
- X Y2ROW(row, balls[i].bally);
- X
- X x = balls[i].oldx;
- X y = balls[i].oldy;
- X
- X cx = balls[i].dx > 0 ? 1 : -1;
- X cy = balls[i].dy > 0 ? 1 : -1;
- X
- X if (abs(balls[i].dx) == abs(balls[i].dy))
- X {
- X incx = (float) cx;
- X incy = (float) cy;
- X step = abs(balls[i].dx);
- X } else if (abs(balls[i].dx) > abs(balls[i].dy))
- X {
- X incx = (float) cx;
- X incy = ((float) abs(balls[i].dy) / (float) abs(balls[i].dx)) * cy;
- X step = abs(balls[i].dx);
- X }
- X else
- X {
- X incy = (float) cy;
- X incx = ((float) abs(balls[i].dx) / (float) abs(balls[i].dy)) * cx;
- X step = abs(balls[i].dy);
- X }
- X
- X for (j = 0; j < step; j++)
- X {
- X /* Check if the ball has hit a brick or something */
- X if ((ret = CheckForCollision(display, window,
- X (int) x, (int) y, &row, &col, i)) != REGION_NONE)
- X {
- X if (HandleTheBlocks(display, window, row, col, i) == True)
- X return;
- X
- X ddx = ddy = 0;
- X r = (rand() >> 16) % 4;
- X
- X /* Find out which side the ball hit the brick */
- X switch (ret)
- X {
- X case REGION_LEFT:
- X ddx = -r/4;
- X balls[i].dx = -(abs(balls[i].dx));
- X break;
- X
- X case REGION_RIGHT:
- X ddx = r/4;
- X balls[i].dx = abs(balls[i].dx);
- X break;
- X
- X case REGION_TOP:
- X ddy = -r/4;
- X balls[i].dy = -(abs(balls[i].dy));
- X break;
- X
- X case REGION_BOTTOM:
- X ddy = r/4;
- X balls[i].dy = abs(balls[i].dy);
- X break;
- X
- X case (REGION_BOTTOM | REGION_RIGHT):
- X ddy = r;
- X ddx = r;
- X balls[i].dy = abs(balls[i].dy);
- X balls[i].dx = abs(balls[i].dx);
- X break;
- X
- X case (REGION_TOP | REGION_RIGHT):
- X ddy = -r;
- X ddx = r;
- X balls[i].dy = -(abs(balls[i].dy));
- X balls[i].dx = abs(balls[i].dx);
- X break;
- X
- X case (REGION_BOTTOM | REGION_LEFT):
- X ddy = r;
- X ddx = -r;
- X balls[i].dx = -(abs(balls[i].dx));
- X balls[i].dy = abs(balls[i].dy);
- X break;
- X
- X case (REGION_TOP | REGION_LEFT):
- X ddy = -r;
- X ddx = -r;
- X balls[i].dx = -(abs(balls[i].dx));
- X balls[i].dy = -(abs(balls[i].dy));
- X break;
- X }
- X
- X /* Update ball position using dx and dy values */
- X balls[i].ballx = (int) x + balls[i].dx + ddx;
- X balls[i].bally = (int) y + balls[i].dy + ddy;
- X
- X break;
- X }
- X
- X x += incx;
- X y += incy;
- X
- X } /* for */
- X
- X /* Move the ball to the new position */
- X MoveBall(display, window, balls[i].ballx, balls[i].bally, True, i);
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic int CheckRegions(Display *display, Window window, int row, int col,
- X int x, int y, int i)
- X#else
- Xstatic int CheckRegions(display, window, row, col, x, y, i)
- X Display *display;
- X Window window;
- X int row;
- X int col;
- X int x, y;
- X int i;
- X#endif
- X{
- X struct aBlock *blockP;
- X int region = REGION_NONE;
- X
- X if (row < 0 || row >= MAX_ROW) return REGION_NONE;
- X if (col < 0 || col >= MAX_COL) return REGION_NONE;
- X
- X blockP = &blocks[row][col];
- X
- X /* If blocks is occupied then check for collision */
- X if (blockP->occupied == 1 && blockP->exploding == False)
- X {
- X /* Suss out if ball is moving more vertically than horizontally */
- X if (abs(balls[i].dx) > abs(balls[i].dy))
- X {
- X /* Check left and right first as ball is moving more horizontal */
- X
- X /* See if the ball intersects with the block's left region */
- X if (XRectInRegion(blockP->regionLeft, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_LEFT;
- X
- X /* See if the ball intersects with the block's right region */
- X if (XRectInRegion(blockP->regionRight, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_RIGHT;
- X
- X /* See if the ball intersects with the block's bottom region */
- X if (XRectInRegion(blockP->regionBottom, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_BOTTOM;
- X
- X /* See if the ball intersects with the block's top region */
- X if (XRectInRegion(blockP->regionTop, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_TOP;
- X }
- X else
- X {
- X /* Check top and bottom first as ball is moving more vertical */
- X
- X /* See if the ball intersects with the block's bottom region */
- X if (XRectInRegion(blockP->regionBottom, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_BOTTOM;
- X
- X /* See if the ball intersects with the block's top region */
- X if (XRectInRegion(blockP->regionTop, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_TOP;
- X
- X /* See if the ball intersects with the block's left region */
- X if (XRectInRegion(blockP->regionLeft, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_LEFT;
- X
- X /* See if the ball intersects with the block's right region */
- X if (XRectInRegion(blockP->regionRight, x - BALL_WC, y - BALL_HC,
- X BALL_WIDTH, BALL_HEIGHT) != RectangleOut)
- X region |= REGION_RIGHT;
- X }
- X }
- X
- X /* Return the region combination */
- X return region;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic int CheckForCollision(Display *display, Window window, int x, int y,
- X int *r, int *c, int i)
- X#else
- Xstatic int CheckForCollision(display, window, x, y, r, c, i)
- X Display *display;
- X Window window;
- X int x, y;
- X int *r, *c;
- X int i;
- X#endif
- X{
- X /* Check for ball to block collision */
- X int ret, row, col;
- X
- X row = *r;
- X col = *c;
- X
- X if ((ret = CheckRegions(display, window, row, col, x, y, i))
- X != REGION_NONE) /*nothin*/;
- X else if ((ret = CheckRegions(display, window, row+1, col, x, y, i))
- X != REGION_NONE) row++;
- X else if ((ret = CheckRegions(display, window, row-1, col, x, y, i))
- X != REGION_NONE) row--;
- X else if ((ret = CheckRegions(display, window, row, col+1, x, y, i))
- X != REGION_NONE) col++;
- X else if ((ret = CheckRegions(display, window, row, col-1, x, y, i))
- X != REGION_NONE) col--;
- X else if ((ret = CheckRegions(display, window, row+1, col+1, x, y, i))
- X != REGION_NONE) { row++; col++; }
- X else if ((ret = CheckRegions(display, window, row-1, col-1, x, y, i))
- X != REGION_NONE) { row--; col--; }
- X else if ((ret = CheckRegions(display, window, row+1, col-1, x, y, i))
- X != REGION_NONE) { row++; col--; }
- X else if ((ret = CheckRegions(display, window, row-1, col+1, x, y, i))
- X != REGION_NONE)
- X {
- X *r = row-1;
- X *c = col+1;
- X return REGION_NONE;
- X }
- X
- X /* Return the row and column where the ball hit */
- X *r = row;
- X *c = col;
- X
- X return ret;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void updateBallVariables(int i)
- X#else
- Xstatic void updateBallVariables(i)
- X int i;
- X#endif
- X{
- X balls[i].ballx = paddlePos;
- X balls[i].bally = PLAY_HEIGHT - DIST_BALL_OF_PADDLE;
- X balls[i].oldx = balls[i].ballx;
- X balls[i].oldy = balls[i].bally;
- X}
- X
- X#if NeedFunctionPrototypes
- Xint StartAnotherBall(Display *display, Window window)
- X#else
- Xint StartAnotherBall(display, window)
- X Display *display;
- X Window window;
- X#endif
- X{
- X int i;
- X
- X i = AddANewBall(0, 0, 3, -3);
- X if (i >= 0)
- X {
- X /* Make sure that all variables are updated */
- X updateBallVariables(i);
- X
- X /* Set up animation for ball creation */
- X SetBallWait(BALL_ACTIVE, frame + 1, i);
- X
- X return i;
- X }
- X
- X return -1;
- X}
- X
- X#if NeedFunctionPrototypes
- Xint GetAnActiveBall(void)
- X#else
- Xint GetAnActiveBall()
- X#endif
- X{
- X int i;
- X
- X /* Zap through the list of balls */
- X for (i = 0; i < MAX_BALLS; i++)
- X {
- X /* Return this ball */
- X if (balls[i].ballState == BALL_ACTIVE)
- X return i;
- X }
- X
- X return -1;
- X}
- X
- X#if NeedFunctionPrototypes
- Xint IsBallWaiting(void)
- X#else
- Xint IsBallWaiting()
- X#endif
- X{
- X int i;
- X
- X /* Zap through the list of balls */
- X for (i = 0; i < MAX_BALLS; i++)
- X {
- X /* Ok it must be on the paddle so shoot it off */
- X if (balls[i].ballState == BALL_READY)
- X return True;
- X }
- X
- X return False;
- X}
- X
- X#if NeedFunctionPrototypes
- Xint ActivateWaitingBall(void)
- X#else
- Xint ActivateWaitingBall()
- X#endif
- X{
- X int i;
- X
- X /* Zap through the list of balls */
- X for (i = 0; i < MAX_BALLS; i++)
- X {
- X /* Ok it must be on the paddle so shoot it off */
- X if (balls[i].ballState == BALL_READY)
- X {
- X /* Change the balls mode so that it shoots off */
- X ChangeBallMode(BALL_ACTIVE, i);
- X return True;
- X }
- X }
- X
- X return False;
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid ResetBallStart(Display *display, Window window)
- X#else
- Xvoid ResetBallStart(display, window)
- X Display *display;
- X Window window;
- X#endif
- X{
- X int i;
- X
- X i = AddANewBall(0, 0, 3, -3);
- X if (i >= 0)
- X {
- X /* Make sure that all variables are updated */
- X updateBallVariables(i);
- X
- X /* Add 2 bullets every ball death or creation as it happens */
- X AddABullet(display);
- X AddABullet(display);
- X
- X /* Set up animation for ball creation */
- X SetBallWait(BALL_CREATE, frame + 1, i);
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void AnimateBallPop(Display *display, Window window, int i)
- X#else
- Xstatic void AnimateBallPop(display, window, i)
- X Display *display;
- X Window window;
- X int i;
- X#endif
- X{
- X static int slide = BIRTH_SLIDES + 1;
- X
- X if (frame == balls[i].nextFrame)
- X {
- X /* We are imploding so go backwards through slides */
- X slide--;
- X
- X /* Wait for the next frame */
- X balls[i].nextFrame += BIRTH_FRAME_RATE;
- X
- X /* First frame is to clear the ball away */
- X if (slide == BIRTH_SLIDES)
- X {
- X /* Clear the ball area */
- X EraseTheBall(display, window, balls[i].oldx, balls[i].oldy);
- X slide--;
- X }
- X
- X if (slide < 0)
- X {
- X /* Erase the ball birth image */
- X MoveBallBirth(display, window,
- X balls[i].oldx, balls[i].oldy, -1, True, i);
- X
- X slide = BIRTH_SLIDES + 1;
- X
- X /* Stop the ball by killing it! */
- X ClearBall(i);
- X ResetBallStart(display, window);
- X DeadBall(display, window);
- X }
- X else
- X /* Draw ball birth - handles ball moving as well */
- X MoveBallBirth(display, window,
- X balls[i].oldx, balls[i].oldy, slide, True, i);
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void AnimateBallCreate(Display *display, Window window, int i)
- X#else
- Xstatic void AnimateBallCreate(display, window, i)
- X Display *display;
- X Window window;
- X int i;
- X#endif
- X{
- X static int slide = 0;
- X
- X /* Draw the ball birth at the new position */
- X MoveBallBirth(display, window, paddlePos,
- X PLAY_HEIGHT - DIST_BALL_OF_PADDLE, slide, True, i);
- X
- X if (frame == balls[i].nextFrame)
- X {
- X /* Next slide thanks */
- X slide++;
- X
- X /* Frame that will trigger the new slide */
- X balls[i].nextFrame += BIRTH_FRAME_RATE;
- X
- X if (slide == BIRTH_SLIDES)
- X {
- X /* Erase the ball birth image */
- X MoveBallBirth(display, window,
- X paddlePos, PLAY_HEIGHT - DIST_BALL_OF_PADDLE, -1,
- X True, i);
- X
- X slide = 0;
- X
- X updateBallVariables(i);
- X
- X MoveBall(display, window, paddlePos,
- X PLAY_HEIGHT - DIST_BALL_OF_PADDLE, True, i);
- X
- X ChangeBallMode(BALL_READY, i);
- X
- X /* This frame will trigger the auto shoot off the ball if you
- X * don't press space within a specified time
- X */
- X balls[i].nextFrame = frame + BALL_AUTO_ACTIVE_DELAY;
- X }
- X else
- X MoveBallBirth(display, window,
- X paddlePos, PLAY_HEIGHT - DIST_BALL_OF_PADDLE,
- X slide, True, i);
- X
- X if (paddleIsMoving())
- X updateBallVariables(i);
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xint GetBallMode(int i)
- X#else
- Xint GetBallMode(i)
- X int i;
- X#endif
- X{
- X /* Return the current state of the ball */
- X return balls[i].ballState;
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid ChangeBallMode(int newMode, int i)
- X#else
- Xvoid ChangeBallMode(newMode, i)
- X int newMode;
- X int i;
- X#endif
- X{
- X /* Change the ball mode */
- X balls[i].ballState = newMode;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void SetBallWait(int newMode, int waitFrame, int i)
- X#else
- Xstatic void SetBallWait(newMode, waitFrame, i)
- X int newMode;
- X int waitFrame;
- X int i;
- X#endif
- X{
- X /* Set up the ball waiting loop */
- X balls[i].waitingFrame = waitFrame;
- X balls[i].waitMode = newMode;
- X balls[i].ballState = BALL_WAIT;
- X}
- X
- X#if NeedFunctionPrototypes
- Xstatic void DoBallWait(int i)
- X#else
- Xstatic void DoBallWait(i)
- X int i;
- X#endif
- X{
- X /* Once the waiting frame is reached then activate new state */
- X if (frame == balls[i].waitingFrame)
- X {
- X balls[i].nextFrame = frame + 10;
- X balls[i].ballState = balls[i].waitMode;
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xint AddANewBall(int x, int y, int dx, int dy)
- X#else
- Xint AddANewBall(x, y, dx, dy)
- X int x;
- X int y;
- X int dx;
- X int dy;
- X#endif
- X{
- X int i;
- X
- X /* Add a new ball to the balls array */
- X for (i = 0; i < MAX_BALLS; i++)
- X {
- X /* Is the ball free for us to use? */
- X if (balls[i].active == False)
- X {
- X /* Make sure that it is clear */
- X ClearBall(i);
- X
- X /* We have found a new ball spot so setup the ball */
- X balls[i].active = True;
- X balls[i].ballx = x;
- X balls[i].bally = y;
- X balls[i].oldx = balls[i].ballx;
- X balls[i].oldy = balls[i].bally;
- X balls[i].dx = dx;
- X balls[i].dy = dy;
- X balls[i].ballState = BALL_CREATE;
- X balls[i].slide = 0;
- X balls[i].nextFrame = frame + BIRTH_FRAME_RATE;
- X
- X return i;
- X }
- X }
- X
- X /* No more free balls available */
- X ErrorMessage("Warning: Cannot create a new ball - all active.");
- X
- X return -1;
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid ClearBall(int i)
- X#else
- Xvoid ClearBall(i)
- X int i;
- X#endif
- X{
- X /* Clear out the ball structure */
- X balls[i].waitMode = BALL_NONE;
- X balls[i].waitingFrame = 0;
- X balls[i].lastPaddleHitFrame = 0;
- X balls[i].nextFrame = 0;
- X balls[i].newMode = BALL_NONE;
- X balls[i].active = False;
- X balls[i].oldx = 0;
- X balls[i].oldy = 0;
- X balls[i].ballx = 0;
- X balls[i].bally = 0;
- X balls[i].dx = 0;
- X balls[i].dy = 0;
- X balls[i].slide = 0;
- X balls[i].ballState = BALL_CREATE;
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid ClearAllBalls(void)
- X#else
- Xvoid ClearAllBalls()
- X#endif
- X{
- X int i;
- X
- X /* Clear all the balls in the balls array */
- X for (i = 0; i < MAX_BALLS; i++)
- X {
- X /* "Clear the ball" - in an American accent */
- X ClearBall(i);
- X }
- X}
- X
- X#if NeedFunctionPrototypes
- Xvoid HandleBallMode(Display *display, Window window)
- X#else
- Xvoid HandleBallMode(display, window)
- X Display *display;
- X Window window;
- X#endif
- X{
- X int i;
- X
- X /* Loop through all the balls */
- X for (i = 0; i < MAX_BALLS; i++)
- X {
- X /* Only handle active balls - sounds disgusting! :-) */
- X if (balls[i].active == True)
- X {
- X /* Switch on the state of the ball */
- X switch (balls[i].ballState)
- X {
- X case BALL_POP: /* Ball pop animation */
- X AnimateBallPop(display, window, i);
- X break;
- X
- X case BALL_ACTIVE: /* Animate the ball normally */
- X if ((frame % BALL_FRAME_RATE) == 0)
- X UpdateABall(display, window, i);
- X break;
- X
- X case BALL_READY: /* ball created and waiting to move */
- X if (paddleIsMoving())
- X {
- X balls[i].ballx = paddlePos;
- X balls[i].bally = PLAY_HEIGHT - DIST_BALL_OF_PADDLE;
- X
- X MoveBall(display, window, balls[i].ballx,
- X balls[i].bally, True, i);
- X }
- X
- X /* After a certain number of seconds fire off anyway */
- X if (frame == balls[i].nextFrame)
- X ChangeBallMode(BALL_ACTIVE, i);
- X break;
- X
- X case BALL_STOP: /* Ball dead and stopped */
- X break;
- X
- X case BALL_CREATE: /* Create ball animation */
- X AnimateBallCreate(display, window, i);
- X break;
- X
- X case BALL_WAIT: /* In wait mode waiting to change state */
- X DoBallWait(i);
- X break;
- X
- X case BALL_DIE: /* Ball is going to die */
- X if ((frame % BALL_FRAME_RATE) == 0)
- X UpdateABall(display, window, i);
- X break;
- X
- X case BALL_NONE: /* Really cool mode ;-) */
- X default:
- X break;
- X
- X } /* Ball modes */
- X } /* If active */
- X } /* For loop */
- X}
- END_OF_FILE
- if test 43006 -ne `wc -c <'ball.c'`; then
- echo shar: \"'ball.c'\" unpacked with wrong size!
- fi
- # end of 'ball.c'
- fi
- if test ! -d 'bitmaps' ; then
- echo shar: Creating directory \"'bitmaps'\"
- mkdir 'bitmaps'
- fi
- if test ! -d 'levels' ; then
- echo shar: Creating directory \"'levels'\"
- mkdir 'levels'
- fi
- if test ! -d 'sounds' ; then
- echo shar: Creating directory \"'sounds'\"
- mkdir 'sounds'
- fi
- echo shar: End of archive 1 \(of 26\).
- cp /dev/null ark1isdone
- MISSING=""
- 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
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 26 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- echo "merging split files..."
- cat blocks.c[12] > blocks.c
- rm blocks.c[12]
- echo "blocks.c done"
- cat bitmaps/earth.xpm.Z.u.[ab] > bitmaps/earth.xpm.Z.uue
- rm bitmaps/earth.xpm.Z.u.[ab]
- echo "bitmaps/earth.xpm.Z.uue done"
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- // chris@Sterling.COM | Send comp.sources.x submissions to:
- \X/ Amiga - The only way to fly! | sources-x@sterling.com
- "It's intuitively obvious to the |
- most casual observer..." | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
-