www.pudn.com > sxdl.zip > bounce.cpp


#include "bounce.h" 
 
Game game ; 
 
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) 
{ 
    return game.FrameworkRun ( hInst ) ; 
} 
 
CBasicSprite * Game::Sprites  [ 12 ] ;  
CBasicSprite * Game::BrickSprites  [ 12 ] ;  
 
Resource Game::Resources [ ] =  
{ 
	{ NewLevel  ,	Resource::Sound   , NULL , true , "powerup.wav" } ,   
	{ WallHit   ,	Resource::Sound   , NULL , true , "wallhit.wav" } ,   
	{ BrickHit  ,	Resource::Sound   , NULL , true , "brickhit.wav" } ,   
	{ NewBall   ,	Resource::Sound   , NULL , true , "newball.wav" } ,   
	{ GameOver  ,	Resource::Sound   , NULL , true , "gameover.wav" } ,   
	{ MidiMusic ,	Resource::Music   , NULL , true , "onestop.mid" } ,   
	{ Flare     ,   Resource::Texture , NULL , true , "ball.png" } ,   
	{ Brick     ,   Resource::Texture , NULL , true , "brick.png" } ,   
	{ Anna1     ,   Resource::Texture , NULL , true , "anna1.jpg" } ,   
	{ Anna2     ,   Resource::Texture , NULL , true , "anna2.jpg" } ,   
	// Must end with a zero id  
	{ Null , Resource::Null , NULL , false , NULL } ,   
} ;  
 
void Game::OnStartup ( void )  
{ 
	FrameworkName ( TEXT ( "So Cool Bouncing Balls!" ) ) ;  
	FrameworkWindow ( 620 , 620 , false ) ;   
	Media.Table ( Resources ) ;  
} 
 
void Game::OnCreateGame ( void )  
{ 
	Timing.Speed ( 1.0f ) ; // game time is real time 
	Music.Play ( ( int ) MidiMusic ) ;  
	// Create 22 rendering objects 
	for ( int i = 0 ; i < 11 ; ++ i )  
	{  
		// define white blue, red, gold, green, etc colors for sprites, all with about 50% alpha  
		Color Colors [ 11 ] =  
		{  
			0x90FFFFFF ,  
			0x9000EECC , 0x9022EE00 , 0x90CC0033 , 0x90AA0099 , 0x90EEAA00 ,  
			0x9022AA77 , 0x90118833 , 0x90AA1111 , 0x90881166 , 0x90AA7711  
		} ;  
		// this tells SxDL to be ready to render objects of that kind. 
		// here SxDL will need to load a texture and create a VB 
		Sprites [ i ] =  
			// resource , color, tex offset, tex size 
			new CBasicSprite ( Flare , Colors [ i ] ,  0 ,  0 , 64 , 64 ) ;  
		BrickSprites  [ i ] =  
			// resource , color, tex offset, tex size 
			new CBasicSprite ( Brick , Colors [ i ] ,  0 ,  0 , 64 , 64 ) ;  
	} ;  
	// create four walls 
	new CWall ( -310 ,    0 ,  20 , 620 ) ;  
	new CWall (  310 ,    0 ,  20 , 620 ) ;  
	new CWall (    0 , -310 , 620 ,  20 ) ;  
	new CWall (    0 ,  310 , 620 ,  20 ) ;  
	// create one pad  
	Pad = new CPad ( 0 , - 280 , 200 , 20 ) ;  
	// Hide the Pad until the game really starts  
	Pad->WillRenderLike ( NullRenderer ) ;  
	// create the colliders 
	Collider_BallsWalls   = new CCollider ( Balls , Walls ) ;  
	Collider_BallsBalls   = new CCollider ( Balls , Balls ) ;  
	Collider_BallsBricks  = new CCollider ( Balls , Bricks ) ;  
	Collider_BallsGround  = new CCollider ( Balls , Ground ) ;  
	Collider_BallsPads    = new CCollider ( Balls , Pads ) ;  
	Collider_BricksGround = new CCollider ( Bricks , Ground ) ;  
	Collider_BricksPads   = new CCollider ( Bricks , Pads ) ;  
	Collider_WallsPads    = new CCollider ( Walls , Pads ) ;  
	// Start in game mode  
	GameMode = true ; 
	// Register the F2 key 
	Input.Register ( CInput::NewGame ) ;  
	// Create a font  
	Font = new CFont ( _T("Impact"), 24 , CFont::Bold ) ;  
	Backdrop = new CBackground ( Tools.Toss ( ) ? Anna1 : Anna2 , 0xFFffFFff ) ;  
	Backdrop->Enable ( ) ;  
} 
 
