diff --git a/stepmania/src/Actor.cpp b/stepmania/src/Actor.cpp new file mode 100644 index 0000000000..078e28704f --- /dev/null +++ b/stepmania/src/Actor.cpp @@ -0,0 +1,172 @@ +#include "stdafx.h" // testing updates +//----------------------------------------------------------------------------- +// File: Actor.cpp +// +// Desc: Base class for all objects that appear on the screen. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#include "Actor.h" +#include + + +Actor::Actor() +{ + Init(); +} + +void Actor::Init() +{ + m_size = D3DXVECTOR2( 0, 0 ); + m_pos = D3DXVECTOR2( 0, 0 ); + m_rotation = D3DXVECTOR3( 0, 0, 0 ); + m_scale = D3DXVECTOR2( 1, 1 ); + m_color = D3DXCOLOR( 1, 1, 1, 1 ); + + m_start_pos = m_end_pos = D3DXVECTOR2( 0.0f, 0.0f ); + m_start_rotation= m_end_rotation = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); + m_start_scale = m_end_scale = D3DXVECTOR2( 1.0f, 1.0f ); + m_start_color = m_end_color = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ); + + m_TweenType = no_tween; + m_fTweenTime = 0.0f; + m_fTimeIntoTween = 0.0f; +} + + +void Actor::Update( const FLOAT &fDeltaTime ) +{ +// RageLog( "Actor::Update( %f )", fDeltaTime ); + + // update tweening + if( m_TweenType != no_tween ) // we are performing some type of tweening + { + m_fTimeIntoTween += fDeltaTime; + + if( m_fTimeIntoTween > m_fTweenTime ) // The tweening is over. Stop the tweening + { + m_pos = m_end_pos; + m_scale = m_end_scale; + m_rotation = m_end_rotation; + m_color = m_end_color; + m_TweenType = no_tween; + } + else // Tweening. Recalcute the curent position. + { + FLOAT fPercentThroughTween = m_fTimeIntoTween / m_fTweenTime; + + // distort the percentage if appropriate + if( m_TweenType == tween_bias_begin ) + fPercentThroughTween = (FLOAT) sqrt( fPercentThroughTween ); + else if( m_TweenType == tweening_bias_end ) + fPercentThroughTween = fPercentThroughTween * fPercentThroughTween; + + + m_pos = m_start_pos + (m_end_pos - m_start_pos )*fPercentThroughTween; + m_scale = m_start_scale + (m_end_scale - m_start_scale )*fPercentThroughTween; + m_rotation = m_start_rotation+ (m_end_rotation - m_start_rotation)*fPercentThroughTween; + m_color = m_start_color*(1.0f-fPercentThroughTween) + m_end_color*(fPercentThroughTween); + } + + } // end if m_TweenType != no_tween + + +} + + +void Actor::TweenTo( FLOAT time, FLOAT x, FLOAT y, FLOAT zoom, FLOAT rot, D3DXCOLOR col, TweenType tt ) +{ + // set our tweeen starting values to the current position + m_start_pos = m_pos; + m_start_scale = m_scale; + m_start_rotation = m_rotation; + m_start_color = m_color; + + // set the ending tweening position to what the user asked for + m_end_pos.x = (FLOAT)x; + m_end_pos.y = (FLOAT)y; + m_end_scale.x = zoom; + m_end_scale.y = zoom; + m_end_rotation.z = rot; + m_end_color = col; + m_TweenType = tt; + m_fTweenTime = time; + m_fTimeIntoTween = 0; + +} + +void Actor::SetTweening( FLOAT time, TweenType tt ) +{ + // set our tweeen starting and ending values to the current position + m_start_pos = m_end_pos = m_pos; + m_start_scale = m_end_scale = m_scale; + m_start_rotation = m_end_rotation = m_rotation; + m_start_color = m_end_color = m_color; + + m_TweenType = tt; + m_fTweenTime = time; + m_fTimeIntoTween = 0; +} + +void Actor::SetTweenX( FLOAT x ) { m_end_pos.x = x; } +void Actor::SetTweenY( FLOAT y ) { m_end_pos.y = y; } +void Actor::SetTweenXY( FLOAT x, FLOAT y ) { SetTweenX(x); SetTweenY(y); } +void Actor::SetTweenZoom( FLOAT zoom ) { m_end_scale.x = zoom; m_end_scale.y = zoom; } +void Actor::SetTweenRotationX( FLOAT r ) { m_end_rotation.x = r; } +void Actor::SetTweenRotationY( FLOAT r ) { m_end_rotation.y = r; } +void Actor::SetTweenRotationZ( FLOAT r ) { m_end_rotation.z = r; } +void Actor::SetTweenColor( D3DXCOLOR c ) { m_end_color = c; } + + +void Actor::ScaleTo( LPRECT pRect, StretchType st ) +{ + // width and height of rectangle + int rect_width = RECTWIDTH(*pRect); + int rect_height = RECTHEIGHT(*pRect); + + // center of the rectangle + int rect_cx = pRect->left + rect_width/2; + int rect_cy = pRect->top + rect_height/2; + + // zoom factor needed to scale the Actor to fill the rectangle + FLOAT fNewZoomX = (FLOAT)fabs(rect_width / m_size.x); + FLOAT fNewZoomY = (FLOAT)fabs(rect_height / m_size.y); + + if( rect_width < 0 ) SetRotationY( D3DX_PI ); + if( rect_height < 0 ) SetRotationX( D3DX_PI ); + + FLOAT fNewZoom; + switch( st ) + { + case cover: + fNewZoom = fNewZoomX>fNewZoomY ? fNewZoomX : fNewZoomY; // use larger zoom + break; + case fit_inside: + fNewZoom = fNewZoomX>fNewZoomY ? fNewZoomY : fNewZoomX; // use smaller zoom + break; + } + + SetXY( (FLOAT)rect_cx, (FLOAT)rect_cy ); + SetZoom( fNewZoom ); +} + + +void Actor::StretchTo( LPRECT pRect ) +{ + // width and height of rectangle + int rect_width = RECTWIDTH(*pRect); + int rect_height = RECTHEIGHT(*pRect); + + // center of the rectangle + int rect_cx = pRect->left + rect_width/2; + int rect_cy = pRect->top + rect_height/2; + + // zoom factor needed to scale the Actor to fill the rectangle + FLOAT fNewZoomX = (FLOAT)fabs(rect_width / m_size.x); + FLOAT fNewZoomY = (FLOAT)fabs(rect_height / m_size.y); + + SetXY( (FLOAT)rect_cx, (FLOAT)rect_cy ); + m_scale.x = fNewZoomX; + m_scale.y = fNewZoomY; +} diff --git a/stepmania/src/Actor.h b/stepmania/src/Actor.h new file mode 100644 index 0000000000..2f88cad3d7 --- /dev/null +++ b/stepmania/src/Actor.h @@ -0,0 +1,112 @@ +//----------------------------------------------------------------------------- +// File: Actor.h +// +// Desc: Base class for all objects that appear on the screen. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#ifndef _ACTOR_H_ +#define _ACTOR_H_ + +#include "RageUtil.h" + +#include + + + + +class Actor +{ +public: + Actor(); + + enum TweenType { no_tween, tween_linear, tween_bias_begin, tweening_bias_end }; + + virtual void Draw() = 0; + virtual void Update( const FLOAT &fDeltaTime ); + + virtual FLOAT GetX() { return m_pos.x; }; + virtual FLOAT GetY() { return m_pos.y; }; + virtual void SetX( FLOAT x ) { m_pos.x = x; m_TweenType = no_tween; }; + virtual void SetY( FLOAT y ) { m_pos.y = y; m_TweenType = no_tween; }; + virtual void SetXY( FLOAT x, FLOAT y ) { m_pos.x = x; m_pos.y = y; m_TweenType = no_tween; }; + + // height and width vary depending on zoom + virtual FLOAT GetZoomedWidth() { return m_size.x * m_scale.x; } + virtual FLOAT GetZoomedHeight() { return m_size.y * m_scale.y; } + virtual void SetWidth( FLOAT width ){ m_size.x = width; } + virtual void SetHeight( FLOAT height ){ m_size.y = height; } + + virtual FLOAT GetZoom() { return m_scale.x; } + virtual void SetZoom( FLOAT zoom ) { m_scale.x = zoom; m_scale.y = zoom; } + + virtual FLOAT GetRotation() { return m_rotation.z; } + virtual void SetRotation( FLOAT rot ) { m_rotation.z = rot; } + virtual FLOAT GetRotationX() { return m_rotation.x; } + virtual void SetRotationX( FLOAT rot ) { m_rotation.x = rot; } + virtual FLOAT GetRotationY() { return m_rotation.y; } + virtual void SetRotationY( FLOAT rot ) { m_rotation.y = rot; } + + virtual void SetColor( D3DXCOLOR newColor ) { m_color = newColor; }; + virtual D3DXCOLOR GetColor() { return m_color; }; + + virtual void TweenTo( FLOAT time, + FLOAT x, FLOAT y, + FLOAT zoom = 1.0, + FLOAT rot = 0.0, + D3DXCOLOR col = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ), + TweenType tt = tween_linear ); + + virtual void SetTweening( FLOAT time, TweenType tt = tween_linear ); + virtual void SetTweenX( FLOAT x ); + virtual void SetTweenY( FLOAT y ); + virtual void SetTweenXY( FLOAT x, FLOAT y ); + virtual void SetTweenZoom( FLOAT zoom ); + virtual void SetTweenRotationX( FLOAT r ); + virtual void SetTweenRotationY( FLOAT r ); + virtual void SetTweenRotationZ( FLOAT r ); + virtual void SetTweenColor( D3DXCOLOR c ); + + + // NOTE: GetEdge functions don't consider rotation + virtual FLOAT GetLeftEdge() { return m_pos.x - GetZoomedWidth()/2.0f; }; + virtual FLOAT GetRightEdge() { return m_pos.x + GetZoomedWidth()/2.0f; }; + virtual FLOAT GetTopEdge() { return m_pos.y - GetZoomedHeight()/2.0f; }; + virtual FLOAT GetBottomEdge() { return m_pos.y + GetZoomedHeight()/2.0f; }; + + enum StretchType { fit_inside, cover }; + + void ScaleToCover( LPRECT rect ) { ScaleTo( rect, cover ); }; + void ScaleToFitInside( LPRECT rect ) { ScaleTo( rect, fit_inside); }; + void ScaleTo( LPRECT rect, StretchType st ); + + void StretchTo( LPRECT rect ); + +protected: + + void Init(); + + D3DXVECTOR2 m_size; // width, height + D3DXVECTOR2 m_pos; // X-Y coordinate of where the center point will appear on screen + D3DXVECTOR3 m_rotation; // X, Y, and Z m_rotation + D3DXVECTOR2 m_scale; // X and Y zooming + D3DXCOLOR m_color; + + // start and end position for tweening + D3DXVECTOR2 m_start_pos, m_end_pos; + D3DXVECTOR3 m_start_rotation, m_end_rotation; + D3DXVECTOR2 m_start_scale, m_end_scale; + D3DXCOLOR m_start_color, m_end_color; + + // counters for tweening + TweenType m_TweenType; + FLOAT m_fTweenTime; // seconds between Start and End positions/zooms + FLOAT m_fTimeIntoTween; // how long we have been tweening for + +}; + + + +#endif \ No newline at end of file diff --git a/stepmania/src/Background.cpp b/stepmania/src/Background.cpp new file mode 100644 index 0000000000..6fb84fc178 --- /dev/null +++ b/stepmania/src/Background.cpp @@ -0,0 +1,47 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Background.cpp +// +// Desc: Cropped version of the song background displayed in Song Select. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "Background.h" +#include "RageUtil.h" + + +const CString sVisDir = "Visualizations\\"; + + +void Background::LoadFromSong( Song& song ) +{ + Sprite::LoadFromTexture( song.GetBackgroundPath() ); + Sprite::StretchTo( CRect(0,0,640,480) ); + Sprite::SetColor( D3DXCOLOR(0.7f,0.7f,0.7f,1) ); + + CStringArray sVisualizationPaths; + GetDirListing( sVisDir + "*.*", sVisualizationPaths ); + if( sVisualizationPaths.GetSize() > 0 ) // there is at least one visualization + { + int iIndexRandom = rand() % sVisualizationPaths.GetSize(); + + m_sprVis.LoadFromTexture( sVisDir + sVisualizationPaths[iIndexRandom] ); + m_sprVis.StretchTo( CRect(0,0,640,480) ); + m_sprVis.SetBlendMode( TRUE ); + //m_sprVis.SetColor( D3DXCOLOR(1,1,1,0.5f) ); + } +} + +void Background::Update( const FLOAT& fDeltaTime) +{ + Sprite::Update( fDeltaTime ); + m_sprVis.Update( fDeltaTime ); +} + +void Background::Draw() +{ + Sprite::Draw(); + m_sprVis.Draw(); +} \ No newline at end of file diff --git a/stepmania/src/Background.h b/stepmania/src/Background.h new file mode 100644 index 0000000000..45b186b8a9 --- /dev/null +++ b/stepmania/src/Background.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// File: Background.h +// +// Desc: Cropped version of the song background displayed in Song Select. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _Background_H_ +#define _Background_H_ + + +#include "Sprite.h" +#include "Song.h" + + +class Background : public Sprite +{ +public: + void LoadFromSong( Song& song ); + + void Update( const FLOAT& fDeltaTime); + void Draw(); + + Sprite m_sprVis; + +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/Banner.cpp b/stepmania/src/Banner.cpp new file mode 100644 index 0000000000..a6d446d5b6 --- /dev/null +++ b/stepmania/src/Banner.cpp @@ -0,0 +1,61 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Banner.cpp +// +// Desc: The song's banner displayed in Song Select. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + + +#include "RageUtil.h" + +#include "Banner.h" + + + +BOOL Banner::LoadFromSong( Song &song ) +{ + BOOL bResult = Sprite::LoadFromTexture( song.GetBannerPath() ); + if( bResult ) + { + RECT r; + int iImageWidth = this->GetZoomedWidth(); + int iImageHeight = this->GetZoomedHeight(); + + // first find the correct zoom + ::SetRect( &r, 0, 0, BANNER_WIDTH, BANNER_HEIGHT ); + Sprite::ScaleToCover( &r ); + FLOAT fFinalZoom = this->GetZoom(); + + // find which dimension is larger + BOOL bYDimIsLarger = this->GetZoomedHeight() > BANNER_HEIGHT; + + // now crop it + if( !bYDimIsLarger ) // crop X + { + int iScreenPixelsToCrop = (this->GetZoomedWidth() - BANNER_WIDTH) / 2; + int iImagePixelsToCrop = roundf( iScreenPixelsToCrop / fFinalZoom ); + RECT rectNewSrc; + ::SetRect( &rectNewSrc, iImagePixelsToCrop, + 0, + iImageWidth - iImagePixelsToCrop, + iImageHeight ); + Sprite::SetCustomSrcRect( rectNewSrc ); + } + else // crop Y + { + int iScreenPixelsToCrop = (this->GetZoomedHeight() - BANNER_HEIGHT) / 2; + int iImagePixelsToCrop = roundf( iScreenPixelsToCrop / fFinalZoom ); + RECT rectNewSrc; + ::SetRect( &rectNewSrc, 0, + iImagePixelsToCrop, + iImageWidth, + iImageHeight - iImagePixelsToCrop ); + Sprite::SetCustomSrcRect( rectNewSrc ); + } + } + + return TRUE; +} diff --git a/stepmania/src/Banner.h b/stepmania/src/Banner.h new file mode 100644 index 0000000000..38b78541cb --- /dev/null +++ b/stepmania/src/Banner.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// File: Banner.h +// +// Desc: The song's banner displayed in Song Select. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _Banner_H_ +#define _Banner_H_ + + +#include "Sprite.h" +#include "Song.h" + + +#define COMMON_BANNER_TEXTURE_WIDTH 384 +#define COMMON_BANNER_TEXTURE_HEIGHT 110 + +#define BANNER_WIDTH (COMMON_BANNER_TEXTURE_WIDTH/2) +#define BANNER_HEIGHT (COMMON_BANNER_TEXTURE_HEIGHT / 2) + + +class Banner : public Sprite +{ +public: + + BOOL LoadFromSong( Song &song); + +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/BitmapText.cpp b/stepmania/src/BitmapText.cpp new file mode 100644 index 0000000000..4d4128ac4b --- /dev/null +++ b/stepmania/src/BitmapText.cpp @@ -0,0 +1,112 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: BitmapText.cpp +// +// Desc: A font class that draws from a bitmap. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "BitmapText.h" +#include +#include "IniFile.h" + + + +BitmapText::BitmapText() +{ + +} + + + +BOOL BitmapText::LoadFromFontFile( CString sFontFilePath ) +{ + RageLog( "BitmapText::LoadFromFontFile(%s)", sFontFilePath ); + + m_sFontFilePath = sFontFilePath; + + // read font file + IniFile ini; + ini.SetPath( m_sFontFilePath ); + if( !ini.ReadFile() ) + RageError( ssprintf("Error opening Font file: %s.", m_sFontFilePath) ); + + CString sTexturePath = ini.GetValue( "Font", "Texture" ); + if( sTexturePath == "" ) + RageError( ssprintf("Error reading value 'Texture' from %s.", m_sFontFilePath) ); + + this->LoadFromTexture( sTexturePath ); + + // fill in our map from characters to frame no + CString sCharacters = ini.GetValue( "Font", "Characters" ); + if( sCharacters == "" ) + RageError( ssprintf("Error reading value 'Characters' from %s.", m_sFontFilePath) ); + + for( int i=0; iGetNumStates() ) + RageError( ssprintf("The Font %s specifies %d characters, but the Texture has %d frames.", + m_sFontFilePath, sCharacters.GetLength(), (int)this->GetNumStates()) ); + + ResetWidthAndHeight(); + + return TRUE; +} + + +void BitmapText::SetText( CString sText ) +{ + m_sText = sText; + + ResetWidthAndHeight(); +} + + +void BitmapText::Draw() +{ + //RageLog( "BitmapText::Draw()" ); + // UGLY!!!! + + TCHAR c; + UINT uFrameNo; + int iNumChars = m_sText.GetLength(); + int iLeftEdge = this->GetLeftEdge(); + int iOriginalCenterX = (int)this->GetX(); + FLOAT fOriginalWidth = m_size.x; + + int iFrameWidth = (int)( m_pTexture->GetFrameWidth() * this->GetZoom() ); + m_size.x = (FLOAT)iFrameWidth; + + // draw each character in the string + for( int i=0; iSetState( uFrameNo ); + this->SetX( (int)(iLeftEdge + iFrameWidth*(i+0.5f)) ); + + Sprite::Draw(); + } + + this->SetX( iOriginalCenterX ); + m_size.x = fOriginalWidth; +} + + +void BitmapText::ResetWidthAndHeight() +{ + m_size.x = (FLOAT)m_pTexture->GetFrameWidth() * m_sText.GetLength(); + m_size.y = (FLOAT)m_pTexture->GetFrameHeight(); +} diff --git a/stepmania/src/BitmapText.h b/stepmania/src/BitmapText.h new file mode 100644 index 0000000000..f40191a6b7 --- /dev/null +++ b/stepmania/src/BitmapText.h @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// File: BitmapText.h +// +// Desc: A font class that draws from a bitmap. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _BITMAPTEXT_H_ +#define _BITMAPTEXT_H_ + + +//#include "Actor.h" +#include "Sprite.h" +#include "BitmapText.h" + + + + +class BitmapText : public Sprite +{ +public: + BitmapText(); +// virtual ~BitmapText(); + + BOOL LoadFromFontFile( CString sFontFilePath ); + void SetText( CString sText ); + CString GetText() { return m_sText; }; + + virtual void Draw(); + +protected: + void ResetWidthAndHeight(); + + CString m_sFontFilePath; + CString m_sText; // the string that the font is displaying + //Sprite m_Sprite; // holder for the graphic + CMap m_mapCharToFrameNo; +}; + + +#endif \ No newline at end of file diff --git a/stepmania/src/Combo.cpp b/stepmania/src/Combo.cpp new file mode 100644 index 0000000000..0a76f1b675 --- /dev/null +++ b/stepmania/src/Combo.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Combo.cpp +// +// Desc: Combo counter that displays while dancing. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + + +#include "RageUtil.h" + +#include "Combo.h" + + +#define CENTER_X 320 +#define CENTER_Y 240 + + +#define FONT "Fonts\\Font - Arial Bold numbers 30px.font" + +#define COMBO_TWEEN_TIME 0.5f +#define COMBO_SPRITE "Sprites\\Combo.sprite" +#define COMBO_Y (CENTER_Y+60) + + +Combo::Combo() +{ + m_bVisible = FALSE; + + m_sprCombo.LoadFromSpriteFile( COMBO_SPRITE ); + m_textNum.LoadFromFontFile( FONT ); + m_textNum.SetText( "" ); + + SetX( CENTER_X ); +} + +Combo::~Combo() +{ + +} + + +void Combo::SetX( int iNewX ) +{ + m_sprCombo.SetXY( iNewX+40, COMBO_Y ); + m_textNum.SetXY( iNewX-50, COMBO_Y ); +} + +void Combo::Update( const FLOAT &fDeltaTime ) +{ + m_sprCombo.Update( fDeltaTime ); + m_textNum.Update( fDeltaTime ); +} + +void Combo::Draw() +{ + if( m_bVisible ) + { + m_textNum.Draw(); + m_sprCombo.Draw(); + } +} + + +void Combo::SetCombo( int iNum ) +{ + if( iNum <= 4 ) + { + m_bVisible = FALSE; + } + else + { + m_bVisible = TRUE; + + m_textNum.SetText( ssprintf("%d", iNum) ); + m_textNum.SetZoom( 1.0f + iNum/200.0f ); + m_textNum.TweenTo( COMBO_TWEEN_TIME, m_textNum.GetX(), m_textNum.GetY() ); + } + +} + diff --git a/stepmania/src/Combo.h b/stepmania/src/Combo.h new file mode 100644 index 0000000000..b29ca849b4 --- /dev/null +++ b/stepmania/src/Combo.h @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// File: Combo.h +// +// Desc: Combo counter that displays while dancing. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _COMBO_H_ +#define _COMBO_H_ + + +#include "Sprite.h" +#include "BitmapText.h" + +class Combo +{ +public: + Combo(); + ~Combo(); + + void SetX( int iNewX ); + + void Update( const FLOAT &fDeltaTime ); + void Draw(); + + void SetCombo( int iNum ); + +private: + + BOOL m_bVisible; + + Sprite m_sprCombo; + BitmapText m_textNum; +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/IniFile.cpp b/stepmania/src/IniFile.cpp new file mode 100644 index 0000000000..afb911784e --- /dev/null +++ b/stepmania/src/IniFile.cpp @@ -0,0 +1,277 @@ +//----------------------------------------------------------------------------- +// File: IniFile.cpp +// +// Desc: wrapper for reading and writing an .ini file. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#include "stdafx.h" +#include "IniFile.h" +#include "fstream.h" + + +///////////////////////////////////////////////////////////////////// +// Construction/Destruction +///////////////////////////////////////////////////////////////////// + +//default constructor +IniFile::IniFile() +{ +} + +//constructor, can specify pathname here instead of using SetPath later +IniFile::IniFile(CString inipath) +{ + path = inipath; +} + +//default destructor +IniFile::~IniFile() +{ + +} + +///////////////////////////////////////////////////////////////////// +// Public Functions +///////////////////////////////////////////////////////////////////// + +//sets path of ini file to read and write from +void IniFile::SetPath(CString newpath) +{ + path = newpath; +} + +//reads ini file specified using IniFile::SetPath() +//returns true if successful, false otherwise +BOOL IniFile::ReadFile() +{ + CFile file; + CFileStatus status; + if( !file.GetStatus(path,status) ) + return FALSE; + ifstream inifile; + CString readinfo; + inifile.open(path); + int curkey = -1, curval = -1; + if( inifile.fail() ) + { + error = "Unable to open ini file."; + return FALSE; + } + CString keyname, valuename, value; + CString temp; + while( getline(inifile,readinfo) ) + { + if( readinfo != "" ) + { + if( readinfo[0] == '[' && readinfo[readinfo.GetLength()-1] == ']' ) //if a section heading + { + keyname = readinfo; + keyname.TrimLeft('['); + keyname.TrimRight(']'); + } + else //if a value + { + valuename = readinfo.Left(readinfo.Find("=")); + value = readinfo.Right(readinfo.GetLength()-valuename.GetLength()-1); + SetValue(keyname,valuename,value); + } + } + } + inifile.close(); + return 1; +} + +//writes data stored in class to ini file +void IniFile::WriteFile() +{ + ofstream inifile; + inifile.open(path); + + // foreach key + for( int keynum = 0; keynum <= names.GetUpperBound(); keynum++ ) + { + inifile << '[' << names[keynum] << ']' << endl; + + CMapStringToString &map = keys[keynum]; + + // for each value_name/value pair + for( POSITION pos = map.GetStartPosition(); pos != NULL; ) + { + CString value_name; + CString value; + map.GetNextAssoc( pos, value_name, value ); + + inifile << value_name << "=" << value << endl; + } + inifile << endl; + } + + inifile.close(); +} + +//deletes all stored ini data +void IniFile::Reset() +{ + keys.SetSize(0); + names.SetSize(0); +} + +//returns number of keys currently in the ini +int IniFile::GetNumKeys() +{ + return keys.GetSize(); +} + +//returns a refernce to the key for direct modification +CMapStringToString& IniFile::GetKeyRef( CString keyname ) +{ + int keynum = FindKey(keyname); + if (keynum == -1) + return keys[0]; + else + return keys[keynum]; +} + +//returns number of values stored for specified key, or -1 if key found +int IniFile::GetNumValues(CString keyname) +{ + int keynum = FindKey(keyname); + if (keynum == -1) + return -1; + else + return keys[keynum].GetCount(); +} + +//gets value of [keyname] valuename = +//overloaded to return CString, int, and double +CString IniFile::GetValue(CString keyname, CString valuename) +{ + int keynum = FindKey(keyname);//, valuenum = FindValue(keynum,valuename); + if( keynum == -1 ) + { + error = "Unable to locate specified key."; + return ""; + } + + CMapStringToString &map = keys[keynum]; + CString value; + if( !map.Lookup(valuename, value) ) + { + error = "Unable to locate specified value."; + return ""; + } + return value; +} + +//gets value of [keyname] valuename = +//overloaded to return CString, int, and double +int IniFile::GetValueI(CString keyname, CString valuename) +{ + return atoi( GetValue(keyname,valuename) ); +} + +//gets value of [keyname] valuename = +//overloaded to return CString, int, and double +double IniFile::GetValueF(CString keyname, CString valuename) +{ + return atof( GetValue(keyname, valuename) ); +} + +//sets value of [keyname] valuename =. +//specify the optional paramter as false (0) if you do not want it to create +//the key if it doesn't exist. Returns true if data entered, false otherwise +//overloaded to accept CString, int, and double +BOOL IniFile::SetValue(CString keyname, CString valuename, CString value, BOOL create) +{ + int keynum = FindKey(keyname); + + if( keynum == -1 ) //if key doesn't exist + { + if( !create ) //and user does not want to create it, + return FALSE; //stop entering this key + names.SetSize(names.GetSize()+1); + keys.SetSize(keys.GetSize()+1); + keynum = names.GetSize()-1; + names[keynum] = keyname; + } + + // insert value + CMapStringToString &map = keys[keynum]; + CString oldvalue; + if( !map.Lookup(valuename, oldvalue) && !create ) + return FALSE; + map[valuename] = value; + return TRUE; +} + +//sets value of [keyname] valuename =. +//specify the optional paramter as false (0) if you do not want it to create +//the key if it doesn't exist. Returns true if data entered, false otherwise +//overloaded to accept CString, int, and double +BOOL IniFile::SetValueI(CString keyname, CString valuename, int value, BOOL create) +{ + CString temp; + temp.Format("%d",value); + return SetValue(keyname, valuename, temp, create); +} + +//sets value of [keyname] valuename =. +//specify the optional paramter as false (0) if you do not want it to create +//the key if it doesn't exist. Returns true if data entered, false otherwise +//overloaded to accept CString, int, and double +BOOL IniFile::SetValueF(CString keyname, CString valuename, double value, BOOL create) +{ + CString temp; + temp.Format("%e",value); + return SetValue(keyname, valuename, temp, create); +} + +//deletes specified value +//returns true if value existed and deleted, false otherwise +BOOL IniFile::DeleteValue(CString keyname, CString valuename) +{ + int keynum = FindKey(keyname); + if( keynum == -1 ) + return FALSE; + + CMapStringToString &map = keys[keynum]; + return map.RemoveKey( valuename ); +} + +//deletes specified key and all values contained within +//returns true if key existed and deleted, false otherwise +BOOL IniFile::DeleteKey(CString keyname) +{ + int keynum = FindKey(keyname); + if (keynum == -1) + return 0; + keys.RemoveAt(keynum); + names.RemoveAt(keynum); + return 1; +} + +///////////////////////////////////////////////////////////////////// +// Private Functions +///////////////////////////////////////////////////////////////////// + +//returns index of specified key, or -1 if not found +int IniFile::FindKey(CString keyname) +{ + int keynum = 0; + while ( keynum < keys.GetSize() && names[keynum] != keyname) + keynum++; + if (keynum == keys.GetSize()) + return -1; + return keynum; +} + +//overloaded from original getline to take CString +istream & IniFile:: getline(istream & is, CString & str) +{ + char buf[2048]; + is.getline(buf,2048); + str = buf; + return is; +} diff --git a/stepmania/src/IniFile.h b/stepmania/src/IniFile.h new file mode 100644 index 0000000000..4dcb4a67ec --- /dev/null +++ b/stepmania/src/IniFile.h @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +// File: IniFile.h +// +// Desc: wrapper for reading and writing an .ini file. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _INIFILE_H_ +#define _INIFILE_H_ + +#include +#include + + +class IniFile +{ + //all private variables +private: + + //stores pathname of ini file to read/write + CString path; + + //all keys are of this time + typedef CMapStringToString key; + + //list of keys in ini + CArray keys; + + //corresponding list of keynames + CArray names; + + + + //all private functions +private: + //overloaded to take CString + istream & getline( istream & is, CString & str ); + + //returns index of specified key, or -1 if not found + int FindKey(CString keyname); + + + //public variables +public: + + //will contain error info if one occurs + //ended up not using much, just in ReadFile and GetValue + CString error; + + + //public functions +public: + //default constructor + IniFile(); + + //constructor, can specify pathname here instead of using SetPath later + IniFile(CString inipath); + + //default destructor + virtual ~IniFile(); + + //sets path of ini file to read and write from + void SetPath(CString newpath); + + //reads ini file specified using IniFile::SetPath() + //returns true if successful, false otherwise + BOOL ReadFile(); + + //writes data stored in class to ini file + void WriteFile(); + + //deletes all stored ini data + void Reset(); + + //returns number of keys currently in the ini + int GetNumKeys(); + + //returns a refernce to the key for direct modification + CMapStringToString& GetKeyRef( CString keyname ); + + //returns number of values stored for specified key + int GetNumValues( CString keyname ); + + //gets value of [keyname] valuename = + //overloaded to return CString, int, and double, + //returns "", or 0 if key/value not found. Sets error member to show problem + CString GetValue(CString keyname, CString valuename); + int GetValueI(CString keyname, CString valuename); + double GetValueF(CString keyname, CString valuename); + + //sets value of [keyname] valuename =. + //specify the optional paramter as false (0) if you do not want it to create + //the key if it doesn't exist. Returns true if data entered, false otherwise + //overloaded to accept CString, int, and double + BOOL SetValue(CString key, CString valuename, CString value, BOOL create = 1); + BOOL SetValueI(CString key, CString valuename, int value, BOOL create = 1); + BOOL SetValueF(CString key, CString valuename, double value, BOOL create = 1); + + //deletes specified value + //returns true if value existed and deleted, false otherwise + BOOL DeleteValue(CString keyname, CString valuename); + + //deletes specified key and all values contained within + //returns true if key existed and deleted, false otherwise + BOOL DeleteKey(CString keyname); +}; + + +#endif diff --git a/stepmania/src/Judgement.cpp b/stepmania/src/Judgement.cpp new file mode 100644 index 0000000000..8d036ba6a6 --- /dev/null +++ b/stepmania/src/Judgement.cpp @@ -0,0 +1,104 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Judgement.h +// +// Desc: Feedback about the last step that appears in the middle of a player's stream of arrows. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#include "RageUtil.h" + +#include "Judgement.h" + + +#define CENTER_X 320 +#define CENTER_Y 240 + +#define JUDGEMENT_DISPLAY_TIME 1.0f +#define JUDGEMENT_SPRITE "Sprites\\Judgement.sprite" +#define JUDGEMENT_Y CENTER_Y + + + +Judgement::Judgement() : + m_fDisplayTimeLeft( 0.0 ) +{ + m_sprJudgement.LoadFromSpriteFile( JUDGEMENT_SPRITE ); + + SetX( CENTER_X ); +} + +Judgement::~Judgement() +{ + +} + +void Judgement::SetX( int iNewX ) +{ + m_sprJudgement.SetXY( iNewX, CENTER_Y ); +} + +void Judgement::Update( const FLOAT &fDeltaTime ) +{ + if( m_fDisplayTimeLeft > 0.0 ) + m_fDisplayTimeLeft -= fDeltaTime; + m_sprJudgement.Update( fDeltaTime ); +} + +void Judgement::Draw() +{ +// RageLog( "Judgement::Draw()" ); + + if( m_fDisplayTimeLeft > 0.0 ) + m_sprJudgement.Draw(); +} + + +void Judgement::Perfect() +{ + RageLog( "Judgement::Perfect()" ); + + m_sprJudgement.SetState( 0 ); + + TweenFromBigToSmall(); +} + +void Judgement::Great() +{ + m_sprJudgement.SetState( 1 ); + + TweenFromBigToSmall(); +} + +void Judgement::Good() +{ + m_sprJudgement.SetState( 2 ); + + TweenFromBigToSmall(); +} + +void Judgement::Boo() +{ + m_sprJudgement.SetState( 3 ); + + TweenFromBigToSmall(); +} + +void Judgement::Miss() +{ + m_sprJudgement.SetState( 4 ); + + TweenFromBigToSmall(); +} + + +void Judgement::TweenFromBigToSmall() +{ + m_fDisplayTimeLeft = JUDGEMENT_DISPLAY_TIME; + + m_sprJudgement.SetZoom( 1.5f ); + m_sprJudgement.TweenTo( JUDGEMENT_DISPLAY_TIME/2.0, + m_sprJudgement.GetX(), + m_sprJudgement.GetY() ); +} diff --git a/stepmania/src/Judgement.h b/stepmania/src/Judgement.h new file mode 100644 index 0000000000..27970cc870 --- /dev/null +++ b/stepmania/src/Judgement.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// File: Judgement.h +// +// Desc: Feedback about the last step that appears in the middle of a player's stream of arrows. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _JUDGEMENT_H_ +#define _JUDGEMENT_H_ + + +#include "Sprite.h" + + +class Judgement +{ +public: + Judgement(); + ~Judgement(); + + void SetX( int iNewX ); + + void Update( const FLOAT &fDeltaTime ); + void Draw(); + + void Perfect(); + void Great(); + void Good(); + void Boo(); + void Miss(); + +private: + void TweenFromBigToSmall(); + + + FLOAT m_fDisplayTimeLeft; + + Sprite m_sprJudgement; +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/LifeMeter.cpp b/stepmania/src/LifeMeter.cpp new file mode 100644 index 0000000000..6a8267a635 --- /dev/null +++ b/stepmania/src/LifeMeter.cpp @@ -0,0 +1,102 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: LifeMeter.cpp +// +// Desc: LifeMeter counter that displays while dancing. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "RageUtil.h" + +#include "LifeMeter.h" + + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 +#define CENTER_X 320 +#define CENTER_Y 240 + + +#define FONT "Fonts\\Font - Arial Bold numbers 30px.font" + +#define NUM_PILLS 17 + +//#define LIFEMETER_TWEEN_TIME 0.5f +#define LIFEMETER_FRAME_SPRITE "Sprites\\Life Meter Frame.sprite" +#define LIFEMETER_PILLS_SPRITE "Sprites\\Life Meter Pills.sprite" +#define LIFEMETER_Y 30 +#define LIFEMETER_PILLS_Y (LIFEMETER_Y+2) + +const FLOAT PILL_OFFSET[NUM_PILLS] = { + 0.3f, 0.7f, 1.0f, 0.7f, 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f +}; + + +LifeMeter::LifeMeter() : + m_fLifePercentage( 0.5f ) +{ + m_sprLifeMeterFrame.LoadFromSpriteFile( LIFEMETER_FRAME_SPRITE ); + m_sprLifeMeterPills.LoadFromSpriteFile( LIFEMETER_PILLS_SPRITE ); + + SetX( CENTER_X ); +} + +LifeMeter::~LifeMeter() +{ + +} + + +void LifeMeter::SetX( FLOAT iNewX ) +{ + m_sprLifeMeterFrame.SetXY( iNewX, LIFEMETER_Y ); + m_sprLifeMeterPills.SetXY( iNewX, LIFEMETER_PILLS_Y ); +} + +void LifeMeter::Update( const FLOAT &fDeltaTime ) +{ + m_sprLifeMeterFrame.Update( fDeltaTime ); + m_sprLifeMeterPills.Update( fDeltaTime ); +} + +void LifeMeter::Draw( FLOAT fSongBeat ) +{ + FLOAT fBeatPercentage = fSongBeat - (int)fSongBeat; + int iOffsetStart = roundf( NUM_PILLS*fBeatPercentage ); + + m_sprLifeMeterFrame.Draw(); + + FLOAT iX = m_sprLifeMeterFrame.GetLeftEdge() + 27; + int iNumPills = (int)(m_sprLifeMeterPills.GetNumStates() * m_fLifePercentage); + int iPillWidth = m_sprLifeMeterPills.GetZoomedWidth(); + + for( int i=0; i= 0.0f && fNewLife <= 1.0f ); + m_fLifePercentage = fNewLife; + + if( fNewLife >= 0.9f ) + m_sprLifeMeterFrame.SetEffectCamelion( 5, D3DXCOLOR(0.2f,0.2f,0.2f,1), D3DXCOLOR(1,1,1,1) ); + else if( fNewLife < 0.25f ) + m_sprLifeMeterFrame.SetEffectCamelion( 5, D3DXCOLOR(1,0.8f,0.8f,1), D3DXCOLOR(1,0.2f,0.2f,1) ); + else + m_sprLifeMeterFrame.SetEffectNone(); + +} diff --git a/stepmania/src/LifeMeter.h b/stepmania/src/LifeMeter.h new file mode 100644 index 0000000000..2e83f2a484 --- /dev/null +++ b/stepmania/src/LifeMeter.h @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// File: LifeMeter.h +// +// Desc: LifeMeter display at the bottom of the screen while dancing. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _LIFEMETER_H_ +#define _LIFEMETER_H_ + + +#include "Sprite.h" + +class LifeMeter +{ +public: + LifeMeter(); + ~LifeMeter(); + + void SetX( FLOAT iNewX ); + + void Update( const FLOAT &fDeltaTime ); + void Draw( FLOAT fSongBeat ); + + void SetLife( FLOAT fNewLife ); + +private: + + Sprite m_sprLifeMeterFrame; + Sprite m_sprLifeMeterPills; + + FLOAT m_fLifePercentage; +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp new file mode 100644 index 0000000000..4d72a0b8bf --- /dev/null +++ b/stepmania/src/Player.cpp @@ -0,0 +1,270 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Player.cpp +// +// Desc: Object that accepts pad input, knocks down ColorArrows that were stepped on, +// and keeps score for the player. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "Util.h" +#include "Math.h" // for fabs() + +#include "Player.h" + + + +#define STEP_DOWN_TIME 0.05f + +#define SCORE_ADD_PERFECT 700 +#define SCORE_ADD_GREAT 400 +#define SCORE_ADD_GOOD 200 +#define SCORE_ADD_BOO 100 + +#define SCORE_MULT_PERFECT 1.007f +#define SCORE_MULT_GREAT 1.004f +#define SCORE_MULT_GOOD 1.002f +#define SCORE_MULT_BOO 1.001f + +#define LIFE_PERFECT 0.015f +#define LIFE_GREAT 0.008f +#define LIFE_GOOD 0.000f +#define LIFE_BOO -0.015f +#define LIFE_MISS -0.060f + + +void Player::Set( GrayArrows *pGA, ColorArrows *pCA, + Judgement *pJ, Combo *pC, + Score *pS, LifeMeter *pL, + Steps steps, FLOAT fMaxBeatDifference ) +{ + RageLog( "Player::Set()" ); + + m_pGA = pGA; + m_pCA = pCA; + m_pJudgement = pJ; + m_pCombo = pC; + m_pScore = pS; + m_pLifeMeter = pL; + if( m_pLifeMeter ) m_pLifeMeter->SetLife( m_fLife ); + + m_Steps = steps; + + m_StepScore.SetSize( MAX_STEP_ELEMENTS ); + for( int i=0; i 0.0 ) + m_fStepCountDown[i][j] -= fDeltaTime; + } + } + + + int iNumMisses = UpdateMissedStepsOlderThan( m_fSongBeat-m_fMaxBeatDifference ); + if( iNumMisses > 0 ) + { + m_pJudgement->Miss(); + m_iCurCombo = 0; + m_pCombo->SetCombo( 0 ); + m_fLife += LIFE_MISS * iNumMisses; + if( m_fLife < 0.0f ) + m_fLife = 0.0f; + m_pLifeMeter->SetLife( m_fLife ); + } + +} + +void Player::StepOn( Step player_step ) +{ +// DebugLog( CString("Player::Step() ") + padStepL.ToString() + CString(" ") + padStepR.ToString() ); + + // Fill the "step buffer" so that the player doesn't have to hit 2 buttons + // at the exact same time in order to hit a two direction step + if( player_step & STEP_P1_LEFT ) m_fStepCountDown[0][0] = STEP_DOWN_TIME; + if( player_step & STEP_P1_DOWN ) m_fStepCountDown[0][1] = STEP_DOWN_TIME; + if( player_step & STEP_P1_UP ) m_fStepCountDown[0][2] = STEP_DOWN_TIME; + if( player_step & STEP_P1_RIGHT ) m_fStepCountDown[0][3] = STEP_DOWN_TIME; + + // make the gray foot steps on the screen follow the input + m_pGA->StepOn( player_step ); + + HandleStep(); +} + + + +void Player::HandleStep() +{ + //RageLog( "Player::HandleStep()" ); + + // This is being called just after a step, so we know at + // least one direction is being depressed. + + // Build pad steps to check against + Step player_step = 0x0000; + if( m_fStepCountDown[0][0] > 0.0f ) player_step |= STEP_P1_LEFT; + if( m_fStepCountDown[0][1] > 0.0f ) player_step |= STEP_P1_DOWN; + if( m_fStepCountDown[0][2] > 0.0f ) player_step |= STEP_P1_UP; + if( m_fStepCountDown[0][3] > 0.0f ) player_step |= STEP_P1_RIGHT; + + // find the closest step that our PadSteps cover + //RageLog( "I ask: What step %s, %s, is near %f (within %f )", + // padStepL.ToString(), + // padStepR.ToString(), + // m_fSongBeat, + // MAX_BEAT_DIFFERENCE ); + + int iIndexOfClosest = + m_Steps.GetIndexOfClosestStep( m_fSongBeat, + m_fMaxBeatDifference, + player_step ); + + if( iIndexOfClosest == -1 ) // if no steps in our specified range are covered + return; + + + + FLOAT fStepBeat = StepIndexToBeat( iIndexOfClosest ); // this is the beat of the note we stepped on + + //RageLog( "GetClosestMatch returned: iIndexOfClosest = %d (%s, %s, fStepBeat: %f)", + // iIndexOfClosest, + // m_Steps.StepsLeft [iIndexOfClosest].ToString(), + // m_Steps.StepsRight[iIndexOfClosest].ToString(), + // fStepBeat ); + + + FLOAT fBeatsUntilStep = fStepBeat - m_fSongBeat; + FLOAT fPercentFromPerfect = (FLOAT)fabs( fBeatsUntilStep / m_fMaxBeatDifference ); + + RageLog( "fBeatsUntilStep: %f, fPercentFromPerfect: %f", + fBeatsUntilStep, fPercentFromPerfect ); + + // step on the note so that it can't be stepped on any more + m_Steps.StatusArray[iIndexOfClosest] = stepped_on; + + // compute what the score should be for the note we stepped on + StepScore &score = m_StepScore[iIndexOfClosest]; + + if( fPercentFromPerfect < 0.20f ) + score = perfect; + else if( fPercentFromPerfect < 0.45f ) + score = great; + else if( fPercentFromPerfect < 0.75f ) + score = good; + else + score = boo; + + // update the judgement display + switch( score ) + { + case perfect: m_pJudgement->Perfect(); break; + case great: m_pJudgement->Great(); break; + case good: m_pJudgement->Good(); break; + case boo: m_pJudgement->Boo(); break; + } + + // update the combo display + switch( score ) + { + case perfect: + case great: + m_iCurCombo++; + m_pCombo->SetCombo( m_iCurCombo ); + break; + case good: + case boo: + // combo stopped + if( m_iCurCombo > m_iMaxCombo ) + m_iMaxCombo = m_iCurCombo; + m_iCurCombo = 0; + m_pCombo->SetCombo( m_iCurCombo ); + break; + } + + // remove the arrows from the ColorArrow columns if the score is high enough + if( score == perfect || score == great ) + { + m_pCA->StepOn( BeatToStepIndex(fStepBeat) ); + } + + // update running score + switch( score ) + { + case perfect: m_fScore += SCORE_ADD_PERFECT; m_fScore *= SCORE_MULT_PERFECT; break; + case great: m_fScore += SCORE_ADD_GREAT; m_fScore *= SCORE_MULT_GREAT; break; + case good: m_fScore += SCORE_ADD_GOOD; m_fScore *= SCORE_MULT_GOOD; break; + case boo: m_fScore += SCORE_ADD_BOO; m_fScore *= SCORE_MULT_BOO; break; + case miss: break; + } + + // update life meter + switch( score ) + { + case perfect: m_fLife += LIFE_PERFECT; break; + case great: m_fLife += LIFE_GREAT; break; + case good: m_fLife += LIFE_GOOD; break; + case boo: m_fLife += LIFE_BOO; break; + } + if( m_fLife < 0.0f ) m_fLife = 0.0f; + else if( m_fLife > 1.0f ) m_fLife = 1.0f; + + + m_pScore->SetScore( m_fScore ); + m_pLifeMeter->SetLife( m_fLife ); +} + +int Player::UpdateMissedStepsOlderThan( FLOAT iMissIfOlderThanThisBeat ) +{ + //RageLog( "Steps::UpdateMissedStepsOlderThan(%f)", iMissIfOlderThanThisBeat ); + + int iMissIfOlderThanThisIndex = BeatToStepIndex( iMissIfOlderThanThisBeat ); + + int iNumMissesFound = 0; + + for( int i=0; i m_StepScore; + + int m_iCurCombo; + int m_iMaxCombo; + + FLOAT m_fLife; + FLOAT m_fScore; + +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/RageBitmapTexture.cpp b/stepmania/src/RageBitmapTexture.cpp new file mode 100644 index 0000000000..6d4c3a6412 --- /dev/null +++ b/stepmania/src/RageBitmapTexture.cpp @@ -0,0 +1,99 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageBitmapTexture.cpp +// +// Desc: +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// In-line Links +//----------------------------------------------------------------------------- +//#pragma comment(lib, "winmm.lib") +#pragma comment(lib, "dxerr8.lib") + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "RageBitmapTexture.h" +#include "dxerr8.h" +#include "DXUtil.h" +#include "RageUtil.h" + +//#include +#include + +//----------------------------------------------------------------------------- +// RageBitmapTexture constructor +//----------------------------------------------------------------------------- +RageBitmapTexture::RageBitmapTexture( LPRageScreen pScreen, CString sFilePath ) : + RageTexture( pScreen, sFilePath ) +{ +// RageLog( "RageBitmapTexture::RageBitmapTexture()" ); + + Create(); + + CreateFrameRects(); +} + +RageBitmapTexture::~RageBitmapTexture() +{ + SAFE_RELEASE(m_pd3dTexture); +} + + +//----------------------------------------------------------------------------- +// GetTexture +//----------------------------------------------------------------------------- +LPDIRECT3DTEXTURE8 RageBitmapTexture::GetD3DTexture() +{ + return m_pd3dTexture; +} + + +VOID RageBitmapTexture::Create() +{ + HRESULT hr; + + D3DXIMAGE_INFO ddii; + + // load texture + if (FAILED (hr = D3DXCreateTextureFromFileEx( + m_pd3dDevice, + m_sFilePath, + D3DX_DEFAULT, D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + D3DFMT_A4R4G4B4, //D3DFMT_UNKNOWN, // get format from source + D3DPOOL_MANAGED, + D3DX_FILTER_NONE, // don't blow up the image to the texure size + D3DX_FILTER_NONE, + 0, // no color key + &ddii, + NULL, // no palette + &m_pd3dTexture ) ) ) + RageErrorHr( ssprintf("D3DXCreateTextureFromFileEx() failed for file '%s'.", m_sFilePath), hr ); + + + m_uImageWidth = ddii.Width; + m_uImageHeight= ddii.Height; + + + // D3DXCreateTexture can silently change the parameters on us + D3DSURFACE_DESC ddsd; + if ( FAILED( hr = m_pd3dTexture->GetLevelDesc( 0, &ddsd ) ) ) + RageErrorHr( "Could not get level Description of D3DX texture!", hr ); + + m_uTextureWidth = ddsd.Width; + m_uTextureHeight = ddsd.Height; + m_TextureFormat = ddsd.Format; +// if (m_TextureFormat != D3DFMT_A8R8G8B8 && +// m_TextureFormat != D3DFMT_A1R5G5B5) { +// DXTRACE_ERR(TEXT("Texture is format we can't handle! Format = 0x%x"), m_TextureFormat); +// return E_FAIL; +// } + +} + diff --git a/stepmania/src/RageBitmapTexture.h b/stepmania/src/RageBitmapTexture.h new file mode 100644 index 0000000000..c9e90db2f9 --- /dev/null +++ b/stepmania/src/RageBitmapTexture.h @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// File: RageBitmapTexture.h +// +// Desc: +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +class RageBitmapTexture; +typedef RageBitmapTexture* LPRageBitmapTexture; + + + + +#ifndef _RageBitmapTexture_H_ +#define _RageBitmapTexture_H_ + + +#include "RageScreen.h" +#include +#include +//#include + + +//----------------------------------------------------------------------------- +// RageBitmapTexture Class Declarations +//----------------------------------------------------------------------------- +class RageBitmapTexture : public RageTexture +{ +public: + RageBitmapTexture( LPRageScreen pScreen, CString sFilePath ); + ~RageBitmapTexture(); + + virtual LPDIRECT3DTEXTURE8 GetD3DTexture(); + +protected: + virtual VOID Create(); +}; + + +#endif diff --git a/stepmania/src/RageInput.cpp b/stepmania/src/RageInput.cpp new file mode 100644 index 0000000000..51304a3fd6 --- /dev/null +++ b/stepmania/src/RageInput.cpp @@ -0,0 +1,647 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageInput.cpp +// +// Desc: DirectInput wrapper class +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// In-line Links +//----------------------------------------------------------------------------- +#pragma comment(lib, "dinput8.lib") +#pragma comment(lib, "dxguid.lib") + + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include +#include +#include "RageInput.h" +#include "RageUtil.h" + + +LPRageInput INPUT = NULL; + + +BOOL RageRawInput::LookupChar( TCHAR &char_out ) const +{ + switch( button ) + { + case DIK_1: char_out = '1'; break; + case DIK_2: char_out = '2'; break; + case DIK_3: char_out = '3'; break; + case DIK_4: char_out = '4'; break; + case DIK_5: char_out = '5'; break; + case DIK_6: char_out = '6'; break; + case DIK_7: char_out = '7'; break; + case DIK_8: char_out = '8'; break; + case DIK_9: char_out = '9'; break; + case DIK_0: char_out = '0'; break; + case DIK_MINUS: char_out = '-'; break; + case DIK_EQUALS: char_out = '='; break; + case DIK_Q: char_out = 'Q'; break; + case DIK_W: char_out = 'W'; break; + case DIK_E: char_out = 'E'; break; + case DIK_R: char_out = 'R'; break; + case DIK_T: char_out = 'T'; break; + case DIK_Y: char_out = 'Y'; break; + case DIK_U: char_out = 'U'; break; + case DIK_I: char_out = 'I'; break; + case DIK_O: char_out = 'O'; break; + case DIK_P: char_out = 'P'; break; + case DIK_LBRACKET: char_out = '['; break; + case DIK_RBRACKET: char_out = ']'; break; + case DIK_A: char_out = 'A'; break; + case DIK_S: char_out = 'S'; break; + case DIK_D: char_out = 'D'; break; + case DIK_F: char_out = 'F'; break; + case DIK_G: char_out = 'G'; break; + case DIK_H: char_out = 'H'; break; + case DIK_J: char_out = 'J'; break; + case DIK_K: char_out = 'K'; break; + case DIK_L: char_out = 'L'; break; + case DIK_SEMICOLON: char_out = ';'; break; + case DIK_APOSTROPHE:char_out = '\'';break; + case DIK_GRAVE: char_out = '`'; break; + case DIK_BACKSLASH: char_out = '\\';break; + case DIK_Z: char_out = 'Z'; break; + case DIK_X: char_out = 'X'; break; + case DIK_C: char_out = 'C'; break; + case DIK_V: char_out = 'V'; break; + case DIK_B: char_out = 'B'; break; + case DIK_N: char_out = 'N'; break; + case DIK_M: char_out = 'M'; break; + case DIK_COMMA: char_out = ','; break; + case DIK_PERIOD: char_out = '.'; break; + case DIK_SLASH: char_out = '/'; break; + case DIK_MULTIPLY: char_out = '*'; break; + case DIK_SPACE: char_out = ' '; break; + case DIK_NUMPAD7: char_out = '7'; break; + case DIK_NUMPAD8: char_out = '8'; break; + case DIK_NUMPAD9: char_out = '9'; break; + case DIK_SUBTRACT: char_out = '-'; break; + case DIK_NUMPAD4: char_out = '4'; break; + case DIK_NUMPAD5: char_out = '5'; break; + case DIK_NUMPAD6: char_out = '6'; break; + case DIK_ADD: char_out = '+'; break; + case DIK_NUMPAD1: char_out = '1'; break; + case DIK_NUMPAD2: char_out = '2'; break; + case DIK_NUMPAD3: char_out = '3'; break; + case DIK_NUMPAD0: char_out = '0'; break; + case DIK_DECIMAL: char_out = '.'; break; + + default: return FALSE; // This key doesn't correspond to a character. + } + + return TRUE; +} + + +CString RageRawInput::GetDescription() const +{ + CString sReturn; + + switch( device ) + { + case DEVICE_NONE: + sReturn = "None"; + break; + case DEVICE_JOYSTICK: // joystick + sReturn.Format( "Joystick%d ", device_no ); + switch( button ) + { + case JOY_LEFT: sReturn += "Left"; break; + case JOY_RIGHT: sReturn += "Right"; break; + case JOY_UP: sReturn += "Up"; break; + case JOY_DOWN: sReturn += "Down"; break; + default: + { + CString sButtonString; + sButtonString.Format( "Button %d", button ); + sReturn += sButtonString; + } + break; + } + break; + case DEVICE_KEYBOARD: + sReturn = "Keyboard "; + + switch( button ) + { + case DIK_ESCAPE: sReturn += "Escape"; break; + case DIK_1: sReturn += "1"; break; + case DIK_2: sReturn += "2"; break; + case DIK_3: sReturn += "3"; break; + case DIK_4: sReturn += "4"; break; + case DIK_5: sReturn += "5"; break; + case DIK_6: sReturn += "6"; break; + case DIK_7: sReturn += "7"; break; + case DIK_8: sReturn += "8"; break; + case DIK_9: sReturn += "9"; break; + case DIK_0: sReturn += "0"; break; + case DIK_MINUS: sReturn += "Minus"; break; + case DIK_EQUALS: sReturn += "Equals"; break; + case DIK_BACK: sReturn += "Backspace"; break; + case DIK_TAB: sReturn += "Tab"; break; +// why? case DIK_BACK: sReturn += "Backspace"; break; + case DIK_Q: sReturn += "Q"; break; + case DIK_W: sReturn += "W"; break; + case DIK_E: sReturn += "E"; break; + case DIK_R: sReturn += "R"; break; + case DIK_T: sReturn += "T"; break; + case DIK_Y: sReturn += "Y"; break; + case DIK_U: sReturn += "U"; break; + case DIK_I: sReturn += "I"; break; + case DIK_O: sReturn += "O"; break; + case DIK_P: sReturn += "P"; break; + case DIK_LBRACKET: sReturn += "LBracket"; break; + case DIK_RBRACKET: sReturn += "RBracket"; break; + case DIK_RETURN: sReturn += "Return"; break; + case DIK_LCONTROL: sReturn += "LControl"; break; + case DIK_A: sReturn += "A"; break; + case DIK_S: sReturn += "S"; break; + case DIK_D: sReturn += "D"; break; + case DIK_F: sReturn += "F"; break; + case DIK_G: sReturn += "G"; break; + case DIK_H: sReturn += "H"; break; + case DIK_J: sReturn += "J"; break; + case DIK_K: sReturn += "K"; break; + case DIK_L: sReturn += "L"; break; + case DIK_SEMICOLON: sReturn += "Semicolon"; break; + case DIK_APOSTROPHE:sReturn += "Apostroph"; break; + case DIK_GRAVE: sReturn += "Grave"; break; + case DIK_LSHIFT: sReturn += "LShift"; break; + case DIK_BACKSLASH: sReturn += "Backslash"; break; + case DIK_Z: sReturn += "Z"; break; + case DIK_X: sReturn += "X"; break; + case DIK_C: sReturn += "C"; break; + case DIK_V: sReturn += "V"; break; + case DIK_B: sReturn += "B"; break; + case DIK_N: sReturn += "N"; break; + case DIK_M: sReturn += "M"; break; + case DIK_COMMA: sReturn += "Comma"; break; + case DIK_PERIOD: sReturn += "Period"; break; + case DIK_SLASH: sReturn += "Slash"; break; + case DIK_RSHIFT: sReturn += "R Shift"; break; + case DIK_MULTIPLY: sReturn += "Multiply"; break; + case DIK_LMENU: sReturn += "Left Menu"; break; + case DIK_SPACE: sReturn += "Space"; break; + case DIK_CAPITAL: sReturn += "Caps Lock"; break; + case DIK_F1: sReturn += "F1"; break; + case DIK_F2: sReturn += "F2"; break; + case DIK_F3: sReturn += "F3"; break; + case DIK_F4: sReturn += "F4"; break; + case DIK_F5: sReturn += "F5"; break; + case DIK_F6: sReturn += "F6"; break; + case DIK_F7: sReturn += "F7"; break; + case DIK_F8: sReturn += "F8"; break; + case DIK_F9: sReturn += "F9"; break; + case DIK_F10: sReturn += "F10"; break; + case DIK_NUMLOCK: sReturn += "Numlock"; break; + case DIK_SCROLL: sReturn += "Scroll"; break; + case DIK_NUMPAD7: sReturn += "NumPad7"; break; + case DIK_NUMPAD8: sReturn += "NumPad8"; break; + case DIK_NUMPAD9: sReturn += "NumPad9"; break; + case DIK_SUBTRACT: sReturn += "Subtract"; break; + case DIK_NUMPAD4: sReturn += "NumPad4"; break; + case DIK_NUMPAD5: sReturn += "NumPad5"; break; + case DIK_NUMPAD6: sReturn += "NumPad6"; break; + case DIK_ADD: sReturn += "Add"; break; + case DIK_NUMPAD1: sReturn += "NumPad1"; break; + case DIK_NUMPAD2: sReturn += "NumPad2"; break; + case DIK_NUMPAD3: sReturn += "NumPad3"; break; + case DIK_NUMPAD0: sReturn += "NumPad0"; break; + case DIK_DECIMAL: sReturn += "Decimal"; break; + case DIK_RMENU: sReturn += "Right Alt"; break; + case DIK_PAUSE: sReturn += "Pause"; break; + case DIK_HOME: sReturn += "Home"; break; + case DIK_UP: sReturn += "Up"; break; + case DIK_PRIOR: sReturn += "Page Up"; break; + case DIK_LEFT: sReturn += "Left"; break; + case DIK_RIGHT: sReturn += "Right"; break; + case DIK_END: sReturn += "End"; break; + case DIK_DOWN: sReturn += "Down"; break; + case DIK_NEXT: sReturn += "Page Down"; break; + case DIK_INSERT: sReturn += "Insert"; break; + case DIK_DELETE: sReturn += "Delete"; break; + case DIK_LWIN: sReturn += "Left Win"; break; + case DIK_RWIN: sReturn += "Right Win"; break; + case DIK_APPS: sReturn += "App Menu"; break; + + default: sReturn += "Unknown Key"; break; + } + break; + default: + sReturn = "Invalid Device"; + break; + } + + return sReturn; +} + + + + +//----------------------------------------------------------------------------- +// Name: EnumJoysticksCallback() +// Desc: Called once for each enumerated joystick. If we find one, create a +// device interface on it so we can play with it. +//----------------------------------------------------------------------------- +BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, + VOID* pContext ) +{ + LPRageInput pInput = (LPRageInput)pContext; + LPDIRECTINPUT8 pDI = pInput->GetDirectInput(); + + + HRESULT hr; + + // Obtain an interface to the enumerated joystick. + for( int i=0; iCreateDevice( pdidInstance->guidInstance, + &pInput->m_pJoystick[i], + NULL ); + // This will only fail if the user unplugs while we were in the middle of enumerating. + + return DIENUM_CONTINUE; + } + + return DIENUM_STOP; // already enumerated NUm_pJoystick times +} + + + + +//----------------------------------------------------------------------------- +// Name: EnumAxesCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + LPDIRECTINPUTDEVICE8 pJoystick = (LPDIRECTINPUTDEVICE8)pContext; + + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis + diprg.lMin = -1000; + diprg.lMax = +1000; + + // Set the range for the axis + if( FAILED( pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) + return DIENUM_STOP; + + + return DIENUM_CONTINUE; +} + + + + +RageInput::RageInput( HWND hWnd ) +{ + m_hWnd = hWnd; + + + m_pDI = NULL; + m_pKeyboard = NULL; + m_pMouse = NULL; + for( int i=0; iCreateDevice( GUID_SysKeyboard, &m_pKeyboard, NULL ) ) ) + RageErrorHr( "CreateDevice keyboard failed.", hr ); + + // Set our Cooperation Level with each Device + if( FAILED( hr = m_pKeyboard->SetCooperativeLevel(m_hWnd, DISCL_FOREGROUND | + DISCL_NOWINKEY | + DISCL_NONEXCLUSIVE) ) ) + RageErrorHr( "m_pKeyboard->SetCooperativeLevel failed.", hr ); + + // Set the Data Format of each device + if( FAILED( hr = m_pKeyboard->SetDataFormat(&c_dfDIKeyboard) ) ) + RageErrorHr( "m_pKeyboard->SetDataFormat failed.", hr ); + + // Acquire the Keyboard Device + //if( FAILED( hr = m_pKeyboard->Acquire() ) ) + // RageErrorHr( "m_pKeyboard->Acquire failed.", hr ); + + + + ////////////////////////// + // Create the mouse device + ////////////////////////// + + // Obtain an interface to the system mouse device. + if( FAILED( hr = m_pDI->CreateDevice( GUID_SysMouse, &m_pMouse, NULL ) ) ) + RageErrorHr( "CreateDevice mouse failed.", hr ); + + if( FAILED( hr = m_pMouse->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND ) ) ) + RageErrorHr( "m_pMouse->SetCooperativeLevel failed.", hr ); + + if( FAILED( hr = m_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) ) + RageErrorHr( "m_pMouse->SetDataFormat failed.", hr ); + +/* + DIPROPDWORD dipdw; + dipdw.diph.dwSize = sizeof(DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = DIPROPAXISMODE_ABS; + + if( FAILED( m_pMouse->SetProperty( DIPROP_AXISMODE, &dipdw.diph ) ) ) + return E_FAIL;*/ + //if( FAILED( hr = m_pMouse->Acquire())) + // RageErrorHr( "m_pMouse->Acquire failed.", hr ); + + m_RelPosition_x = 0; + m_RelPosition_y = 0; + + m_AbsPosition_x = 640/2; + m_AbsPosition_y = 480/2; + + ////////////////////////////// + // Create the joystick devices + ////////////////////////////// + // Look for joysticks + // TODO: Why is this function so slow to return? Is it just my machine? + if( FAILED( hr = m_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + (VOID*)this, + DIEDFL_ATTACHEDONLY ) ) ) + RageErrorHr( "m_pDI->EnumDevices failed.", hr ); + + for( int i=0; iSetDataFormat( &c_dfDIJoystick2 ) ) ) + RageErrorHr( "m_pJoystick[i]->SetDataFormat failed.", hr ); + + + // Set the cooperative level to let DInput know how this device should + // interact with the system and with other DInput applications. + if( m_pJoystick[i] ) + if( FAILED( hr = m_pJoystick[i]->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND ) ) ) + RageErrorHr( "m_pJoystick[i]->SetCooperativeLevel failed.", hr ); + + + /* + // Determine how many axis the joystick has (so we don't error out setting + // properties for unavailable axis) + if ( m_pJoystick[i] ) { + g_diDevCaps.dwSize = sizeof(DIDEVCAPS); + if ( FAILED( hr = m_pJoystick[i]->GetCapabilities(&g_diDevCaps) ) ) + return hr; + } + */ + + // Enumerate the axes of the joyctick and set the range of each axis. Note: + // we could just use the defaults, but we're just trying to show an example + // of enumerating device objects (axes, buttons, etc.). + if( m_pJoystick[i] ) + if ( FAILED( hr = m_pJoystick[i]->EnumObjects( EnumAxesCallback, (VOID*)m_pJoystick[i], DIDFT_AXIS ) ) ) + RageErrorHr( "m_pJoystick[i]->EnumObjects failed.", hr ); + + // Acquire the newly created devices + if( m_pJoystick[i] ) + if( FAILED( hr = m_pJoystick[i]->Acquire() ) ) + RageErrorHr( "m_pJoystick[i]->Acquire failed.", hr ); + } + + return S_OK; +} + +VOID RageInput::Release() +{ + // Unacquire the keyboard device + if (m_pKeyboard) + m_pKeyboard->Unacquire(); + // Release the keyboard device + SAFE_RELEASE(m_pKeyboard); + // Unacquire the Mouse device + if (m_pMouse) + m_pMouse->Unacquire(); + // Release the Mouse device + SAFE_RELEASE(m_pMouse); + + for( int i=0; iUnacquire(); + // Release the Mouse device + SAFE_RELEASE(m_pJoystick[i]); + } + + // Release the DirectInput object + SAFE_RELEASE(m_pDI); +} + + +HRESULT RageInput::GetRawInput( RageRawInputList &listRawInput ) +{ +// macros for reading DI state structures +#define IS_PRESSED(b) (b & 0x80) +#define AXIS_THRESHOLD 50 // joystick axis threshold +#define IS_LEFT(a) (a <= -AXIS_THRESHOLD) +#define IS_RIGHT(a) (a >= AXIS_THRESHOLD) +#define IS_UP(a) IS_LEFT(a) +#define IS_DOWN(a) IS_RIGHT(a) + + + HRESULT hr; + + ////////////////////////////////////////////////////////////////// + // the current state last update becomes the old state this update + ////////////////////////////////////////////////////////////////// + + CopyMemory( &m_oldKeys, &m_keys, sizeof(m_keys) ); + CopyMemory( &m_oldJoyState, &m_joyState, sizeof(m_joyState) ); + + ZeroMemory( &m_keys, sizeof(m_keys) ); + ZeroMemory( &m_joyState, sizeof(m_joyState) ); + + + //////////////////// + // Read the keyboard + //////////////////// + if( NULL == m_pKeyboard ) + return E_FAIL; + + if FAILED(m_pKeyboard->GetDeviceState( sizeof(m_keys),(LPVOID)&m_keys )) + { + // DirectInput may be telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. + // We just re-acquire and try again. + + // If input is lost then acquire and keep trying + hr = m_pKeyboard->Acquire(); + while( hr == DIERR_INPUTLOST ) + hr = m_pKeyboard->Acquire(); + + return E_FAIL; + } + + // get keyboard state was successful. Compare this state to the last state + for( int k = 0; k < 256; k++ ) // foreach key + { + // check if key is depressed this update and was not depressed last update + if( IS_PRESSED( m_keys[k] ) && !IS_PRESSED( m_oldKeys[k] ) ) + listRawInput.AddTail( RageRawInput( DEVICE_KEYBOARD, 1, k, FALSE ) ); + } + + + //////////////////// + // Read the mouse + //////////////////// + if( NULL == m_pMouse ) + return E_FAIL; + + ZeroMemory( &m_mouseState, sizeof(m_mouseState) ); + + // Get the input's device state, and put the state in DIMOUSESTATE2 + if (FAILED(m_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &m_mouseState ))) + { + // If input is lost then acquire and keep trying + hr = m_pMouse->Acquire(); + while( hr == DIERR_INPUTLOST ) + hr = m_pMouse->Acquire(); + + return E_FAIL; + } + + + m_RelPosition_x = m_mouseState.lX; + m_RelPosition_y = m_mouseState.lY; + + + m_AbsPosition_x += m_mouseState.lX; + m_AbsPosition_y += m_mouseState.lY; + + if (m_AbsPosition_x >= 640) + m_AbsPosition_x = 640-1; + else + if (m_AbsPosition_x < 0) + m_AbsPosition_x = 0; + + // now the y boundaries + if (m_AbsPosition_y >= 480) + m_AbsPosition_y= 480-1; + else + if (m_AbsPosition_y < 0) + m_AbsPosition_y = 0; + + + ///////////////////// + // Read the joysticks + ///////////////////// + + // read joystick state + for( BYTE i=0; i<4; i++ ) // foreach joystick + { + // read joystick states + if ( m_pJoystick[i] ) + { + // Poll the device to read the current state + hr = m_pJoystick[i]->Poll(); + if( FAILED(hr) ) + { + // DInput is telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. We + // just re-acquire and try again. + hr = m_pJoystick[i]->Acquire(); + while( hr == DIERR_INPUTLOST ) + hr = m_pJoystick[i]->Acquire(); + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This + // may occur when the app is minimized or in the process of + // switching, so just try again later + return E_FAIL; + } + + // Get the input's device state + if( FAILED( hr = m_pJoystick[i]->GetDeviceState( sizeof(DIJOYSTATE2), &m_joyState[i] ) ) ) + return hr; // The device should have been acquired during the Poll() + else + { + + // check if key is depressed this update and was not depressed last update + if( IS_LEFT( m_joyState[i].lX ) && + !IS_LEFT( m_oldJoyState[i].lX ) ) + listRawInput.AddTail( RageRawInput( DEVICE_JOYSTICK, i+1, JOY_LEFT, FALSE ) ); + + if( IS_RIGHT( m_joyState[i].lX ) && + !IS_RIGHT( m_oldJoyState[i].lX ) ) + listRawInput.AddTail( RageRawInput( DEVICE_JOYSTICK, i+1, JOY_RIGHT, FALSE ) ); + + if( IS_UP( m_joyState[i].lY ) && + !IS_UP( m_oldJoyState[i].lY ) ) + listRawInput.AddTail( RageRawInput( DEVICE_JOYSTICK, i+1, JOY_UP, FALSE ) ); + + if( IS_DOWN( m_joyState[i].lY ) && + !IS_DOWN( m_oldJoyState[i].lY ) ) + listRawInput.AddTail( RageRawInput( DEVICE_JOYSTICK, i+1, JOY_DOWN, FALSE ) ); + + + for( BYTE b=0; b<10; b++ ) + { + if( IS_PRESSED(m_joyState[i].rgbButtons[b]) && !IS_PRESSED(m_oldJoyState[i].rgbButtons[b]) ) + listRawInput.AddTail( RageRawInput( DEVICE_JOYSTICK, i+1, b+1, FALSE ) ); + } + } + } + } + + + + return S_OK; +} + + diff --git a/stepmania/src/RageInput.h b/stepmania/src/RageInput.h new file mode 100644 index 0000000000..cfb3779fab --- /dev/null +++ b/stepmania/src/RageInput.h @@ -0,0 +1,133 @@ +//----------------------------------------------------------------------------- +// File: RageInput.h +// +// Desc: DirectInput wrapper class +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _RAGEINPUT_H_ +#define _RAGEINPUT_H_ + + +#include +#include "RageUtil.h" + + +#define NUM_JOYSTICKS 4 + +// button byte codes for directional pad +#define JOY_LEFT 101 +#define JOY_RIGHT 102 +#define JOY_UP 103 +#define JOY_DOWN 104 + + + +#define DEVICE_NONE 0 +#define DEVICE_KEYBOARD 1 +#define DEVICE_JOYSTICK 2 + + +class RageRawInput +{ +public: + RageRawInput() { device = device_no = button = just_pressed = 0; }; + RageRawInput( BYTE device, + BYTE device_no, + BYTE button, + BYTE just_pressed ) + { + this->device = device; + this->device_no = device_no; + this->button = button; + this->just_pressed = just_pressed; + }; + RageRawInput( CString sEncoding ) + { + CStringArray a; + split( sEncoding, "-", a); + this->device = atoi( a[0] ); + this->device_no = atoi( a[1] ); + this->button = atoi( a[2] ); + }; + CString Encode() { return ssprintf("%u-%u-%u", device, device_no, button); }; + + BOOL LookupChar( TCHAR &char_out ) const; + CString GetDescription() const; + + BOOL IsBlank() { return device == DEVICE_NONE; }; + + BYTE device; + BYTE device_no; + BYTE button; + BYTE just_pressed; +}; + + + +typedef CList RageRawInputList; + + +class RageInput +{ + // Our Windows Handle + HWND m_hWnd; + + // Main DirectInput Object + LPDIRECTINPUT8 m_pDI; + // Keyboard Device + LPDIRECTINPUTDEVICE8 m_pKeyboard; + // Mouse Device + LPDIRECTINPUTDEVICE8 m_pMouse; +public: + // hack: make them public to allow the callbacks access to the pointers + // Joystick Devices + LPDIRECTINPUTDEVICE8 m_pJoystick[NUM_JOYSTICKS]; + +private: + // Arrays for Keyboard Data + byte m_keys[256]; + byte m_oldKeys[256]; + + // DirectInput mouse state structure + DIMOUSESTATE2 m_mouseState; + + // Joystick data for 4 controllers + DIJOYSTATE2 m_joyState[4]; + DIJOYSTATE2 m_oldJoyState[4]; + + INT m_AbsPosition_x; + INT m_AbsPosition_y; + + INT m_RelPosition_x; + INT m_RelPosition_y; + +public: + RageInput(HWND hWnd); + ~RageInput(); + + // Initialize DirectInput Resources + HRESULT Initialize(); + // Release all DirectInput Resources + VOID Release(); + // Get our Devices State + HRESULT GetRawInput( RageRawInputList &listRawInput ); + + LPDIRECTINPUT8 GetDirectInput() { return m_pDI; } + LPDIRECTINPUTDEVICE8 GetMouseDevice() { return m_pMouse; } + LPDIRECTINPUTDEVICE8 GetKeyboardDevice() { return m_pKeyboard; } + LPDIRECTINPUTDEVICE8 GetJoystickDevice( int i ) { return m_pJoystick[i]; } + +// DIMOUSESTATE2 GetMouseState() { return dimMouseState; } + VOID GetAbsPosition( DWORD &x, DWORD &y ) { x = m_AbsPosition_x; y = m_AbsPosition_y; } + +}; + + +typedef RageInput* LPRageInput; + +extern LPRageInput INPUT; // global and accessable from anywhere in our program + + +#endif \ No newline at end of file diff --git a/stepmania/src/RageMovieTexture.cpp b/stepmania/src/RageMovieTexture.cpp new file mode 100644 index 0000000000..03b5ad1da1 --- /dev/null +++ b/stepmania/src/RageMovieTexture.cpp @@ -0,0 +1,417 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageMovieTexture.cpp +// +// Desc: Based on the DShowTextures example in the DX8 SDK. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// In-line Links +//----------------------------------------------------------------------------- +#pragma comment(lib, "winmm.lib") +#pragma comment(lib, "dxerr8.lib") + +// Link with the DirectShow base class libraries +#if defined(DEBUG) | defined(_DEBUG) + #pragma comment(lib, "C:\\Program Files\\DX8aSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Debug\\strmbasd.lib") +#else + #pragma comment(lib, "C:\\Program Files\\DX8aSDK\\samples\\Multimedia\\DirectShow\\BaseClasses\\Release\\strmbase.lib") +#endif + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "RageMovieTexture.h" +#include "dxerr8.h" +#include "DXUtil.h" +#include "RageUtil.h" + +#include +#include + +//----------------------------------------------------------------------------- +// Global Constants +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// CTextureRenderer constructor +//----------------------------------------------------------------------------- +CTextureRenderer::CTextureRenderer( LPUNKNOWN pUnk, HRESULT *phr ) + : CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer), + NAME("Texture Renderer"), pUnk, phr) +{ + // Store and ARageef the texture for our use. + m_pTexture = NULL; + m_bLocked = FALSE; + *phr = S_OK; +} + + +//----------------------------------------------------------------------------- +// CTextureRenderer destructor +//----------------------------------------------------------------------------- +CTextureRenderer::~CTextureRenderer() +{ + // Do nothing +} + + +//----------------------------------------------------------------------------- +// CheckMediaType: This method forces the graph to give us an R8G8B8 video +// type, making our copy to texture memory trivial. +//----------------------------------------------------------------------------- +HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt) +{ + HRESULT hr = E_FAIL; + VIDEOINFO *pvi; + + // Reject the connection if this is not a video type + if( *pmt->FormatType() != FORMAT_VideoInfo ) { + return E_INVALIDARG; + } + + // Only accept RGB24 + pvi = (VIDEOINFO *)pmt->Format(); + if(IsEqualGUID( *pmt->Type(), MEDIATYPE_Video) && + IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB24)) +// IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB565)) + { + hr = S_OK; + } + + return hr; +} + + +//----------------------------------------------------------------------------- +// SetMediaType: Graph connection has been made. +//----------------------------------------------------------------------------- +HRESULT CTextureRenderer::SetMediaType(const CMediaType *pmt) +{ +// HRESULT hr; + + // Retrive the size of this media type + VIDEOINFO *pviBmp; // Bitmap info header + pviBmp = (VIDEOINFO *)pmt->Format(); + m_lVidWidth = pviBmp->bmiHeader.biWidth; + m_lVidHeight = abs(pviBmp->bmiHeader.biHeight); + m_lVidPitch = (m_lVidWidth * 3 + 3) & ~(3); // We are forcing RGB24 + + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// SetRenderTarget: Save all the information we'll need to render to a D3D texture. +//----------------------------------------------------------------------------- +HRESULT CTextureRenderer::SetRenderTarget(LPDIRECT3DTEXTURE8 pTexture) +{ + HRESULT hr; + + if (pTexture == NULL) { + DXTRACE_ERR(TEXT("SetRenderTarget called with a NULL texture!"), 0); + return E_FAIL; + } + m_pTexture = pTexture; + + + // get the format of the texture + D3DSURFACE_DESC ddsd; + if ( FAILED( hr = m_pTexture->GetLevelDesc( 0, &ddsd ) ) ) { + DXTRACE_ERR(TEXT("Could not get level Description of D3DX texture! hr = 0x%x"), hr); + return hr; + } + + m_TextureFormat = ddsd.Format; + if (m_TextureFormat != D3DFMT_A8R8G8B8 && + m_TextureFormat != D3DFMT_A1R5G5B5) { + DXTRACE_ERR(TEXT("Texture is format we can't handle! Format = 0x%x"), m_TextureFormat); + return E_FAIL; + } + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// DoRenderSample: A sample has been delivered. Copy it to the texture. +//----------------------------------------------------------------------------- +HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample ) +{ + BYTE *pBmpBuffer, *pTxtBuffer; // Bitmap buffer, texture buffer + LONG lTxtPitch; // Pitch of bitmap, texture + + // Get the video bitmap buffer + pSample->GetPointer( &pBmpBuffer ); + + // Lock the Texture + D3DLOCKED_RECT d3dlr; + if (FAILED(m_pTexture->LockRect(0, &d3dlr, 0, 0))) { + DXTRACE_ERR_NOMSGBOX(TEXT("Failed to lock the texture!"), E_FAIL); + return E_FAIL; + } + + m_bLocked = TRUE; + + // Get the texture buffer & pitch + pTxtBuffer = static_cast(d3dlr.pBits); + lTxtPitch = d3dlr.Pitch; + + + // Copy the bits + // OPTIMIZATION OPPORTUNITY: Use a video and texture + // format that allows a simpler copy than this one. + if (m_TextureFormat == D3DFMT_A8R8G8B8) { + for(int y = 0; y < m_lVidHeight; y++ ) { + BYTE *pBmpBufferOld = pBmpBuffer; + BYTE *pTxtBufferOld = pTxtBuffer; + for (int x = 0; x < m_lVidWidth; x++) { + pTxtBuffer[0] = pBmpBuffer[0]; + pTxtBuffer[1] = pBmpBuffer[1]; + pTxtBuffer[2] = pBmpBuffer[2]; + pTxtBuffer[3] = 0xff; + pTxtBuffer += 4; + pBmpBuffer += 3; + } + pBmpBuffer = pBmpBufferOld + m_lVidPitch; + pTxtBuffer = pTxtBufferOld + lTxtPitch; + } + } + + if (m_TextureFormat == D3DFMT_A1R5G5B5) { + for(int y = 0; y < m_lVidHeight; y++ ) { + BYTE *pBmpBufferOld = pBmpBuffer; + BYTE *pTxtBufferOld = pTxtBuffer; + for (int x = 0; x < m_lVidWidth; x++) { + *(WORD *)pTxtBuffer = + 0x8000 + + ((pBmpBuffer[2] & 0xF8) << 7) + + ((pBmpBuffer[1] & 0xF8) << 2) + + (pBmpBuffer[0] >> 3); + pTxtBuffer += 2; + pBmpBuffer += 3; + } + pBmpBuffer = pBmpBufferOld + m_lVidPitch; + pTxtBuffer = pTxtBufferOld + lTxtPitch; + } + } + + + // Unlock the Texture + if (FAILED(m_pTexture->UnlockRect(0))) { + DXTRACE_ERR_NOMSGBOX(TEXT("Failed to unlock the texture!"), E_FAIL); + return E_FAIL; + } + + m_bLocked = FALSE; + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// RageMovieTexture constructor +//----------------------------------------------------------------------------- +RageMovieTexture::RageMovieTexture( LPRageScreen pScreen, CString sFilePath ) : + RageTexture( pScreen, sFilePath ) +{ + RageLog( "RageBitmapTexture::RageBitmapTexture()" ); + + Create(); + + CreateFrameRects(); +} + +RageMovieTexture::~RageMovieTexture() +{ + CleanupDShow(); + + SAFE_RELEASE(m_pd3dTexture); +} + +//----------------------------------------------------------------------------- +// GetTexture +//----------------------------------------------------------------------------- +LPDIRECT3DTEXTURE8 RageMovieTexture::GetD3DTexture() +{ + // Wait until the TextureRenderer is not copying to our texture. + // If we try to draw using the texture while it is locked, the primitive + // will appear without a texture. + // Most of the time, the TextureRenderer is not busy copying (copying + // a frame of video is very quick). If it is busy, it's usually becase + // the video fell behind and is trying to copy several frames in a row + // to catch up. So, if the TextureRenderer is busy, give it a 1ms slice of + // time for it to catch up and copy all the frames it fell behind on. + while( m_pCTR->IsLocked() ) + ::Sleep(1); + + // restart the movie if we reach the end + CheckMovieStatus(); + + return m_pd3dTexture; +} + + +//----------------------------------------------------------------------------- +// RageMovieTexture::Create() +//----------------------------------------------------------------------------- +VOID RageMovieTexture::Create() +{ + HRESULT hr; + + // Initialize the filter graph find and get information about the + // video (dimensions, color depth, etc.) + if( FAILED( hr = InitDShowTextureRenderer() ) ) + RageErrorHr( "Could not initialize the DirectShow Texture Renderer!", hr ); + + if( FAILED( hr = CreateD3DTexture() ) ) + RageErrorHr( "Could not create the D3D Texture!", hr ); + + // Pass the D3D texture to our TextureRenderer so it knows + // where to render new movie frames to. + if( FAILED( hr = m_pCTR->SetRenderTarget(GetD3DTexture()) ) ) + RageErrorHr( "RageMovieTexture: SetRenderTarget failed.", hr ); + + // Start the graph running + if( FAILED( hr = PlayMovie() ) ) + RageErrorHr( "Could not run the DirectShow graph.", hr ); + +} + + + +//----------------------------------------------------------------------------- +// InitDShowTextureRenderer : Create DirectShow filter graph and run the graph +//----------------------------------------------------------------------------- +HRESULT RageMovieTexture::InitDShowTextureRenderer() +{ + HRESULT hr = S_OK; + CComPtr pFTR; // Texture Renderer Filter + CComPtr pFTRPinIn; // Texture Renderer Input Pin + CComPtr pFSrc; // Source Filter + CComPtr pFSrcPinOut; // Source Filter Output Pin + + // Create the filter graph + if( FAILED( m_pGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC) ) ) + RageErrorHr( "Could not create CLSID_FilterGraph!", hr ); + + // Create the Texture Renderer object + m_pCTR = new CTextureRenderer(NULL, &hr); + if( FAILED(hr) ) + RageErrorHr( "Could not create texture renderer object!", hr ); + + // Get a pointer to the IBaseFilter on the TextureRenderer, add it to graph + pFTR = m_pCTR; + if( FAILED( hr = m_pGB->AddFilter(pFTR, L"TEXTURERENDERER" ) ) ) + RageErrorHr( "Could not add renderer filter to graph!", hr ); + + // convert movie file path to wide char string + WCHAR wFileName[MAX_PATH]; + + #ifndef UNICODE + MultiByteToWideChar(CP_ACP, 0, m_sFilePath, -1, wFileName, MAX_PATH); + #else + lstrcpy(wFileName, m_szFilePath); + #endif + + + // Add the source filter + if( FAILED( hr = m_pGB->AddSourceFilter( wFileName, L"SOURCE", &pFSrc ) ) ) + RageErrorHr( "Could not create source filter to graph!", hr ); + + // Find the source's output and the renderer's input + if( FAILED( hr = pFTR->FindPin( L"In", &pFTRPinIn ) ) ) + RageErrorHr( "Could not find input pin!", hr ); + + if( FAILED( hr = pFSrc->FindPin( L"Output", &pFSrcPinOut ) ) ) + RageErrorHr( "Could not find output pin!", hr ); + + // Connect these two filters + if( FAILED( hr = m_pGB->Connect( pFSrcPinOut, pFTRPinIn ) ) ) + RageErrorHr( "Could not connect pins!", hr ); + + // Get the graph's media control, event & position interfaces + m_pGB.QueryInterface(&m_pMC); + m_pGB.QueryInterface(&m_pMP); + m_pGB.QueryInterface(&m_pME); + + // The graph is built, now get the set the output video width and height + m_uImageWidth = m_pCTR->GetVidWidth(); + m_uImageHeight = m_pCTR->GetVidHeight(); + + + return S_OK; +} + +HRESULT RageMovieTexture::CreateD3DTexture() +{ + HRESULT hr; + + ////////////////////////////////////////////////// + // Create the texture that maps to this media type + ////////////////////////////////////////////////// + if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice, + m_uImageWidth, m_uImageHeight, + 1, 0, + D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture ) ) ) + RageErrorHr( "Could not create the D3DX texture!", hr ); + + // D3DXCreateTexture can silently change the parameters on us + D3DSURFACE_DESC ddsd; + if ( FAILED( hr = m_pd3dTexture->GetLevelDesc( 0, &ddsd ) ) ) + RageErrorHr( "Could not get level Description of D3DX texture!", hr ); + + m_uTextureWidth = ddsd.Width; + m_uTextureHeight = ddsd.Height; + m_TextureFormat = ddsd.Format; + if( m_TextureFormat != D3DFMT_A8R8G8B8 && + m_TextureFormat != D3DFMT_A1R5G5B5 ) + RageErrorHr( "Texture is format we can't handle! Format = 0x%x!", m_TextureFormat ); + + + return S_OK; +} + +HRESULT RageMovieTexture::PlayMovie() +{ + HRESULT hr; + + // Start the graph running; + if( FAILED( hr = m_pMC->Run() ) ) + RageErrorHr( "Could not run the DirectShow graph.", hr ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// CheckMovieStatus: If the movie has ended, rewind to beginning +//----------------------------------------------------------------------------- +void RageMovieTexture::CheckMovieStatus() +{ + long lEventCode; + long lParam1; + long lParam2; + + // Check for completion events + m_pME->GetEvent( &lEventCode, &lParam1, &lParam2, 0 ); + if( EC_COMPLETE == lEventCode ) + m_pMP->put_CurrentPosition(0); +} + + +//----------------------------------------------------------------------------- +// CleanupDShow +//----------------------------------------------------------------------------- +void RageMovieTexture::CleanupDShow() +{ + // Shut down the graph + if (m_pMC) m_pMC->Stop(); + if (m_pGB) m_pGB.Release (); +} + diff --git a/stepmania/src/RageMovieTexture.h b/stepmania/src/RageMovieTexture.h new file mode 100644 index 0000000000..79b1f47a08 --- /dev/null +++ b/stepmania/src/RageMovieTexture.h @@ -0,0 +1,99 @@ +//----------------------------------------------------------------------------- +// File: RageMovieTexture.h +// +// Desc: Based on the DShowTextures example in the DX8 SDK. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _RAGEMOVIETEXTURE_H_ +#define _RAGEMOVIETEXTURE_H_ + + +#include "RageScreen.h" +#include +//#include +#include + +#include + +//----------------------------------------------------------------------------- +// Define GUID for Texture Renderer +// {71771540-2017-11cf-AE26-0020AFD79767} +//----------------------------------------------------------------------------- +struct __declspec(uuid("{71771540-2017-11cf-ae26-0020afd79767}")) CLSID_TextureRenderer; + + +//----------------------------------------------------------------------------- +// CTextureRenderer Class Declarations +// +// Usage: 1) CheckMediaType is called by the graph +// 2) SetMediaType is called by the graph +// 3) call GetVidWidth and GetVidHeight to get texture information +// 4) call SetRenderTarget +// 5) Do RenderSample is called by the graph +//----------------------------------------------------------------------------- +class CTextureRenderer : public CBaseVideoRenderer +{ +public: + CTextureRenderer(LPUNKNOWN pUnk,HRESULT *phr); + ~CTextureRenderer(); + +public: + // overwritten methods + HRESULT CheckMediaType(const CMediaType *pmt ); // Format acceptable? + HRESULT SetMediaType(const CMediaType *pmt ); // Video format notification + HRESULT DoRenderSample(IMediaSample *pMediaSample); // New video sample + + // new methods + LONG GetVidWidth() {return m_lVidWidth;}; + LONG GetVidHeight(){return m_lVidHeight;}; + HRESULT SetRenderTarget(LPDIRECT3DTEXTURE8 pTexture); + BOOL IsLocked() { return m_bLocked; }; + +protected: + LONG m_lVidWidth; // Video width + LONG m_lVidHeight; // Video Height + LONG m_lVidPitch; // Video Pitch + + LPDIRECT3DTEXTURE8 m_pTexture; // the video surface we will copy new frames to + D3DFORMAT m_TextureFormat; // Texture format + BOOL m_bLocked; // Is the texture currently locked while we + // copy the movie frame to it? +}; + + +//----------------------------------------------------------------------------- +// RageMovieTexture Class Declarations +//----------------------------------------------------------------------------- +class RageMovieTexture : public RageTexture +{ +public: + RageMovieTexture( LPRageScreen pScreen, CString sFilePath ); + virtual ~RageMovieTexture(); + + LPDIRECT3DTEXTURE8 GetD3DTexture(); + +protected: + virtual VOID Create(); + + virtual HRESULT CreateD3DTexture(); + virtual HRESULT InitDShowTextureRenderer(); + virtual HRESULT PlayMovie(); + virtual void CheckMovieStatus(); + virtual void CleanupDShow(); + + //----------------------------------------------------------------------------- + // DirectShow pointers + //----------------------------------------------------------------------------- + CComPtr m_pGB; // GraphBuilder + CComPtr m_pMC; // Media Control + CComPtr m_pMP; // Media Postion + CComPtr m_pME; // Media Event + CTextureRenderer *m_pCTR; // DShow Texture renderer +}; + +typedef RageMovieTexture* LPRageMovieTexture; + + +#endif \ No newline at end of file diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp new file mode 100644 index 0000000000..22c48972de --- /dev/null +++ b/stepmania/src/RageSound.cpp @@ -0,0 +1,70 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageSound.cpp +// +// Desc: Sound effects library (currently a wrapper around Bass Sound Library). +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + + +#include "RageSound.h" +#include "RageUtil.h" + +#include "bass/bass.h" +#pragma comment(lib, "bass/bass.lib") + + +LPRageSound SOUND = NULL; + + +RageSound::RageSound( HWND hWnd ) +{ + // save the HWND + if( !hWnd ) + RageError( "RageSound called with NULL hWnd." ); + m_hWndApp = hWnd; + + if( BASS_GetVersion() != MAKELONG(1,1) ) + RageError( "BASS version 1.1 DLL could not be loaded. Verify that Bass.dll exists in the program directory."); + + if( !BASS_Init( -1, 44100, BASS_DEVICE_NOSYNC, m_hWndApp ) ) + RageError( "BASS can't initialize sound device." ); + + BASS_Start(); +} + +RageSound::~RageSound() +{ + BASS_Free(); +} + + +HSAMPLE RageSound::LoadSound( const CString sFileName ) +{ + RageLog( "RageSound::LoadSound( '%s' )", sFileName ); + + HSAMPLE hSample = BASS_SampleLoad( FALSE, (void*)((LPCTSTR)sFileName), 0, 0, 0, 0 ); + if( hSample == NULL ) + RageError( ssprintf("RageSound::LoadSound: error loading %s (error code %d)", + sFileName, BASS_ErrorGetCode()) ); + return hSample; +} + +VOID RageSound::UnloadSound( HSAMPLE hSample ) +{ + BASS_SampleFree( hSample ); +} + +VOID RageSound::Play( HSAMPLE hSample ) +{ + if( NULL == BASS_SamplePlay( hSample ) ) + RageError( "There was an error playing a sound sample. Are you sure this is a valid HSAMPLE?" ); +} + +VOID RageSound::Stop( HSAMPLE hSample ) +{ + if( FALSE == BASS_SampleStop( hSample ) ) + RageError( "There was an error stopping a sound sample. Are you sure this is a valid HSAMPLE?" ); +} \ No newline at end of file diff --git a/stepmania/src/RageSound.h b/stepmania/src/RageSound.h new file mode 100644 index 0000000000..2dcc2e150f --- /dev/null +++ b/stepmania/src/RageSound.h @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// File: RageSound.h +// +// Desc: Sound effects library (currently a wrapper around Bass Sound Library). +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _RAGESOUND_H_ +#define _RAGESOUND_H_ + + +#include "bass/bass.h" + + +#define NUM_STREAMS 16 + +#define EFFECT_CHANNEL_1 0 +#define EFFECT_CHANNEL_2 1 +#define EFFECT_CHANNEL_3 2 +#define EFFECT_CHANNEL_4 3 +#define EFFECT_CHANNEL_5 4 +#define ANOUNCER_CHANNEL 13 +#define CROWD_CHANNEL 14 +#define MUSIC_CHANNEL 15 + + +class RageSound +{ +public: + RageSound( HWND hWnd ); + ~RageSound(); + + HSAMPLE LoadSound( const CString sFileName ); + VOID UnloadSound( HSAMPLE hSample ); + VOID Play( HSAMPLE hSample ); + VOID Stop( HSAMPLE hSample ); + +private: + HWND m_hWndApp; // this is set on GRAPHICS_Create() +// HSAMPLE m_hSample[NUM_STREAMS]; +}; + + +typedef RageSound* LPRageSound; + + +extern LPRageSound SOUND; // global and accessable from anywhere in our program + + +#endif \ No newline at end of file diff --git a/stepmania/src/RageTexture.cpp b/stepmania/src/RageTexture.cpp new file mode 100644 index 0000000000..9274bbbdfc --- /dev/null +++ b/stepmania/src/RageTexture.cpp @@ -0,0 +1,120 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageTexture.cpp +// +// Desc: +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "RageTexture.h" +#include "RageUtil.h" + + +//----------------------------------------------------------------------------- +// RageTexture constructor +//----------------------------------------------------------------------------- +RageTexture::RageTexture( LPRageScreen pScreen, CString sFilePath ) : + m_uImageWidth( 0 ), + m_uImageHeight( 0 ), + m_uTextureWidth( 0 ), + m_uTextureHeight( 0 ), + m_uFramesWide( 1 ), + m_uFramesHigh( 1 ), + m_uFrameWidth( 0 ), + m_uFrameHeight( 0 ) +{ +// RageLog( "RageTexture::RageTexture()" ); + + // save a pointer to the D3D device + m_pd3dDevice = pScreen->GetDevice(); + assert( m_pd3dDevice != NULL ); + + // save the file path + m_sFilePath = sFilePath; + m_pd3dTexture = NULL; + m_iRefCount = 1; + + +} + +RageTexture::~RageTexture() +{ + +} + + +VOID RageTexture::CreateFrameRects() +{ + GetFrameDimensionsFromFileName( m_sFilePath, m_uFramesWide, m_uFramesHigh ); + + /////////////////////////////////// + // Fill in the m_FrameRects with the bounds of each frame in the animation. + /////////////////////////////////// + + // calculate the width and height of the frames + m_uFrameWidth = GetImageWidth() / m_uFramesWide; + m_uFrameHeight= GetImageHeight() / m_uFramesHigh; + + for( UINT j=0; j +#include +//#include + + +//----------------------------------------------------------------------------- +// RageTexture Class Declarations +//----------------------------------------------------------------------------- +class RageTexture +{ +public: + RageTexture( LPRageScreen pScreen, CString sFilePath ); + virtual ~RageTexture() PURE; + + virtual LPDIRECT3DTEXTURE8 GetD3DTexture() PURE; + + UINT GetImageWidth() {return m_uImageWidth;}; + UINT GetImageHeight() {return m_uImageHeight;}; + UINT GetTextureWidth() {return m_uTextureWidth;}; + UINT GetTextureHeight() {return m_uTextureHeight;}; + + UINT GetFramesWide() {return m_uFramesWide;}; + UINT GetFramesHigh() {return m_uFramesHigh;}; + UINT GetFrameWidth() {return m_uFrameWidth;}; + UINT GetFrameHeight() {return m_uFrameHeight;}; + LPRECT GetFrameRect( UINT uFrameNo ) {return &m_FrameRects[uFrameNo];}; + UINT GetNumFrames() {return m_FrameRects.GetSize();}; + CString GetFilePath() {return m_sFilePath;}; + + INT m_iRefCount; + +protected: + virtual VOID CreateFrameRects(); + virtual VOID GetFrameDimensionsFromFileName( CString sPath, UINT &uFramesWide, UINT &uFramesHigh ) const; + + CString m_sFilePath; + LPDIRECT3DDEVICE8 m_pd3dDevice; + LPDIRECT3DTEXTURE8 m_pd3dTexture; + + UINT m_uImageWidth, m_uImageHeight; + UINT m_uTextureWidth, m_uTextureHeight; + D3DFORMAT m_TextureFormat; + + // The number of frames of animation in each row and column of this texture. + UINT m_uFramesWide, m_uFramesHigh; + UINT m_uFrameWidth, m_uFrameHeight; + + // RECTs that hold the bounds of each frame in the bitmap. + // e.g., if the texture has 4 frames of animation, the SrcRect for each frame would + // be in m_FrameRects[0..4]. + CArray m_FrameRects; + +}; + + +#endif diff --git a/stepmania/src/RageTextureManager.cpp b/stepmania/src/RageTextureManager.cpp new file mode 100644 index 0000000000..c6a8589f59 --- /dev/null +++ b/stepmania/src/RageTextureManager.cpp @@ -0,0 +1,118 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageTextureManager.cpp +// +// Desc: Loads and releases textures +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "RageTextureManager.h" +#include "RageBitmapTexture.h" +#include "RageMovieTexture.h" +#include "RageUtil.h" +#include + +LPRageTextureManager TM = NULL; + +//----------------------------------------------------------------------------- +// constructor/destructor +//----------------------------------------------------------------------------- +RageTextureManager::RageTextureManager( LPRageScreen pScreen ) +{ + assert( pScreen != NULL ); + m_pScreen = pScreen; + +} + +RageTextureManager::~RageTextureManager() +{ + // delete all textures + POSITION pos = m_mapPathToTexture.GetStartPosition(); + CString key; + LPRageTexture value; + + while( pos != NULL ) // iterate over all k/v pairs in map + { + m_mapPathToTexture.GetNextAssoc( pos, key, value ); + SAFE_DELETE( value ); + } + + m_mapPathToTexture.RemoveAll(); +} + + +//----------------------------------------------------------------------------- +// Load/Unload textures from disk +//----------------------------------------------------------------------------- +LPRageTexture RageTextureManager::LoadTexture( CString sTexturePath ) +{ +// RageLog( "RageTextureManager::LoadTexture(%s).", sTexturePath ); + + // holder for the new texture + LPRageTexture pTexture; + + // Convert the path to lowercase so that we don't load duplicates. + // Really, this does not solve the duplicate problem. We could have to copies + // of the same bitmap if there are equivalent but different paths + // (e.g. "Bitmaps\me.bmp" and "..\Rage PC Edition\Bitmaps\me.bmp" ). + sTexturePath.MakeLower(); + + if( m_mapPathToTexture.Lookup( sTexturePath, pTexture ) ) // if the texture already exists in the map + { +// RageLog( ssprintf("Found that '%s' is already loaded. Using the loaded copy.", sTexturePath) ); + pTexture->m_iRefCount++; + } + else + { + RageLog( ssprintf("Didn't find '%s' already loaded. Creating a new texture.", sTexturePath) ); + + CString sDrive, sDir, sFName, sExt; + splitpath( FALSE, sTexturePath, sDrive, sDir, sFName, sExt ); + + if( sExt == "avi" || sExt == "mpg" || sExt == "mpeg" ) + pTexture = (LPRageTexture) new RageMovieTexture( m_pScreen, sTexturePath ); + else + pTexture = (LPRageTexture) new RageBitmapTexture( m_pScreen, sTexturePath ); + + m_mapPathToTexture.SetAt( sTexturePath, pTexture ); + } + + return pTexture; +} + +VOID RageTextureManager::UnloadTexture( CString sTexturePath ) +{ +// RageLog( "RageTextureManager::UnloadTexture(%s).", sTexturePath ); + + if( sTexturePath == "" ) + { + RageLog( "RageTextureManager::UnloadTexture() tried to Unload a blank" ); + return; + } + + sTexturePath.MakeLower(); + LPRageTexture pTexture; + + if( m_mapPathToTexture.Lookup( sTexturePath, pTexture ) ) // if the texture exists in the map + { + pTexture->m_iRefCount--; + if( pTexture->m_iRefCount == 0 ) // there are no more references to this texture + { + RageLog( ssprintf("The texture '%s' has no more references. It will be deleted.", sTexturePath) ); + SAFE_DELETE( pTexture ); // free the texture + m_mapPathToTexture.RemoveKey( sTexturePath ); // and remove the key in the map + } +// else +// RageLog( ssprintf("The texture '%s' has %d more references. It will not be deleted.", +// sTexturePath, pTexture->m_iRefCount) ); + + } + else + RageError( ssprintf("Tried to Unload a texture that wasn't loaded. '%s'", sTexturePath) ); + +} diff --git a/stepmania/src/RageTextureManager.h b/stepmania/src/RageTextureManager.h new file mode 100644 index 0000000000..02541618aa --- /dev/null +++ b/stepmania/src/RageTextureManager.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// File: RageTextureManager.h +// +// Desc: Loads and releases textures +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +class RageTextureManager; +typedef RageTextureManager* LPRageTextureManager; + + + + +#ifndef _RAGETEXTUREMANAGER_H_ +#define _RAGETEXTUREMANAGER_H_ + + +#include "RageTexture.h" +//#include +//#include + + +//----------------------------------------------------------------------------- +// RageTextureManager Class Declarations +//----------------------------------------------------------------------------- +class RageTextureManager +{ +public: + RageTextureManager( LPRageScreen pScreen ); + ~RageTextureManager(); + + LPRageTexture LoadTexture( CString sTexturePath ); + VOID UnloadTexture( CString sTexturePath ); + +protected: + LPRageScreen m_pScreen; + + // map from file name to a texture holder + CTypedPtrMap m_mapPathToTexture; +}; + +extern LPRageTextureManager TM; // global and accessable from anywhere in our program + +#endif diff --git a/stepmania/src/RageUtil.cpp b/stepmania/src/RageUtil.cpp new file mode 100644 index 0000000000..3b24e8181a --- /dev/null +++ b/stepmania/src/RageUtil.cpp @@ -0,0 +1,297 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: RageUtil.cpp +// +// Desc: +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#include "RageUtil.h" + + +//----------------------------------------------------------------------------- +// UTIL globals +//----------------------------------------------------------------------------- +const CString g_sLogFileName = "debug.log"; + + +//----------------------------------------------------------------------------- +// Name: randomf() +// Desc: +//----------------------------------------------------------------------------- +FLOAT randomf( FLOAT low, FLOAT high ) +{ + return low + ( high - low ) * ( (FLOAT)rand() ) / RAND_MAX; +} + +//----------------------------------------------------------------------------- +// Name: roundf() +// Desc: +//----------------------------------------------------------------------------- +int roundf( FLOAT f ) +{ + return (int)((f)+0.5f); +} + +int roundf( double f ) +{ + return (int)((f)+0.5f); +} + +//----------------------------------------------------------------------------- +// Name: RageLogStart() +// Desc: +//----------------------------------------------------------------------------- +void RageLogStart() +{ + // delete the old log and create a new one + DeleteFile( g_sLogFileName ); + FILE *fp = NULL; + fp = fopen( g_sLogFileName, "w" ); + fclose( fp ); + + + SYSTEMTIME st; + GetLocalTime( &st ); + + RageLog( "%s: last compiled on %s.", g_sLogFileName, __TIMESTAMP__ ); + RageLog( "Log starting %.4d-%.2d-%.2d %.2d:%.2d:%.2d", + st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond ); + RageLog( "\n" ); +} + + +//----------------------------------------------------------------------------- +// Name: RageLog() +// Desc: +//----------------------------------------------------------------------------- +void RageLog( LPCTSTR fmt, ...) +{ + +#if defined(DEBUG) | defined(_DEBUG) + va_list va; + va_start(va, fmt); + + CString sBuff = vssprintf( fmt, va ); + sBuff += "\n"; + + FILE *fp = NULL; + + // open our logging file + fp = fopen( g_sLogFileName, "a" ); + if( fp==NULL ) + RageLog( ssprintf("Couldn't write to log %s", g_sLogFileName) ); + + fprintf(fp, sBuff); + + fclose(fp); +#endif + +} + + +//----------------------------------------------------------------------------- +// Name: ssprintf() +// Desc: +//----------------------------------------------------------------------------- +CString ssprintf( LPCTSTR fmt, ...) +{ + va_list va; + va_start(va, fmt); + return vssprintf(fmt, va); +} + + +//----------------------------------------------------------------------------- +// Name: vssprintf() +// Desc: +//----------------------------------------------------------------------------- +CString vssprintf( LPCTSTR fmt, va_list argList) +{ + CString str; + str.FormatV(fmt, argList); + return str; +} + + + +//----------------------------------------------------------------------------- +// Name: join() +// Desc: +//----------------------------------------------------------------------------- +CString join(CString Deliminator, CStringArray& Source) +{ + CString csReturn; + CString csTmp; + + // Loop through the Array and Append the Deliminator + for( int iNum = 0; iNum < Source.GetSize(); iNum++ ) { + csTmp += Source.GetAt(iNum); + csTmp += Deliminator; + } + csReturn = csTmp.Left(csTmp.GetLength() - 1); + return csReturn; +} + + +//----------------------------------------------------------------------------- +// Name: split() +// Desc: +//----------------------------------------------------------------------------- +void split( CString Source, CString Deliminator, CStringArray& AddIt ) +{ + CString newCString; + CString tmpCString; + CString AddCString; + + int pos1 = 0; + int pos = 0; + + newCString = Source; + do { + pos1 = 0; + pos = newCString.Find(Deliminator, pos1); + if ( pos != -1 ) { + CString AddCString = newCString.Left(pos); + if (!AddCString.IsEmpty()) + AddIt.Add(AddCString); + + tmpCString = newCString.Mid(pos + Deliminator.GetLength()); + newCString = tmpCString; + } + } while ( pos != -1 ); + + if (!newCString.IsEmpty()) + AddIt.Add(newCString); +} + + +//----------------------------------------------------------------------------- +// Name: splitpath() +// Desc: +//----------------------------------------------------------------------------- +void splitpath (BOOL UsingDirsOnly, CString Path, CString& Drive, CString& Dir, CString& FName, CString& Ext) +{ + + int nSecond; + + // Look for a UNC Name! + if (Path.Left(2) == "\\\\") { + int nFirst = Path.Find("\\",3); + nSecond = Path.Find("\\",nFirst + 1); + if (nSecond == -1) { + Drive = Path; + Dir = ""; + FName = ""; + Ext = ""; + } + else if (nSecond > nFirst) + Drive = Path.Left(nSecond); + } + else { // Look for normal Drive Structure + nSecond = 2; + Drive = Path.Left(2); + } + + if (UsingDirsOnly) { + Dir = Path.Right((Path.GetLength() - nSecond) - 1); + FName = ""; + Ext = ""; + } + else { + int nDirEnd = Path.ReverseFind('\\'); + if (nDirEnd == Path.GetLength()) { + Dir = ""; + FName = ""; + Ext = ""; + } + else { + + Dir = Path.Mid(nSecond + 1, (nDirEnd - nSecond) - 1); + + int nFileEnd = Path.ReverseFind('.'); + if (nFileEnd != -1) { + + if (nDirEnd > nFileEnd) { + FName = Path.Right(Path.GetLength() - nDirEnd); + Ext = ""; + } + else { + FName = Path.Mid(nDirEnd + 1, (nFileEnd - nDirEnd) - 1); + Ext = Path.Right((Path.GetLength() - nFileEnd) - 1); + } + } + else { + FName = Path.Right((Path.GetLength() - nDirEnd) - 1); + Ext = ""; + } + } + } +} + +void GetDirListing( CString sPath, CStringArray &AddTo, BOOL bOnlyDirs ) +{ + WIN32_FIND_DATA fd; + HANDLE hFind = ::FindFirstFile( sPath, &fd ); + + if( INVALID_HANDLE_VALUE != hFind ) + { + do + { + if( !bOnlyDirs || fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + CString sDirName( fd.cFileName ); + if( sDirName != "." && sDirName != ".." ) + AddTo.Add( sDirName ); + } + } while( ::FindNextFile( hFind, &fd ) ); + ::FindClose( hFind ); + } +} + +BOOL DoesFileExist( CString sPath ) +{ + RageLog( "DoesFileExist(%s)", sPath ); + + DWORD dwAttr = GetFileAttributes( sPath ); + if( dwAttr == (DWORD)-1 ) + return FALSE; + else + return TRUE; + +} + +int CompareCStrings(const void *arg1, const void *arg2) +{ + CString str1 = *(CString *)arg1; + CString str2 = *(CString *)arg2; + return str1.CompareNoCase( str2 ); +} + +void SortCStringArray( CStringArray &AddTo, BOOL bSortAcsending ) +{ + qsort( AddTo.GetData(), AddTo.GetSize(), sizeof(CString), CompareCStrings ); +} + +//----------------------------------------------------------------------------- +// Name: DisplayErrorAndDie() +// Desc: +//----------------------------------------------------------------------------- + +VOID DisplayErrorAndDie( CString sError ) +{ + RageLog( "" ); + RageLog( "// Fatal Error /////////////////////////////" ); + RageLog( sError ); + RageLog( "////////////////////////////////////////////" ); + + // Something very bad happened. Display an error dialog, then exit right away. + MessageBox( + NULL, // handle of owner window + sError, // text in message box + "Fatal Error", // address of title of message box + MB_OK | MB_ICONERROR // style of message box + ); + exit(1); +} diff --git a/stepmania/src/RageUtil.h b/stepmania/src/RageUtil.h new file mode 100644 index 0000000000..89e58b240c --- /dev/null +++ b/stepmania/src/RageUtil.h @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// File: RageUtil.h +// +// Desc: +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _RAGEUTIL_H_ +#define _RAGEUTIL_H_ + +//----------------------------------------------------------------------------- +// SAFE_ Macros +//----------------------------------------------------------------------------- +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + + +//----------------------------------------------------------------------------- +// Other Macros +//----------------------------------------------------------------------------- +#define RECTWIDTH(rect) ((rect).right - (rect).left) +#define RECTHEIGHT(rect) ((rect).bottom - (rect).top) + + +//----------------------------------------------------------------------------- +// Misc helper functions +//----------------------------------------------------------------------------- + +// Simple function for generating random numbers +FLOAT randomf( FLOAT low=-1.0f, FLOAT high=1.0f ); +int roundf( FLOAT f ); +int roundf( double f ); + +CString ssprintf( LPCTSTR fmt, ...); +CString vssprintf( LPCTSTR fmt, va_list argList ); + + +/* + @FUNCTION: Splits a Path into 4 parts (Directory, Drive, Filename, Extention). + NOTE: Supports UNC path names. + @PARAM1: Whether the Supplied Path (PARAM2) contains a directory name only + or a file name (Reason: some directories will end with "xxx.xxx" + which is like a file name). + @PARAM2: Path to Split. + @PARAM3: (Referenced) Directory. + @PARAM4: (Referenced) Drive. + @PARAM5: (Referenced) Filename. + @PARAM6: (Referenced) Extention. +*/ +void splitpath(BOOL UsingDirsOnly, CString Path, CString& Drive, CString& Dir, CString& FName, CString& Ext); + +/* + @FUNCTION: Splits a CString into an CStringArray according the Deliminator. + NOTE: Supports UNC path names. + @PARAM1: Source string to be Split. + @PARAM2: Deliminator. + @PARAM3: (Referenced) CStringArray to Add to. +*/ +void split(CString Source, CString Deliminator, CStringArray& AddIt ); + +/* + @FUNCTION: Joins a CStringArray to create a CString according the Deliminator. + @PARAM1: Deliminator. + @PARAM2: (Referenced) CStringArray to Add to. +*/ +CString join(CString Deliminator, CStringArray& Source); + +void GetDirListing( CString sPath, CStringArray &AddTo, BOOL bOnlyDirs=FALSE ); + +BOOL DoesFileExist( CString sPath ); + +int CompareCStrings(const void *arg1, const void *arg2); +void SortCStringArray( CStringArray &AddTo, BOOL bSortAcsending = TRUE ); + +//----------------------------------------------------------------------------- +// Log helpers +//----------------------------------------------------------------------------- +void RageLogStart(); +void RageLog( LPCTSTR fmt, ...); + +//----------------------------------------------------------------------------- +// Error helpers +//----------------------------------------------------------------------------- +#include "dxerr8.h" +#pragma comment(lib, "dxerr8.lib") + + +VOID DisplayErrorAndDie( CString sError ); + + +//#if defined(DEBUG) | defined(_DEBUG) + #define RageError(str) DisplayErrorAndDie( ssprintf( "%s\n\n%s(%d)", str, __FILE__, (DWORD)__LINE__, str) ) + #define RageErrorHr(str,hr) DisplayErrorAndDie( ssprintf("%s (%s)\n\n%s(%d)", str, DXGetErrorString8(hr), __FILE__, (DWORD)__LINE__, str) ) +//#else +// #define RageError(str) (0L) +// #define RageErrorHr(str,hr) (hr) +//#endif + + + + +#endif diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp new file mode 100644 index 0000000000..224eae9b7b --- /dev/null +++ b/stepmania/src/Song.cpp @@ -0,0 +1,417 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Song.cpp +// +// Desc: Holds metadata for a song and the song's step data. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "Util.h" +#include "IniFile.h" +#include "BmsFile.h" +#include "Steps.h" +#include "RageUtil.h" + +#include "Song.h" +#include + + +////////////////////////////// +// Song +////////////////////////////// + +bool Song::LoadFromSongDir( CString sDir ) +{ + RageLog( "Song::LoadFromSongDir(%s)", sDir ); + + // make sure there is a trailing '\\' at the end of sDir + if( sDir.Right(1) != "\\" ) + sDir += "\\"; + + // save song dir + m_sSongDir = sDir; + + // We are going to load from either a .song or .msd file. + // If no .song files exist, then look for an .msd. + + CStringArray arrayBMSFileNames; + GetDirListing( sDir + CString("*.bms"), arrayBMSFileNames ); + int iNumBMSFiles = arrayBMSFileNames.GetSize(); + + CStringArray arrayMSDFileNames; + GetDirListing( sDir + CString("*.msd"), arrayMSDFileNames ); + int iNumMSDFiles = arrayMSDFileNames.GetSize(); + + /* + int j; + RageLog( "Found the following .bms files:" ); + for( j=0; j 0 ) + { + for( int i=0; i 0 ) + RageError( ssprintf("Found more than one MSD file in '%s'. Which should I use?", sDir) ); + else + RageError( ssprintf("Couldn't find any BMS or MSD files in '%s'", sDir) ); + + + return TRUE; + +} + +BOOL Song::LoadFromBMSFile( CString sPath ) +{ + RageLog( "Song::LoadFromBMSFile(%s)", sPath ); + + BmsFile bms( sPath ); + bms.ReadFile(); + + Steps new_steps; // just assume one steps per file for now + + CMapStringToString &mapValues = bms.mapValues; + + POSITION pos = mapValues.GetStartPosition(); + while( pos != NULL ) + { + CString valuename; + CString data_string; + CStringArray data_array; + mapValues.GetNextAssoc( pos, valuename, data_string ); + split(data_string, ":", data_array); + + // handle the data + if( valuename == "#PLAYER" ) + ; + + else if( valuename == "#GENRE" ) + m_sCreator = data_array[0]; + + else if( valuename == "#TITLE" ) + m_sTitle = data_array[0]; + + else if( valuename == "#ARTIST" ) + m_sArtist = data_array[0]; + + else if( valuename == "#BPM" ) + m_fBPM = (FLOAT)atof( data_array[0] ); + + else if( valuename == "#PLAYLEVEL" ) + new_steps.iDifficulty = atoi( data_array[0] ); + + else if( valuename == "#BackBMP" || valuename == "#backBMP") + m_sBackground = data_array[0]; + + else if( valuename == "#WAV99" ) + m_sMusic = data_array[0]; + + else if( valuename.GetLength() == 6 ) // this is probably step or offset data. Looks like "#00705" + { + int iMeasureNo = atoi( valuename.Mid(1,3) ); + int iNoteNum = atoi( valuename.Mid(4,2) ); + CString sNoteData = data_array[0]; + CArray arrayNotes; + + for( int i=0; i mapBMSNumberToOurStepBit; +mapBMSNumberToOurStepBit[11] = 0x0001; +mapBMSNumberToOurStepBit[12] = 0x0002; +mapBMSNumberToOurStepBit[13] = 0x0004; +mapBMSNumberToOurStepBit[14] = 0x0008; +mapBMSNumberToOurStepBit[15] = 0x0010; +mapBMSNumberToOurStepBit[16] = 0x0020; +mapBMSNumberToOurStepBit[21] = 0x0040; +mapBMSNumberToOurStepBit[22] = 0x0080; +mapBMSNumberToOurStepBit[23] = 0x0100; +mapBMSNumberToOurStepBit[24] = 0x0200; +mapBMSNumberToOurStepBit[25] = 0x0400; +mapBMSNumberToOurStepBit[26] = 0x0800; + + new_steps.StepArray[iStepIndex] |= mapBMSNumberToOurStepBit[iNoteNum]; + new_steps.StatusArray[iStepIndex] = not_stepped_on; + + } + } + } + } + + int iNumSteps = 0; + for( int i=0; i") >0 ) new_steps.sDescription = "BASIC"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "ANOTHER"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "TRICK"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "MANIAC"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "SSR"; + else if( m_sTitle.Find("<6PANELS BASIC>") >0 ) new_steps.sDescription = "BASIC"; + else if( m_sTitle.Find("<6PANELS ANOTHER>") >0 ) new_steps.sDescription = "ANOTHER"; + else if( m_sTitle.Find("<6PANELS TRICK>") >0 ) new_steps.sDescription = "TRICK"; + else if( m_sTitle.Find("<6PANELS MANIAC>") >0 ) new_steps.sDescription = "MANIAC"; + else if( m_sTitle.Find("<6PANELS SSR>") >0 ) new_steps.sDescription = "SSR"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "BASIC DOUBLE"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "ANOTHER DOUBLE"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "TRICK DOUBLE"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "MANIAC DOUBLE"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "SSR DOUBLE"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "COUPLE"; + else if( m_sTitle.Find("") >0 ) new_steps.sDescription = "BATTLE"; + else new_steps.sDescription = "UNKNOWN"; + + if( new_steps.sDescription.Find("COUPLE") >0 ) new_steps.type = st_couple; + else if( new_steps.sDescription.Find("BATTLE") >0 ) new_steps.type = st_couple; + else if( new_steps.sDescription.Find("DOUBLE") >0 ) new_steps.type = st_double; + else new_steps.type = st_single; + + arraySteps.Add( new_steps ); + + // strip steps type out of description + m_sTitle.Replace( " <" + new_steps.sDescription + ">", "" ); + + FillEmptyValuesWithDefaults(); + + return TRUE; +} + + +BOOL Song::LoadFromMSDFile( CString sPath ) +{ + RageLog( "Song::LoadFromMSDFile(%s)", sPath ); + + + // BROKEN + /* + CStdioFile file; + if( !file.Open( GetSongFilePath(), CFile::modeRead ) ) + RageError( ssprintf("Error opening Song file '%s'.", GetSongFilePath()) ); + + // read the whole file into a sFileText + CString sFileText; + CString buffer; + while( file.ReadString(buffer) ) + sFileText += buffer; + file.Close(); + + // split sFileText into strings containing each value expression + CStringArray arrayValueStrings; + split( sFileText, ";", arrayValueStrings ); + + + // for each value expression string, parse it into a value name and data + for( int i=0; i < arrayValueStrings.GetSize(); i++ ) + { + CString sValueString = arrayValueStrings[i]; + + // split the value string into tokens + CStringArray arrayValueTokens; + split( sValueString, ":", arrayValueTokens ); + + CString sValueName = arrayValueTokens.GetAt( 0 ); + + // handle the data + if( sValueName == "#TITLE" ) + m_sTitle = arrayValueTokens[1]; + + else if( sValueName == "#ARTIST" ) + m_sArtist = arrayValueTokens[1]; + + else if( sValueName == "#REMIXER" || sValueName == "#MSD") + m_sCreator = arrayValueTokens[1]; + + else if( sValueName == "#BPM" ) + m_fBPM = (FLOAT)atof( arrayValueTokens[1] ); + + else if( sValueName == "#OFFSET" ) + m_fBeatOffset = (FLOAT)atoi( arrayValueTokens[1] ); + + else if( sValueName == "#GAP" ) + // the units of GAP is 1/10 second + m_fBeatOffset = (FLOAT)atof( arrayValueTokens[1] ) / 10.0f; + + else if( sValueName == "#MUSIC" ) + m_sMusic = arrayValueTokens[1]; + + else if( sValueName == "#SAMPLE" ) + m_sSample = arrayValueTokens[1]; + + else if( sValueName == "#BANNER" ) + m_sBanner = arrayValueTokens[1]; + + else if( sValueName == "#BACKGROUND" ) + m_sBackground = arrayValueTokens[1]; + + // handle STEPS defined in the file for backwards compatibility with MSD files + else if( sValueName == "#SINGLE" || sValueName == "#DOUBLE" || sValueName == "#COUPLE" ) + { + Steps s; + if( sValueName == "#SINGLE" ) + s.type = st_single; + else if( sValueName == "#DOUBLE" ) + s.type = st_double; + else if( sValueName == "#COUPLE" ) + s.type = st_couple; + else + RageError( ssprintf("Unknown game type '%s' in '%s'", sValueName, GetSongFilePath()) ); + + s.sDescription = arrayValueTokens[1]; + s.iDifficulty = atoi( arrayValueTokens[2] ); + s.sPadDataLeft = arrayValueTokens[3]; + if( sValueName == "#DOUBLE" || sValueName == "#COUPLE" ) + s.sPadDataRight = arrayValueTokens[4]; + + switch( s.type) + { + case st_single: + arraySingleSteps.Add( s ); + break; + case st_double: + arrayDoubleSteps.Add( s ); + break; + case st_couple: + arrayCoupleSteps.Add( s ); + break; + } + } + else + // do nothing. We don't care about this value name + ; + } + + FillEmptyValuesWithDefaults(); + */ + + return TRUE; +} + + +void Song::FillEmptyValuesWithDefaults() +{ + if( m_sTitle == "" ) m_sTitle = "Untitled song"; + if( m_sArtist == "" ) m_sArtist = "Unknown artist"; + if( m_sCreator == "" ) m_sCreator = ""; + if( m_fBPM == 0.0 ) + RageError( ssprintf("No #BPM specified in '%s.'", GetSongFilePath()) ); + + if( m_fBeatOffset == 0.0 ) + RageLog( "Warning: #OFFSET or #GAP in '%s' is either 0.0, or was missing.", GetSongFilePath() ); + + if( m_sMusic == "" ) + { + m_sMusic = "music.mp3"; + if( !DoesFileExist( m_sSongDir + m_sMusic ) ) + { + // music.mp3 didn't exist, so search for any mp3 in the same dir + CStringArray arrayMP3Files; + GetDirListing( m_sSongDir + CString("*.mp3"), arrayMP3Files ); + + if( arrayMP3Files.GetSize() != 0 ) // we found a .mp3 file! + m_sMusic = arrayMP3Files.GetAt( 0 ); + else + RageError( ssprintf("Music could not be found. In Song file '%s' no #MUSIC was specified, music.mp3 doesn't exist, and no other MP3s could be found.", GetSongFilePath()) ); + } + } + if( m_sSample == "" ) + { + m_sSample = "sample.mp3"; + if( !DoesFileExist( m_sSongDir + m_sSample ) ) + m_sSample = m_sMusic; // we assured above that the m_sMusic file exists + } + if( m_sBanner == "" ) + { + m_sBanner = "banner.bmp"; + if( !DoesFileExist( m_sSongDir + m_sBanner ) ) + { + m_sBanner = "banner.png"; + if( !DoesFileExist( m_sSongDir + m_sBanner ) ) + { + // couldn't find a true banner, so search for any bmp in the same dir + CStringArray arrayBMPFiles; + GetDirListing( m_sSongDir + CString("*.bmp"), arrayBMPFiles ); + + if( arrayBMPFiles.GetSize() != 0 ) // we found a .bmp file! + m_sBanner = arrayBMPFiles.GetAt( 0 ); + else + RageError( ssprintf("Banner could not be found. In Song file '%s' no #BANNER was specified, banner.bmp doesn't exist, and no other BMPs could be found.", GetSongFilePath()) ); + } + } + } + if( m_sBackground == "" ) + { + m_sBackground = "background.bmp"; + if( !DoesFileExist( m_sSongDir + m_sBackground ) ) + m_sBackground = m_sBanner; // we assured above that the m_sBanner file exists + } +} + diff --git a/stepmania/src/Sprite.cpp b/stepmania/src/Sprite.cpp new file mode 100644 index 0000000000..841d736566 --- /dev/null +++ b/stepmania/src/Sprite.cpp @@ -0,0 +1,376 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Sprite.cpp +// +// Desc: A bitmap actor that animates and moves around. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "Sprite.h" +#include "RageTextureManager.h" +#include "IniFile.h" +#include +#include + + +Sprite::Sprite() +{ + Init(); +} + +void Sprite::Init() +{ + Actor::Init(); + + m_pTexture = NULL; + m_uNumStates = 0; + m_uCurState = 0; + m_bIsAnimating = TRUE; + m_fSecsIntoState = 0.0; + m_bUsingCustomSrcRect = FALSE ; + m_Effect = no_effect ; + m_fPercentBetweenColors = 0.0f ; + m_bTweeningTowardEndColor = TRUE ; + m_fDeltaPercentPerSecond = 1.0 ; + m_fWagRadians = 0.2f ; + m_fWagPeriod = 2.0f ; + m_fWagTimer = 0.0f ; + m_fSpinSpeed = 2.0f ; + m_fVibrationDistance = 5.0f ; + m_bVisibleThisFrame = FALSE; + m_bBlendAdd = FALSE; +} + +Sprite::~Sprite() +{ +// RageLog( "Sprite Destructor" ); + + TM->UnloadTexture( m_sTexturePath ); +} + + +BOOL Sprite::LoadFromTexture( CString sTexturePath ) +{ + RageLog( ssprintf("Sprite::LoadFromTexture(%s)", sTexturePath) ); + + Init(); + return LoadTexture( sTexturePath ); +} + +// Sprite file has the format: +// +// [Sprite] +// Texture=Textures\Logo 1x1.bmp +// Frame0000=0 +// Delay0000=1.0 +// Frame0001=3 +// Delay0000=2.0 +BOOL Sprite::LoadFromSpriteFile( CString sSpritePath ) +{ + RageLog( ssprintf("Sprite::LoadFromSpriteFile(%s)", sSpritePath) ); + + Init(); + + m_sSpritePath = sSpritePath; + + // read sprite file + IniFile ini; + ini.SetPath( m_sSpritePath ); + if( !ini.ReadFile() ) + RageError( ssprintf("Error opening Sprite file '%s'.", m_sSpritePath) ); + + CString sTexturePath = ini.GetValue( "Sprite", "Texture" ); + if( sTexturePath == "" ) + RageError( ssprintf("Error reading value 'Texture' from %s.", m_sSpritePath) ); + + // Load the texture + if( !LoadTexture( sTexturePath ) ) + return FALSE; + + + // Read in frames and delays from the sprite file, + // overwriting the states that LoadFromTexture created. + for( UINT i=0; i= m_pTexture->GetNumFrames() ) + RageError( ssprintf("In '%s', %s is %d, but the texture %s only has %d frames.", + m_sSpritePath, sFrameKey, m_uFrame[i], sTexturePath, m_pTexture->GetNumFrames()) ); + m_fDelay[i] = (float)ini.GetValueF( "Sprite", sDelayKey ); + + if( m_uFrame[i] == 0 && m_fDelay[i] > -0.00001f && m_fDelay[i] < 0.00001f ) // both values are empty + break; + + m_uNumStates = i+1; + } + + if( m_uNumStates == 0 ) + RageError( ssprintf("Failed to find at least one state in %s.", m_sSpritePath) ); + + return TRUE; +} + +BOOL Sprite::LoadTexture( CString sTexturePath ) +{ + if( m_sTexturePath != "" ) // If there was a previous bitmap... + TM->UnloadTexture( m_sTexturePath ); // Unload it. + + + m_sTexturePath = sTexturePath; + + m_pTexture = TM->LoadTexture( m_sTexturePath ); + assert( m_pTexture != NULL ); + SetWidth( (FLOAT)m_pTexture->GetFrameWidth() ); + SetHeight( (FLOAT)m_pTexture->GetFrameHeight() ); + + // Assume the frames of this animation play in sequential order with 0.2 second delay. + for( UINT i=0; iGetNumFrames(); i++ ) + { + m_uFrame[i] = i; + m_fDelay[i] = 0.1f; + m_uNumStates = i+1; + } + + return TRUE; +} + + +void Sprite::PrintDebugInfo() +{ +// Actor::PrintDebugInfo(); + + RageLog( "Sprite::PrintDebugInfo()" ); + RageLog( "m_uNumStates: %u, m_uCurState: %u, m_fSecsIntoState: %f", + m_uNumStates, m_uCurState, m_fSecsIntoState ); +} + + +void Sprite::Update( const FLOAT &fDeltaTime ) +{ + //PrintDebugInfo(); + + Actor::Update( fDeltaTime ); // do tweening + + + // update animation + if( m_bIsAnimating ) + { + m_fSecsIntoState += fDeltaTime; + + if( m_fSecsIntoState > m_fDelay[m_uCurState] ) // it's time to switch frames + { + // increment frame and reset the counter + m_fSecsIntoState -= m_fDelay[m_uCurState]; // leave the left over time for the next frame + m_uCurState ++; + if( m_uCurState >= m_uNumStates ) + m_uCurState = 0; + } + } + + // update SpriteEffect + switch( m_Effect ) + { + case no_effect: + break; + case blinking: + case camelion: + case glowing: + if( m_bTweeningTowardEndColor ) { + m_fPercentBetweenColors += m_fDeltaPercentPerSecond * fDeltaTime; + if( m_fPercentBetweenColors > 1.0f ) { + m_fPercentBetweenColors = 1.0f; + m_bTweeningTowardEndColor = FALSE; + } + } + else { // !m_bTweeningTowardEndColor + m_fPercentBetweenColors -= m_fDeltaPercentPerSecond * fDeltaTime; + if( m_fPercentBetweenColors < 0.0f ) { + m_fPercentBetweenColors = 0.0f; + m_bTweeningTowardEndColor = TRUE; + } + } + case wagging: + m_fWagTimer += fDeltaTime; + if( m_fWagTimer > m_fWagPeriod ) + m_fWagTimer -= m_fWagPeriod; + break; + case spinning: + FLOAT rotation; + rotation = GetRotation(); + rotation += m_fSpinSpeed * fDeltaTime; + if( rotation > 2.0f * D3DX_PI ) + rotation -= 2.0f * D3DX_PI; + else if( rotation < 0.0f ) + rotation += 2.0f * D3DX_PI; + SetRotation( rotation ); + break; + case vibrating: + break; + case flickering: + break; + } + + +} + + +void Sprite::Draw() +{ + if( m_pTexture == NULL ) + return; + + UINT uFrameNo = m_uFrame[m_uCurState]; + + LPRECT pRectSrc; + if( m_bUsingCustomSrcRect ) + pRectSrc = &m_rectCustomSrcRect; + else + pRectSrc = m_pTexture->GetFrameRect( uFrameNo ); + + //::SetRect( &rectSrc, 0, 0, m_pTexture->GetImageWidth(), m_pTexture->GetImageHeight() ); + + D3DXVECTOR2 scaling; + scaling.x = GetZoom(); + scaling.y = GetZoom(); + + D3DXVECTOR2 translation; + translation.x = (float)GetLeftEdge(); + translation.y = (float)GetTopEdge(); + + D3DXVECTOR3 rotation = m_rotation; + + D3DXVECTOR2 rot_center; + rot_center.x = GetZoomedWidth()/2.0f; + rot_center.y = GetZoomedHeight()/2.0f; + + D3DXCOLOR color = m_color; + + + // update SpriteEffect + switch( m_Effect ) + { + case no_effect: + break; + case blinking: + color = m_bTweeningTowardEndColor ? m_start_color : m_end_color; + break; + case camelion: + case glowing: + color = m_start_color*m_fPercentBetweenColors + m_end_color*(1.0f-m_fPercentBetweenColors); + break; + case wagging: + rotation.z = m_fWagRadians * (FLOAT)sin( + (m_fWagTimer / m_fWagPeriod) // percent through wag + * 2.0 * D3DX_PI ); + break; + case spinning: + // nothing special needed + break; + case vibrating: + translation.x += m_fVibrationDistance * randomf(-1.0f, 1.0f) * GetZoom(); + translation.y += m_fVibrationDistance * randomf(-1.0f, 1.0f) * GetZoom(); + break; + case flickering: + m_bVisibleThisFrame = !m_bVisibleThisFrame; + if( m_bVisibleThisFrame ) + return; // don't draw the frame + break; + } + + SCREEN->DrawQuad( m_pTexture, + pRectSrc, + &scaling, // scaling + &rot_center, // rotation center + &rotation, // rotation + &translation, // translation + color, + m_Effect == glowing ? op_add : op_modulate, + m_bBlendAdd ); + +} + + +void Sprite::SetState( UINT uNewState ) +{ + ASSERT( uNewState >= 0 && uNewState < m_uNumStates ); + m_uCurState = uNewState; + m_fSecsIntoState = 0.0; +} + +void Sprite::SetCustomSrcRect( RECT newRect ) +{ + m_bUsingCustomSrcRect = TRUE; + m_rectCustomSrcRect = newRect; + + SetWidth( (FLOAT) RECTWIDTH(newRect) ); + SetHeight( (FLOAT) RECTHEIGHT(newRect) ); + +}; + +VOID Sprite::SetEffectNone() +{ + m_Effect = no_effect; + //m_color = D3DXCOLOR( 1.0,1.0,1.0,1.0 ); +} + +VOID Sprite::SetEffectBlinking( FLOAT fDeltaPercentPerSecond, D3DXCOLOR Color, D3DXCOLOR Color2 ) +{ + m_Effect = blinking; + m_start_color = Color; + m_end_color = Color2; + //m_fPercentBetweenColors = 0.0; + //m_bTweeningTowardEndColor = TRUE; + m_fDeltaPercentPerSecond = fDeltaPercentPerSecond; +} + +VOID Sprite::SetEffectCamelion( FLOAT fDeltaPercentPerSecond, D3DXCOLOR Color, D3DXCOLOR Color2 ) +{ + m_Effect = camelion; + m_start_color = Color; + m_end_color = Color2; + //m_fPercentBetweenColors = 0.0; + //m_bTweeningTowardEndColor = TRUE; + m_fDeltaPercentPerSecond = fDeltaPercentPerSecond; +} + +VOID Sprite::SetEffectGlowing( FLOAT fDeltaPercentPerSecond, D3DXCOLOR Color, D3DXCOLOR Color2 ) +{ + m_Effect = glowing; + m_start_color = Color; + m_end_color = Color2; + //m_fPercentBetweenColors = 0.0; + //m_bTweeningTowardEndColor = TRUE; + m_fDeltaPercentPerSecond = fDeltaPercentPerSecond; +} + +VOID Sprite::SetEffectWagging( FLOAT fWagRadians, FLOAT fWagPeriod ) +{ + m_Effect = wagging; + m_fWagRadians = fWagRadians; + m_fWagPeriod = fWagPeriod; +} + +VOID Sprite::SetEffectSpinning( FLOAT fSpinSpeed /*radians per second*/ ) +{ + m_Effect = spinning; + m_fSpinSpeed = fSpinSpeed; +} + +VOID Sprite::SetEffectVibrating( FLOAT fVibrationDistance ) +{ + m_Effect = vibrating; + m_fVibrationDistance = fVibrationDistance; +} + +VOID Sprite::SetEffectFlickering() +{ + m_Effect = flickering; +} diff --git a/stepmania/src/Sprite.h b/stepmania/src/Sprite.h new file mode 100644 index 0000000000..29483c2d2f --- /dev/null +++ b/stepmania/src/Sprite.h @@ -0,0 +1,122 @@ +//----------------------------------------------------------------------------- +// File: Sprite.h +// +// Desc: A bitmap Actor that animates and moves around. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _SPRITE_H_ +#define _SPRITE_H_ + + +#include "Actor.h" +#include "RageUtil.h" +#include "RageTexture.h" + + + +#define MAX_SPRITE_STATES 256 + + + +class Sprite: public Actor +{ +public: + Sprite(); + virtual ~Sprite(); + + + enum SpriteEffect { no_effect, + blinking, camelion, glowing, + wagging, spinning, + vibrating, flickering + }; + + + BOOL LoadFromTexture( CString sTexturePath ); + BOOL LoadFromSpriteFile( CString sSpritePath ); + + VOID PrintDebugInfo(); + + virtual void Draw(); + virtual void Update( const FLOAT &fDeltaTime ); + + void StartAnimating() { m_bIsAnimating = TRUE; }; + void StopAnimating() { m_bIsAnimating = FALSE; }; + void SetState( UINT uNewState ); + + UINT GetNumStates() { return m_uNumStates; }; + CString GetTexturePath() { return m_sTexturePath; }; + + + VOID SetCustomSrcRect( RECT newRect ); // for cropping or flipping + + + VOID SetEffectNone(); + VOID SetEffectBlinking( FLOAT fDeltaPercentPerSecond = 2.5, + D3DXCOLOR Color = D3DXCOLOR(0.5f,0.5f,0.5f,1), + D3DXCOLOR Color2 = D3DXCOLOR(1,1,1,1) ); + VOID SetEffectCamelion( FLOAT fDeltaPercentPerSecond = 2.5, + D3DXCOLOR Color = D3DXCOLOR(0,0,0,1), + D3DXCOLOR Color2 = D3DXCOLOR(1,1,1,1) ); + VOID SetEffectGlowing( FLOAT fDeltaPercentPerSecond = 2.5, + D3DXCOLOR Color = D3DXCOLOR(0.4f,0.4f,0.4f,0), + D3DXCOLOR Color2 = D3DXCOLOR(1.0f,1.0f,1.0f,0) ); + VOID SetEffectWagging( FLOAT fWagRadians = 0.2, + FLOAT fWagPeriod = 2.0 ); + VOID SetEffectSpinning( FLOAT fRadsPerSpeed = 2.0 ); + VOID SetEffectVibrating( FLOAT fVibrationDistance = 5.0 ); + VOID SetEffectFlickering(); + SpriteEffect GetEffect() { return m_Effect; }; + + VOID SetBlendMode( BOOL bBlendAdd ) { m_bBlendAdd = bBlendAdd; }; + +protected: + void Init(); + + BOOL LoadTexture( CString sTexture ); + + CString m_sSpritePath; + LPRageTexture m_pTexture; + CString m_sTexturePath; + + UINT m_uFrame[MAX_SPRITE_STATES]; // array of indicies into m_rectBitmapFrames + FLOAT m_fDelay[MAX_SPRITE_STATES]; + UINT m_uNumStates; + UINT m_uCurState; + BOOL m_bIsAnimating; + FLOAT m_fSecsIntoState; // number of seconds that have elapsed since we switched to this frame + + BOOL m_bBlendAdd; + + BOOL m_bUsingCustomSrcRect; + RECT m_rectCustomSrcRect; + + SpriteEffect m_Effect; + + // Counting variables for sprite effects: + // camelion and glowing: +// D3DXCOLOR m_Color2; + FLOAT m_fPercentBetweenColors; + BOOL m_bTweeningTowardEndColor; // TRUE is fading toward end_color, FALSE if fading toward start_color + FLOAT m_fDeltaPercentPerSecond; // percentage change in tweening per second + + // wagging: + FLOAT m_fWagRadians; + FLOAT m_fWagPeriod; // seconds to complete a wag (back and forth) + FLOAT m_fWagTimer; // num of seconds into this wag + + // spinning: + FLOAT m_fSpinSpeed; // radians per second + + // vibrating: + FLOAT m_fVibrationDistance; + + // flickering: + BOOL m_bVisibleThisFrame; + +}; + + +#endif \ No newline at end of file diff --git a/stepmania/src/StdAfx.cpp b/stepmania/src/StdAfx.cpp new file mode 100644 index 0000000000..0e30492cba --- /dev/null +++ b/stepmania/src/StdAfx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// Basic.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/stepmania/src/StdAfx.h b/stepmania/src/StdAfx.h new file mode 100644 index 0000000000..8e0a4b0705 --- /dev/null +++ b/stepmania/src/StdAfx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__9FF379EB_FAE2_11D1_BFC5_D41F722B624A__INCLUDED_) +#define AFX_STDAFX_H__9FF379EB_FAE2_11D1_BFC5_D41F722B624A__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC templated collections +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__9FF379EB_FAE2_11D1_BFC5_D41F722B624A__INCLUDED_) diff --git a/stepmania/src/StepMania.ICO b/stepmania/src/StepMania.ICO new file mode 100644 index 0000000000..2a574f29c9 Binary files /dev/null and b/stepmania/src/StepMania.ICO differ diff --git a/stepmania/src/StepMania.RC b/stepmania/src/StepMania.RC new file mode 100644 index 0000000000..dc0400b93e --- /dev/null +++ b/stepmania/src/StepMania.RC @@ -0,0 +1,133 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAIN_ACCEL ACCELERATORS DISCARDABLE +BEGIN + "P", IDM_PADS, VIRTKEY, CONTROL, NOINVERT + VK_ESCAPE, IDM_WINDOWED, VIRTKEY, NOINVERT + VK_F4, IDM_TOGGLEFULLSCREEN, VIRTKEY, NOINVERT + VK_RETURN, IDM_TOGGLEFULLSCREEN, VIRTKEY, ALT, NOINVERT + "X", IDM_EXIT, VIRTKEY, ALT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON DISCARDABLE "StepMania.ICO" + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Chris Danford\0" + VALUE "FileDescription", "StepMania\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "StepMania\0" + VALUE "LegalCopyright", "Copyright © 2001\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "StepMania.exe\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", " StepMania\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp new file mode 100644 index 0000000000..435146db07 --- /dev/null +++ b/stepmania/src/StepMania.cpp @@ -0,0 +1,477 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: StepMania.cpp +// +// Desc: +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Includes +//----------------------------------------------------------------------------- +#include "resource.h" + +#include "RageScreen.h" +#include "RageTextureManager.h" +#include "RageSound.h" +#include "RageMusic.h" +#include "RageInput.h" + +#include "GameOptions.h" +#include "WindowManager.h" + +#include "WindowIntroCovers.h" + +#include + +//----------------------------------------------------------------------------- +// Links +//----------------------------------------------------------------------------- +#pragma comment(lib, "d3dx8.lib") +#pragma comment(lib, "d3d8.lib") + + +//----------------------------------------------------------------------------- +// Application globals +//----------------------------------------------------------------------------- +const CString g_sAppName = "StepMania"; +const CString g_sAppClassName = "StepMania Class"; + + +HWND g_hWndMain; // Main Window Handle +HINSTANCE g_hInstance; // The Handle to Window Instance + +const DWORD g_dwScreenWidth = 640; // The window width +const DWORD g_dwScreenHeight = 480; // The window height + + +const DWORD g_dwWindowStyle = WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU; + + +BOOL g_bFullscreen = FALSE; // Whether app is fullscreen (or windowed) +BOOL g_bIsActive = FALSE; // Whether the focus is on our app + + +//LPRageMovieTexture g_pMovieTexture = NULL; + + +//----------------------------------------------------------------------------- +// Function prototypes +//----------------------------------------------------------------------------- +// Main game functions +LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); + +void Update(); // Update the game logic +void Render(); // Render a frame +void ShowFrame(); // Display the contents of the back buffer to the screen +void SetFullscreen( BOOL bFullscreen ); // Switch between fullscreen and windowed modes. + + +// Functions that work with game objects +HRESULT CreateObjects( HWND hWnd ); // allocate and initialize game objects +HRESULT InvalidateObjects(); // invalidate game objects before a display mode change +HRESULT RestoreObjects(); // restore game objects after a display mode change +VOID DestroyObjects(); // deallocate game objects when we're done with them + + +//----------------------------------------------------------------------------- +// Name: WinMain() +// Desc: Application entry point +//----------------------------------------------------------------------------- +int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow ) +{ + CoInitialize (NULL); // Initialize COM + + // Register the window class + WNDCLASS wndClass = { + 0, + WndProc, // callback handler + 0, // cbClsExtra; + 0, // cbWndExtra; + hInstance, + LoadIcon( hInstance, MAKEINTRESOURCE(IDI_ICON) ), + LoadCursor( hInstance, IDC_ARROW), + (HBRUSH)GetStockObject( BLACK_BRUSH ), + NULL, // lpszMenuName; + g_sAppClassName // lpszClassName; + }; + RegisterClass( &wndClass ); + + + // Set the window's initial width + RECT rcWnd; + SetRect( &rcWnd, 0, 0, g_dwScreenWidth, g_dwScreenHeight ); + AdjustWindowRect( &rcWnd, g_dwWindowStyle, FALSE ); + + + // Create our main window + g_hWndMain = CreateWindow( + g_sAppClassName,// pointer to registered class name + g_sAppName, // pointer to window name + g_dwWindowStyle, // window style + CW_USEDEFAULT, // horizontal position of window + CW_USEDEFAULT, // vertical position of window + RECTWIDTH(rcWnd), // window width + RECTHEIGHT(rcWnd),// window height + NULL, // handle to parent or owner window + NULL, // handle to menu, or child-window identifier + hInstance, // handle to application instance + NULL // pointer to window-creation data + ); + if( NULL == g_hWndMain ) + exit(1); + + + // Load keyboard accelerators + HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) ); + + + // run the game + CreateObjects( g_hWndMain ); // Create the game objects + + // Now we're ready to recieve and process Windows messages. + MSG msg; + ZeroMemory( &msg, sizeof(msg) ); + + + while( WM_QUIT != msg.message ) + { + // Look for messages, if none are found then + // update the state and display it + if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) + { + GetMessage(&msg, NULL, 0, 0 ); + + // Translate and dispatch the message + if( 0 == TranslateAccelerator( g_hWndMain, hAccel, &msg ) ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + } + else // No messages are waiting. Render a frame during idle time. + { + Update(); + Render(); + ShowFrame(); + //if( !g_bFullscreen ) + ::Sleep(16); // cap the frame rate to ~30 fps for now + } + } // end while( WM_QUIT != msg.message ) + + + // clean up after a normal exit + DestroyObjects(); // deallocate our game objects and leave fullscreen + DestroyWindow( g_hWndMain ); + UnregisterClass( g_sAppClassName, hInstance ); + CoUninitialize(); // Uninitialize COM + return 0L; +} + + + +//----------------------------------------------------------------------------- +// Name: WndProc() +// Desc: Callback for all Windows messages +//----------------------------------------------------------------------------- +LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + switch( msg ) + { + case WM_ACTIVATEAPP: + // Check to see if we are losing our window... + g_bIsActive = (BOOL)wParam; + break; + + case WM_SIZE: + // Check to see if we are losing our window... + if( SIZE_MAXIMIZED == wParam) + MessageBeep( MB_OK ); + else if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam ) + g_bIsActive = FALSE; + else + g_bIsActive = TRUE; + break; + + case WM_GETMINMAXINFO: + { + // don't allow the window to be resized smaller than the screen resolution + RECT rcWnd; + SetRect( &rcWnd, 0, 0, g_dwScreenWidth, g_dwScreenHeight ); + DWORD dwWindowStyle = GetWindowLong( g_hWndMain, GWL_STYLE ); + AdjustWindowRect( &rcWnd, dwWindowStyle, FALSE ); + + ((MINMAXINFO*)lParam)->ptMinTrackSize.x = RECTWIDTH(rcWnd); + ((MINMAXINFO*)lParam)->ptMinTrackSize.y = RECTHEIGHT(rcWnd); + } + break; + + case WM_SETCURSOR: + // Turn off Windows cursor in fullscreen mode + if( g_bFullscreen ) + { + SetCursor( NULL ); + return TRUE; // prevent Windows from setting the cursor + } + break; + + case WM_SYSCOMMAND: + // Prevent moving/sizing and power loss + switch( wParam ) + { + case SC_MOVE: + case SC_SIZE: + case SC_KEYMENU: + case SC_MONITORPOWER: + return 1; + case SC_MAXIMIZE: + SendMessage( g_hWndMain, WM_COMMAND, IDM_TOGGLEFULLSCREEN, 0 ); + return 1; + break; + } + break; + + + case WM_COMMAND: + switch( LOWORD(wParam) ) + { + case IDM_TOGGLEFULLSCREEN: + SetFullscreen( !g_bFullscreen ); + return 0; + + case IDM_WINDOWED: + SetFullscreen( FALSE ); + return 0; + + case IDM_EXIT: + // Recieved key/menu command to exit app + SendMessage( hWnd, WM_CLOSE, 0, 0 ); + return 0; + + case IDM_PADS: + + return 0; + + } + break; + + case WM_NCHITTEST: + // Prevent the user from selecting the menu in fullscreen mode + if( g_bFullscreen ) + return HTCLIENT; + break; + + case WM_PAINT: + // redisplay the contents of the back buffer if the window needs to be redrawn + ShowFrame(); + break; + + case WM_DESTROY: + PostQuitMessage( 0 ); + break; + } + + return DefWindowProc( hWnd, msg, wParam, lParam ); +} + + + +//----------------------------------------------------------------------------- +// Name: CreateObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CreateObjects( HWND hWnd ) +{ + SCREEN = new RageScreen( hWnd ); + TM = new RageTextureManager( SCREEN ); + SOUND = new RageSound( hWnd ); + MUSIC = new RageMusic; + INPUT = new RageInput( hWnd ); + + GAMEOPTIONS = new GameOptions; + WM = new WindowManager; + + RageLogStart(); + + WM->SetNewWindow( new WindowIntroCovers ); + + srand( (unsigned)time(NULL) ); + // Start the accurate timer + DXUtil_Timer( TIMER_START ); + + return S_OK; +} + +//----------------------------------------------------------------------------- +// Name: DestroyObjects() +// Desc: +//----------------------------------------------------------------------------- +void DestroyObjects() +{ + // Setup the app so it can support single-stepping + DXUtil_Timer( TIMER_STOP ); + + SAFE_DELETE( WM ); + SAFE_DELETE( GAMEOPTIONS ); + + SAFE_DELETE( INPUT ); + SAFE_DELETE( MUSIC ); + SAFE_DELETE( SOUND ); + SAFE_DELETE( TM ); + SAFE_DELETE( SCREEN ); +} + + +//----------------------------------------------------------------------------- +// Name: RestoreObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT RestoreObjects() +{ + ///////////////////// + // Restore the window + ///////////////////// + + // Set window size + RECT rcWnd; + if( g_bFullscreen ) + SetRect( &rcWnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) ); + else // if( !g_bFullscreen ) + { + SetRect( &rcWnd, 0, 0, g_dwScreenWidth, g_dwScreenHeight ); + AdjustWindowRect( &rcWnd, g_dwWindowStyle, FALSE ); + } + + // Bring the window to the foreground + SetWindowPos( g_hWndMain, + HWND_NOTOPMOST, + 0, + 0, + RECTWIDTH(rcWnd), + RECTHEIGHT(rcWnd), + 0 ); + + + /////////////////////////// + // Restore all game objects + /////////////////////////// + + SCREEN->Restore(); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: InvalidateObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT InvalidateObjects() +{ + SCREEN->Invalidate(); + + return S_OK; +} + + + +//----------------------------------------------------------------------------- +// Name: Update() +// Desc: +//----------------------------------------------------------------------------- +void Update() +{ + FLOAT fDeltaTime = DXUtil_Timer( TIMER_GETELAPSEDTIME ); + + // This was a hack to fix timing issues with the old WindowSelectSong + // + //if( fDeltaTime > 0.050f ) // we dropped > 5 frames + // fDeltaTime = 0.050f; + + MUSIC->Update( fDeltaTime ); + + WM->Update( fDeltaTime ); + + + static RageRawInputList listRawInput; + listRawInput.RemoveAll(); + INPUT->GetRawInput( listRawInput ); + + RageRawInput ri; + PadInput pi; + POSITION pos = listRawInput.GetHeadPosition(); + while( pos != NULL ) + { + ri = listRawInput.GetNext( pos ); + pi = GAMEOPTIONS->RawToPad( ri ); + + WM->Input( ri, pi ); + } + +} + + +//----------------------------------------------------------------------------- +// Name: Render() +// Desc: +//----------------------------------------------------------------------------- +void Render() +{ + HRESULT hr = SCREEN->BeginFrame(); + switch( hr ) + { + case D3DERR_DEVICELOST: + // The user probably alt-tabbed out of fullscreen. + // Do not render a frame until we re-acquire the device + break; + case D3DERR_DEVICENOTRESET: + InvalidateObjects(); + + // Resize the device + if( SUCCEEDED( SCREEN->Reset() ) ) + { + // Initialize the app's device-dependent objects + RestoreObjects(); + return; + } + else + RageError( "Failed to SCREEN->Reset()" ); + + break; + case S_OK: + // draw the game + WM->Draw(); + + + SCREEN->EndFrame(); + break; + } +} + + +//----------------------------------------------------------------------------- +// Name: ShowFrame() +// Desc: +//----------------------------------------------------------------------------- +void ShowFrame() +{ + // display the contents of the back buffer to the front + if( SCREEN ) + SCREEN->ShowFrame(); +} + + +//----------------------------------------------------------------------------- +// Name: SetFullscreen() +// Desc: +//----------------------------------------------------------------------------- +void SetFullscreen( BOOL bFullscreen ) +{ + InvalidateObjects(); + g_bFullscreen = bFullscreen; + SCREEN->SwitchDisplayModes( g_bFullscreen, + g_dwScreenWidth, + g_dwScreenHeight ); + RestoreObjects(); +} diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp new file mode 100644 index 0000000000..6b007512d0 --- /dev/null +++ b/stepmania/src/StepMania.dsp @@ -0,0 +1,531 @@ +# Microsoft Developer Studio Project File - Name="StepMania" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=StepMania - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "StepMania.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "StepMania.mak" CFG="StepMania - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "StepMania - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "StepMania - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "StepMania - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 1 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../Release" +# PROP Intermediate_Dir "../Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "StepMania - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 1 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../Debug" +# PROP Intermediate_Dir "../Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "StepMania - Win32 Release" +# Name "StepMania - Win32 Debug" +# Begin Group "Rage" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\RageBitmapTexture.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageBitmapTexture.h +# End Source File +# Begin Source File + +SOURCE=.\RageInput.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageInput.h +# End Source File +# Begin Source File + +SOURCE=.\RageMovieTexture.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageMovieTexture.h +# End Source File +# Begin Source File + +SOURCE=.\RageMusic.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageMusic.h +# End Source File +# Begin Source File + +SOURCE=.\RageScreen.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageScreen.h +# End Source File +# Begin Source File + +SOURCE=.\RageSound.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageSound.h +# End Source File +# Begin Source File + +SOURCE=.\RageTexture.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageTexture.h +# End Source File +# Begin Source File + +SOURCE=.\RageTextureManager.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageTextureManager.h +# End Source File +# Begin Source File + +SOURCE=.\RageUtil.cpp +# End Source File +# Begin Source File + +SOURCE=.\RageUtil.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Window.cpp +# End Source File +# Begin Source File + +SOURCE=.\Window.h +# End Source File +# Begin Source File + +SOURCE=.\WindowConfigurePads.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowConfigurePads.h +# End Source File +# Begin Source File + +SOURCE=.\WindowDancing.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowDancing.h +# End Source File +# Begin Source File + +SOURCE=.\WindowIntroCovers.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowIntroCovers.h +# End Source File +# Begin Source File + +SOURCE=.\WindowManager.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowManager.h +# End Source File +# Begin Source File + +SOURCE=.\WindowResults.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowResults.h +# End Source File +# Begin Source File + +SOURCE=.\WindowSandbox.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowSandbox.h +# End Source File +# Begin Source File + +SOURCE=.\WindowSelectGameMode.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowSelectGameMode.h +# End Source File +# Begin Source File + +SOURCE=.\WindowSelectSong.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowSelectSong.h +# End Source File +# Begin Source File + +SOURCE=.\WindowSelectSteps.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowSelectSteps.h +# End Source File +# Begin Source File + +SOURCE=.\WindowTitleMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\WindowTitleMenu.h +# End Source File +# End Group +# Begin Group "Game Objects" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Actor.cpp +# End Source File +# Begin Source File + +SOURCE=.\Actor.h +# End Source File +# Begin Source File + +SOURCE=.\Background.cpp +# End Source File +# Begin Source File + +SOURCE=.\Background.h +# End Source File +# Begin Source File + +SOURCE=.\Banner.cpp +# End Source File +# Begin Source File + +SOURCE=.\Banner.h +# End Source File +# Begin Source File + +SOURCE=.\BitmapText.cpp +# End Source File +# Begin Source File + +SOURCE=.\BitmapText.h +# End Source File +# Begin Source File + +SOURCE=.\BlurredTitle.cpp +# End Source File +# Begin Source File + +SOURCE=.\BlurredTitle.h +# End Source File +# Begin Source File + +SOURCE=.\Button.cpp +# End Source File +# Begin Source File + +SOURCE=.\button.h +# End Source File +# Begin Source File + +SOURCE=.\ColorArrows.cpp +# End Source File +# Begin Source File + +SOURCE=.\ColorArrows.h +# End Source File +# Begin Source File + +SOURCE=.\Combo.cpp +# End Source File +# Begin Source File + +SOURCE=.\Combo.h +# End Source File +# Begin Source File + +SOURCE=.\FootBar.cpp +# End Source File +# Begin Source File + +SOURCE=.\FootBar.h +# End Source File +# Begin Source File + +SOURCE=.\GameOptions.cpp +# End Source File +# Begin Source File + +SOURCE=.\GameOptions.h +# End Source File +# Begin Source File + +SOURCE=.\GrayArrows.cpp +# End Source File +# Begin Source File + +SOURCE=.\GrayArrows.h +# End Source File +# Begin Source File + +SOURCE=.\Judgement.cpp +# End Source File +# Begin Source File + +SOURCE=.\Judgement.h +# End Source File +# Begin Source File + +SOURCE=.\LifeMeter.cpp +# End Source File +# Begin Source File + +SOURCE=.\LifeMeter.h +# End Source File +# Begin Source File + +SOURCE=.\PadInput.h +# End Source File +# Begin Source File + +SOURCE=.\Player.cpp +# End Source File +# Begin Source File + +SOURCE=.\Player.h +# End Source File +# Begin Source File + +SOURCE=.\PreviewGraphic.cpp +# End Source File +# Begin Source File + +SOURCE=.\previewgraphic.h +# End Source File +# Begin Source File + +SOURCE=.\Score.cpp +# End Source File +# Begin Source File + +SOURCE=.\Score.h +# End Source File +# Begin Source File + +SOURCE=.\Song.cpp +# End Source File +# Begin Source File + +SOURCE=.\song.h +# End Source File +# Begin Source File + +SOURCE=.\SoundSet.cpp +# End Source File +# Begin Source File + +SOURCE=.\SoundSet.h +# End Source File +# Begin Source File + +SOURCE=.\Sprite.cpp +# End Source File +# Begin Source File + +SOURCE=.\Sprite.h +# End Source File +# Begin Source File + +SOURCE=.\Steps.cpp +# End Source File +# Begin Source File + +SOURCE=.\Steps.h +# End Source File +# End Group +# Begin Group "File Types" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\BmsFile.cpp +# End Source File +# Begin Source File + +SOURCE=.\BmsFile.h +# End Source File +# Begin Source File + +SOURCE=.\IniFile.cpp +# End Source File +# Begin Source File + +SOURCE=.\IniFile.h +# End Source File +# End Group +# Begin Group "System" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\dxutil.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\StepMania.cpp +# End Source File +# Begin Source File + +SOURCE=.\StepMania.ICO +# End Source File +# Begin Source File + +SOURCE=.\StepMania.RC +# End Source File +# End Group +# Begin Group "Transitions" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Transition.cpp +# End Source File +# Begin Source File + +SOURCE=.\Transition.h +# End Source File +# Begin Source File + +SOURCE=.\TransitionFade.cpp +# End Source File +# Begin Source File + +SOURCE=.\TransitionFade.h +# End Source File +# Begin Source File + +SOURCE=.\TransitionFadeWipe.cpp +# End Source File +# Begin Source File + +SOURCE=.\TransitionFadeWipe.h +# End Source File +# Begin Source File + +SOURCE=.\TransitionRectWipe.cpp +# End Source File +# Begin Source File + +SOURCE=.\TransitionRectWipe.h +# End Source File +# Begin Source File + +SOURCE=.\TransitionStarburst.cpp +# End Source File +# Begin Source File + +SOURCE=.\TransitionStarburst.h +# End Source File +# Begin Source File + +SOURCE=.\TransitionStarWipe.cpp +# End Source File +# Begin Source File + +SOURCE=.\TransitionStarWipe.h +# End Source File +# End Group +# End Target +# End Project diff --git a/stepmania/src/StepMania.dsw b/stepmania/src/StepMania.dsw new file mode 100644 index 0000000000..2bfcbaa0e6 --- /dev/null +++ b/stepmania/src/StepMania.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "StepMania"=".\StepMania.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/stepmania/src/Transition.cpp b/stepmania/src/Transition.cpp new file mode 100644 index 0000000000..a40942a5ce --- /dev/null +++ b/stepmania/src/Transition.cpp @@ -0,0 +1,139 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: Transition.cpp +// +// Desc: Abstract base class for all transitions +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "RageUtil.h" + +#include "Transition.h" + +#define SOUND_BACK "Sounds\\back.mp3" +#define SOUND_NEXT "Sounds\\next.mp3" + + +Transition::Transition() : + m_TransitionState( closed ), + m_fTransitionTime( DEFAULT_TRANSITION_TIME ), + m_fPercentThroughTransition( 0.0f ), + m_Color(0,0,0,1) +{ + m_bPlayCloseWipingRightSound = TRUE; + m_bPlayCloseWipingLeftSound = TRUE; + m_hCloseWipingRightSound = SOUND->LoadSound( SOUND_NEXT ); + m_hCloseWipingLeftSound = SOUND->LoadSound( SOUND_BACK ); +} + +Transition::~Transition() +{ + SOUND->UnloadSound( m_hCloseWipingRightSound ); + SOUND->UnloadSound( m_hCloseWipingLeftSound ); +} + +void Transition::Update( const FLOAT &fDeltaTime ) +{ + switch( m_TransitionState ) + { + case opening_right: + case opening_left: + case closing_right: + case closing_left: + + m_fPercentThroughTransition += fDeltaTime/m_fTransitionTime; + if( m_fPercentThroughTransition > 1.0f ) // the wipe is over + { + m_fPercentThroughTransition = 0.0; + switch( m_TransitionState ) + { + case opening_right: + case opening_left: + m_TransitionState = opened; + break; + case closing_right: + case closing_left: + m_TransitionState = closed; + break; + } + WM->SendMessageToTopWindow( m_MessageToSendWhenDone, 0 ); + + } + break; + } +} + +void Transition::SetClosed() +{ + m_TransitionState = closed; +} + +void Transition::SetOpened() +{ + m_TransitionState = opened; +} + +void Transition::OpenWipingRight( WindowMessage send_when_done ) +{ + m_MessageToSendWhenDone = send_when_done; + m_TransitionState = opening_right; + m_fPercentThroughTransition = 0.0; +} + +void Transition::OpenWipingLeft( WindowMessage send_when_done ) +{ + m_MessageToSendWhenDone = send_when_done; + m_TransitionState = opening_left; + m_fPercentThroughTransition = 0.0; +} + +void Transition::CloseWipingRight( WindowMessage send_when_done ) +{ + m_MessageToSendWhenDone = send_when_done; + m_TransitionState = closing_right; + m_fPercentThroughTransition = 0.0; + if( m_bPlayCloseWipingRightSound ) + SOUND->Play( m_hCloseWipingRightSound ); +} + +void Transition::CloseWipingLeft( WindowMessage send_when_done ) +{ + m_MessageToSendWhenDone = send_when_done; + m_TransitionState = closing_left; + m_fPercentThroughTransition = 0.0; + if( m_bPlayCloseWipingLeftSound ) + SOUND->Play( m_hCloseWipingLeftSound ); +} + + +void Transition::SetCloseWipingRightSound( CString sSoundPath ) +{ + if( sSoundPath == "" ) + { + SOUND->UnloadSound( m_hCloseWipingRightSound ); + m_bPlayCloseWipingRightSound = FALSE; + } + else + { + SOUND->UnloadSound( m_hCloseWipingRightSound ); + m_hCloseWipingRightSound = SOUND->LoadSound( SOUND_NEXT ); + m_bPlayCloseWipingRightSound = TRUE; + } +} + +void Transition::SetCloseWipingLeftSound( CString sSoundPath ) +{ + if( sSoundPath == "" ) + { + SOUND->UnloadSound( m_hCloseWipingRightSound ); + m_bPlayCloseWipingLeftSound = FALSE; + } + else + { + SOUND->UnloadSound( m_hCloseWipingLeftSound ); + m_hCloseWipingLeftSound = SOUND->LoadSound( SOUND_NEXT ); + m_bPlayCloseWipingLeftSound = TRUE; + } +}; diff --git a/stepmania/src/Transition.h b/stepmania/src/Transition.h new file mode 100644 index 0000000000..bba3e63a2d --- /dev/null +++ b/stepmania/src/Transition.h @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +// File: Transition.cpp +// +// Desc: Abstract base class for all transitions +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#ifndef _Transition_H_ +#define _Transition_H_ + + +#include "Actor.h" +#include "RageScreen.h" +#include "RageSound.h" +#include "Window.h" +#include "WindowManager.h" + + +#define DEFAULT_TRANSITION_TIME 1.0f + + +class Transition +{ +public: + Transition(); + ~Transition(); + + void Update( const FLOAT &fDeltaTime ); + virtual void Draw() PURE; + + virtual void SetOpened(); + virtual void SetClosed(); + + virtual void OpenWipingRight( WindowMessage send_when_done ); + virtual void OpenWipingLeft( WindowMessage send_when_done ); + virtual void CloseWipingRight(WindowMessage send_when_done ); + virtual void CloseWipingLeft( WindowMessage send_when_done ); + + BOOL IsClosed() { return m_TransitionState == closed; }; + BOOL IsClosing() { return m_TransitionState == closing_right || m_TransitionState == closing_left; }; + + VOID SetTransitionTime( FLOAT fNewTransitionTime ) { m_fTransitionTime = fNewTransitionTime; }; + + void SetColor( D3DXCOLOR new_color ) { m_Color = new_color; }; + void SetCloseWipingRightSound( CString sSoundPath ); + void SetCloseWipingLeftSound( CString sSoundPath ); + +protected: + + enum TransitionState { opened, closed, + opening_right, opening_left, + closing_right, closing_left }; + + TransitionState m_TransitionState; + FLOAT m_fTransitionTime; + FLOAT m_fPercentThroughTransition; + + WindowMessage m_MessageToSendWhenDone; + + BOOL m_bPlayCloseWipingRightSound; + BOOL m_bPlayCloseWipingLeftSound; + HSAMPLE m_hCloseWipingRightSound; + HSAMPLE m_hCloseWipingLeftSound; + + D3DXCOLOR m_Color; +}; + + +#endif \ No newline at end of file diff --git a/stepmania/src/TransitionFade.cpp b/stepmania/src/TransitionFade.cpp new file mode 100644 index 0000000000..75157eb8f4 --- /dev/null +++ b/stepmania/src/TransitionFade.cpp @@ -0,0 +1,60 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: TransitionFade.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "RageUtil.h" + +#include "TransitionFade.h" + + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define RECTANGLE_WIDTH 20 +#define NUM_RECTANGLES (SCREEN_WIDTH/RECTANGLE_WIDTH) +#define FADE_RECTS_WIDE (NUM_RECTANGLES/3) // number of rects from fade start to fade end + + + +TransitionFade::TransitionFade() +{ +} + +TransitionFade::~TransitionFade() +{ + +} + +void TransitionFade::Draw() +{ + FLOAT fPercentageOpaque; + switch( m_TransitionState ) + { + case opened: + fPercentageOpaque = 0.0; + break; + case closed: + fPercentageOpaque = 1.0; + break; + case opening_right: + case opening_left: + fPercentageOpaque = 1.0f - m_fPercentThroughTransition; + break; + case closing_right: + case closing_left: + fPercentageOpaque = m_fPercentThroughTransition; + break; + } + + m_Color.a = fPercentageOpaque; + int alpha = (int)( fPercentageOpaque * 255 ); + SCREEN->DrawRect( CRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT), m_Color ); +} + + diff --git a/stepmania/src/TransitionFade.h b/stepmania/src/TransitionFade.h new file mode 100644 index 0000000000..f39d113564 --- /dev/null +++ b/stepmania/src/TransitionFade.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// File: TransitionFade.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#ifndef _TransitionFade_H_ +#define _TransitionFade_H_ + + +#include "Transition.h" +#include "RageScreen.h" +#include "RageSound.h" + + +class TransitionFade : public Transition +{ +public: + TransitionFade(); + ~TransitionFade(); + + void Draw(); + +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/TransitionFadeWipe.cpp b/stepmania/src/TransitionFadeWipe.cpp new file mode 100644 index 0000000000..c61f8a7705 --- /dev/null +++ b/stepmania/src/TransitionFadeWipe.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: TransitionFadeWipe.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "RageUtil.h" + +#include "TransitionFadeWipe.h" + + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define RECTANGLE_WIDTH 20 +#define NUM_RECTANGLES (SCREEN_WIDTH/RECTANGLE_WIDTH) +#define FADE_RECTS_WIDE (NUM_RECTANGLES/3) // number of rects from fade start to fade end + + + +TransitionFadeWipe::TransitionFadeWipe() +{ + +} + +TransitionFadeWipe::~TransitionFadeWipe() +{ + +} + +void TransitionFadeWipe::Draw() +{ + if( m_TransitionState == opened ) + return; + + ///////////////////////// + // draw rectangles that get progressively smaller at the edge of the wipe + ///////////////////////// + BOOL bLeftEdgeIsDarker = m_TransitionState == opening_left || m_TransitionState == closing_right; + BOOL bFadeIsMovingLeft = m_TransitionState == opening_left || m_TransitionState == closing_left; + + double fPercentComplete = m_fPercentThroughTransition; + double fPercentAlongScreen = bFadeIsMovingLeft ? 1-fPercentComplete : fPercentComplete; + + int iFadeLeftEdge = (int) + (-FADE_RECTS_WIDE + (NUM_RECTANGLES + FADE_RECTS_WIDE) * fPercentAlongScreen); + int iFadeRightEdge = (int) + (0 + (NUM_RECTANGLES + FADE_RECTS_WIDE) * fPercentAlongScreen); + + // draw all rectangles + for( int i=0; i iFadeRightEdge ) + iRectWidth = bLeftEdgeIsDarker ? 0 : RECTANGLE_WIDTH; + //iRectWidth = 0; + else // this is a fading rectangle + { + int iRectsFromLeftFadeEdge = i - iFadeLeftEdge; + double fPercentAlongFade = iRectsFromLeftFadeEdge / (double)FADE_RECTS_WIDE; + double fPercentDarkness = bLeftEdgeIsDarker ? 1-fPercentAlongFade : fPercentAlongFade; + iRectWidth = (int)(RECTANGLE_WIDTH * fPercentDarkness); + + } + //iRectWidth = RECTANGLE_WIDTH; + + if( iRectWidth > 0 ) + //if( i == iFadeLeftEdge || i == iFadeRightEdge ) + { // draw the rectangle + int iRectAlpha = (int)( iRectWidth * 255.0f / RECTANGLE_WIDTH ); + RECT rect; + SetRect( &rect, iRectX-RECTANGLE_WIDTH/2, 0, + iRectX+RECTANGLE_WIDTH/2, SCREEN_HEIGHT ); + SCREEN->DrawRect( &rect, D3DCOLOR_ARGB(iRectAlpha,0,0,0) ); + } + } // end foreach rect +} + + diff --git a/stepmania/src/TransitionFadeWipe.h b/stepmania/src/TransitionFadeWipe.h new file mode 100644 index 0000000000..8f8cdb1eb3 --- /dev/null +++ b/stepmania/src/TransitionFadeWipe.h @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// File: TransitionFadeWipe.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#ifndef _TransitionFadeWipe_H_ +#define _TransitionFadeWipe_H_ + + +#include "Transition.h" +#include "RageScreen.h" +#include "RageSound.h" + + +class TransitionFadeWipe : public Transition +{ +public: + TransitionFadeWipe(); + ~TransitionFadeWipe(); + + void Draw(); +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/TransitionRectWipe.cpp b/stepmania/src/TransitionRectWipe.cpp new file mode 100644 index 0000000000..dcab402904 --- /dev/null +++ b/stepmania/src/TransitionRectWipe.cpp @@ -0,0 +1,87 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: TransitionRectWipe.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "RageUtil.h" + +#include "TransitionRectWipe.h" + + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define RECTANGLE_WIDTH 20 +#define NUM_RECTANGLES (SCREEN_WIDTH/RECTANGLE_WIDTH) +#define FADE_RECTS_WIDE (NUM_RECTANGLES/4) // number of rects from fade start to fade end + + + +TransitionRectWipe::TransitionRectWipe() +{ + +} + +TransitionRectWipe::~TransitionRectWipe() +{ + +} + +void TransitionRectWipe::Draw() +{ + if( m_TransitionState == opened ) + return; + + ///////////////////////// + // draw rectangles that get progressively smaller at the edge of the wipe + ///////////////////////// + BOOL bLeftEdgeIsDarker = m_TransitionState == opening_left || m_TransitionState == closing_right; + BOOL bFadeIsMovingLeft = m_TransitionState == opening_left || m_TransitionState == closing_left; + + double fPercentComplete = m_fPercentThroughTransition; + double fPercentAlongScreen = bFadeIsMovingLeft ? 1-fPercentComplete : fPercentComplete; + + int iFadeLeftEdge = (int) + (-FADE_RECTS_WIDE + (NUM_RECTANGLES + FADE_RECTS_WIDE) * fPercentAlongScreen); + int iFadeRightEdge = (int) + (0 + (NUM_RECTANGLES + FADE_RECTS_WIDE) * fPercentAlongScreen); + + // draw all rectangles + for( int i=0; i iFadeRightEdge ) + iRectWidth = bLeftEdgeIsDarker ? 0 : RECTANGLE_WIDTH; + //iRectWidth = 0; + else // this is a fading rectangle + { + int iRectsFromLeftFadeEdge = i - iFadeLeftEdge; + double fPercentAlongFade = iRectsFromLeftFadeEdge / (double)FADE_RECTS_WIDE; + double fPercentDarkness = bLeftEdgeIsDarker ? 1-fPercentAlongFade : fPercentAlongFade; + iRectWidth = (int)(RECTANGLE_WIDTH * fPercentDarkness); + + } + //iRectWidth = RECTANGLE_WIDTH; + + if( iRectWidth > 0 ) + //if( i == iFadeLeftEdge || i == iFadeRightEdge ) + { // draw the rectangle + RECT rect; + SetRect( &rect, iRectX-iRectWidth/2, 0, + iRectX+iRectWidth/2, SCREEN_HEIGHT ); + SCREEN->DrawRect( &rect, D3DCOLOR_ARGB(255,0,0,0) ); + } + } // end foreach rect +} + + diff --git a/stepmania/src/TransitionRectWipe.h b/stepmania/src/TransitionRectWipe.h new file mode 100644 index 0000000000..9cf66b813c --- /dev/null +++ b/stepmania/src/TransitionRectWipe.h @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// File: TransitionRectWipe.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#ifndef _TransitionRectWipe_H_ +#define _TransitionRectWipe_H_ + + +#include "Transition.h" +#include "RageScreen.h" +#include "RageSound.h" + + +class TransitionRectWipe : public Transition +{ +public: + TransitionRectWipe(); + ~TransitionRectWipe(); + + void Draw(); +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/TransitionStarWipe.cpp b/stepmania/src/TransitionStarWipe.cpp new file mode 100644 index 0000000000..1b0c57823c --- /dev/null +++ b/stepmania/src/TransitionStarWipe.cpp @@ -0,0 +1,127 @@ +#include "stdafx.h" +//----------------------------------------------------------------------------- +// File: TransitionStarWipe.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#include "RageUtil.h" + +#include "TransitionStarWipe.h" + + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define TEXTURE_STAR_BLUE "Textures\\Star Blue.png" +#define TEXTURE_STAR_YELLOW "Textures\\Star Yellow.png" + +TransitionStarWipe::TransitionStarWipe() +{ + m_fTransitionTime = m_fTransitionTime * 1.5f; +} + +TransitionStarWipe::~TransitionStarWipe() +{ + +} + +void TransitionStarWipe::Draw() +{ + if( m_TransitionState == opened ) + return; + else if( m_TransitionState == closed ) { + SCREEN->DrawRect( CRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT), D3DCOLOR_RGBA(0,0,0,255) ); + return; + } + + FLOAT fPercentOpen; + switch( m_TransitionState ) + { + case opening_right: + case opening_left: + fPercentOpen = (1.0f - m_fPercentThroughTransition); + break; + case closing_right: + case closing_left: + fPercentOpen = m_fPercentThroughTransition; + break; + } + + + int iNumStars = SCREEN_HEIGHT/m_iStarHeight + 1; + + for( int row=0; rowDrawRect( CRect(x_rect_leading_edge, y_top, + x_rect_trailing_edge, y_bot ), + D3DCOLOR_ARGB(255,0,0,0) + ); + + } +} + +void TransitionStarWipe::OpenWipingRight( WindowMessage send_when_done ) +{ + Transition::OpenWipingRight( send_when_done ); + LoadNewStarSprite( TEXTURE_STAR_BLUE ); +} + +void TransitionStarWipe::OpenWipingLeft( WindowMessage send_when_done ) +{ + Transition::OpenWipingLeft( send_when_done ); + LoadNewStarSprite( TEXTURE_STAR_BLUE ); +} + +void TransitionStarWipe::CloseWipingRight(WindowMessage send_when_done ) +{ + Transition::CloseWipingRight( send_when_done ); + LoadNewStarSprite( TEXTURE_STAR_YELLOW ); +} + +void TransitionStarWipe::CloseWipingLeft( WindowMessage send_when_done ) +{ + Transition::CloseWipingLeft( send_when_done ); + LoadNewStarSprite( TEXTURE_STAR_YELLOW ); +} + +void TransitionStarWipe::LoadNewStarSprite( CString sFileName ) +{ + m_sprStar.LoadFromTexture( sFileName ); + m_iStarWidth = m_sprStar.GetZoomedWidth(); + m_iStarHeight = m_sprStar.GetZoomedHeight(); +} diff --git a/stepmania/src/TransitionStarWipe.h b/stepmania/src/TransitionStarWipe.h new file mode 100644 index 0000000000..3a5fa7d8a3 --- /dev/null +++ b/stepmania/src/TransitionStarWipe.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// File: TransitionStarWipe.cpp +// +// Desc: "Window blinds"-type transition. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + + +#ifndef _TransitionStarWipe_H_ +#define _TransitionStarWipe_H_ + + +#include "Transition.h" +#include "RageScreen.h" +#include "RageSound.h" + + +class TransitionStarWipe : public Transition +{ +public: + TransitionStarWipe(); + ~TransitionStarWipe(); + + void Draw(); + + void OpenWipingRight( WindowMessage send_when_done ); + void OpenWipingLeft( WindowMessage send_when_done ); + void CloseWipingRight(WindowMessage send_when_done ); + void CloseWipingLeft( WindowMessage send_when_done ); + +protected: + void LoadNewStarSprite( CString sFileName ); + + Sprite m_sprStar; + int m_iStarWidth; + int m_iStarHeight; +}; + + + + +#endif \ No newline at end of file diff --git a/stepmania/src/resource.h b/stepmania/src/resource.h new file mode 100644 index 0000000000..07b416b66d --- /dev/null +++ b/stepmania/src/resource.h @@ -0,0 +1,22 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by StepMania.RC +// +#define IDR_MAIN_ACCEL 1001 +#define IDM_TOGGLEFULLSCREEN 1002 +#define IDI_ICON 1003 +#define IDC_CURSOR 1004 +#define IDM_EXIT 40003 +#define IDM_WINDOWED 40008 +#define IDM_PADS 40011 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1006 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/stepmania/src/song.h b/stepmania/src/song.h new file mode 100644 index 0000000000..07ee6971a7 --- /dev/null +++ b/stepmania/src/song.h @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// File: Song.h +// +// Desc: Holds metadata for a song and the song's step data. +// +// Copyright (c) 2001 Chris Danford. All rights reserved. +//----------------------------------------------------------------------------- + +#ifndef _SONG_H_ +#define _SONG_H_ + + +#include +#include "Steps.h" + + +#define BEATS_IN_MEASURE 4 + + +class Song +{ +public: + Song() : + m_fBPM(0.0), + m_fBeatOffset(0.0) + { + }; + Song( Song &from ) + { + Copy( from ); + }; + Song& operator=( const Song &from ) + { + if (this != &from) + { + Copy( from ); + } + return *this; + }; + void Copy( const Song &from ) + { + m_sSongFile = from.m_sSongFile; + m_sSongDir = from.m_sSongDir; + m_sTitle = from.m_sTitle; + m_sArtist = from.m_sArtist; + m_sCreator = from.m_sCreator; + m_fBPM = from.m_fBPM; + m_fBeatOffset = from.m_fBeatOffset; + + m_sMusic = from.m_sMusic; + m_sSample = from.m_sSample; + m_sBanner = from.m_sBanner; + m_sBackground = from.m_sBackground; + + arraySteps.Copy( from.arraySteps ); + }; + + bool LoadFromSongDir( CString sDir ); + + bool IsUsingBitmapBG() + { + CString sBGFile = m_sBackground; + sBGFile.MakeLower(); + return sBGFile.Right(3) == "bmp"; + }; + +private: + BOOL LoadFromBMSFile( CString sPath ); + BOOL LoadFromMSDFile( CString sPath ); + + void FillEmptyValuesWithDefaults(); + +public: + CString GetSongFilePath() {return m_sSongDir + m_sSongFile; }; + CString GetSongFileDir() {return m_sSongDir; }; + CString GetMusicPath() {return m_sSongDir + m_sMusic; }; + CString GetSamplePath() {return m_sSongDir + m_sSample; }; + CString GetBannerPath() {return m_sSongDir + m_sBanner; }; + CString GetBackgroundPath() {return m_sSongDir + m_sBackground; }; +// Steps& GetStepsAt( int iIndex ) {return arraySteps[iIndex]; }; + + CString GetTitle() {return m_sTitle; }; + CString GetArtist() {return m_sArtist; }; + CString GetCreator() {return m_sCreator; }; + FLOAT GetBeatOffset() {return m_fBeatOffset; }; + FLOAT GetBPM() {return m_fBPM; }; + FLOAT GetBeatsPerSecond() {return m_fBPM / 60.0f; }; + +public: + + +private: + CString m_sSongFile; + CString m_sSongDir; + + CString m_sTitle; + CString m_sArtist; + CString m_sCreator; + FLOAT m_fBPM; + FLOAT m_fBeatOffset; + + CString m_sMusic; + CString m_sSample; + CString m_sBanner; + CString m_sBackground; + +public: + CArray arraySteps; +}; + + + +#endif \ No newline at end of file