1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "../renderer/Image.h"
- #include "DeviceContext.h"
- #include "Window.h"
- #include "UserInterfaceLocal.h"
- #include "GameBustOutWindow.h"
- #define BALL_RADIUS 12.f
- #define BALL_SPEED 250.f
- #define BALL_MAXSPEED 450.f
- #define S_UNIQUE_CHANNEL 6
- /*
- *****************************************************************************
- * BOEntity
- ****************************************************************************
- */
- BOEntity::BOEntity(idGameBustOutWindow* _game) {
- game = _game;
- visible = true;
- materialName = "";
- material = NULL;
- width = height = 8;
- color = colorWhite;
- powerup = POWERUP_NONE;
- position.Zero();
- velocity.Zero();
- removed = false;
- fadeOut = 0;
- }
- BOEntity::~BOEntity() {
- }
- /*
- ======================
- BOEntity::WriteToSaveGame
- ======================
- */
- void BOEntity::WriteToSaveGame( idFile *savefile ) {
- savefile->Write( &visible, sizeof(visible) );
- game->WriteSaveGameString( materialName, savefile );
- savefile->Write( &width, sizeof(width) );
- savefile->Write( &height, sizeof(height) );
- savefile->Write( &color, sizeof(color) );
- savefile->Write( &position, sizeof(position) );
- savefile->Write( &velocity, sizeof(velocity) );
- savefile->Write( &powerup, sizeof(powerup) );
- savefile->Write( &removed, sizeof(removed) );
- savefile->Write( &fadeOut, sizeof(fadeOut) );
- }
- /*
- ======================
- BOEntity::ReadFromSaveGame
- ======================
- */
- void BOEntity::ReadFromSaveGame( idFile *savefile, idGameBustOutWindow* _game ) {
- game = _game;
- savefile->Read( &visible, sizeof(visible) );
- game->ReadSaveGameString( materialName, savefile );
- SetMaterial( materialName );
- savefile->Read( &width, sizeof(width) );
- savefile->Read( &height, sizeof(height) );
- savefile->Read( &color, sizeof(color) );
- savefile->Read( &position, sizeof(position) );
- savefile->Read( &velocity, sizeof(velocity) );
- savefile->Read( &powerup, sizeof(powerup) );
- savefile->Read( &removed, sizeof(removed) );
- savefile->Read( &fadeOut, sizeof(fadeOut) );
- }
- /*
- ======================
- BOEntity::SetMaterial
- ======================
- */
- void BOEntity::SetMaterial(const char* name) {
- materialName = name;
- material = declManager->FindMaterial( name );
- material->SetSort( SS_GUI );
- }
- /*
- ======================
- BOEntity::SetSize
- ======================
- */
- void BOEntity::SetSize( float _width, float _height ) {
- width = _width;
- height = _height;
- }
- /*
- ======================
- BOEntity::SetVisible
- ======================
- */
- void BOEntity::SetColor( float r, float g, float b, float a ) {
- color.x = r;
- color.y = g;
- color.z = b;
- color.w = a;
- }
- /*
- ======================
- BOEntity::SetVisible
- ======================
- */
- void BOEntity::SetVisible( bool isVisible ) {
- visible = isVisible;
- }
- /*
- ======================
- BOEntity::Update
- ======================
- */
- void BOEntity::Update( float timeslice, int guiTime ) {
-
- if ( !visible ) {
- return;
- }
- // Move the entity
- position += velocity * timeslice;
- // Fade out the ent
- if ( fadeOut ) {
- color.w -= timeslice * 2.5;
- if ( color.w <= 0.f ) {
- color.w = 0.f;
- removed = true;
- }
- }
- }
- /*
- ======================
- BOEntity::Draw
- ======================
- */
- void BOEntity::Draw() {
- if ( visible ) {
- dc->DrawMaterialRotated( position.x, position.y, width, height, material, color, 1.0f, 1.0f, DEG2RAD(0.f) );
- }
- }
- /*
- *****************************************************************************
- * BOBrick
- ****************************************************************************
- */
- BOBrick::BOBrick() {
- ent = NULL;
- x = y = width = height = 0;
- powerup = POWERUP_NONE;
- isBroken = false;
- }
- BOBrick::BOBrick( BOEntity *_ent, float _x, float _y, float _width, float _height ) {
- ent = _ent;
- x = _x;
- y = _y;
- width = _width;
- height = _height;
- powerup = POWERUP_NONE;
- isBroken = false;
- ent->position.x = x;
- ent->position.y = y;
- ent->SetSize( width, height );
- ent->SetMaterial( "game/bustout/brick" );
- ent->game->entities.Append( ent );
- }
- BOBrick::~BOBrick() {
- }
- /*
- ======================
- BOBrick::WriteToSaveGame
- ======================
- */
- void BOBrick::WriteToSaveGame( idFile *savefile ) {
- savefile->Write( &x, sizeof(x) );
- savefile->Write( &y, sizeof(y) );
- savefile->Write( &width, sizeof(width) );
- savefile->Write( &height, sizeof(height) );
- savefile->Write( &powerup, sizeof(powerup) );
- savefile->Write( &isBroken, sizeof(isBroken) );
- int index = ent->game->entities.FindIndex( ent );
- savefile->Write( &index, sizeof(index) );
- }
- /*
- ======================
- BOBrick::ReadFromSaveGame
- ======================
- */
- void BOBrick::ReadFromSaveGame( idFile *savefile, idGameBustOutWindow *game ) {
- savefile->Read( &x, sizeof(x) );
- savefile->Read( &y, sizeof(y) );
- savefile->Read( &width, sizeof(width) );
- savefile->Read( &height, sizeof(height) );
- savefile->Read( &powerup, sizeof(powerup) );
- savefile->Read( &isBroken, sizeof(isBroken) );
- int index;
- savefile->Read( &index, sizeof(index) );
- ent = game->entities[index];
- }
- /*
- ======================
- BOBrick::SetColor
- ======================
- */
- void BOBrick::SetColor( idVec4 bcolor ) {
- ent->SetColor( bcolor.x, bcolor.y, bcolor.z, bcolor.w );
- }
- /*
- ======================
- BOBrick::checkCollision
- ======================
- */
- collideDir_t BOBrick::checkCollision( idVec2 pos, idVec2 vel ) {
- idVec2 ptA, ptB;
- float dist;
- collideDir_t result = COLLIDE_NONE;
- if ( isBroken ) {
- return result;
- }
- // Check for collision with each edge
- idVec2 vec;
- // Bottom
- ptA.x = x;
- ptA.y = y + height;
- ptB.x = x + width;
- ptB.y = y + height;
- if ( vel.y < 0 && pos.y > ptA.y ) {
- if( pos.x > ptA.x && pos.x < ptB.x ) {
- dist = pos.y - ptA.y;
- if ( dist < BALL_RADIUS ) {
- result = COLLIDE_DOWN;
- }
- } else {
- if ( pos.x <= ptA.x ) {
- vec = pos - ptA;
- } else {
- vec = pos - ptB;
- }
- if ( (idMath::Fabs(vec.y) > idMath::Fabs(vec.x)) && (vec.LengthFast() < BALL_RADIUS) ) {
- result = COLLIDE_DOWN;
- }
- }
- }
- if ( result == COLLIDE_NONE ) {
- // Top
- ptA.y = y;
- ptB.y = y;
- if ( vel.y > 0 && pos.y < ptA.y ) {
- if( pos.x > ptA.x && pos.x < ptB.x ) {
- dist = ptA.y - pos.y;
- if ( dist < BALL_RADIUS ) {
- result = COLLIDE_UP;
- }
- } else {
- if ( pos.x <= ptA.x ) {
- vec = pos - ptA;
- } else {
- vec = pos - ptB;
- }
- if ( (idMath::Fabs(vec.y) > idMath::Fabs(vec.x)) && (vec.LengthFast() < BALL_RADIUS) ) {
- result = COLLIDE_UP;
- }
- }
- }
- if ( result == COLLIDE_NONE ) {
- // Left side
- ptA.x = x;
- ptA.y = y;
- ptB.x = x;
- ptB.y = y + height;
- if ( vel.x > 0 && pos.x < ptA.x ) {
- if( pos.y > ptA.y && pos.y < ptB.y ) {
- dist = ptA.x - pos.x;
- if ( dist < BALL_RADIUS ) {
- result = COLLIDE_LEFT;
- }
- } else {
- if ( pos.y <= ptA.y ) {
- vec = pos - ptA;
- } else {
- vec = pos - ptB;
- }
- if ( (idMath::Fabs(vec.x) >= idMath::Fabs(vec.y)) && (vec.LengthFast() < BALL_RADIUS) ) {
- result = COLLIDE_LEFT;
- }
- }
- }
- if ( result == COLLIDE_NONE ) {
- // Right side
- ptA.x = x + width;
- ptB.x = x + width;
- if ( vel.x < 0 && pos.x > ptA.x ) {
- if( pos.y > ptA.y && pos.y < ptB.y ) {
- dist = pos.x - ptA.x;
- if ( dist < BALL_RADIUS ) {
- result = COLLIDE_LEFT;
- }
- } else {
- if ( pos.y <= ptA.y ) {
- vec = pos - ptA;
- } else {
- vec = pos - ptB;
- }
- if ( (idMath::Fabs(vec.x) >= idMath::Fabs(vec.y)) && (vec.LengthFast() < BALL_RADIUS) ) {
- result = COLLIDE_LEFT;
- }
- }
- }
- }
- }
- }
- return result;
- }
- /*
- *****************************************************************************
- * idGameBustOutWindow
- ****************************************************************************
- */
- idGameBustOutWindow::idGameBustOutWindow(idUserInterfaceLocal *g) : idWindow(g) {
- gui = g;
- CommonInit();
- }
- idGameBustOutWindow::~idGameBustOutWindow() {
- entities.DeleteContents(true);
- Mem_Free( levelBoardData );
- }
- /*
- =============================
- idGameBustOutWindow::WriteToSaveGame
- =============================
- */
- void idGameBustOutWindow::WriteToSaveGame( idFile *savefile ) {
- idWindow::WriteToSaveGame( savefile );
- gamerunning.WriteToSaveGame( savefile );
- onFire.WriteToSaveGame( savefile );
- onContinue.WriteToSaveGame( savefile );
- onNewGame.WriteToSaveGame( savefile );
- onNewLevel.WriteToSaveGame( savefile );
- savefile->Write( &timeSlice, sizeof(timeSlice) );
- savefile->Write( &gameOver, sizeof(gameOver) );
- savefile->Write( &numLevels, sizeof(numLevels) );
- // Board Data is loaded when GUI is loaded, don't need to save
- savefile->Write( &numBricks, sizeof(numBricks) );
- savefile->Write( ¤tLevel, sizeof(currentLevel) );
- savefile->Write( &updateScore, sizeof(updateScore) );
- savefile->Write( &gameScore, sizeof(gameScore) );
- savefile->Write( &nextBallScore, sizeof(nextBallScore) );
- savefile->Write( &bigPaddleTime, sizeof(bigPaddleTime) );
- savefile->Write( &paddleVelocity, sizeof(paddleVelocity) );
- savefile->Write( &ballSpeed, sizeof(ballSpeed) );
- savefile->Write( &ballsRemaining, sizeof(ballsRemaining) );
- savefile->Write( &ballsInPlay, sizeof(ballsInPlay) );
- savefile->Write( &ballHitCeiling, sizeof(ballHitCeiling) );
- // Write Entities
- int i;
- int numberOfEnts = entities.Num();
- savefile->Write( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- entities[i]->WriteToSaveGame( savefile );
- }
- // Write Balls
- numberOfEnts = balls.Num();
- savefile->Write( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- int ballIndex = entities.FindIndex( balls[i] );
- savefile->Write( &ballIndex, sizeof(ballIndex) );
- }
- // Write Powerups
- numberOfEnts = powerUps.Num();
- savefile->Write( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- int powerIndex = entities.FindIndex( powerUps[i] );
- savefile->Write( &powerIndex, sizeof(powerIndex) );
- }
- // Write paddle
- paddle->WriteToSaveGame( savefile );
- // Write Bricks
- int row;
- for ( row=0; row<BOARD_ROWS; row++ ) {
- numberOfEnts = board[row].Num();
- savefile->Write( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- board[row][i]->WriteToSaveGame( savefile );
- }
- }
- }
- /*
- =============================
- idGameBustOutWindow::ReadFromSaveGame
- =============================
- */
- void idGameBustOutWindow::ReadFromSaveGame( idFile *savefile ) {
- idWindow::ReadFromSaveGame( savefile );
- // Clear out existing paddle and entities from GUI load
- delete paddle;
- entities.DeleteContents( true );
- gamerunning.ReadFromSaveGame( savefile );
- onFire.ReadFromSaveGame( savefile );
- onContinue.ReadFromSaveGame( savefile );
- onNewGame.ReadFromSaveGame( savefile );
- onNewLevel.ReadFromSaveGame( savefile );
- savefile->Read( &timeSlice, sizeof(timeSlice) );
- savefile->Read( &gameOver, sizeof(gameOver) );
- savefile->Read( &numLevels, sizeof(numLevels) );
- // Board Data is loaded when GUI is loaded, don't need to save
- savefile->Read( &numBricks, sizeof(numBricks) );
- savefile->Read( ¤tLevel, sizeof(currentLevel) );
- savefile->Read( &updateScore, sizeof(updateScore) );
- savefile->Read( &gameScore, sizeof(gameScore) );
- savefile->Read( &nextBallScore, sizeof(nextBallScore) );
- savefile->Read( &bigPaddleTime, sizeof(bigPaddleTime) );
- savefile->Read( &paddleVelocity, sizeof(paddleVelocity) );
- savefile->Read( &ballSpeed, sizeof(ballSpeed) );
- savefile->Read( &ballsRemaining, sizeof(ballsRemaining) );
- savefile->Read( &ballsInPlay, sizeof(ballsInPlay) );
- savefile->Read( &ballHitCeiling, sizeof(ballHitCeiling) );
- int i;
- int numberOfEnts;
- // Read entities
- savefile->Read( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- BOEntity *ent;
- ent = new (TAG_OLD_UI) BOEntity( this );
- ent->ReadFromSaveGame( savefile, this );
- entities.Append( ent );
- }
- // Read balls
- savefile->Read( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- int ballIndex;
- savefile->Read( &ballIndex, sizeof(ballIndex) );
- balls.Append( entities[ballIndex] );
- }
- // Read powerups
- savefile->Read( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- int powerIndex;
- savefile->Read( &powerIndex, sizeof(powerIndex) );
- balls.Append( entities[powerIndex] );
- }
- // Read paddle
- paddle = new (TAG_OLD_UI) BOBrick();
- paddle->ReadFromSaveGame( savefile, this );
- // Read board
- int row;
- for ( row=0; row<BOARD_ROWS; row++ ) {
- savefile->Read( &numberOfEnts, sizeof(numberOfEnts) );
- for ( i=0; i<numberOfEnts; i++ ) {
- BOBrick *brick = new (TAG_OLD_UI) BOBrick();
- brick->ReadFromSaveGame( savefile, this );
- board[row].Append( brick );
- }
- }
- }
- /*
- =============================
- idGameBustOutWindow::ResetGameState
- =============================
- */
- void idGameBustOutWindow::ResetGameState() {
- gamerunning = false;
- gameOver = false;
- onFire = false;
- onContinue = false;
- onNewGame = false;
- onNewLevel = false;
- // Game moves forward 16 milliseconds every frame
- timeSlice = 0.016f;
- ballsRemaining = 3;
- ballSpeed = BALL_SPEED;
- ballsInPlay = 0;
- updateScore = false;
- numBricks = 0;
- currentLevel = 1;
- gameScore = 0;
- bigPaddleTime = 0;
- nextBallScore = gameScore + 10000;
- ClearBoard();
- }
- /*
- =============================
- idGameBustOutWindow::CommonInit
- =============================
- */
- void idGameBustOutWindow::CommonInit() {
- BOEntity *ent;
- // Precache images
- declManager->FindMaterial( "game/bustout/ball" );
- declManager->FindMaterial( "game/bustout/doublepaddle" );
- declManager->FindMaterial( "game/bustout/powerup_bigpaddle" );
- declManager->FindMaterial( "game/bustout/powerup_multiball" );
- declManager->FindMaterial( "game/bustout/brick" );
- // Precache sounds
- declManager->FindSound( "arcade_ballbounce" );
- declManager->FindSound( "arcade_brickhit" );
- declManager->FindSound( "arcade_missedball" );
- declManager->FindSound( "arcade_sadsound" );
- declManager->FindSound( "arcade_extraball" );
- declManager->FindSound( "arcade_powerup" );
- ResetGameState();
- numLevels = 0;
- boardDataLoaded = false;
- levelBoardData = NULL;
- // Create Paddle
- ent = new (TAG_OLD_UI) BOEntity( this );
- paddle = new (TAG_OLD_UI) BOBrick( ent, 260.f, 440.f, 96.f, 24.f );
- paddle->ent->SetMaterial( "game/bustout/paddle" );
- }
- /*
- =============================
- idGameBustOutWindow::HandleEvent
- =============================
- */
- const char *idGameBustOutWindow::HandleEvent(const sysEvent_t *event, bool *updateVisuals) {
- int key = event->evValue;
- // need to call this to allow proper focus and capturing on embedded children
- const char *ret = idWindow::HandleEvent(event, updateVisuals);
- if ( event->evType == SE_KEY ) {
- if ( !event->evValue2 ) {
- return ret;
- }
- if ( key == K_MOUSE1) {
- // Mouse was clicked
- if ( ballsInPlay == 0 ) {
- BOEntity *ball = CreateNewBall();
- ball->SetVisible( true );
- ball->position.x = paddle->ent->position.x + 48.f;
- ball->position.y = 430.f;
- ball->velocity.x = ballSpeed;
- ball->velocity.y = -ballSpeed*2.f;
- ball->velocity.NormalizeFast();
- ball->velocity *= ballSpeed;
- }
- } else {
- return ret;
- }
- }
- return ret;
- }
- /*
- =============================
- idGameBustOutWindow::ParseInternalVar
- =============================
- */
- bool idGameBustOutWindow::ParseInternalVar(const char *_name, idTokenParser *src) {
- if ( idStr::Icmp(_name, "gamerunning") == 0 ) {
- gamerunning = src->ParseBool();
- return true;
- }
- if ( idStr::Icmp(_name, "onFire") == 0 ) {
- onFire = src->ParseBool();
- return true;
- }
- if ( idStr::Icmp(_name, "onContinue") == 0 ) {
- onContinue = src->ParseBool();
- return true;
- }
- if ( idStr::Icmp(_name, "onNewGame") == 0 ) {
- onNewGame = src->ParseBool();
- return true;
- }
- if ( idStr::Icmp(_name, "onNewLevel") == 0 ) {
- onNewLevel = src->ParseBool();
- return true;
- }
- if ( idStr::Icmp(_name, "numLevels") == 0 ) {
- numLevels = src->ParseInt();
- // Load all the level images
- LoadBoardFiles();
- return true;
- }
- return idWindow::ParseInternalVar(_name, src);
- }
- /*
- =============================
- idGameBustOutWindow::GetWinVarByName
- =============================
- */
- idWinVar *idGameBustOutWindow::GetWinVarByName(const char *_name, bool winLookup, drawWin_t** owner) {
- idWinVar *retVar = NULL;
- if ( idStr::Icmp(_name, "gamerunning") == 0 ) {
- retVar = &gamerunning;
- } else if ( idStr::Icmp(_name, "onFire") == 0 ) {
- retVar = &onFire;
- } else if ( idStr::Icmp(_name, "onContinue") == 0 ) {
- retVar = &onContinue;
- } else if ( idStr::Icmp(_name, "onNewGame") == 0 ) {
- retVar = &onNewGame;
- } else if ( idStr::Icmp(_name, "onNewLevel") == 0 ) {
- retVar = &onNewLevel;
- }
- if(retVar) {
- return retVar;
- }
- return idWindow::GetWinVarByName(_name, winLookup, owner);
- }
- /*
- =============================
- idGameBustOutWindow::PostParse
- =============================
- */
- void idGameBustOutWindow::PostParse() {
- idWindow::PostParse();
- }
- /*
- =============================
- idGameBustOutWindow::Draw
- =============================
- */
- void idGameBustOutWindow::Draw(int time, float x, float y) {
- int i;
- //Update the game every frame before drawing
- UpdateGame();
- for( i = entities.Num()-1; i >= 0; i-- ) {
- entities[i]->Draw();
- }
- }
- /*
- =============================
- idGameBustOutWindow::Activate
- =============================
- */
- const char *idGameBustOutWindow::Activate(bool activate) {
- return "";
- }
- /*
- =============================
- idGameBustOutWindow::UpdateScore
- =============================
- */
- void idGameBustOutWindow::UpdateScore() {
- if ( gameOver ) {
- gui->HandleNamedEvent( "GameOver" );
- return;
- }
- // Check for level progression
- if ( numBricks == 0 ) {
- ClearBalls();
- gui->HandleNamedEvent( "levelComplete" );
- }
- // Check for new ball score
- if ( gameScore >= nextBallScore ) {
- ballsRemaining++;
- gui->HandleNamedEvent( "extraBall" );
- // Play sound
- common->SW()->PlayShaderDirectly( "arcade_extraball", S_UNIQUE_CHANNEL );
- nextBallScore = gameScore + 10000;
- }
- gui->SetStateString( "player_score", va("%i", gameScore ) );
- gui->SetStateString( "balls_remaining", va("%i", ballsRemaining ) );
- gui->SetStateString( "current_level", va("%i", currentLevel ) );
- gui->SetStateString( "next_ball_score", va("%i", nextBallScore ) );
- }
- /*
- =============================
- idGameBustOutWindow::ClearBoard
- =============================
- */
- void idGameBustOutWindow::ClearBoard() {
- int i,j;
- ClearPowerups();
- ballHitCeiling = false;
- for ( i=0; i<BOARD_ROWS; i++ ) {
- for ( j=0; j<board[i].Num(); j++ ) {
- BOBrick *brick = board[i][j];
- brick->ent->removed = true;
- }
- board[i].DeleteContents( true );
- }
- }
- /*
- =============================
- idGameBustOutWindow::ClearPowerups
- =============================
- */
- void idGameBustOutWindow::ClearPowerups() {
- while ( powerUps.Num() ) {
- powerUps[0]->removed = true;
- powerUps.RemoveIndex( 0 );
- }
- }
- /*
- =============================
- idGameBustOutWindow::ClearBalls
- =============================
- */
- void idGameBustOutWindow::ClearBalls() {
- while ( balls.Num() ) {
- balls[0]->removed = true;
- balls.RemoveIndex( 0 );
- }
- ballsInPlay = 0;
- }
- /*
- =============================
- idGameBustOutWindow::LoadBoardFiles
- =============================
- */
- void idGameBustOutWindow::LoadBoardFiles() {
- int i;
- int w,h;
- ID_TIME_T time;
- int boardSize;
- byte *currentBoard;
- if ( boardDataLoaded ) {
- return;
- }
- boardSize = 9 * 12 * 4;
- levelBoardData = (byte*)Mem_Alloc( boardSize * numLevels, TAG_CRAP );
- currentBoard = levelBoardData;
- for ( i=0; i<numLevels; i++ ) {
- byte *pic;
- idStr name = "guis/assets/bustout/level";
- name += (i+1);
- name += ".tga";
- R_LoadImage( name, &pic, &w, &h, &time, false );
- if ( pic != NULL ) {
- if ( w != 9 || h != 12 ) {
- common->DWarning( "Hell Bust-Out level image not correct dimensions! (%d x %d)", w, h );
- }
- memcpy( currentBoard, pic, boardSize );
- Mem_Free(pic);
- }
- currentBoard += boardSize;
- }
- boardDataLoaded = true;
- }
- /*
- =============================
- idGameBustOutWindow::SetCurrentBoard
- =============================
- */
- void idGameBustOutWindow::SetCurrentBoard() {
- int i,j;
- int realLevel = ((currentLevel-1) % numLevels);
- int boardSize;
- byte *currentBoard;
- float bx = 11.f;
- float by = 24.f;
- float stepx = 619.f / 9.f;
- float stepy = ( 256 / 12.f );
- boardSize = 9 * 12 * 4;
- currentBoard = levelBoardData + ( realLevel * boardSize );
- for ( j=0; j<BOARD_ROWS; j++ ) {
- bx = 11.f;
- for ( i=0; i<9; i++ ) {
- int pixelindex = (j*9*4) + (i*4);
- if ( currentBoard[pixelindex + 3] ) {
- idVec4 bcolor;
- float pType = 0.f;
- BOEntity *bent = new (TAG_OLD_UI) BOEntity( this );
- BOBrick *brick = new (TAG_OLD_UI) BOBrick( bent, bx, by, stepx, stepy );
- bcolor.x = currentBoard[pixelindex + 0] / 255.f;
- bcolor.y = currentBoard[pixelindex + 1] / 255.f;
- bcolor.z = currentBoard[pixelindex + 2] / 255.f;
- bcolor.w = 1.f;
- brick->SetColor( bcolor );
- pType = currentBoard[pixelindex + 3] / 255.f;
- if ( pType > 0.f && pType < 1.f ) {
- if ( pType < 0.5f ) {
- brick->powerup = POWERUP_BIGPADDLE;
- } else {
- brick->powerup = POWERUP_MULTIBALL;
- }
- }
- board[j].Append( brick );
- numBricks++;
- }
- bx += stepx;
- }
- by += stepy;
- }
- }
- /*
- =============================
- idGameBustOutWindow::CreateNewBall
- =============================
- */
- BOEntity * idGameBustOutWindow::CreateNewBall() {
- BOEntity *ball;
- ball = new (TAG_OLD_UI) BOEntity( this );
- ball->position.x = 300.f;
- ball->position.y = 416.f;
- ball->SetMaterial( "game/bustout/ball" );
- ball->SetSize( BALL_RADIUS*2.f, BALL_RADIUS*2.f );
- ball->SetVisible( false );
- ballsInPlay++;
- balls.Append( ball );
- entities.Append( ball );
- return ball;
- }
- /*
- =============================
- idGameBustOutWindow::CreatePowerup
- =============================
- */
- BOEntity * idGameBustOutWindow::CreatePowerup( BOBrick *brick ) {
- BOEntity *powerEnt = new (TAG_OLD_UI) BOEntity( this );
- powerEnt->position.x = brick->x;
- powerEnt->position.y = brick->y;
- powerEnt->velocity.x = 0.f;
- powerEnt->velocity.y = 64.f;
- powerEnt->powerup = brick->powerup;
- switch( powerEnt->powerup ) {
- case POWERUP_BIGPADDLE:
- powerEnt->SetMaterial( "game/bustout/powerup_bigpaddle" );
- break;
- case POWERUP_MULTIBALL:
- powerEnt->SetMaterial( "game/bustout/powerup_multiball" );
- break;
- default:
- powerEnt->SetMaterial( "textures/common/nodraw" );
- break;
- }
- powerEnt->SetSize( 619/9, 256/12 );
- powerEnt->SetVisible( true );
- powerUps.Append( powerEnt );
- entities.Append( powerEnt );
- return powerEnt;
- }
- /*
- =============================
- idGameBustOutWindow::UpdatePowerups
- =============================
- */
- void idGameBustOutWindow::UpdatePowerups() {
- idVec2 pos;
- for ( int i=0; i < powerUps.Num(); i++ ) {
- BOEntity *pUp = powerUps[i];
- // Check for powerup falling below screen
- if ( pUp->position.y > 480 ) {
- powerUps.RemoveIndex( i );
- pUp->removed = true;
- continue;
- }
- // Check for the paddle catching a powerup
- pos.x = pUp->position.x + ( pUp->width / 2 );
- pos.y = pUp->position.y + ( pUp->height / 2 );
- collideDir_t collision = paddle->checkCollision( pos, pUp->velocity );
- if ( collision != COLLIDE_NONE ) {
- BOEntity *ball;
- // Give the powerup to the player
- switch( pUp->powerup ) {
- case POWERUP_BIGPADDLE:
- bigPaddleTime = gui->GetTime() + 15000;
- break;
- case POWERUP_MULTIBALL:
- // Create 2 new balls in the spot of the existing ball
- for ( int b=0; b<2; b++ ) {
- ball = CreateNewBall();
- ball->position = balls[0]->position;
- ball->velocity = balls[0]->velocity;
- if ( b == 0 ) {
- ball->velocity.x -= 35.f;
- } else {
- ball->velocity.x += 35.f;
- }
- ball->velocity.NormalizeFast();
- ball->velocity *= ballSpeed;
- ball->SetVisible( true );
- }
- break;
- default:
- break;
- }
- // Play the sound
- common->SW()->PlayShaderDirectly( "arcade_powerup", S_UNIQUE_CHANNEL );
- // Remove it
- powerUps.RemoveIndex( i );
- pUp->removed = true;
- }
- }
- }
- /*
- =============================
- idGameBustOutWindow::UpdatePaddle
- =============================
- */
- void idGameBustOutWindow::UpdatePaddle() {
- idVec2 cursorPos;
- float oldPos = paddle->x;
- cursorPos.x = gui->CursorX();
- cursorPos.y = gui->CursorY();
- if ( bigPaddleTime > gui->GetTime() ) {
- paddle->x = cursorPos.x - 80.f;
- paddle->width = 160;
- paddle->ent->width = 160;
- paddle->ent->SetMaterial( "game/bustout/doublepaddle" );
- } else {
- paddle->x = cursorPos.x - 48.f;
- paddle->width = 96;
- paddle->ent->width = 96;
- paddle->ent->SetMaterial( "game/bustout/paddle" );
- }
- paddle->ent->position.x = paddle->x;
- paddleVelocity = (paddle->x - oldPos);
- }
- /*
- =============================
- idGameBustOutWindow::UpdateBall
- =============================
- */
- void idGameBustOutWindow::UpdateBall() {
- int ballnum,i,j;
- bool playSoundBounce = false;
- bool playSoundBrick = false;
- static int bounceChannel = 1;
- if ( ballsInPlay == 0 ) {
- return;
- }
- for ( ballnum = 0; ballnum < balls.Num(); ballnum++ ) {
- BOEntity *ball = balls[ballnum];
- // Check for ball going below screen, lost ball
- if ( ball->position.y > 480.f ) {
- ball->removed = true;
- continue;
- }
- // Check world collision
- if ( ball->position.y < 20 && ball->velocity.y < 0 ) {
- ball->velocity.y = -ball->velocity.y;
- // Increase ball speed when it hits ceiling
- if ( !ballHitCeiling ) {
- ballSpeed *= 1.25f;
- ballHitCeiling = true;
- }
- playSoundBounce = true;
- }
- if ( ball->position.x > 608 && ball->velocity.x > 0 ) {
- ball->velocity.x = -ball->velocity.x;
- playSoundBounce = true;
- } else if ( ball->position.x < 8 && ball->velocity.x < 0 ) {
- ball->velocity.x = -ball->velocity.x;
- playSoundBounce = true;
- }
- // Check for Paddle collision
- idVec2 ballCenter = ball->position + idVec2( BALL_RADIUS, BALL_RADIUS );
- collideDir_t collision = paddle->checkCollision( ballCenter, ball->velocity );
- if ( collision == COLLIDE_UP ) {
- if ( ball->velocity.y > 0 ) {
- idVec2 paddleVec( paddleVelocity*2, 0 );
- float centerX;
-
- if ( bigPaddleTime > gui->GetTime() ) {
- centerX = paddle->x + 80.f;
- } else {
- centerX = paddle->x + 48.f;
- }
- ball->velocity.y = -ball->velocity.y;
- paddleVec.x += (ball->position.x - centerX) * 2;
- ball->velocity += paddleVec;
- ball->velocity.NormalizeFast();
- ball->velocity *= ballSpeed;
- playSoundBounce = true;
- }
- } else if ( collision == COLLIDE_LEFT || collision == COLLIDE_RIGHT ) {
- if ( ball->velocity.y > 0 ) {
- ball->velocity.x = -ball->velocity.x;
- playSoundBounce = true;
- }
- }
- collision = COLLIDE_NONE;
- // Check for collision with bricks
- for ( i=0; i<BOARD_ROWS; i++ ) {
- int num = board[i].Num();
- for ( j=0; j<num; j++ ) {
- BOBrick *brick = (board[i])[j];
- collision = brick->checkCollision( ballCenter, ball->velocity );
- if ( collision ) {
- // Now break the brick if there was a collision
- brick->isBroken = true;
- brick->ent->fadeOut = true;
- if ( brick->powerup > POWERUP_NONE ) {
- verify( CreatePowerup( brick ) != NULL );
- }
- numBricks--;
- gameScore += 100;
- updateScore = true;
- // Go ahead an forcibly remove the last brick, no fade
- if ( numBricks == 0 ) {
- brick->ent->removed = true;
- }
- board[i].Remove( brick );
- break;
- }
- }
- if ( collision ) {
- playSoundBrick = true;
- break;
- }
- }
- if ( collision == COLLIDE_DOWN || collision == COLLIDE_UP ) {
- ball->velocity.y *= -1;
- } else if ( collision == COLLIDE_LEFT || collision == COLLIDE_RIGHT ) {
- ball->velocity.x *= -1;
- }
- if ( playSoundBounce ) {
- common->SW()->PlayShaderDirectly( "arcade_ballbounce", bounceChannel );
- } else if ( playSoundBrick ) {
- common->SW()->PlayShaderDirectly( "arcade_brickhit", bounceChannel );
- }
- if ( playSoundBounce || playSoundBrick ) {
- bounceChannel++;
- if ( bounceChannel == 4 ) {
- bounceChannel = 1;
- }
- }
- }
- // Check to see if any balls were removed from play
- for ( ballnum=0; ballnum<balls.Num(); ballnum++ ) {
- if ( balls[ballnum]->removed ) {
- ballsInPlay--;
- balls.RemoveIndex( ballnum );
- }
- }
- // If all the balls were removed, update the game accordingly
- if ( ballsInPlay == 0 ) {
- if ( ballsRemaining == 0 ) {
- gameOver = true;
- // Game Over sound
- common->SW()->PlayShaderDirectly( "arcade_sadsound", S_UNIQUE_CHANNEL );
- } else {
- ballsRemaining--;
- // Ball was lost, but game is not over
- common->SW()->PlayShaderDirectly( "arcade_missedball", S_UNIQUE_CHANNEL );
- }
- ClearPowerups();
- updateScore = true;
- }
- }
- /*
- =============================
- idGameBustOutWindow::UpdateGame
- =============================
- */
- void idGameBustOutWindow::UpdateGame() {
- int i;
- if ( onNewGame ) {
- ResetGameState();
- // Create Board
- SetCurrentBoard();
- gamerunning = true;
- }
- if ( onContinue ) {
- gameOver = false;
- ballsRemaining = 3;
- onContinue = false;
- }
- if ( onNewLevel ) {
- currentLevel++;
- ClearBoard();
- SetCurrentBoard();
- ballSpeed = BALL_SPEED * ( 1.f + ((float)currentLevel/5.f) );
- if ( ballSpeed > BALL_MAXSPEED ) {
- ballSpeed = BALL_MAXSPEED;
- }
- updateScore = true;
- onNewLevel = false;
- }
- if(gamerunning == true) {
- UpdatePaddle();
- UpdateBall();
- UpdatePowerups();
- for( i = 0; i < entities.Num(); i++ ) {
- entities[i]->Update( timeSlice, gui->GetTime() );
- }
- // Delete entities that need to be deleted
- for( i = entities.Num()-1; i >= 0; i-- ) {
- if( entities[i]->removed ) {
- BOEntity* ent = entities[i];
- delete ent;
- entities.RemoveIndex(i);
- }
- }
- if ( updateScore ) {
- UpdateScore();
- updateScore = false;
- }
- }
- }
|