/*************************************************************** * * * Copyright (C) 1995 by Sony Computer Entertainment * * All rights Reserved * * * * L.Evans May 97 * * * ***************************************************************/ /**************************************************************************** includes ****************************************************************************/ #include #include #include "pad.h" #include "2d1.h" #include "rand.h" #include "text_str.h" #include "address.h" #include "sound.h" #include "tmd.h" #include "object.h" #include "geom.h" #include "sincos.h" #include "breakout.h" /**************************************************************************** structures, constants, globals ****************************************************************************/ GsIMAGE FireTextureInfo; GsSPRITE FireSprite; GsIMAGE MascotsTextureInfo; GsSPRITE MascotsSprite; GsIMAGE WaveTextureInfo; GsSPRITE WaveSprite; GsIMAGE MassivePictureTextureInfo; GsSPRITE MassivePictureSprite; GsIMAGE MassivePicture2TextureInfo; GsSPRITE MassivePicture2Sprite; // not really variable for this program #define ScreenWidth 320 #define ScreenHeight 240 #define PACKETMAX 2048 /* Max GPU packets */ #define PACKETMAX2 (PACKETMAX*24) PACKET packetArea[2][PACKETMAX2]; /* GPU PACKETS AREA */ PACKET packetArea2[2][PACKETMAX*24]; // another packet area PACKET packetArea3[2][PACKETMAX]; PACKET packetArea4[2][PACKETMAX]; PACKET packetArea5[2][PACKETMAX]; PACKET packetArea6[2][PACKETMAX]; PACKET packetArea7[2][PACKETMAX]; #define FIRST_OT_LENGTH 9 GsOT Wot[2]; /* Handler of OT */ GsOT_TAG wtags[2][1< (b)) ? (b) : (a)) #define max(a,b) ( ((a) > (b)) ? (a) : (b)) #define KeepWithinRange(quantity, min, max) \ { \ if ((quantity) < (min)) \ (quantity) = (min); \ else if ((quantity) > (max)) \ (quantity) = (max); \ } #define setVECTOR(vector, x, y, z) \ (vector)->vx = (x), (vector)->vy = (y), (vector)->vz = (z) #define setNORMAL(normal, x, y, z) \ (normal)->nx = (x), (normal)->ny = (y), (normal)->nz = (z) #define setVERTEX(vertex, x, y, z) \ (vertex)->vx = (x), (vertex)->vy = (y), (vertex)->vz = (z) #define copyRECT(from, to) \ (to)->x = (from)->x, (to)->y = (from)->y, (to)->w = (from)->w, (to)->h = (from)->h #define ALL_ONES 0xffffffff u_long onlyNthBitOn, onlyNthBitOffMask; #define TURN_NTH_BIT_OFF(argument, sizeInBits, N) \ { \ onlyNthBitOn = 1 << (N); \ onlyNthBitOffMask = ALL_ONES ^ onlyNthBitOn; \ argument &= onlyNthBitOn; \ } /**************************************************************************** functions ****************************************************************************/ // nice and simple void main (void) { InitialiseAll(); //PrintDataTypeSizes(); bufferIndex = GsGetActiveBuff(); OpeningSequence(); HandleGameState(); CleanupProgram(); } void HandleGameState (void) { while (ProgramQuitFlag != TRUE) { switch(TopLevelGameState) { case MODE_MENU_SCREEN: HandleSimpleMenuScreen(); break; case MODE_MAIN_GAME: HandleMainGameLoop(); break; default: assert(FALSE); } } } void ChangeGameState (int newState) { switch(newState) { case MODE_MENU_SCREEN: assert(TopLevelGameState == MODE_MAIN_GAME); TopLevelGameState = MODE_MENU_SCREEN; SetMenuScreenDefaultSettings(); break; case MODE_MAIN_GAME: assert(TopLevelGameState == MODE_MENU_SCREEN); TopLevelGameState = MODE_MAIN_GAME; ClearTheCreatedTmds(); //CreateTheInnerCube(); //CreateTheOuterCube(); InitialiseBreakout2(); ViewDistanceFromOrigin = 2000; switch(MenuScreenOption) { case CHOOSE_GAME_DEMO: // make random choices CameraControlFlag = AUTO_CAMERA; AutoCameraMode = MUTATE_ON_FOUR + (rand() % 2); BackgroundGraphicsFlag = PLAY_ON_INNER_SIMPLE_OUTER_TEXTURE + (rand() % 4); OverallCameraSpeedFlag = GREYHOUND + (rand() % 2); FrameWhenDemoStarts = frameNumber; BreakoutNumberOfPlayers = 1; break; case CHOOSE_START_GAME: // menu choices apply //AutoCameraMode = OverallCameraType; switch(OverallGameDifficulty) { case CHICKEN: AutoCameraMode = FIXED_IN_FIRST; OverallCameraSpeedFlag = TORTOISE; break; case WALLABY: AutoCameraMode = FIXED_IN_FOURTH; OverallCameraSpeedFlag = WILDERBEAST; break; case COBRA: AutoCameraMode = MUTATE_ON_THREE; OverallCameraSpeedFlag = GREYHOUND; break; case DRAGON: AutoCameraMode = MUTATE_ON_FOUR; OverallCameraSpeedFlag = CHEETAH; break; default: assert(FALSE); } break; default: assert(FALSE); } CreateTheInnerCube(); CreateTheOuterCube(); if (CameraControlFlag == AUTO_CAMERA) { SetUpAutoCamera(); } else { InitNewBasicViewMode(); } break; default: assert(FALSE); } FramesInNewState = 0; } void SetMenuScreenDefaultSettings (void) { BackgroundGraphicsFlag = PLAY_ON_INNER_SIMPLE_OUTER_TEXTURE; CameraControlFlag = AUTO_CAMERA; OverallCameraType = FIXED_IN_FIRST; OverallCameraSpeedFlag = TORTOISE; MenuScreenOption = CHOOSE_GRAPHICS_FLAG; BreakoutNumberOfPlayers = 1; } char string1[64], string2[64], string3[64], string4[64]; void HandleSimpleMenuScreen (void) { int string2offset, string3offset, string4offset; frameNumber++; FramesInNewState++; DealWithMenuControls(); GsSetRefView2(&TheView); HandleSound(); switch(BackgroundGraphicsFlag) { case PLAY_ON_INNER_SIMPLE_OUTER_TEXTURE: sprintf(string1, "Play on Inner surface"); sprintf(string2, "background graphics simple and fast"); string2offset = 0; break; case PLAY_ON_INNER_FLASH_OUTER_TEXTURE: sprintf(string1, "Play on Inner surface"); sprintf(string2, "background graphics flashy but slow"); string2offset = 0; break; case PLAY_ON_OUTER_ONLY: sprintf(string1, "Play on Outer surface"); sprintf(string2, "no background graphics"); string2offset = 50; break; case PLAY_ON_BOTH_SURFACES: sprintf(string1, "Play on both surfaces"); sprintf(string2, "no background graphics"); string2offset = 50; break; default: assert(FALSE); } switch(BreakoutNumberOfPlayers) { case 1: sprintf(string3, "Single player"); string3offset = 0; break; case 2: sprintf(string3, "Two player"); string3offset = 15; break; default: assert(FALSE); } switch(OverallGameDifficulty) { case CHICKEN: sprintf(string4, "Game difficulty chicken"); string4offset = 0; break; case WALLABY: sprintf(string4, "Game difficulty wallabe"); string4offset = 0; break; case COBRA: sprintf(string4, "Game difficulty cobra"); string4offset = 10; break; case DRAGON: sprintf(string4, "Game difficulty dragon"); string4offset = 0; break; default: assert(FALSE); } switch(MenuScreenOption) { case CHOOSE_GRAPHICS_FLAG: RegisterTextStringForDisplay(string1, -72, -90, RED_COLOUR); RegisterTextStringForDisplay(string2, -128 + string2offset, -75, RED_COLOUR); RegisterTextStringForDisplay(string3, -55 + string3offset, -35, NORMAL_COLOUR); RegisterTextStringForDisplay(string4, -88 + string4offset, 5, NORMAL_COLOUR); RegisterTextStringForDisplay("Rolling demo", -46, 45, NORMAL_COLOUR); RegisterTextStringForDisplay("Start Game", -38, 75, NORMAL_COLOUR); break; case CHOOSE_NUMBER_PLAYERS: RegisterTextStringForDisplay(string1, -72, -90, NORMAL_COLOUR); RegisterTextStringForDisplay(string2, -128 + string2offset, -75, NORMAL_COLOUR); RegisterTextStringForDisplay(string3, -55 + string3offset, -35, RED_COLOUR); RegisterTextStringForDisplay(string4, -88 + string4offset, 5, NORMAL_COLOUR); RegisterTextStringForDisplay("Rolling demo", -46, 45, NORMAL_COLOUR); RegisterTextStringForDisplay("Start Game", -38, 75, NORMAL_COLOUR); break; case CHOOSE_GAME_DIFFICULTY: RegisterTextStringForDisplay(string1, -72, -90, NORMAL_COLOUR); RegisterTextStringForDisplay(string2, -128 + string2offset, -75, NORMAL_COLOUR); RegisterTextStringForDisplay(string3, -55 + string3offset, -35, NORMAL_COLOUR); RegisterTextStringForDisplay(string4, -88 + string4offset, 5, RED_COLOUR); RegisterTextStringForDisplay("Rolling demo", -46, 45, NORMAL_COLOUR); RegisterTextStringForDisplay("Start Game", -38, 75, NORMAL_COLOUR); break; case CHOOSE_GAME_DEMO: RegisterTextStringForDisplay(string1, -72, -90, NORMAL_COLOUR); RegisterTextStringForDisplay(string2, -128 + string2offset, -75, NORMAL_COLOUR); RegisterTextStringForDisplay(string3, -55 + string3offset, -35, NORMAL_COLOUR); RegisterTextStringForDisplay(string4, -88 + string4offset, 5, NORMAL_COLOUR); RegisterTextStringForDisplay("Rolling demo", -46, 45, RED_COLOUR); RegisterTextStringForDisplay("Start Game", -38, 75, NORMAL_COLOUR); break; case CHOOSE_START_GAME: RegisterTextStringForDisplay(string1, -72, -90, NORMAL_COLOUR); RegisterTextStringForDisplay(string2, -128 + string2offset, -75, NORMAL_COLOUR); RegisterTextStringForDisplay(string3, -55 + string3offset, -35, NORMAL_COLOUR); RegisterTextStringForDisplay(string4, -88 + string4offset, 5, NORMAL_COLOUR); RegisterTextStringForDisplay("Rolling demo", -46, 45, NORMAL_COLOUR); RegisterTextStringForDisplay("Start Game", -38, 75, RED_COLOUR); break; default: assert(FALSE); } GsSetWorkBase( (PACKET*)packetArea[bufferIndex]); GsClearOt(0, 0, &Wot[bufferIndex]); DisplayTextStrings (&Wot[bufferIndex]); cpuLoad = VSync(1); DrawSync(0); gpuLoad = VSync(1); hsync = VSync(0); ResetGraph(1); GsSwapDispBuff(); GsSortClear(0, 0, 0, &Wot[bufferIndex]); GsDrawOt(&Wot[bufferIndex]); bufferIndex = GsGetActiveBuff(); FntFlush(-1); } void DealWithMenuControls (void) { long pad; int pause = 10; static int framesSinceLastChoice = 0; pad = PadRead(); framesSinceLastChoice++; // start rolling demo after 5 seconds of inactivity if (framesSinceLastChoice > (50 * 5)) { MenuScreenOption = CHOOSE_GAME_DEMO; ChangeGameState(MODE_MAIN_GAME); BreakoutAutoPilotFlag = TRUE; //printf("going to main game from menu screen: TIME_OUT\n"); framesSinceLastChoice = 0; return; } if (FramesInNewState < NEW_MODE_PAUSE) return; if (framesSinceLastChoice >= pause) { if (pad & PADstart && pad & PADselect) { ProgramQuitFlag = TRUE; return; } switch(MenuScreenOption) { case CHOOSE_GRAPHICS_FLAG: if (pad & PADLright) { if (BackgroundGraphicsFlag == PLAY_ON_BOTH_SURFACES) return; else { BackgroundGraphicsFlag++; } framesSinceLastChoice = 0; return; } else if (pad & PADLleft) { if (BackgroundGraphicsFlag == PLAY_ON_INNER_SIMPLE_OUTER_TEXTURE) return; else { BackgroundGraphicsFlag--; } framesSinceLastChoice = 0; return; } break; case CHOOSE_NUMBER_PLAYERS: if ((pad & PADLright) || (pad & PADLleft)) { if (BreakoutNumberOfPlayers == 1) BreakoutNumberOfPlayers = 2; else { assert(BreakoutNumberOfPlayers == 2); BreakoutNumberOfPlayers = 1; } framesSinceLastChoice = 0; return; } break; case CHOOSE_GAME_DIFFICULTY: if (pad & PADLright) { if (OverallGameDifficulty == DRAGON) { OverallGameDifficulty = CHICKEN; } else { OverallGameDifficulty++; } framesSinceLastChoice = 0; return; } else if (pad & PADLleft) { if (OverallGameDifficulty == CHICKEN) { OverallGameDifficulty = DRAGON; } else { OverallGameDifficulty--; } framesSinceLastChoice = 0; return; } break; case CHOOSE_GAME_DEMO: if ((pad & PADLright) || (pad & PADLleft) || (pad & PADRdown) || (pad & PADstart)) { ChangeGameState(MODE_MAIN_GAME); BreakoutAutoPilotFlag = TRUE; //printf("going to main game from menu screen\n"); framesSinceLastChoice = 0; return; } break; case CHOOSE_START_GAME: if ((pad & PADLright) || (pad & PADLleft) || (pad & PADRdown) || (pad & PADstart)) { ChangeGameState(MODE_MAIN_GAME); BreakoutAutoPilotFlag = FALSE; //printf("going to main game from menu screen\n"); framesSinceLastChoice = 0; return; } break; default: assert(FALSE); } if (pad & PADLup) { if (MenuScreenOption == CHOOSE_GRAPHICS_FLAG) MenuScreenOption = CHOOSE_START_GAME; else MenuScreenOption--; framesSinceLastChoice = 0; return; } if (pad & PADLdown) { if (MenuScreenOption == CHOOSE_START_GAME) MenuScreenOption = CHOOSE_GRAPHICS_FLAG; else MenuScreenOption++; framesSinceLastChoice = 0; return; } } } int numBricks; void HandleMainGameLoop (void) { u_short zValue; MATRIX tmpls; ObjectHandler *object; int phase; int i; #if 0 FntPrint("~cf00frame %d\n", frameNumber); FntPrint("~cf00hsync %d\n", hsync); FntPrint("~cf00maxHsync %d\n", maxHsync); FntPrint("~cf00Average %d\n", average); FntPrint("~cf00cpu %d gpu %d\n", cpuLoad, gpuLoad); FntPrint("~cf00Many keys modify Rpad actions\n"); FntPrint("~cf00L right mod: view move time\n"); FntPrint("~cf00L down mod: auto camera mode\n"); FntPrint("~cf00Select mod: basic view mode\n"); FntPrint("~cf00L up mod: distance to origin\n"); FntPrint("~cf00L left toggles camera control\n"); switch(BasicViewMode) { case FIRST_VIEW_MODE: FntPrint("~cf00FIRS\n"); break; case SECOND_VIEW_MODE: FntPrint("~cf00SECOND\n"); break; case THIRD_VIEW_MODE: FntPrint("~cf00THIRD\n"); break; case FOURTH_VIEW_MODE: FntPrint("~cf00FOURTH\n"); break; case FIFTH_VIEW_MODE: FntPrint("~cf00FIFTH\n"); break; default: assert(FALSE); } switch(CameraControlFlag) { case CONTROLLER_PAD_CAMERA: FntPrint("control pad camera\n"); break; case AUTO_CAMERA: FntPrint("Proper Auto camera\n"); break; default: assert(FALSE); } FntPrint("~cf00auto camera mode %d\n", AutoCameraMode); if (frameNumber % 60 == 0) { numBricks = CountNumberOfBricks(); } FntPrint("~cf00Number Bricks %d\n", numBricks); #endif if (frameNumber % 10 == 0) { numBricks = CountNumberOfBricks(); //printf("numBricks %d\n", numBricks); } //FntPrint("~cf00Number Bricks %d\n", numBricks); if (GameHasFinishedAndResultsNeedDisplayingFlag == TRUE) HandleEndOfGame(); // sort breakout BreakoutFontPrinting(); BreakoutMainLoopGameLogic(); frameNumber++; FramesInNewState++; DealWithControllerPad(); //GsSetRefView2(&TheView); HandleTheView(); HandleSound(); HandleAllObjects(); GsSetWorkBase( (PACKET*)packetArea[bufferIndex]); GsClearOt(0, 0, &Wot[bufferIndex]); DisplayTextStrings (&Wot[bufferIndex]); CycleLightsAroundAxes(); for (i = 0; i < MAX_OBJECTS; i++) { if (ObjectArray[i] != NULL) { if (ObjectArray[i]->alive == TRUE) { object = ObjectArray[i]; if (object->displayFlag == TMD) { GsGetLs(&(object->coord), &tmpls); // local to screen matrix GsSetLightMatrix(&tmpls); GsSetLsMatrix(&tmpls); GsSortObject4( &(object->handler), &Wot[bufferIndex], 3, getScratchAddr(0)); } else if (object->displayFlag == SPRITE) // speed-up here: use a fast flag { // some can use GsSortFastSprite zValue = SortSpriteObjectPosition(object); GsSortSprite( &object->sprite, &Wot[bufferIndex], zValue); } else { assert(FALSE); } } } } DrawCube( &InsideCube, &Wot[bufferIndex]); DrawCube( &OutsideCube, &Wot[bufferIndex]); cpuLoad = VSync(1); DrawSync(0); gpuLoad = VSync(1); hsync = VSync(0); if (hsync > maxHsync) maxHsync = hsync; phase = frameNumber % 60; if (phase == 0) { average = 0; for (i = 0; i < 60; i++) { average += hsyncRecord[i]; } average /= 60; } else { hsyncRecord[phase] = hsync; } ResetGraph(1); GsSwapDispBuff(); GsSortClear(0, 0, 0, &Wot[bufferIndex]); GsDrawOt(&Wot[bufferIndex]); bufferIndex = GsGetActiveBuff(); FntFlush(-1); // handle list of tasks, each for drawing into off-screen area of VRAM HandleOffScreenDrawing(bufferIndex); } void InitialiseAll (void) { PadInit(); InitialiseRandomNumbers(); InitialiseTextStrings(); InitialiseSound(); SortVideoMode(); GsInitGraph(ScreenWidth, ScreenHeight, GsINTER|GsOFSGPU, 1, 0); GsDefDispBuff(0,0,0,ScreenHeight); GsInit3D(); // sort our first ordering table Wot[0].length = FIRST_OT_LENGTH; Wot[0].org = wtags[0]; Wot[1].length = FIRST_OT_LENGTH; Wot[1].org = wtags[1]; GsClearOt(0,0,&Wot[0]); GsClearOt(0,0,&Wot[1]); SortInitialGraphics(); // sort our second ordering table Wot2[0].length = SECOND_OT_LENGTH; Wot2[0].org = wtags2[0]; Wot2[1].length = SECOND_OT_LENGTH; Wot2[1].org = wtags2[1]; GsClearOt(0,0,&Wot2[0]); GsClearOt(0,0,&Wot2[1]); // sort our third ordering table Wot3[0].length = SECOND_OT_LENGTH; Wot3[0].org = wtags3[0]; Wot3[1].length = SECOND_OT_LENGTH; Wot3[1].org = wtags3[1]; GsClearOt(0,0,&Wot3[0]); GsClearOt(0,0,&Wot3[1]); // sort our fourth ordering table Wot4[0].length = SECOND_OT_LENGTH; Wot4[0].org = wtags4[0]; Wot4[1].length = SECOND_OT_LENGTH; Wot4[1].org = wtags4[1]; GsClearOt(0,0,&Wot4[0]); GsClearOt(0,0,&Wot4[1]); // sort our fifth ordering table Wot5[0].length = SECOND_OT_LENGTH; Wot5[0].org = wtags5[0]; Wot5[1].length = SECOND_OT_LENGTH; Wot5[1].org = wtags5[1]; GsClearOt(0,0,&Wot5[0]); GsClearOt(0,0,&Wot5[1]); // sort our sixth ordering table Wot6[0].length = SECOND_OT_LENGTH; Wot6[0].org = wtags6[0]; Wot6[1].length = SECOND_OT_LENGTH; Wot6[1].org = wtags6[1]; GsClearOt(0,0,&Wot6[0]); GsClearOt(0,0,&Wot6[1]); // sort our seventh ordering table Wot7[0].length = SECOND_OT_LENGTH; Wot7[0].org = wtags7[0]; Wot7[1].length = SECOND_OT_LENGTH; Wot7[1].org = wtags7[1]; GsClearOt(0,0,&Wot7[0]); GsClearOt(0,0,&Wot7[1]); InitialiseFaceGeometry(); InitialiseLighting(); InitialiseView(); ProperInitialiseTexture(FIRE_TEXTURE_ADDRESS, &FireTextureInfo); LinkSpriteToImageInfo(&FireSprite, &FireTextureInfo); ProperInitialiseTexture(MASCOTS_TEXTURE_ADDRESS, &MascotsTextureInfo); LinkSpriteToImageInfo(&MascotsSprite, &MascotsTextureInfo); ProperInitialiseTexture(WAVE_TEXTURE_ADDRESS, &WaveTextureInfo); LinkSpriteToImageInfo(&WaveSprite, &WaveTextureInfo); ProperInitialiseTexture(MASSIVE_PICTURE_TEXTURE_ADDRESS, &MassivePictureTextureInfo); LinkSpriteToImageInfo(&MassivePictureSprite, &MassivePictureTextureInfo); //ProperInitialiseTexture(MASSIVE_PICTURE_2_TEXTURE_ADDRESS, &MassivePicture2TextureInfo); ForceTextureIntoPosition(MASSIVE_PICTURE_TEXTURE_ADDRESS, &MassivePicture2TextureInfo, 320, 256, -1, -1); LinkSpriteToImageInfo(&MassivePicture2Sprite, &MassivePicture2TextureInfo); // sort basic text printing FntLoad( 960, 256); FntOpen( -120, -50, 256, 200, 0, 512); InitialiseObjects(); ClearTheCreatedTmds(); InitialiseDrawingProcesses(); //printf("before init breakout\n"); InitialiseBreakout2(); //printf("after init breakout\n"); HighScore.points = 200; // once only init //strcpy(HighScore.name, "Whizzkid"); SetUpDrawingProcesses(); SetMenuScreenDefaultSettings(); } // simplest overall video-mode initialiser void SortVideoMode (void) { int currentMode; currentMode = GetVideoMode(); printf("\n"); switch(currentMode) { case MODE_PAL: printf("currently in video mode PAL\n"); break; case MODE_NTSC: printf("currently in video mode NTSC\n"); break; default: assert(FALSE); } printf("If everything is black and white\n"); printf("or there are lines at bottom or top of screen\n"); printf("Then you need to change video mode\n\n"); } void InitialiseLighting (void) { // three flat light sources TheLights[0].vx = ONE; TheLights[0].vy = 0; TheLights[0].vz = 0; TheLights[0].r = 128; TheLights[0].g = 0; TheLights[0].b = 0; GsSetFlatLight(0, &TheLights[0]); TheLights[1].vx = 0; TheLights[1].vy = ONE; TheLights[1].vz = 0; TheLights[1].r = 0; TheLights[1].g = 128; TheLights[1].b = 0; GsSetFlatLight(1, &TheLights[1]); TheLights[2].vx = 0; TheLights[2].vy = 0; TheLights[2].vz = ONE; TheLights[2].r = 0; TheLights[2].g = 0; TheLights[2].b = 128; GsSetFlatLight(2, &TheLights[2]); // background lighting GsSetAmbient(ONE/2, ONE/2, ONE/2); // overall lighting conditions OverallLightMode = 0; // does not allow fogging GsSetLightMode(OverallLightMode); } void InitialiseView (void) { CameraControlFlag = AUTO_CAMERA; AutoCameraMode = MUTATE_ON_FOUR; // FIXED_IN_FIRST; SetUpAutoCamera(); } void InitialiseFaceGeometry (void) { int i; // these go outwards from cube faces off into space setVECTOR( &FaceOutsideNormals[FRONT], 0, 0, -ONE); setVECTOR( &FaceOutsideNormals[RIGHT], ONE, 0, 0); setVECTOR( &FaceOutsideNormals[BACK], 0, 0, ONE); setVECTOR( &FaceOutsideNormals[LEFT], -ONE, 0, 0); setVECTOR( &FaceOutsideNormals[TOP], 0, -ONE, 0); setVECTOR( &FaceOutsideNormals[BOTTOM], 0, ONE, 0); // these go from face centres to centre of cube for (i = 0; i < 6; i++) { setVECTOR( &FaceInsideNormals[i], -FaceOutsideNormals[i].vx, -FaceOutsideNormals[i].vy, -FaceOutsideNormals[i].vz); } // corners of unit cube; also unit vectors // from any cube centre to its corners setVECTOR( &CubeCorners[FRONT_LEFT_TOP_CORNER], -ONE, -ONE, -ONE); setVECTOR( &CubeCorners[FRONT_LEFT_BOTTOM_CORNER], -ONE, ONE, -ONE); setVECTOR( &CubeCorners[FRONT_RIGHT_TOP_CORNER], ONE, -ONE, -ONE); setVECTOR( &CubeCorners[FRONT_RIGHT_BOTTOM_CORNER], ONE, ONE, -ONE); setVECTOR( &CubeCorners[BACK_LEFT_TOP_CORNER], -ONE, -ONE, ONE); setVECTOR( &CubeCorners[BACK_LEFT_BOTTOM_CORNER], -ONE, ONE, ONE); setVECTOR( &CubeCorners[BACK_RIGHT_TOP_CORNER], ONE, -ONE, ONE); setVECTOR( &CubeCorners[BACK_RIGHT_BOTTOM_CORNER], ONE, ONE, ONE); setVECTOR( &FaceXVectors[FRONT], ONE, 0, 0); setVECTOR( &FaceYVectors[FRONT], 0, -ONE, 0); setVECTOR( &FaceXVectors[RIGHT], 0, 0, ONE); setVECTOR( &FaceYVectors[RIGHT], 0, -ONE, 0); setVECTOR( &FaceXVectors[BACK], -ONE, 0, 0); setVECTOR( &FaceYVectors[BACK], 0, -ONE, 0); setVECTOR( &FaceXVectors[LEFT], 0, 0, -ONE); setVECTOR( &FaceYVectors[LEFT], 0, -ONE, 0); setVECTOR( &FaceXVectors[TOP], ONE, 0, 0); setVECTOR( &FaceYVectors[TOP], 0, 0, ONE); setVECTOR( &FaceXVectors[BOTTOM], ONE, 0, 0); setVECTOR( &FaceYVectors[BOTTOM], 0, 0, -ONE); // which can be got to from which others FaceAccessTable[FRONT][NORTH] = TOP; FaceAccessTable[FRONT][EAST] = RIGHT; FaceAccessTable[FRONT][SOUTH] = BOTTOM; FaceAccessTable[FRONT][WEST] = LEFT; FaceAccessTable[RIGHT][NORTH] = TOP; FaceAccessTable[RIGHT][EAST] = BACK; FaceAccessTable[RIGHT][SOUTH] = BOTTOM; FaceAccessTable[RIGHT][WEST] = FRONT; FaceAccessTable[BACK][NORTH] = TOP; FaceAccessTable[BACK][EAST] = LEFT; FaceAccessTable[BACK][SOUTH] = BOTTOM; FaceAccessTable[BACK][WEST] = RIGHT; FaceAccessTable[LEFT][NORTH] = TOP; FaceAccessTable[LEFT][EAST] = FRONT; FaceAccessTable[LEFT][SOUTH] = BOTTOM; FaceAccessTable[LEFT][WEST] = BACK; FaceAccessTable[TOP][NORTH] = BACK; FaceAccessTable[TOP][EAST] = RIGHT; FaceAccessTable[TOP][SOUTH] = FRONT; FaceAccessTable[TOP][WEST] = LEFT; FaceAccessTable[BOTTOM][NORTH] = FRONT; FaceAccessTable[BOTTOM][EAST] = RIGHT; FaceAccessTable[BOTTOM][SOUTH] = BACK; FaceAccessTable[BOTTOM][WEST] = LEFT; } void InitialiseObjects (void) { int i; InitialiseObjectClass(); InitialiseMiniObjectClass(); for (i = 0; i < MAX_CUBES; i++) { InitSingleObject(&TheCubes[i]); BringObjectToLife(&TheCubes[i], CUBE, CUBE_MODEL_ADDRESS, 0, NONE); RegisterObjectIntoObjectArray(&TheCubes[i]); } for (i = 0; i < MAX_POLYGONS; i++) { InitMiniObject( &ThePolygons[i]); RegisterMiniObjectIntoMiniObjectArray( &ThePolygons[i]); ThePolygons[i].alive = FALSE; } LinkAllObjectsToModelsOrSprites(); LinkAllObjectsToTheirCoordinateSystems(); for (i = 0; i < MAX_CUBES; i++) { TheCubes[i].alive = FALSE; // start off dead } //CreateMoreLittleCubesAroundLargerOne(); } void CreateMoreLittleCubesAroundLargerOne (void) { int i; for (i = 0; i < 8; i++) { TheCubes[i].alive = TRUE; } setVECTOR( &TheCubes[0].position, 400, 400, 400); setVECTOR( &TheCubes[1].position, 400, 400, -400); setVECTOR( &TheCubes[2].position, 400, -400, 400); setVECTOR( &TheCubes[3].position, -400, 400, 400); setVECTOR( &TheCubes[4].position, 400, -400, -400); setVECTOR( &TheCubes[5].position, -400, 400, -400); setVECTOR( &TheCubes[6].position, -400, -400, 400); setVECTOR( &TheCubes[7].position, -400, -400, -400); for (i = 0; i < 8; i++) { if (TheCubes[i].position.vx == 400) SetObjectScaling( &TheCubes[i], ONE/2, ONE/2, ONE/2); if (TheCubes[i].position.vy == 400) { TheCubes[i].rotationMomentumFlag = TRUE; setVECTOR( &TheCubes[i].twist, 0, 0, (rand() % 30) ); } } } void InitialiseCubes (void) { //RECT insideTextureAreasList[6]; RECT singleInsideCubeTexture; //RECT outsideTextureAreasList[6]; RECT singleOutsideCubeTexture; //int i; GsIMAGE *usersChoice; assert(FALSE); // out of date //printf("Start of InitialiseCubes\n"); // init to void and dead InitCube(&InsideCube); InitCube(&OutsideCube); // inside cube: each surface gets same large 16bit texture setRECT( &singleInsideCubeTexture, MassivePictureTextureInfo.px, MassivePictureTextureInfo.py, MassivePictureTextureInfo.pw, MassivePictureTextureInfo.ph); CreateCube ( &InsideCube, INSIDE_CUBE, 800, VISIBLE_FROM_OUTSIDE, 2, SINGLE_CUBE_TEXTURE, TRUE, &singleInsideCubeTexture); //printf("BackgroundGraphicsFlag: %d\n", BackgroundGraphicsFlag); switch(BackgroundGraphicsFlag) { case TRUE: usersChoice = &MassivePicture2TextureInfo; break; case FALSE: usersChoice = &WaveTextureInfo; break; default: assert(FALSE); } setRECT( &singleOutsideCubeTexture, usersChoice->px, usersChoice->py, usersChoice->pw, usersChoice->ph); // outside cube: each surface gets same texture // which depends on user #if 0 // old: forces simple texture setRECT( &singleOutsideCubeTexture, WaveTextureInfo.px, WaveTextureInfo.py, WaveTextureInfo.pw, WaveTextureInfo.ph); #endif CreateCube ( &OutsideCube, OUTSIDE_CUBE, 5000, VISIBLE_FROM_INSIDE, 2, SINGLE_CUBE_TEXTURE, TRUE, &singleOutsideCubeTexture); //printf("End of InitialiseCubes\n"); //printf("INSIDE cube\n"); //PrintCubeInfo (&InsideCube); //printf("OUTSIDE cube\n"); //PrintCubeInfo (&OutsideCube); } void CreateTheInnerCube (void) { RECT singleInsideCubeTexture; InitCube(&InsideCube); if (BackgroundGraphicsFlag == PLAY_ON_OUTER_ONLY) return; // inside cube: each surface gets same large 16bit texture setRECT( &singleInsideCubeTexture, MassivePictureTextureInfo.px, MassivePictureTextureInfo.py, MassivePictureTextureInfo.pw, MassivePictureTextureInfo.ph); CreateCube ( &InsideCube, INSIDE_CUBE, 800, VISIBLE_FROM_OUTSIDE, 2, SINGLE_CUBE_TEXTURE, TRUE, &singleInsideCubeTexture); } void CreateTheOuterCube (void) { RECT outsideTextureAreasList[6]; RECT singleOutsideCubeTexture; InitCube(&OutsideCube); // outside cube: each surface gets same texture // which depends on user //printf("BackgroundGraphicsFlag: %d\n", BackgroundGraphicsFlag); switch(BackgroundGraphicsFlag) { case PLAY_ON_INNER_SIMPLE_OUTER_TEXTURE: // six textures, one for each face; each one a portion of mascots2.tim setRECT( &outsideTextureAreasList[0], MascotsTextureInfo.px + 36, MascotsTextureInfo.py + 59, 32, 32); setRECT( &outsideTextureAreasList[1], MascotsTextureInfo.px + 35, MascotsTextureInfo.py + 3, 32, 32); setRECT( &outsideTextureAreasList[2], MascotsTextureInfo.px + 103, MascotsTextureInfo.py + 2, 32, 32); setRECT( &outsideTextureAreasList[3], MascotsTextureInfo.px + 171, MascotsTextureInfo.py + 63, 32, 32); setRECT( &outsideTextureAreasList[4], MascotsTextureInfo.px + 172, MascotsTextureInfo.py + 2, 32, 32); setRECT( &outsideTextureAreasList[5], MascotsTextureInfo.px + 70, MascotsTextureInfo.py + 63, 32, 32); CreateCube ( &OutsideCube, OUTSIDE_CUBE, 5000, VISIBLE_FROM_INSIDE, 4, ONE_TEXTURE_PER_FACE, FALSE, outsideTextureAreasList); break; case PLAY_ON_INNER_FLASH_OUTER_TEXTURE: setRECT( &singleOutsideCubeTexture, MassivePicture2TextureInfo.px, MassivePicture2TextureInfo.py, MassivePicture2TextureInfo.pw, MassivePicture2TextureInfo.ph); CreateCube ( &OutsideCube, OUTSIDE_CUBE, 5000, VISIBLE_FROM_INSIDE, 4, SINGLE_CUBE_TEXTURE, TRUE, &singleOutsideCubeTexture); break; case PLAY_ON_OUTER_ONLY: case PLAY_ON_BOTH_SURFACES: setRECT( &singleOutsideCubeTexture, MassivePictureTextureInfo.px, MassivePictureTextureInfo.py, MassivePictureTextureInfo.pw, MassivePictureTextureInfo.ph); CreateCube ( &OutsideCube, OUTSIDE_CUBE, 5000, VISIBLE_FROM_INSIDE, 4, SINGLE_CUBE_TEXTURE, TRUE, &singleOutsideCubeTexture); break; #if 0 case TRUE: // single massive picture for outside cube surfaces setRECT( &singleOutsideCubeTexture, MassivePicture2TextureInfo.px, MassivePicture2TextureInfo.py, MassivePicture2TextureInfo.pw, MassivePicture2TextureInfo.ph); CreateCube ( &OutsideCube, OUTSIDE_CUBE, 5000, VISIBLE_FROM_INSIDE, 4, SINGLE_CUBE_TEXTURE, TRUE, &singleOutsideCubeTexture); break; case FALSE: // six textures, one for each face; each one a portion of mascots2.tim setRECT( &outsideTextureAreasList[0], MascotsTextureInfo.px + 36, MascotsTextureInfo.py + 59, 32, 32); setRECT( &outsideTextureAreasList[1], MascotsTextureInfo.px + 35, MascotsTextureInfo.py + 3, 32, 32); setRECT( &outsideTextureAreasList[2], MascotsTextureInfo.px + 103, MascotsTextureInfo.py + 2, 32, 32); setRECT( &outsideTextureAreasList[3], MascotsTextureInfo.px + 171, MascotsTextureInfo.py + 63, 32, 32); setRECT( &outsideTextureAreasList[4], MascotsTextureInfo.px + 172, MascotsTextureInfo.py + 2, 32, 32); setRECT( &outsideTextureAreasList[5], MascotsTextureInfo.px + 70, MascotsTextureInfo.py + 63, 32, 32); CreateCube ( &OutsideCube, OUTSIDE_CUBE, 5000, VISIBLE_FROM_INSIDE, 4, ONE_TEXTURE_PER_FACE, FALSE, outsideTextureAreasList); break; #endif default: assert(FALSE); } } void CleanupProgram (void) { // This screen-storing done in-game when cheats are on //StoreScreen2 ( (u_long*)SCREEN_SAVE_ADDRESS, 0, 0, ScreenWidth, ScreenHeight); //StoreScreen(); ResetGraph(3); CleanUpSound(); // if this program part of a multiple module, // can printf to siocons to tell user to // invoke a new batch file, etc } void CycleLightsAroundAxes (void) { int cyclePoint, theta; int lightEffectPeriod = 90; int smallerPeriod; int overallPhase; int localCyclePoint; cyclePoint = (frameNumber % lightEffectPeriod); theta = ONE * cyclePoint / lightEffectPeriod; // not very sorted, but will do TheLights[0].vx = rcos(theta); TheLights[0].vy = rsin(theta); //GsSetFlatLight(0, &TheLights[0]); TheLights[1].vz = rcos(theta); TheLights[1].vx = rsin(theta); //GsSetFlatLight(1, &TheLights[1]); TheLights[2].vy = rcos(theta); TheLights[2].vz = rsin(theta); //GsSetFlatLight(2, &TheLights[2]); overallPhase = (cyclePoint * 2) / lightEffectPeriod; smallerPeriod = lightEffectPeriod/2; switch(overallPhase) { case 0: localCyclePoint = cyclePoint; TheLights[0].r = 64 + ((localCyclePoint * 128) / smallerPeriod); TheLights[1].g = 64 + ((localCyclePoint * 128) / smallerPeriod); TheLights[2].b = 64 + ((localCyclePoint * 128) / smallerPeriod); break; case 1: localCyclePoint = cyclePoint - smallerPeriod; TheLights[0].r = 192 - ((localCyclePoint * 128) / smallerPeriod); TheLights[1].g = 192 - ((localCyclePoint * 128) / smallerPeriod); TheLights[2].b = 192 - ((localCyclePoint * 128) / smallerPeriod); break; default: assert(FALSE); } // register in system GsSetFlatLight(0, &TheLights[0]); GsSetFlatLight(1, &TheLights[1]); GsSetFlatLight(2, &TheLights[2]); //dumpLIGHT( &TheLights[0]); //dumpLIGHT( &TheLights[1]); //dumpLIGHT( &TheLights[2]); } void DealWithControllerPad (void) { long pad; int controlSpeed; int pause = 12; static int framesSinceLastChoice = 0; int longPauseFlag = FALSE; pad = PadRead(); framesSinceLastChoice++; if (FramesInNewState < NEW_MODE_PAUSE) return; if (MenuScreenOption == CHOOSE_GAME_DEMO) { if ( (frameNumber - FrameWhenDemoStarts) > ROLLING_DEMO_DURATION) { ChangeGameState(MODE_MENU_SCREEN); } else if (pad != 0) { ChangeGameState(MODE_MENU_SCREEN); } return; // no controller actions in demo mode; just return to menu } //