GliderPRO/Sources/GameOver.c
John Calhoun 7a70d18ba6 First check-in.
Sources for Glider PRO, a Macintosh game written by John Calhoun and
published by Casady & Greene, Inc. I believe it was using CodeWarrior
IDE to create a fat (68K and PowerPC) binary.
2016-01-28 08:10:38 -08:00

1 line
12 KiB
C
Executable File

//============================================================================
//----------------------------------------------------------------------------
// GameOver.c
//----------------------------------------------------------------------------
//============================================================================
#include <ToolUtils.h>
#include "Externs.h"
#include "Environ.h"
#include "MainWindow.h"
#include "Objects.h"
#include "RectUtils.h"
#include "Utilities.h"
#define kNumCountDownFrames 16
#define kPageFrames 14
#define kPagesPictID 1990
#define kPagesMaskID 1989
#define kLettersPictID 1988
#define kMilkywayPictID 1021
typedef struct
{
Rect dest, was;
short frame, counter;
Boolean stuck;
} pageType, *pagePtr;
void DoGameOverStarAnimation (void);
void SetUpFinalScreen (void);
void InitDiedGameOver (void);
void HandlePages (void);
void DrawPages (void);
pageType pages[8];
Rect pageSrcRect, pageSrc[kPageFrames], lettersSrc[8], angelSrcRect;
RgnHandle roomRgn;
GWorldPtr pageSrcMap, gameOverSrcMap, angelSrcMap;
GWorldPtr pageMaskMap, angelMaskMap;
short countDown, stopPages, pagesStuck;
Boolean gameOver;
extern Rect justRoomsRect;
extern short splashOriginH, splashOriginV, numWork2Main;
extern short numBack2Work;
extern Boolean playing, shadowVisible, demoGoing;
//============================================================== Functions
//-------------------------------------------------------------- DoGameOver
// Handles a game over. This is a game over where the player hasÉ
// completed the house.
void DoGameOver (void)
{
playing = false;
SetUpFinalScreen();
SetPort((GrafPtr)mainWindow);
ColorRect(&mainWindowRect, 244);
DoGameOverStarAnimation();
if (!TestHighScore())
RedrawSplashScreen();
}
//-------------------------------------------------------------- SetUpFinalScreen
// This sets up the game over screen (again, this function is for whenÉ
// the player completes the house).
void SetUpFinalScreen (void)
{
Rect tempRect;
Str255 tempStr, subStr;
short count, offset, i, textDown;
char wasState;
SetPort((GrafPtr)workSrcMap);
ColorRect(&workSrcRect, 244);
QSetRect(&tempRect, 0, 0, 640, 460);
CenterRectInRect(&tempRect, &workSrcRect);
LoadScaledGraphic(kMilkywayPictID, &tempRect);
textDown = tempRect.top;
if (textDown < 0)
textDown = 0;
wasState = HGetState((Handle)thisHouse);
HLock((Handle)thisHouse);
PasStringCopy((*thisHouse)->trailer, tempStr);
HSetState((Handle)thisHouse, wasState);
count = 0;
do
{
GetLineOfText(tempStr, count, subStr);
offset = ((thisMac.screen.right - thisMac.screen.left) -
TextWidth(subStr, 1, subStr[0])) / 2;
TextFont(applFont);
TextFace(bold);
TextSize(12);
ForeColor(blackColor);
MoveTo(offset + 1, textDown + 33 + (count * 20));
DrawString(subStr);
ForeColor(whiteColor);
MoveTo(offset, textDown + 32 + (count * 20));
DrawString(subStr);
ForeColor(blackColor);
count++;
}
while (subStr[0] > 0);
CopyRectWorkToBack(&workSrcRect);
for (i = 0; i < 5; i++) // initialize the falling stars
{
pages[i].dest = starSrc[0];
QOffsetRect(&pages[i].dest,
workSrcRect.right + RandomInt(workSrcRect.right / 5) +
(workSrcRect.right/ 4) * i,
RandomInt(workSrcRect.bottom) - workSrcRect.bottom / 2);
pages[i].was = pages[i].dest;
pages[i].frame = RandomInt(6);
}
}
//-------------------------------------------------------------- DoGameOverStarAnimation
// This handles the falling stars and the flying angel when a playerÉ
// completes a house.
void DoGameOverStarAnimation (void)
{
#define kStarFalls 8
EventRecord theEvent;
KeyMap theKeys;
Rect angelDest;
long nextLoop;
short which, i, count, pass;
Boolean noInteruption;
angelDest = angelSrcRect;
QOffsetRect(&angelDest, -96, 0);
noInteruption = true;
nextLoop = TickCount() + 2;
count = 0;
pass = 0;
FlushEvents(everyEvent, 0);
while (noInteruption)
{
if ((angelDest.left % 32) == 0) // add a star
{
PlayPrioritySound(kMysticSound, kMysticPriority);
which = angelDest.left / 32;
which = which % 5;
ZeroRectCorner(&pages[which].dest);
QOffsetRect(&pages[which].dest, angelDest.left, angelDest.bottom);
if (count < (which + 1))
count = which + 1;
}
for (i = 0; i < count; i++)
{
pages[i].frame++;
if (pages[i].frame >= 6)
pages[i].frame = 0;
CopyMask((BitMap *)*GetGWorldPixMap(bonusSrcMap),
(BitMap *)*GetGWorldPixMap(bonusMaskMap),
(BitMap *)*GetGWorldPixMap(workSrcMap),
&starSrc[pages[i].frame],
&starSrc[pages[i].frame],
&pages[i].dest);
pages[i].was = pages[i].dest;
pages[i].was.top -= kStarFalls;
AddRectToWorkRectsWhole(&pages[i].was);
AddRectToBackRects(&pages[i].dest);
if (pages[i].dest.top < workSrcRect.bottom)
QOffsetRect(&pages[i].dest, 0, kStarFalls);
}
if (angelDest.left <= (workSrcRect.right + 2))
{
CopyMask((BitMap *)*GetGWorldPixMap(angelSrcMap),
(BitMap *)*GetGWorldPixMap(angelMaskMap),
(BitMap *)*GetGWorldPixMap(workSrcMap),
&angelSrcRect, &angelSrcRect, &angelDest);
angelDest.left -= 2;
AddRectToWorkRectsWhole(&angelDest);
angelDest.left += 2;
AddRectToBackRects(&angelDest);
QOffsetRect(&angelDest, 2, 0);
pass = 0;
}
CopyRectsQD();
numWork2Main = 0;
numBack2Work = 0;
do
{
GetKeys(theKeys);
if ((BitTst(&theKeys, kCommandKeyMap)) || (BitTst(&theKeys, kOptionKeyMap)) ||
(BitTst(&theKeys, kShiftKeyMap)) || (BitTst(&theKeys, kControlKeyMap)))
noInteruption = false;
if (GetNextEvent(everyEvent, &theEvent))
if ((theEvent.what == mouseDown) || (theEvent.what == keyDown))
noInteruption = false;
}
while (TickCount() < nextLoop);
nextLoop = TickCount() + 2;
if (pass < 80)
pass++;
else
{
WaitForInputEvent(5);
noInteruption = false;
}
}
}
//-------------------------------------------------------------- FlagGameOver
// Called to indicate (flag) that a game is over. Actual game overÉ
// sequence comes up after a short delay.
void FlagGameOver (void)
{
gameOver = true;
countDown = kNumCountDownFrames;
SetMusicalMode(kPlayWholeScoreMode);
}
//-------------------------------------------------------------- InitDiedGameOver
// This is called when a game is over due to the fact that the playerÉ
// lost their last glider (died), not due to getting through the entireÉ
// house. This function initializes the strucures/variables.
void InitDiedGameOver (void)
{
#define kPageSpacing 40
#define kPageRightOffset 128
#define kPageBackUp 128
short i;
CGrafPtr wasCPort;
GDHandle wasWorld;
OSErr theErr;
GetGWorld(&wasCPort, &wasWorld);
QSetRect(&pageSrcRect, 0, 0, 25, 32 * 8);
theErr = CreateOffScreenGWorld(&gameOverSrcMap, &pageSrcRect, kPreferredDepth);
SetGWorld(gameOverSrcMap, nil);
LoadGraphic(kLettersPictID);
QSetRect(&pageSrcRect, 0, 0, 32, 32 * kPageFrames);
theErr = CreateOffScreenGWorld(&pageSrcMap, &pageSrcRect, kPreferredDepth);
SetGWorld(pageSrcMap, nil);
LoadGraphic(kPagesPictID);
theErr = CreateOffScreenGWorld(&pageMaskMap, &pageSrcRect, 1);
SetGWorld(pageMaskMap, nil);
LoadGraphic(kPagesMaskID);
for (i = 0; i < kPageFrames; i++) // initialize src page rects
{
QSetRect(&pageSrc[i], 0, 0, 32, 32);
QOffsetRect(&pageSrc[i], 0, 32 * i);
}
for (i = 0; i < 8; i++) // initialize dest page rects
{
QSetRect(&pages[i].dest, 0, 0, 32, 32);
CenterRectInRect(&pages[i].dest, &thisMac.screen);
QOffsetRect(&pages[i].dest, -thisMac.screen.left, -thisMac.screen.top);
if (i < 4)
QOffsetRect(&pages[i].dest, -kPageSpacing * (4 - i), 0);
else
QOffsetRect(&pages[i].dest, kPageSpacing * (i - 3), 0);
QOffsetRect(&pages[i].dest, (thisMac.screen.right - thisMac.screen.left) / -2,
(thisMac.screen.right - thisMac.screen.left) / -2);
if (pages[i].dest.left % 2 == 1)
QOffsetRect(&pages[i].dest, 1, 0);
pages[i].was = pages[i].dest;
pages[i].frame = 0;
pages[i].counter = RandomInt(32);
pages[i].stuck = false;
}
for (i = 0; i < 8; i++)
{
QSetRect(&lettersSrc[i], 0, 0, 25, 32);
QOffsetRect(&lettersSrc[i], 0, 32 * i);
}
roomRgn = NewRgn();
RectRgn(roomRgn, &justRoomsRect);
pagesStuck = 0;
stopPages = ((thisMac.screen.bottom - thisMac.screen.top) / 2) - 16;
}
//-------------------------------------------------------------- HandlePages
// This handles the pieces of paper that blow across the screen.
void HandlePages (void)
{
short i;
for (i = 0; i < 8; i++)
{
if ((pages[i].dest.bottom + RandomInt(8)) > stopPages)
{
pages[i].frame = 0;
if (!pages[i].stuck)
{
pages[i].dest.right = pages[i].dest.left + 25;
pages[i].stuck = true;
pagesStuck++;
}
}
else
{
if (pages[i].frame == 0)
{
pages[i].counter--;
if (pages[i].counter <= 0)
pages[i].frame = 1;
}
else if (pages[i].frame == 7)
{
pages[i].counter--;
if (pages[i].counter <= 0)
{
pages[i].frame = 8;
if (RandomInt(2) == 0)
PlayPrioritySound(kPaper3Sound, kPapersPriority);
else
PlayPrioritySound(kPaper4Sound, kPapersPriority);
}
else
QOffsetRect(&pages[i].dest, 10, 10);
}
else
{
pages[i].frame++;
switch (pages[i].frame)
{
case 5:
QOffsetRect(&pages[i].dest, 6, 6);
break;
case 6:
QOffsetRect(&pages[i].dest, 8, 8);
break;
case 7:
QOffsetRect(&pages[i].dest, 8, 8);
pages[i].counter = RandomInt(4) + 4;
break;
case 8:
case 9:
QOffsetRect(&pages[i].dest, 8, 8);
break;
case 10:
QOffsetRect(&pages[i].dest, 6, 6);
break;
case kPageFrames:
QOffsetRect(&pages[i].dest, 8, 0);
pages[i].frame = 0;
pages[i].counter = RandomInt(8) + 8;
if (RandomInt(2) == 0)
PlayPrioritySound(kPaper1Sound, kPapersPriority);
else
PlayPrioritySound(kPaper2Sound, kPapersPriority);
break;
}
}
}
}
}
//-------------------------------------------------------------- DrawPages
// This function does the drawing for the pieces of paper that blowÉ
// across the screen.
void DrawPages (void)
{
short i;
for (i = 0; i < 8; i++)
{
if (pages[i].stuck)
{
CopyBits((BitMap *)*GetGWorldPixMap(gameOverSrcMap),
(BitMap *)*GetGWorldPixMap(workSrcMap),
&lettersSrc[i], &pages[i].dest,
srcCopy, roomRgn);
}
else
{
CopyMask((BitMap *)*GetGWorldPixMap(pageSrcMap),
(BitMap *)*GetGWorldPixMap(pageMaskMap),
(BitMap *)*GetGWorldPixMap(workSrcMap),
&pageSrc[pages[i].frame],
&pageSrc[pages[i].frame],
&pages[i].dest);
}
QUnionSimilarRect(&pages[i].dest, &pages[i].was, &pages[i].was);
AddRectToWorkRects(&pages[i].was);
AddRectToBackRects(&pages[i].dest);
CopyRectsQD();
numWork2Main = 0;
numBack2Work = 0;
pages[i].was = pages[i].dest;
}
}
//-------------------------------------------------------------- DoDiedGameOver
// This is called when a game is over due to the fact that the playerÉ
// lost their last glider (died), not due to getting through the entireÉ
// house.
void DoDiedGameOver (void)
{
EventRecord theEvent;
KeyMap theKeys;
long nextLoop;
Boolean userAborted;
userAborted = false;
InitDiedGameOver();
CopyRectMainToWork(&workSrcRect);
CopyRectMainToBack(&workSrcRect);
FlushEvents(everyEvent, 0);
nextLoop = TickCount() + 2;
while (pagesStuck < 8)
{
HandlePages();
DrawPages();
do
{
GetKeys(theKeys);
if ((BitTst(&theKeys, kCommandKeyMap)) || (BitTst(&theKeys, kOptionKeyMap)) ||
(BitTst(&theKeys, kShiftKeyMap)) || (BitTst(&theKeys, kControlKeyMap)))
{
pagesStuck = 8;
userAborted = true;
}
if (GetNextEvent(everyEvent, &theEvent))
if ((theEvent.what == mouseDown) || (theEvent.what == keyDown))
{
pagesStuck = 8;
userAborted = true;
}
}
while (TickCount() < nextLoop);
nextLoop = TickCount() + 2;
}
if (roomRgn != nil)
DisposeRgn(roomRgn);
DisposeGWorld(pageSrcMap);
pageSrcMap = nil;
DisposeGWorld(pageMaskMap);
pageMaskMap = nil;
DisposeGWorld(gameOverSrcMap);
gameOverSrcMap = nil;
playing = false;
if (demoGoing)
{
if (!userAborted)
WaitForInputEvent(1);
}
else
{
if (!userAborted)
WaitForInputEvent(10);
TestHighScore();
}
RedrawSplashScreen();
}