void Game::OnNewGame ( void )  
{ 
	// Set up scoring  
	Score = 0 ;  
	Level = 0 ;  
	// Delete all stray balls and bricks if any  
	Clean ( ( int ) Balls ) ;  
	Clean ( ( int ) Bricks ) ;  
	BricksInGame = 0 ;  
	// Move the pad down in the middle, stop it.  
	Pad->Position = Vector3 ( 0.0f , -260.0f , 0.0f ) ;  
	Pad->Velocity = Vector3 ( 0.0f , 0.0f , 0.0f ) ;  
	// assign its renderer to the pad 
	Pad->WillRenderLike ( BrickSprites [ 0 ] ) ;  
	// Run the colliders  
	Collider_BallsWalls   ->Enable ( ) ;  
	Collider_BallsBalls   ->Enable ( ) ;  
	Collider_BallsBricks  ->Enable ( ) ;  
	Collider_BallsGround  ->Enable ( ) ;  
	Collider_BallsPads    ->Enable ( ) ; 
	Collider_BricksGround ->Enable ( ) ; 
	Collider_BricksPads   ->Enable ( ) ; 
	Collider_WallsPads    ->Enable ( ) ; 
	// restart time  
	Timing.SetTimer ( StartGame , 1.0f , true ) ; // one shot  
	// create the first level  
	OnNewLevel ( ) ;  
	// drop the bg pic  
	Backdrop->Enable ( false ) ;  
	// Run, baby, run  
	GameMode = true ;  
} 
 
void Game::OnEndGame ( void )  
{ 
	// stop creating new balls  
	Timing.KillTimer ( CreateNewBall ) ;  
	// Disable the collision manager  
	Collider_BallsWalls   ->Enable ( false ) ;  
	Collider_BallsBalls   ->Enable ( false ) ;  
	Collider_BallsBricks  ->Enable ( false ) ;  
	Collider_BallsGround  ->Enable ( false ) ;  
	Collider_BallsPads    ->Enable ( false ) ; 
	Collider_BricksGround ->Enable ( false ) ; 
	Collider_BricksPads   ->Enable ( false ) ; 
	Collider_WallsPads    ->Enable ( false ) ; 
} 
 
void Game::OnNewLevel ( void )  
{ 
	Level ++ ;  
	CreateBricks ( ) ;  
	Timing.SetTimer ( CreateNewBall , ( float ) Level / 4.0f + 1.75f , false ) ; // periodic  
} 
 
inline void Game::CreateBricks ( void )  
{ 
	// create rows of 13 bricks each  
	int Rows = 5 + Level ;  
	const int Cols = 15 ;  
	for ( int row = 0 ; row < Rows ; ++ row )  
	{ 
		const int cx = 40 ;  
		const int cy = 20 ;  
		// Game was too hard with the sidemost columns 
		for ( int col = 1 ; col < Cols - 1 ; ++ col )  
		{ 
			int x = -300 + col * cx + cx / 2 ;  
			int y =  100 + row * cy + cy / 2 ;  
			new CBrick ( row % 5 , BrickSprites  [ 1 + row % 5  ] , x , y , cx - 2 , cy - 2 ) ;   
		}  
	} ;  
	BricksInGame = Rows * ( Cols - 2 ) ;  
} 
 
inline void Game::CreateBall ( void )  
{ 
	int SpriteIndex = ( int ) Tools.randf ( 1.01f , 9.99f ) ;  
	int x = ( int ) Tools.randf ( -50.0f , 50.0f ) ;  
	int y = ( int ) Tools.randf (  50.0f , 250.0f ) ;  
	CBall * ball = new CBall ( Sprites [ SpriteIndex ] ,  x ,  y ,  25 ,  25 ) ;  
	float s = Tools.randf ( 180.0f , 220.0f ) ;  
	Vector3 V = s * Tools.randv ( ) ;  
	V.z = 0.0f ;  
	ball->Velocity = V ;  
} 
 
void Game::OnTimer ( int TimerId )  
{ 
	switch ( TimerId )  
	{ 
	case StartGame :  
		Timing.SetTimer ( CreateNewBall , 2.0f , false ) ; // periodic  
		break ;  
 
	case CreateNewBall :  
		Sound.Play ( NewBall ) ;  
		CreateBall ( ) ;  
		break ;  
	} ; 
}  
 
