home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-30 | 11.2 KB | 527 lines | [TEXT/KAHL] |
- // This is a minor hack of ...
- /* pong.c
- The classic game of pong in Megamax C for the Mac.
- Thanks to MacTutor (Vol 1, No. 5 April 1985 page 39) for
- animation techniques. If you are reading this and don't
- subscribe to MacTutor, consider it. No resource file is
- needed. This program, source and object, is in the
- public domain and not for sale.
-
- Author : David L. O'Connor, 370 Eden St. Buffalo, N.Y.
- 14220. (716) 828-0898. CIS - 70265,1172
- Date : July, 1985 Version 2
- */
- // It had to be modified in order to compile on current Macs.
-
- #ifndef _OSUTILS_
- #include <OSUtils.h>
- #endif
-
- /* the game diRections */
- #define STOPPED 0
- #define UP 1
- #define DOWN 2
- #define LEFT 3
- #define RIGHT 4
- #define UP_LEFT 5
- #define UP_RIGHT 6
- #define DOWN_LEFT 7
- #define DOWN_RIGHT 8
-
- #define DIFFICULTY 2
-
- /* paddle + ball dimensions */
- #define PADWIDTH 10
- #define PADLENGTH 45
- #define PADINSET 10
- #define BALLWIDTH 9
- #define BALLLENGTH 9
-
- #define PADDLESPEED 9
- #define HIGHSCORE 20
-
- /* from the MAC's standard pattern list */
- #define PAD_PAT qd.dkGray
- #define WALL_PAT qd.ltGray
-
- typedef struct {
- Rect r;
- int dir;
- int speed;
- int score;
- } paddle;
-
- typedef struct {
- RgnHandle Rgn;
- RgnHandle oldRgn;
- RgnHandle unRgn;
- int dir;
- int speed;
- int on;
- } target;
-
- paddle l_paddle, r_paddle;
- target ball;
- WindowPtr gamewindow, which_window;
- Rect r, top_wall, bottom_wall;
- EventRecord gameEvent;
- MenuHandle gamemenu[5];
- char menutitle[1];
- int done, paused, last_won, volleys, sound_on;
- short BALLSPEED = 1;
- Str255 title = { 65,
- ' ',' ',' ',' ',' ',' ',' ',' ',
- 'Y','o','u',':',' ',' ',' ','0',
- ' ',' ',' ',' ',' ',' ',' ',' ',
- ' ',' ',' ','H','i','d','d','e',
- 'n',' ','P','o','n','g',' ','G',
- 'a','m','e',' ',' ',' ',' ',' ',
- ' ',' ',' ',' ',' ',' ',' ',' ',
- 'M','a','c',':',' ',' ',' ','0',
- ' ',' ',' ',' ',' ',' ',' ',' ',
- '\0'};
-
- HiddenPongGame(WindowPtr parentWindow)
- {
- SysEnvRec theSystem;
-
- // Check current system info
- if(SysEnvirons(curSysEnvVers, &theSystem) == noErr)
- {
- switch(theSystem.processor)
- {
- case env68000:
- BALLSPEED = 7;
- break;
- case env68010:
- BALLSPEED = 6;
- break;
- case env68020:
- #if defined(powerc) || defined(__powerc)
- BALLSPEED = 1; // Power PC 60x
- #else
- BALLSPEED = 5; // it's a real MC68020
- #endif
- break;
- case env68030:
- BALLSPEED = 4;
- break;
- case env68040:
- BALLSPEED = 2;
- break;
- case envCPUUnknown: // must be newer than PowerPC. Cool!
- BALLSPEED = 1;
- break;
- }
- }
-
- gamewindow = parentWindow;
- setup();
- while (! done){
- Handle_Events();
- play_pong();
- }
- FlushEvents(everyEvent, 0);
- InvalRect(&gamewindow->portRect);
- }
-
- setup()
- {
- done = 0;
- sound_on = 1;
- last_won = RIGHT;
- FlushEvents(everyEvent, 0);
- SetWTitle(gamewindow, title);
- SetPort(gamewindow);
- EraseRect(&gamewindow->portRect);
- create_l_paddle();
- create_r_paddle();
- create_walls();
- create_ball();
- Init_game();
- }
-
- /* pretty much straight from SAMP in I.M. */
- Handle_Events()
- {
- SystemTask();
- if (GetNextEvent(everyEvent, &gameEvent))
- {
- switch (gameEvent.what)
- {
- case mouseDown :
- done = TRUE;
- break;
- case updateEvt :
- SetPort(gamewindow);
- BeginUpdate(gamewindow);
- FillRect(&l_paddle.r, &PAD_PAT);
- FillRect(&r_paddle.r, &PAD_PAT);
- FillRect(&top_wall, &WALL_PAT);
- FillRect(&bottom_wall, &WALL_PAT);
- if (ball.on)
- PaintRgn(ball.Rgn);
- EndUpdate(gamewindow);
- break;
- }
- }
- }
-
- play_pong()
- {
- if (!paused)
- {
- if (! ball.on)
- serve_ball();
- check_status();
- move_left_paddle();
- move_right_paddle();
- move_ball();
- }
- if(l_paddle.score > HIGHSCORE || r_paddle.score > HIGHSCORE)
- done = TRUE;
- }
-
- create_l_paddle()
- {
- l_paddle.dir = STOPPED;
- l_paddle.speed = PADDLESPEED;
- l_paddle.score = 0;
- SetRect (&l_paddle.r,
- gamewindow->portRect.left + PADINSET,
- gamewindow->portRect.top + PADINSET,
- gamewindow->portRect.left + PADINSET + PADWIDTH,
- gamewindow->portRect.top + PADINSET + PADLENGTH);
- FillRect(&l_paddle.r, &PAD_PAT);
- }
-
- create_r_paddle()
- {
- r_paddle.dir = STOPPED;
- r_paddle.speed = PADDLESPEED;
- r_paddle.score = 0;
- SetRect (&r_paddle.r,
- gamewindow->portRect.right - PADWIDTH - PADINSET,
- gamewindow->portRect.top + PADINSET,
- gamewindow->portRect.right - PADWIDTH - PADINSET + PADWIDTH,
- gamewindow->portRect.top + PADINSET + PADLENGTH);
- FillRect(&r_paddle.r, &PAD_PAT);
- }
-
- create_walls()
- {
- SetRect(&top_wall,
- gamewindow->portRect.left + 20,
- gamewindow->portRect.top + 5,
- gamewindow->portRect.right - 20,
- gamewindow->portRect.top + 20);
- FillRect(&top_wall, &WALL_PAT);
- SetRect(&bottom_wall,
- gamewindow->portRect.left + 20,
- gamewindow->portRect.bottom - 20,
- gamewindow->portRect.right - 20,
- gamewindow->portRect.bottom - 5);
- FillRect(&bottom_wall, &WALL_PAT);
- }
-
- create_ball()
- {
- ball.Rgn = NewRgn();
- ball.oldRgn = NewRgn();
- ball.unRgn = NewRgn();
- ball.dir = LEFT;
- ball.speed = BALLSPEED;
- SetRect (&r, 250, 150, 250 + BALLWIDTH, 150 + BALLLENGTH);
- OpenRgn();
- FrameOval(&r);
- CloseRgn(ball.Rgn);
- }
-
- serve_ball()
- {
- register i;
-
- OffsetRgn(ball.Rgn, 250 - ((**ball.Rgn).rgnBBox.right),
- 150 - ((**ball.Rgn).rgnBBox.top) );
- for (i = 0; i < 250; i++){
- check_status();
- move_right_paddle();
- move_left_paddle();
- move_ball();
- }
- ball.dir = (last_won == RIGHT) ? LEFT : RIGHT;
- ball.speed = BALLSPEED;
- ball.on = 1;
- PaintRgn(ball.Rgn);
- }
-
- /* someone scored a point */
- kill_ball()
- {
- ball.on = volleys = 0;
- CopyRgn(ball.Rgn, ball.unRgn);
- EraseRgn(ball.Rgn);
- recover_from_collision();
- display_score();
- }
-
- Init_game()
- {
- l_paddle.score = r_paddle.score = 0;
- ball.speed = BALLSPEED;
- kill_ball();
- }
-
- /* check for bounces, diRection changes, scoring, etc */
- check_status()
- {
- static Rect *ball_r;
-
- register ball_top = (**ball.Rgn).rgnBBox.top;
- register ball_bottom = (**ball.Rgn).rgnBBox.bottom;
- register ball_left = (**ball.Rgn).rgnBBox.left;
- register ball_right = (**ball.Rgn).rgnBBox.right;
-
- ball_r = &((**ball.Rgn).rgnBBox);
-
- /* make it a little harder as time goes by */
- if (volleys > 35)
- ball.speed = BALLSPEED + 6;
- else if (volleys > 30)
- ball.speed = BALLSPEED + 5;
- else if (volleys > 25)
- ball.speed = BALLSPEED + 4;
- else if (volleys > 20)
- ball.speed = BALLSPEED + 3;
- else if (volleys > 15)
- ball.speed = BALLSPEED + 2;
- else if (volleys > 10)
- ball.speed = BALLSPEED + 1;
-
- r_paddle.speed = ball.speed + 2;
-
- /* the right paddle tries to track the ball */
- if ( (ball_right > 250) &&
- (ball.dir == UP_RIGHT || ball.dir == DOWN_RIGHT ||
- ball.dir == RIGHT) ){
- if (ball_top + handicap() < r_paddle.r.top)
- r_paddle.dir = UP;
- else if (ball_bottom - handicap() > r_paddle.r.bottom)
- r_paddle.dir = DOWN;
- else
- r_paddle.dir = STOPPED;
- }
- else
- r_paddle.dir = STOPPED;
-
- /* the ball and the left boundry */
- if (ball_left < l_paddle.r.right ){
- if (SectRect(ball_r, &l_paddle.r, &r)){
- volleys++;
- if (ball_top <= l_paddle.r.top + 15)
- ball.dir = UP_RIGHT;
- else if (ball_top > l_paddle.r.top + 15 && ball_bottom < l_paddle.r.top + 30)
- ball.dir = RIGHT;
- else
- ball.dir = DOWN_RIGHT;
- }
- else{
- last_won = RIGHT;
- r_paddle.score++;
- kill_ball();
- }
- return;
- }
-
- /* the ball and the right boundry */
- if (ball_right > r_paddle.r.left){
- if (SectRect(ball_r, &r_paddle.r, &r)){
- volleys++;
- if (ball_top <= r_paddle.r.top + 15)
- ball.dir = UP_LEFT;
- else if (ball_top > r_paddle.r.top + 15 && ball_bottom < r_paddle.r.top + 30)
- ball.dir = LEFT;
- else
- ball.dir = DOWN_LEFT;
- }
- else{
- last_won = LEFT;
- l_paddle.score++;
- kill_ball();
- }
- return;
- }
-
- /* the ball and the top wall */
- if (ball_top < top_wall.bottom){
- if (ball.dir == UP_LEFT)
- ball.dir = DOWN_LEFT;
- else if (ball.dir == UP_RIGHT)
- ball.dir = DOWN_RIGHT;
- return;
- }
-
- /* the ball and the bottom wall */
- if (ball_bottom > bottom_wall.top){
- if (ball.dir == DOWN_LEFT)
- ball.dir = UP_LEFT;
- else if (ball.dir == DOWN_RIGHT)
- ball.dir = UP_RIGHT;
- return;
- }
- }
-
- /* the ball eats the walls and paddles */
- recover_from_collision()
- {
- register Rect *rp = &((**ball.unRgn).rgnBBox);
-
- if (SectRect(rp, &top_wall, &r))
- FillRect(&r, &WALL_PAT);
- else if (SectRect(rp, &bottom_wall, &r))
- FillRect(&r, &WALL_PAT);
- if (SectRect(rp, &l_paddle.r, &r))
- FillRect(&r, &PAD_PAT);
- else if (SectRect(rp, &r_paddle.r, &r))
- FillRect(&r, &PAD_PAT);
- }
-
- move_left_paddle()
- {
- static Point mouseloc;
- register int newtop, newbottom;
-
- GetMouse(&mouseloc);
- if (mouseloc.v != l_paddle.r.top){
- r.left = l_paddle.r.left;
- r.right = l_paddle.r.right;
- if (mouseloc.v <= gamewindow->portRect.top){
- newtop = gamewindow->portRect.top;
- newbottom = newtop + PADLENGTH;
- }
- else if (mouseloc.v + PADLENGTH >= gamewindow->portRect.bottom){
- newbottom = gamewindow->portRect.bottom;
- newtop = newbottom - PADLENGTH;
- }
- else{
- newtop = mouseloc.v;
- newbottom = newtop + PADLENGTH;
- }
- if (newtop > l_paddle.r.top){
- r.top = l_paddle.r.top;
- r.bottom = (newtop > l_paddle.r.bottom) ? l_paddle.r.bottom : newtop;
- }
- else if (newtop < l_paddle.r.top){
- r.bottom = l_paddle.r.bottom;
- r.top = (newbottom < l_paddle.r.top) ? l_paddle.r.top : newbottom;
- }
- l_paddle.r.top = newtop;
- l_paddle.r.bottom = newbottom;
- EraseRect(&r);
- FillRect(&l_paddle.r, &PAD_PAT);
- }
- else
- FillRect(&l_paddle.r, &PAD_PAT);
- }
-
- move_right_paddle()
- {
- if (r_paddle.dir == STOPPED)
- FillRect(&r_paddle.r, &PAD_PAT);
- else{
- r.left = r_paddle.r.left;
- r.right = r_paddle.r.right;
- switch (r_paddle.dir){
- case UP:
- r.bottom = r_paddle.r.bottom;
- r_paddle.r.top -= r_paddle.speed;
- r_paddle.r.bottom -= r_paddle.speed;
- r.top = r_paddle.r.bottom;
- break;
- case DOWN:
- r.top = r_paddle.r.top;
- r_paddle.r.top += r_paddle.speed;
- r_paddle.r.bottom += r_paddle.speed;
- r.bottom = r_paddle.r.top;
- break;
- }
- EraseRect(&r);
- FillRect(&r_paddle.r, &PAD_PAT);
- }
- }
-
- move_ball()
- {
- if (ball.on){
- CopyRgn(ball.Rgn, ball.oldRgn);
- switch (ball.dir){
- case LEFT:
- OffsetRgn(ball.Rgn, -ball.speed, 0);
- break;
- case RIGHT:
- OffsetRgn(ball.Rgn, ball.speed, 0);
- break;
- case UP_LEFT:
- OffsetRgn(ball.Rgn, -ball.speed, -ball.speed);
- break;
- case UP_RIGHT:
- OffsetRgn(ball.Rgn, ball.speed, -ball.speed);
- break;
- case DOWN_LEFT:
- OffsetRgn(ball.Rgn, -ball.speed, ball.speed);
- break;
- case DOWN_RIGHT:
- OffsetRgn(ball.Rgn, ball.speed, ball.speed);
- break;
- }
- UnionRgn(ball.Rgn, ball.oldRgn, ball.unRgn);
- DiffRgn(ball.unRgn, ball.Rgn, ball.unRgn);
- EraseRgn(ball.unRgn);
- PaintRgn(ball.Rgn);
- recover_from_collision();
- }
- }
-
- display_score()
- {
- static long i;
-
- i = l_paddle.score;
- title[15]=0x30+(i/100);
- title[16]=0x30+((i%100)/10);
- title[17]=0x30+(i%10);
- i = r_paddle.score;
- title[63]=0x30+(i/100);
- title[64]=0x30+((i%100)/10);
- title[65]=0x30+(i%10);
- SetWTitle(gamewindow, title);
- }
-
- /* Every so often, let the Mac's paddle fail to track the ball until
- the ball has passed it by a certain amount.
- This is the heart of a satisfying game. */
- int handicap()
- {
- register mac_skill;
- int skill_level = DIFFICULTY;
-
- switch(skill_level){
- case 1 :
- mac_skill = 2;
- break;
- case 2 :
- mac_skill = 8;
- break;
- case 3 :
- mac_skill = 27;
- break;
- case 4 :
- mac_skill = 64;
- break;
- default :
- mac_skill = 2;
- break;
- }
- return ((Random() % mac_skill) == 0) ? 5 : 0;
- }
-