CWall::CWall ( int x , int y , int cx , int cy )  
{ 
	Family   = ( int ) Game::Walls ;  
	if ( y < 0 )  
		Family   = ( int ) Game::Ground ;  
	Mass     = 0.0f ;  
	Position = Vector3 ( ( float )  x , ( float )  y , 0.0f ) ;  
	Normal   = - Position ;  
	SxDLVec3Normalize ( Normal ) ;  
	Scale    = Vector3 ( ( float ) cx , ( float ) cy , 0.0f ) ;  
	WillRenderLike ( Game::BrickSprites [ 1 ] ) ;  
	DoWorldMatrix ( ) ;  
	Activate ( true , true ) ;  
}  
 
void CWall::OnCollide ( CEntity * CollidingEntity )  
{ 
	if ( CollidingEntity->Family == Game::Pads )  
	{ 
		CPad * pad = ( CPad * ) CollidingEntity ;  
		pad->Velocity = Vector3 ( 0.0f , 0.0f , 0.0f ) ;  
		pad->Position += 2.0f * Normal ;  
	} ;  
}  
 
CBrick::CBrick ( int Hits , CBasicSprite * Sprite , int x , int y , int cx , int cy )  
{ 
	HitPoints = ( float ) Hits ;  
	Family   = ( int ) Game::Bricks ;  
	Mass     = 0.14f ;  
	Position = Vector3 ( ( float )  x , ( float )  y , 0.0f ) ;  
	Scale    = Vector3 ( ( float ) cx , ( float ) cy , 0.0f ) ;  
	WillRenderLike ( Sprite ) ;  
	Activate ( ) ;  
}  
 
void CBrick::OnDying ( )  
{ 
	game.BrickDying ( ) ;  
}  
 
inline void Game::BrickDying ( void )  
{ 
	-- BricksInGame ;  
	Score += Level ;  
	if ( BricksInGame == 0 )  
	{ 
		Score += 50 * Level ;  
		Sound.Play ( NewLevel ) ;  
		OnNewLevel ( ) ;  
	} ;  
}  
 
inline void Game::OnGameOver ( void )  
{ 
	Sound.Play ( GameOver ) ;  
	OnEndGame ( ) ;   
	UserInterface.RunMenu ( UserInterface.GameOverLost ) ;  
}  
 
void CBrick::OnCollide ( CEntity * CollidingEntity )  
{ 
	if ( ( CollidingEntity->Family == Game::Ground ) ||  
	     ( CollidingEntity->Family == Game::Pads ) )  
	{ 
		// Game over !  
		game.OnGameOver ( ) ;  
	} ;  
}  
 
 
CPad::CPad ( int x , int y , int cx , int cy )  
{ 
	Family   = ( int ) Game::Pads ;  
	Mass     = 0.0 ;  
	Position = Vector3 ( ( float )  x , ( float )  y , 0.0f ) ;  
	Scale    = Vector3 ( ( float ) cx , ( float ) cy , 0.0f ) ;  
	WillRenderLike ( Game::BrickSprites [ 0 ] ) ;  
	Activate ( ) ;  
	game.Input.Register ( this , CInput::UpDown ) ;  
	game.Input.Register ( this , CInput::LeftRight ) ;  
}  
 
inline void CPad::OnUserInput ( CInput::VirtualKeys VirtualKey , float ElapsedTime , float Value )  
{ 
	if ( VirtualKey == CInput::UpDown )    OnUpDown    ( ElapsedTime , Value ) ;  
	if ( VirtualKey == CInput::LeftRight ) OnLeftRight ( ElapsedTime , Value ) ;  
}  
 
void CPad::OnUpDown    ( float ElapsedTime , float Value )  
{ 
	Position += Vector3 ( 0.0f , 200.0f * Value * ElapsedTime , 0.0f ) ;  
	const float MaxY = - 280.0f ;  
	if ( Position.y < MaxY  )  
	{	 
		Position.y = MaxY ;  
		return ;  
	} ;  
	if ( Position.y > - MaxY  )  
	{	Position.y = - MaxY ;  
		return ;  
	} ;  
}  
 
void CPad::OnLeftRight ( float ElapsedTime , float Value )  
{ 
	Position -= Vector3 ( 1000.0f * Value * ElapsedTime , 0.0f , 0.0f ) ;  
}  
 
CBall::CBall ( CBasicSprite * _Sprite , int x , int y , int cx , int cy )  
{ 
	Sprite   = _Sprite ;  
	Family   = ( int ) Game::Balls ;  
	Mass     = 190.0f ;  
	Position = Vector3 ( ( float )  x , ( float )  y , 0.0f ) ;  
	SizeRatio = 1.2f ;  
	InitialScale = Vector3 ( ( float ) cx , ( float ) cy , 0.0f ) ;  
	Scale = SizeRatio * InitialScale ;  
	Velocity = Vector3 ( ( float ) cx , ( float ) cy , 0.0f ) ;  
	WillRenderLike ( Sprite ) ;  
	Activate ( ) ;  
}  
 
void CBall::OnCollide ( CEntity * CollidingEntity )  
{ 
	if ( CollidingEntity->Family == Game::Walls )  
	{ 
		game.Sound.Play ( Game::WallHit ) ;  
		CWall * wall = ( CWall * ) CollidingEntity ;  
		DoBounce ( wall->Normal ) ;  
	} ;  
	if ( CollidingEntity->Family == Game::Ground )  
	{ 
		CWall * wall = ( CWall * ) CollidingEntity ;  
		SizeRatio -= 0.15f ;  
		if ( SizeRatio < 0.3f )  
			LifeTime = 0.1f ;  
		else 
		{ 
			Scale = SizeRatio * InitialScale ;  
			DoBounce ( wall->Normal ) ;  
		} ;  
	} ;  
	if ( CollidingEntity->Family == Game::Balls )  
	{ 
		CBall * ball = ( CBall * ) CollidingEntity ;  
		if ( Sprite == ball->Sprite )  
		{ 
			LifeTime = 0.1f ;  
			Vector3 V = 500.0f * game.Tools.randv ( ) ;  
			V.z = 0.0f ;  
			CBall * ball = new CBall ( Game::Sprites [ 0 ] ,  0 ,  0 ,  5 ,  5 ) ;  
			ball->Velocity = V ;  
			ball->Position = Position ;  
			ball->Family   = 0 ;  
			ball->LifeTime = 0.1f ;  
		} ; 
	} ;  
	if ( CollidingEntity->Family == Game::Bricks )  
	{ 
		game.Sound.Play ( Game::BrickHit ) ;  
		CBrick * brick = ( CBrick * ) CollidingEntity ;  
		brick->HitPoints -= 1.0f ;  
		Vector3 Normal = Position - brick->Position ;  
		DoBounce ( Normal ) ;  
	} ;  
	if ( CollidingEntity->Family == Game::Pads )  
	{ 
		CPad * pad = ( CPad * ) CollidingEntity ;  
		Vector3 Normal = Vector3 ( 0.0f , pad->Scale.y , 0.0f ) ;  
		DoBounce ( Normal ) ;  
	} ;  
}  
 
void Game::OnRenderText ( float ElapsedTime , float AbsoluteTime )  
{ 
	D3DCOLOR fontColor = D3DCOLOR_ARGB(200,128,255,200 ); 
	float a = 150.0f + 100.0f * cosf ( AbsoluteTime *  7.0f ) ;  
	float r = 150.0f + 100.0f * cosf ( AbsoluteTime *  5.0f ) ;  
	float g = 150.0f + 100.0f * cosf ( AbsoluteTime * 11.0f ) ;  
	float b = 150.0f + 100.0f * cosf ( AbsoluteTime *  3.0f ) ;  
	Color FadingColor = D3DCOLOR_ARGB ( ( int ) a , ( int ) r , ( int ) g , ( int ) b ) ; 
 
	if ( Level > 0 )  
	{ 
		TCHAR szMsg[MAX_PATH] ; 
		_sntprintf( szMsg, MAX_PATH, _T("Level: %d - Score: %d"), Level , Score ) ; 
		Font->DrawTextScaled ( -0.2f , 0.95f , 0.07f , 0.07f , fontColor, szMsg ); 
	}  
	else  
	{ 
		if ( GameMode )  
		{  
			Font->DrawTextScaled ( 0.0f , 0.4f , 0.10f , 0.10f , FadingColor, "SxDL ~ Bouncing Balls" , CFont::Centered_X ); 
			Font->DrawTextScaled ( 0.0f , 0.2f , 0.05f , 0.05f , fontColor, "Press F2 to start the game!" , CFont::Centered_X ); 
		} ;  
	}  
}