1264 lines
40 KiB
C++
1264 lines
40 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "bagel/afxwin.h"
|
|
#include "bagel/hodjnpodj/hnplibs/stdafx.h"
|
|
#include "bagel/boflib/misc.h"
|
|
#include "bagel/hodjnpodj/hnplibs/sprite.h"
|
|
#include "bagel/hodjnpodj/globals.h"
|
|
#include "bagel/hodjnpodj/hnplibs/mainmenu.h"
|
|
#include "bagel/hodjnpodj/hnplibs/cmessbox.h"
|
|
#include "bagel/hodjnpodj/hnplibs/text.h"
|
|
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
|
|
#include "bagel/hodjnpodj/hnplibs/rules.h"
|
|
#include "bagel/hodjnpodj/hnplibs/button.h"
|
|
#include "bagel/hodjnpodj/garfunkle/resource.h"
|
|
#include "bagel/hodjnpodj/garfunkle/garfunkle.h"
|
|
#include "bagel/hodjnpodj/garfunkle/optndlg.h"
|
|
#include "bagel/hodjnpodj/garfunkle/note.h"
|
|
#include "bagel/hodjnpodj/hodjnpodj.h"
|
|
|
|
namespace Bagel {
|
|
namespace HodjNPodj {
|
|
namespace Garkfunkle {
|
|
|
|
void CALLBACK GetSubOptions(CWnd* pParentWind);
|
|
void add_note_to_series(int nNewValue);
|
|
|
|
CBmpButton *m_pScrollButton; // Scroll button
|
|
CPalette *pGamePalette = nullptr; // Palette of current artwork
|
|
bool bSuccess = false;
|
|
bool m_bIgnoreScrollClick;
|
|
bool bLDown = false; // Make sure we only act on LUp if LDown was on a musician
|
|
bool bPlayingBackSeries = false;
|
|
|
|
#define FIRST_MUSICIAN 100
|
|
#define NOT_PLAYING 0
|
|
#define NOT_THERE 1
|
|
|
|
//
|
|
// Musician-related stuff:
|
|
//
|
|
CSound *pMusic = nullptr; // The sound object for the musician's music
|
|
CSprite *pAnimSprite[MAX_BUTTONS]; // Pointer for the animating musician
|
|
CBitmap *pMusicians[(MAX_BUTTONS * 2)]; // Bitmap for Not_playing and Not_there
|
|
int m_nButID = 0; // button which is animating
|
|
|
|
CText *m_pSignText = nullptr; // The current series length display on the sign
|
|
CBitmap *pRibbon = nullptr; // The blue ribbon to be put on sign at win condition
|
|
|
|
bool m_bPlaying;
|
|
bool m_bNewGame = false;
|
|
|
|
bool m_bPlayGame; // Options variables
|
|
int m_nSpeed; // Speed is in MILLISECONDS
|
|
int m_nNumButtons;
|
|
int m_nWinCondition = 0; // Number needed to win the game (in meta mode only)
|
|
|
|
// Temporary variables for new Options
|
|
bool tempPlayGame;
|
|
int tempSpeed; // Speed is in MILLISECONDS
|
|
int tempNumButtons;
|
|
|
|
int nNoteCount = 0;
|
|
int nCheckCount = 0;
|
|
unsigned int nSButFlag = MAX_BUTTONS;
|
|
CNote *pNoteMarker;
|
|
|
|
static const char *cSoundName[MAX_BUTTONS] = {
|
|
VIOLIN_SOUND, CELLO_SOUND, DRUM_SOUND,
|
|
SAX_SOUND, HARP_SOUND, CLARINET_SOUND
|
|
};
|
|
|
|
static const char *cAnimName[MAX_BUTTONS] = {
|
|
VIOLIN_ANIM, CELLO_ANIM, DRUM_ANIM, SAX_ANIM,
|
|
HARP_ANIM, CLARINET_ANIM
|
|
};
|
|
|
|
static const int nNumCels[MAX_BUTTONS] = { VIOLIN_CELS, CELLO_CELS, DRUM_CELS, SAX_CELS,
|
|
HARP_CELS, CLARINET_CELS
|
|
};
|
|
|
|
static const POINT Offset[MAX_BUTTONS] = {
|
|
{ VIOLIN_OFFSET_X, VIOLIN_OFFSET_Y },
|
|
{ CELLO_OFFSET_X, CELLO_OFFSET_Y },
|
|
{ DRUM_OFFSET_X, DRUM_OFFSET_Y },
|
|
{ SAX_OFFSET_X, SAX_OFFSET_Y },
|
|
{ HARP_OFFSET_X, HARP_OFFSET_Y },
|
|
{ CLARINET_OFFSET_X, CLARINET_OFFSET_Y }
|
|
};
|
|
|
|
extern LPGAMESTRUCT pGameInfo;
|
|
extern HWND ghParentWnd;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CMainWindow constructor:
|
|
// Create the window with the appropriate style, size, menu, etc.;
|
|
// it will be later revealed by CTheApp::InitInstance(). Then
|
|
// create our splash screen object by opening and loading its DIB.
|
|
//
|
|
CMainWindow::CMainWindow() {
|
|
CDC *pDC;
|
|
CString WndClass;
|
|
CRect MainRect, StartRect;
|
|
CBitmap *pBackBitmap = nullptr;
|
|
CPalette *pOldPal = nullptr;
|
|
int i, j;
|
|
|
|
BeginWaitCursor();
|
|
initStatics();
|
|
|
|
pGameInfo->lScore = 0L;
|
|
|
|
// Define a special window class which traps double-clicks, is byte aligned
|
|
// to maximize BITBLT performance, and creates "owned" DCs rather than sharing
|
|
// the five system defined DCs which are not guaranteed to be available;
|
|
// this adds a bit to our app size but avoids hangs/freezes/lockups.
|
|
WndClass = AfxRegisterWndClass(CS_BYTEALIGNWINDOW | CS_OWNDC,
|
|
nullptr,
|
|
nullptr,
|
|
nullptr);
|
|
|
|
// Center our window on the screen
|
|
pDC = GetDC();
|
|
|
|
MainRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) >> 1;
|
|
MainRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) >> 1;
|
|
MainRect.right = MainRect.left + GAME_WIDTH;
|
|
MainRect.bottom = MainRect.top + GAME_HEIGHT;
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
// Create the window as a POPUP so no boarders, title, or menu are present;
|
|
// this is because the game's background art will fill the entire 640x480 area.
|
|
Create(WndClass, "Boffo Games -- Garfunkel", WS_POPUP, MainRect, nullptr, 0);
|
|
|
|
pDC = GetDC();
|
|
pBackBitmap = FetchBitmap(pDC, &pGamePalette, MAINSCREEN);
|
|
pOldPal = pDC->SelectPalette(pGamePalette, false); // select the game palette
|
|
pDC->RealizePalette(); //...and realize it
|
|
|
|
pBackBitmap->DeleteObject();
|
|
delete pBackBitmap;
|
|
|
|
ShowWindow(SW_SHOWNORMAL); // Give 'em something to look at
|
|
SplashScreen(); // Paint the backdrop with no musicians
|
|
|
|
// Build Scroll Command button
|
|
m_pScrollButton = new CBmpButton;
|
|
ASSERT(m_pScrollButton != nullptr);
|
|
StartRect.SetRect(SCROLL_BUTTON_X, SCROLL_BUTTON_Y,
|
|
SCROLL_BUTTON_X + SCROLL_BUTTON_DX - 1,
|
|
SCROLL_BUTTON_Y + SCROLL_BUTTON_DY - 1);
|
|
bSuccess = (*m_pScrollButton).Create(nullptr, BS_OWNERDRAW | WS_CHILD | WS_VISIBLE, StartRect, this, IDC_SCROLL);
|
|
ASSERT(bSuccess);
|
|
bSuccess = (*m_pScrollButton).LoadBitmaps(SCROLLUP, SCROLLDOWN, 0, 0);
|
|
ASSERT(bSuccess);
|
|
m_bIgnoreScrollClick = false;
|
|
|
|
if (pGameInfo->bPlayingMetagame) // only in metamode
|
|
pRibbon = FetchBitmap(pDC, nullptr, RIBBON); // load bitmap for ribbon
|
|
|
|
// Initialize the musician bitmaps and locations
|
|
rectMusic[0].SetRect(VIOLIN_LOCATION_X, VIOLIN_LOCATION_Y,
|
|
VIOLIN_LOCATION_X + VIOLIN_WIDTH, VIOLIN_LOCATION_Y + VIOLIN_HEIGHT);
|
|
rectMusic[1].SetRect(CELLO_LOCATION_X, CELLO_LOCATION_Y,
|
|
CELLO_LOCATION_X + CELLO_WIDTH, CELLO_LOCATION_Y + CELLO_HEIGHT);
|
|
rectMusic[2].SetRect(DRUM_LOCATION_X, DRUM_LOCATION_Y,
|
|
DRUM_LOCATION_X + DRUM_WIDTH, DRUM_LOCATION_Y + DRUM_HEIGHT);
|
|
rectMusic[3].SetRect(SAX_LOCATION_X, SAX_LOCATION_Y,
|
|
SAX_LOCATION_X + SAX_WIDTH, SAX_LOCATION_Y + SAX_HEIGHT);
|
|
rectMusic[4].SetRect(HARP_LOCATION_X, HARP_LOCATION_Y,
|
|
HARP_LOCATION_X + HARP_WIDTH, HARP_LOCATION_Y + HARP_HEIGHT);
|
|
rectMusic[5].SetRect(CLARINET_LOCATION_X, CLARINET_LOCATION_Y,
|
|
CLARINET_LOCATION_X + CLARINET_WIDTH, CLARINET_LOCATION_Y + CLARINET_HEIGHT);
|
|
|
|
for (i = 0; i < MAX_BUTTONS; i++) {
|
|
for (j = 0; j < 2; j++) {
|
|
pMusicians[(i * 2) + j] = FetchResourceBitmap(pDC, nullptr, FIRST_MUSICIAN + (i * 2) + j);
|
|
}
|
|
pAnimSprite[i] = new CSprite;
|
|
(*pAnimSprite[i]).SharePalette(pGamePalette);
|
|
bSuccess = (*pAnimSprite[i]).LoadCels(pDC, cAnimName[i], nNumCels[i]);
|
|
ASSERT(bSuccess);
|
|
(*pAnimSprite[i]).SetMasked(false);
|
|
(*pAnimSprite[i]).SetMobile(false);
|
|
}
|
|
|
|
// Set up the text on the sign to display the current series length
|
|
StartRect.SetRect(SIGN_LOCATION_X, SIGN_LOCATION_Y,
|
|
SIGN_LOCATION_X + SIGN_WIDTH, SIGN_LOCATION_Y + SIGN_HEIGHT);
|
|
if ((m_pSignText = new CText()) != nullptr) {
|
|
(*m_pSignText).SetupText(pDC, pGamePalette, &StartRect, JUSTIFY_CENTER);
|
|
}
|
|
|
|
(*pDC).SelectPalette(pOldPal, false); // Select back the old palette
|
|
ReleaseDC(pDC);
|
|
|
|
//srand((unsigned) time(nullptr)); // seed the random number generator
|
|
|
|
m_bPlayGame = true;
|
|
|
|
if (pGameInfo->bPlayingMetagame) {
|
|
switch (pGameInfo->nSkillLevel) {
|
|
case SKILLLEVEL_LOW:
|
|
m_nNumButtons = 4;
|
|
m_nSpeed = 6; // Allegretto
|
|
m_nWinCondition = LOW_WIN;
|
|
break;
|
|
case SKILLLEVEL_MEDIUM:
|
|
m_nNumButtons = 5;
|
|
m_nSpeed = 8; // Vivace
|
|
m_nWinCondition = MEDIUM_WIN;
|
|
break;
|
|
case SKILLLEVEL_HIGH:
|
|
m_nNumButtons = 6;
|
|
m_nSpeed = 10; // Prestissimo
|
|
m_nWinCondition = HIGH_WIN;
|
|
break;
|
|
} // end switch
|
|
} else {
|
|
m_nNumButtons = MAX_BUTTONS; // 6
|
|
m_nSpeed = 8; // Vivace
|
|
}
|
|
|
|
tempPlayGame = m_bPlayGame;
|
|
tempNumButtons = m_nNumButtons;
|
|
tempSpeed = m_nSpeed;
|
|
|
|
m_bPlaying = false;
|
|
|
|
GetNewSequence(MAX_SEQUENCE); // Get a random sequence
|
|
nNoteCount = 1; // Set the count to the first note
|
|
nCheckCount = 0; // Haven't checked any input yet
|
|
|
|
MSG lpmsg; // Remove any messages in the queue before starting
|
|
while (PeekMessage(&lpmsg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) ; // prevent random 'hits'
|
|
|
|
EndWaitCursor();
|
|
|
|
if (pGameInfo->bPlayingMetagame == false) {
|
|
ActivateButtons(m_nNumButtons, NOT_PLAYING); // Activate the buttons
|
|
PostMessage(WM_COMMAND, IDC_SCROLL, BN_CLICKED); // Activate the Options dialog
|
|
}
|
|
|
|
} //End of CMainWindow
|
|
|
|
void CMainWindow::initStatics() {
|
|
m_pScrollButton = nullptr;
|
|
pGamePalette = nullptr;
|
|
bSuccess = false;
|
|
m_bIgnoreScrollClick = false;
|
|
bLDown = false;
|
|
bPlayingBackSeries = false;
|
|
pMusic = nullptr;
|
|
Common::fill(pAnimSprite, pAnimSprite + MAX_BUTTONS, nullptr);
|
|
Common::fill(pMusicians, pMusicians + (MAX_BUTTONS * 2), nullptr);
|
|
m_nButID = 0;
|
|
|
|
m_pSignText = nullptr;
|
|
pRibbon = nullptr;
|
|
m_bPlaying = false;
|
|
m_bNewGame = false;
|
|
m_bPlayGame = false;
|
|
|
|
m_nSpeed = 0;
|
|
m_nNumButtons = 0;
|
|
m_nWinCondition = 0;
|
|
|
|
tempPlayGame = false;
|
|
tempSpeed = 0;
|
|
tempNumButtons = 0;
|
|
nNoteCount = 0;
|
|
nCheckCount = 0;
|
|
nSButFlag = MAX_BUTTONS;
|
|
pNoteMarker = nullptr;
|
|
}
|
|
|
|
// OnPaint:
|
|
// This is called whenever Windows sends a WM_PAINT message.
|
|
// Note that creating a CPaintDC automatically does a BeginPaint and
|
|
// an EndPaint call is done when it is destroyed at the end of this
|
|
// function. CPaintDC's constructor needs the window (this).
|
|
//
|
|
void CMainWindow::OnPaint() {
|
|
PAINTSTRUCT lpPaint;
|
|
|
|
InvalidateRect(nullptr, false); // invalidate the entire window
|
|
BeginPaint(&lpPaint);
|
|
SplashScreen(); // Paint the backdrop and scroll button
|
|
ActivateButtons(m_nNumButtons, NOT_PLAYING); // Activate the buttons
|
|
EndPaint(&lpPaint);
|
|
}
|
|
|
|
|
|
// Paint the background art (splash screen) in the client area;
|
|
// and repaint the scroll button at the top
|
|
// called by both OnPaint and InitInstance.
|
|
void CMainWindow::SplashScreen() {
|
|
CRect rcDest;
|
|
CRect rcDIB;
|
|
CDC *pDC;
|
|
CDibDoc myDoc;
|
|
HDIB hDIB;
|
|
char msg[4];
|
|
|
|
pDC = GetDC();
|
|
|
|
myDoc.OpenDocument(MAINSCREEN);
|
|
|
|
hDIB = myDoc.GetHDIB();
|
|
|
|
if (pDC && hDIB) {
|
|
GetClientRect(rcDest);
|
|
|
|
int cxDIB = (int) DIBWidth(hDIB);
|
|
int cyDIB = (int) DIBHeight(hDIB);
|
|
|
|
rcDIB.top = rcDIB.left = 0;
|
|
rcDIB.right = cxDIB;
|
|
rcDIB.bottom = cyDIB;
|
|
PaintDIB((*pDC).m_hDC, &rcDest, hDIB, &rcDIB, pGamePalette);
|
|
}
|
|
|
|
if (m_bPlayGame) {
|
|
Common::sprintf_s(msg, "%d", nNoteCount - 1);
|
|
(*m_pSignText).DisplayString(pDC, msg, 32, FW_NORMAL, SIGN_COLOR);
|
|
if (pGameInfo->bPlayingMetagame && (nNoteCount > m_nWinCondition)) {
|
|
PaintMaskedBitmap(pDC, pGamePalette, pRibbon, RIBBON_X, RIBBON_Y);
|
|
}
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Process messages and controls
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// OnCommand
|
|
// This function is called when a WM_COMMAND message is issued,
|
|
// typically in order to process control related activities.
|
|
//
|
|
|
|
bool CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) {
|
|
CDC *pDC;
|
|
CNote *pNewNote;
|
|
CSound *pEffect = nullptr;
|
|
|
|
KillTimer(PLAYER_TIMER);
|
|
|
|
pDC = GetDC();
|
|
|
|
if (HIWORD(lParam) == BN_CLICKED) {
|
|
CRules RulesDlg((CWnd *)this, RULES_TEXT, pGamePalette, pGameInfo->bSoundEffectsEnabled ? RULES_SOUND : nullptr);
|
|
|
|
CMainMenu COptionsWind((CWnd *)this, pGamePalette,
|
|
pGameInfo->bPlayingMetagame ? (NO_NEWGAME | NO_OPTIONS) : 0,
|
|
GetSubOptions, RULES_TEXT, pGameInfo->bSoundEffectsEnabled ? RULES_SOUND : nullptr, pGameInfo) ; // Construct Option dialog
|
|
|
|
switch (wParam) {
|
|
|
|
case IDC_START: // And we're off!
|
|
if (pGameInfo->bPlayingMetagame)
|
|
wait_awhile(PAUSE_TIME); // Give the resources, etc. time to load
|
|
m_bPlaying = true;
|
|
m_bNewGame = true;
|
|
pNewNote = CNote::GetNoteHead(); // Get the first note
|
|
if (pNewNote) { // if list is not empty
|
|
PlayBackSeries(nNoteCount); // Play the first note
|
|
pNoteMarker = CNote::GetNoteHead(); // set checking pointer
|
|
pNewNote = nullptr; // Stop pointing at the note list
|
|
SetTimer(PLAYER_TIMER, TIME_LIMIT, nullptr); // Give the player TIME_LIMIT to respond
|
|
} //...to head of list
|
|
else // no note chain,
|
|
m_bPlaying = false; //...so we can't play
|
|
break;
|
|
|
|
case IDC_A: // If a musician button was hit...
|
|
case IDC_B:
|
|
case IDC_C:
|
|
case IDC_D:
|
|
case IDC_E:
|
|
case IDC_F:
|
|
unsigned int nButID, nHitID;
|
|
char msg[4];
|
|
|
|
nHitID = wParam - IDC_A; // The musician buttons are consecutive
|
|
//...get the index of the one pressed
|
|
if (m_bPlayGame) { // If they're not just playing music
|
|
if (pNoteMarker) // If we're playing a game
|
|
nButID = pNoteMarker->GetValue(); // Get the Index of the correct note
|
|
else break;
|
|
|
|
if (nButID == nHitID) { // If the one pressed is the correct note
|
|
pNoteMarker = pNoteMarker->GetNextNote(); // Move to the next
|
|
nCheckCount++; // Increment the number correct so far
|
|
} else { // They hit the wrong button :-(
|
|
char buf[64];
|
|
Common::sprintf_s(buf, "Longest series: %d", nNoteCount - 1);
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
pEffect = new CSound((CWnd *)this, WRONG_SOUND,
|
|
SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE); //...Wave file, to delete itself
|
|
(*pEffect).play(); //...play the narration
|
|
}
|
|
MSG lpmsg; // Clear out any extraneous mouse clicks
|
|
while (PeekMessage(&lpmsg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) ;
|
|
|
|
CMessageBox GameOverDlg((CWnd *)this, pGamePalette, "Wrong musician!", buf);
|
|
CSound::waitWaveSounds();
|
|
|
|
pNoteMarker = nullptr;
|
|
m_bPlaying = false;
|
|
m_bNewGame = false;
|
|
CNote::FlushNoteList(); // Flush the last series of notes
|
|
if (pGameInfo->bPlayingMetagame)
|
|
PostMessage(WM_CLOSE, 0, 0); // and post a program exit
|
|
break;
|
|
}
|
|
if (nCheckCount == nNoteCount) { // If they completed the series
|
|
pNoteMarker = nullptr;
|
|
if (nNoteCount == MAX_SEQUENCE) {
|
|
nNoteCount++; // Hitting MAX increments NoteCount to MAX + 1
|
|
Common::sprintf_s(msg, "%d", nNoteCount - 1); //...so return is correct
|
|
(*m_pSignText).DisplayString(pDC, msg, 32, FW_NORMAL, SIGN_COLOR);
|
|
|
|
if (pGameInfo->bPlayingMetagame && (nNoteCount > m_nWinCondition)) {
|
|
PaintMaskedBitmap(pDC, pGamePalette, pRibbon, RIBBON_X, RIBBON_Y);
|
|
}
|
|
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
pEffect = new CSound((CWnd *)this, WIN_SOUND,
|
|
SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE); //...Wave file, to delete itself
|
|
(*pEffect).play(); //...play the narration
|
|
}
|
|
MSG lpmsg;
|
|
while (PeekMessage(&lpmsg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) ;
|
|
|
|
CMessageBox GameOverDlg((CWnd *)this, pGamePalette, "Game over", "You have won!");
|
|
CSound::waitWaveSounds();
|
|
m_bPlaying = false;
|
|
m_bNewGame = false;
|
|
CNote::FlushNoteList();
|
|
if (pGameInfo->bPlayingMetagame)
|
|
PostMessage(WM_CLOSE, 0, 0); // and post a program exit
|
|
} else {
|
|
nNoteCount++;
|
|
Common::sprintf_s(msg, "%d", nNoteCount - 1);
|
|
(*m_pSignText).DisplayString(pDC, msg, 32, FW_NORMAL, SIGN_COLOR);
|
|
|
|
if (pGameInfo->bPlayingMetagame && (nNoteCount > m_nWinCondition)) {
|
|
PaintMaskedBitmap(pDC, pGamePalette, pRibbon, RIBBON_X, RIBBON_Y);
|
|
}
|
|
|
|
wait_awhile(PAUSE_TIME); // Pause before playing sequence
|
|
nCheckCount = 0; // Reset checking counter
|
|
if ((nNoteCount % INCREMENT_RATE == 0) && (m_nSpeed != MAX_SPEED))
|
|
m_nSpeed++; // on multiples of the increment rate
|
|
//...increase the speed by one
|
|
|
|
PlayBackSeries(nNoteCount);
|
|
MSG lpmsg;
|
|
while (PeekMessage(&lpmsg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) ;
|
|
SetTimer(PLAYER_TIMER, TIME_LIMIT, nullptr); //Reset time limit
|
|
}
|
|
pNoteMarker = CNote::GetNoteHead(); //set checking pointer to head of list
|
|
} else
|
|
SetTimer(PLAYER_TIMER, TIME_LIMIT, nullptr); //Reset time limit
|
|
}
|
|
|
|
break;
|
|
|
|
case IDC_RULES:
|
|
m_bIgnoreScrollClick = true;
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, true, 0L);
|
|
|
|
CSound::waitWaveSounds();
|
|
RulesDlg.DoModal();
|
|
m_bIgnoreScrollClick = false;
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, false, 0L);
|
|
break;
|
|
|
|
case IDC_SCROLL:
|
|
if (m_bIgnoreScrollClick) {
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, true, 0L);
|
|
break;
|
|
}
|
|
|
|
m_bIgnoreScrollClick = true;
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, true, 0L);
|
|
SendDlgItemMessage(IDC_SCROLL, BM_SETSTATE, true, 0L);
|
|
|
|
switch (COptionsWind.DoModal()) {
|
|
|
|
case IDC_OPTIONS_NEWGAME:
|
|
if (!pGameInfo->bPlayingMetagame)
|
|
NewGame();
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, false, 0L);
|
|
m_bIgnoreScrollClick = false;
|
|
break;
|
|
|
|
case IDC_OPTIONS_RETURN:
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, false, 0L);
|
|
m_bIgnoreScrollClick = false;
|
|
if (m_bPlayGame && m_bNewGame) { // playing repeat game & already
|
|
wait_awhile(PAUSE_TIME); // started...pause for a second
|
|
PostMessage(WM_COMMAND, IDC_START, BN_CLICKED); // Activate the Options dialog
|
|
}
|
|
break;
|
|
|
|
case IDC_OPTIONS_QUIT: // Quit button was clicked
|
|
PostMessage(WM_CLOSE, 0, 0); // and post a program exit
|
|
return false;
|
|
|
|
} //end switch(ComDlg.DoModal())
|
|
|
|
} //end switch(wParam)
|
|
} // end if
|
|
|
|
ReleaseDC(pDC);
|
|
(*this).SetFocus(); // Reset focus back to the main window
|
|
return true;
|
|
}
|
|
|
|
/*****************************************************************
|
|
*
|
|
* OnLButtonDown
|
|
*
|
|
* FUNCTIONAL DESCRIPTION:
|
|
*
|
|
* Left mouse button processing function
|
|
*
|
|
* FORMAL PARAMETERS:
|
|
*
|
|
* unsigned int nFlags Virtual key info
|
|
* CPoint point Location of cursor
|
|
*
|
|
* IMPLICIT INPUT PARAMETERS:
|
|
*
|
|
* [External data read]
|
|
*
|
|
* IMPLICIT OUTPUT PARAMETERS:
|
|
*
|
|
* [External data modified]
|
|
*
|
|
* RETURN VALUE:
|
|
*
|
|
* void
|
|
*
|
|
****************************************************************/
|
|
void CMainWindow::OnLButtonDown(unsigned int nFlags, CPoint point) {
|
|
CRect rectTitle,
|
|
rectWoodsRight,
|
|
rectWoodsLeft,
|
|
rectSign,
|
|
rectBench;
|
|
CDC *pDC;
|
|
CSound *pEffect = nullptr;
|
|
int i,
|
|
nPick = 0;
|
|
char bufName[64];
|
|
|
|
pDC = GetDC();
|
|
|
|
rectTitle.SetRect(NEWGAME_LOCATION_X, NEWGAME_LOCATION_Y,
|
|
NEWGAME_LOCATION_X + NEWGAME_WIDTH,
|
|
NEWGAME_LOCATION_Y + NEWGAME_HEIGHT);
|
|
|
|
rectWoodsRight.SetRect(WOODRIGHT_LOCATION_X, WOODRIGHT_LOCATION_Y,
|
|
WOODRIGHT_LOCATION_X + WOODRIGHT_WIDTH,
|
|
WOODRIGHT_LOCATION_Y + WOODRIGHT_HEIGHT);
|
|
|
|
rectWoodsLeft.SetRect(WOODLEFT_LOCATION_X, WOODLEFT_LOCATION_Y,
|
|
WOODLEFT_LOCATION_X + WOODLEFT_WIDTH,
|
|
WOODLEFT_LOCATION_Y + WOODLEFT_HEIGHT);
|
|
|
|
rectSign.SetRect(SIGN_LOCATION_X, SIGN_LOCATION_Y,
|
|
SIGN_LOCATION_X + SIGN_WIDTH,
|
|
SIGN_LOCATION_Y + SIGN_HEIGHT);
|
|
|
|
rectBench.SetRect(BENCH_LOCATION_X, BENCH_LOCATION_Y,
|
|
BENCH_LOCATION_X + BENCH_WIDTH,
|
|
BENCH_LOCATION_Y + BENCH_HEIGHT);
|
|
|
|
if (rectTitle.PtInRect(point) && (!pGameInfo->bPlayingMetagame))
|
|
NewGame(); // Activate New Game
|
|
else if (m_bNewGame && m_bPlaying) {
|
|
for (i = 0; i < m_nNumButtons; i++) {
|
|
if (rectMusic[i].PtInRect(point)) {
|
|
bLDown = true;
|
|
KillTimer(PLAYER_TIMER); // don't time out
|
|
m_nButID = i;
|
|
StartAnimation();
|
|
wait_awhile(10 * ((NUM_SPEEDS - MAX_SPEED) + SLOW_DOWN));
|
|
return;
|
|
//break;
|
|
} // end if ptinrect
|
|
} // end for
|
|
} // end else if m_bPlaying
|
|
else if (!m_bNewGame) {
|
|
// if (pGameInfo->bPlayingMetagame)
|
|
PostMessage(WM_COMMAND, IDC_START, BN_CLICKED); // Activate the imaginary 'start' button
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
if (rectWoodsRight.PtInRect(point) || rectWoodsLeft.PtInRect(point)) {
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
KillTimer(PLAYER_TIMER); // so it doesn't run out
|
|
pEffect = new CSound((CWnd *)this, TREES_SOUND,
|
|
SOUND_WAVE | SOUND_AUTODELETE); // Wave file, sync, to delete itself
|
|
(*pEffect).play(); // Play the sound
|
|
if (m_bPlayGame && m_bNewGame)
|
|
SetTimer(PLAYER_TIMER, TIME_LIMIT, nullptr); // Reset response time limit
|
|
}
|
|
} else if (rectSign.PtInRect(point)) {
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
KillTimer(PLAYER_TIMER); // so it doesn't run out
|
|
nPick = brand() % NUM_SIGN_SOUNDS;
|
|
switch (nPick) {
|
|
case 0:
|
|
Common::sprintf_s(bufName, SIGN_1_SOUND);
|
|
break;
|
|
case 1:
|
|
Common::sprintf_s(bufName, SIGN_2_SOUND);
|
|
break;
|
|
case 2:
|
|
Common::sprintf_s(bufName, SIGN_3_SOUND);
|
|
break;
|
|
case 3:
|
|
Common::sprintf_s(bufName, SIGN_4_SOUND);
|
|
break;
|
|
default:
|
|
Common::sprintf_s(bufName, SIGN_5_SOUND);
|
|
break;
|
|
}
|
|
pEffect = new CSound((CWnd *)this, bufName,
|
|
SOUND_WAVE | SOUND_AUTODELETE); // Wave file, to delete itself
|
|
(*pEffect).play(); // play the sound
|
|
if (m_bPlayGame && m_bNewGame)
|
|
SetTimer(PLAYER_TIMER, TIME_LIMIT, nullptr); // Reset response time limit
|
|
}
|
|
} else if (rectBench.PtInRect(point)) {
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
KillTimer(PLAYER_TIMER); // so it doesn't run out
|
|
pEffect = new CSound((CWnd *)this, BENCH_SOUND,
|
|
SOUND_WAVE | SOUND_AUTODELETE); // Wave file, to delete itself
|
|
(*pEffect).play(); // Play the sound
|
|
if (m_bPlayGame && m_bNewGame)
|
|
SetTimer(PLAYER_TIMER, TIME_LIMIT, nullptr); // Reset response time limit
|
|
}
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
}
|
|
|
|
|
|
void CMainWindow::OnLButtonUp(unsigned int nFlags, CPoint point) {
|
|
if (m_bNewGame) {
|
|
if (m_bPlaying && bLDown) {
|
|
if (pAnimSprite[m_nButID] != nullptr) {
|
|
StopAnimation();
|
|
MFC::SendMessage(m_hWnd, WM_COMMAND, m_nButID + IDC_A, BN_CLICKED); // Activate hit logic
|
|
}
|
|
bLDown = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMainWindow::OnRButtonDown(unsigned int nFlags, CPoint point) {
|
|
|
|
if (!m_bNewGame) {
|
|
PostMessage(WM_COMMAND, IDC_START, BN_CLICKED); // Activate the imaginary 'start' button
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************
|
|
*
|
|
* OnMouseMove
|
|
*
|
|
* FUNCTIONAL DESCRIPTION:
|
|
*
|
|
* Mouse movement processing function
|
|
*
|
|
* FORMAL PARAMETERS:
|
|
*
|
|
* unsigned int nFlags Virtual key info
|
|
* CPoint point Location of cursor
|
|
*
|
|
* IMPLICIT INPUT PARAMETERS:
|
|
*
|
|
* [External data read]
|
|
*
|
|
* IMPLICIT OUTPUT PARAMETERS:
|
|
*
|
|
* [External data modified]
|
|
*
|
|
* RETURN VALUE:
|
|
*
|
|
* void
|
|
*
|
|
****************************************************************/
|
|
void CMainWindow::OnMouseMove(unsigned int nFlags, CPoint point) {
|
|
if (bPlayingBackSeries) {
|
|
SetCursor(LoadCursor(nullptr, IDC_WAIT)); // Refresh cursor object
|
|
} else {
|
|
SetCursor(LoadCursor(nullptr, IDC_ARROW)); // Refresh cursor object
|
|
}
|
|
|
|
CFrameWnd ::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
|
|
// OnChar and OnSysChar
|
|
// These functions are called when keyboard input generates a character.
|
|
//
|
|
|
|
void CMainWindow::OnChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
CFrameWnd::OnChar(nChar, nRepCnt, nFlags); // default action
|
|
}
|
|
|
|
void CMainWindow::OnSysChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
if ((nChar == 'q') && (nFlags & 0x2000)) // terminate app on ALT-q
|
|
PostMessage(WM_CLOSE, 0, 0); // *** remove later ***
|
|
else
|
|
CFrameWnd::OnChar(nChar, nRepCnt, nFlags); // default action
|
|
}
|
|
|
|
void CMainWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
if ((nChar == VK_F4) && (nFlags & 0x2000)) // terminate app on ALT-q
|
|
PostMessage(WM_CLOSE, 0, 0); // *** remove later ***
|
|
else
|
|
CFrameWnd::OnSysKeyDown(nChar, nRepCnt, nFlags); // default action
|
|
}
|
|
|
|
void CMainWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
if (!bPlayingBackSeries) {
|
|
if (nChar == VK_F1) { // F1 key is hit
|
|
SendMessage(WM_COMMAND, IDC_RULES, BN_CLICKED); // Activate the Rules dialog
|
|
} else if (nChar == VK_F2) { // F2 key is hit
|
|
SendMessage(WM_COMMAND, IDC_SCROLL, BN_CLICKED); // Activate the Options dialog
|
|
}
|
|
}
|
|
/* one-plus of low priority
|
|
else if ((nFlags & 0x40) == 0) { // if the key was previously up
|
|
|
|
switch (nChar) {
|
|
|
|
case '1':
|
|
i = 4;
|
|
break;
|
|
|
|
case '2':
|
|
i = 0;
|
|
break;
|
|
|
|
case '3':
|
|
i = 1;
|
|
break;
|
|
|
|
case '4':
|
|
i = 2;
|
|
break;
|
|
|
|
case '5':
|
|
i = 3;
|
|
break;
|
|
|
|
case '6':
|
|
i = 5;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
} // end switch
|
|
|
|
if ((i < MAX_BUTTONS) && (m_bPlaying)) {
|
|
KillTimer( PLAYER_TIMER ); // don't time out
|
|
m_nButID = i;
|
|
StartAnimation();
|
|
}
|
|
} // end else switch
|
|
*/
|
|
}
|
|
/* one-plus of low priority
|
|
void CMainWindow::OnKeyUp(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags)
|
|
{
|
|
bool bMusician = false;
|
|
|
|
switch (nChar) {
|
|
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
bMusician = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
} // end switch
|
|
|
|
if (bMusician && m_bPlaying) {
|
|
if (pAnimSprite[m_nButID] != nullptr) {
|
|
StopAnimation();
|
|
::SendMessage( m_hWnd, WM_COMMAND, m_nButID + IDC_A, BN_CLICKED ); // Activate hit logic
|
|
}
|
|
}
|
|
|
|
}
|
|
*/
|
|
/*****************************************************************
|
|
*
|
|
* OnTimer
|
|
*
|
|
* FUNCTIONAL DESCRIPTION:
|
|
*
|
|
* Processes Timer events
|
|
*
|
|
* FORMAL PARAMETERS:
|
|
*
|
|
* unsigned int nIDEvent The ID of the timer event activated
|
|
*
|
|
* IMPLICIT INPUT PARAMETERS:
|
|
*
|
|
* [External data read]
|
|
*
|
|
* IMPLICIT OUTPUT PARAMETERS:
|
|
*
|
|
* [External data modified]
|
|
*
|
|
* RETURN VALUE:
|
|
*
|
|
* void
|
|
*
|
|
****************************************************************/
|
|
void CMainWindow::OnTimer(uintptr nIDEvent) {
|
|
CDC *pDC = nullptr;
|
|
CSound *pEffect = nullptr;
|
|
|
|
pDC = GetDC();
|
|
|
|
switch (nIDEvent) {
|
|
|
|
case PLAYER_TIMER: {
|
|
char buf[64];
|
|
Common::sprintf_s(buf, "Longest series: %d", nNoteCount - 1);
|
|
if (pAnimSprite[m_nButID] != nullptr) // If there's an animation
|
|
StopAnimation(); //...running, stop it
|
|
KillTimer(nIDEvent); // Stop this timer
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
pEffect = new CSound((CWnd *)this, SLOW_SOUND,
|
|
SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE); //...Wave file, to delete itself
|
|
(*pEffect).play(); //...play the narration
|
|
}
|
|
MSG lpmsg;
|
|
while (PeekMessage(&lpmsg, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) ;
|
|
|
|
CMessageBox GameOverDlg((CWnd *)this, pGamePalette, "Time ran out!", buf);
|
|
CSound::waitWaveSounds();
|
|
pNoteMarker = nullptr;
|
|
m_bPlaying = false;
|
|
CNote::FlushNoteList();
|
|
if (pGameInfo->bPlayingMetagame)
|
|
PostMessage(WM_CLOSE, 0, 0); // and post a program exit
|
|
}
|
|
KillTimer(nIDEvent); // Stop the timer
|
|
break;
|
|
|
|
case ANIM_TIMER:
|
|
(*pAnimSprite[m_nButID]).PaintSprite(pDC, rectMusic[m_nButID].TopLeft().x - Offset[m_nButID].x,
|
|
rectMusic[m_nButID].TopLeft().y - Offset[m_nButID].y);
|
|
break;
|
|
|
|
default:
|
|
CFrameWnd ::OnTimer(nIDEvent);
|
|
KillTimer(nIDEvent); //Stop the timer
|
|
break;
|
|
} // end switch
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
}
|
|
|
|
void CMainWindow::OnActivate(unsigned int nState, CWnd *pWndOther, bool bMinimized) {
|
|
|
|
if (!bMinimized) {
|
|
switch (nState) {
|
|
case WA_ACTIVE:
|
|
case WA_CLICKACTIVE:
|
|
//InvalidateRect(nullptr, false);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**********************************************************
|
|
The following functions handle operations on the list of notes:
|
|
Getting a new sequence by either:
|
|
reading in a list from a file, or
|
|
generating a random list,
|
|
Adding a new member to the list, and
|
|
Playing back the entire sequence.
|
|
***********************************************************/
|
|
void CMainWindow::NewGame() {
|
|
CDC *pDC;
|
|
char msg[4];
|
|
|
|
pDC = GetDC();
|
|
|
|
(*m_pScrollButton).SendMessage(BM_SETSTATE, false, 0L);
|
|
m_bIgnoreScrollClick = false;
|
|
|
|
m_bPlayGame = tempPlayGame;
|
|
m_nNumButtons = tempNumButtons;
|
|
m_nSpeed = tempSpeed;
|
|
|
|
m_bNewGame = false;
|
|
|
|
CNote::FlushNoteList();
|
|
ActivateButtons(m_nNumButtons, NOT_PLAYING); // Bring on the players!!
|
|
|
|
if (m_bPlayGame) {
|
|
GetNewSequence(MAX_SEQUENCE);
|
|
nNoteCount = 1;
|
|
nCheckCount = 0;
|
|
Common::sprintf_s(msg, "%d", nNoteCount - 1);
|
|
(*m_pSignText).DisplayString(pDC, msg, 32, FW_NORMAL, SIGN_COLOR);
|
|
} else {
|
|
m_bPlaying = true; // Make sure we can play music
|
|
Common::strcpy_s(msg, "");
|
|
(*m_pSignText).DisplayString(pDC, msg, 32, FW_NORMAL, SIGN_COLOR);
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
void CMainWindow::StartAnimation() {
|
|
CDC *pDC;
|
|
|
|
pDC = GetDC();
|
|
|
|
(*pAnimSprite[m_nButID]).SetCel(nNumCels[m_nButID]);
|
|
SetTimer(ANIM_TIMER, ANIM_SLEEP, nullptr);
|
|
|
|
if (pGameInfo->bSoundEffectsEnabled) {
|
|
pMusic = new CSound((CWnd *)this, cSoundName[m_nButID],
|
|
SOUND_MIDI | SOUND_ASYNCH |
|
|
SOUND_LOOP | SOUND_NOTIFY); //...Midi file, looping | SOUND_NOTIFY
|
|
(*pMusic).play(); //...play the sound
|
|
}
|
|
|
|
(*pAnimSprite[m_nButID]).PaintSprite(pDC,
|
|
rectMusic[m_nButID].TopLeft().x - Offset[m_nButID].x,
|
|
rectMusic[m_nButID].TopLeft().y - Offset[m_nButID].y);
|
|
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
|
|
void CMainWindow::StopAnimation() {
|
|
CDC *pDC;
|
|
|
|
pDC = GetDC();
|
|
|
|
KillTimer(ANIM_TIMER);
|
|
|
|
if (pAnimSprite[m_nButID] != nullptr) {
|
|
pAnimSprite[m_nButID]->EraseSprite(pDC);
|
|
}
|
|
|
|
if (pMusic != nullptr) {
|
|
(*pMusic).stop();
|
|
delete pMusic;
|
|
pMusic = nullptr;
|
|
}
|
|
|
|
CSound::clearSounds();
|
|
|
|
PaintBitmap(pDC, pGamePalette, pMusicians[(m_nButID * 2) + NOT_PLAYING],
|
|
rectMusic[m_nButID].TopLeft().x, rectMusic[m_nButID].TopLeft().y);
|
|
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
|
|
bool CMainWindow::GetNewSequence(const char *pszFileName) {
|
|
int nNote;
|
|
char note[5];
|
|
|
|
ifstream IFStream(pszFileName);
|
|
if (IFStream.fail()) {
|
|
return false;
|
|
}
|
|
while (!IFStream.eof()) {
|
|
IFStream.getline(note, sizeof(note));
|
|
nNote = atoi(note);
|
|
add_note_to_series(nNote);
|
|
}
|
|
return true;
|
|
}//end GetNewSequence()
|
|
|
|
bool CMainWindow::GetNewSequence(int nLength) {
|
|
int i;
|
|
for (i = nLength; i > 0; --i) {
|
|
add_note_to_series(brand() % m_nNumButtons);
|
|
}
|
|
return true;
|
|
}//end GetNewSequence()
|
|
|
|
void CMainWindow::ActivateButtons(unsigned int nNumActive, bool bState) {
|
|
CDC *pDC;
|
|
CPalette *pOldPal = nullptr;
|
|
unsigned int i;
|
|
|
|
pDC = GetDC();
|
|
pOldPal = pDC->SelectPalette(pGamePalette, false); // select the game palette
|
|
pDC->RealizePalette(); //...and realize it
|
|
|
|
for (i = 0; i < nNumActive; i++) {
|
|
PaintBitmap(pDC, pGamePalette, pMusicians[(i * 2) + bState],
|
|
rectMusic[i].TopLeft().x, rectMusic[i].TopLeft().y);
|
|
}
|
|
while (i < MAX_BUTTONS) {
|
|
PaintBitmap(pDC, pGamePalette, pMusicians[(i * 2) + NOT_THERE],
|
|
rectMusic[i].TopLeft().x, rectMusic[i].TopLeft().y);
|
|
i++;
|
|
}
|
|
|
|
(*pDC).SelectPalette(pOldPal, false); // Select back the old palette
|
|
ReleaseDC(pDC);
|
|
|
|
}//end ActivateButtons()
|
|
|
|
|
|
void add_note_to_series(int nNewValue) {
|
|
CNote *pNewNote;
|
|
|
|
if ((pNewNote = new CNote()) == 0) {
|
|
MessageBox(nullptr, "Could not create note!!", nullptr, MB_ICONEXCLAMATION);
|
|
}
|
|
(*pNewNote).SetValue(nNewValue);
|
|
(*pNewNote).LinkNote(); //Add the new note to the bottom of the list
|
|
}//end add_note_to_series
|
|
|
|
void CMainWindow::PlayBackSeries(int nNumNotes) {
|
|
CDC *pDC;
|
|
int i;
|
|
CNote *pNewNote;
|
|
|
|
pDC = GetDC();
|
|
|
|
bPlayingBackSeries = true;
|
|
|
|
// HCURSOR HOldCursor = MFC::SetCursor( AfxGetApp ()->LoadStandardCursor( nullptr ) ); // Make cursor go away
|
|
HCURSOR HOldCursor = MFC::SetCursor(LoadCursor(nullptr, IDC_WAIT)); // Refresh cursor object
|
|
MFC::ShowCursor(true);
|
|
|
|
pNewNote = CNote::GetNoteHead();
|
|
for (i = nNumNotes; i > 0; --i) {
|
|
if (g_engine->shouldQuit())
|
|
break;
|
|
|
|
if (pNewNote) { // If this isn't the end
|
|
m_nButID = pNewNote->GetValue(); // Get the new note
|
|
|
|
StartAnimation();
|
|
wait_awhile(10 * ((NUM_SPEEDS - m_nSpeed) + SLOW_DOWN));
|
|
StopAnimation();
|
|
|
|
pNewNote = pNewNote->GetNextNote(); // And move to the next
|
|
|
|
if (i != 1) wait_awhile(5 * (NUM_SPEEDS - m_nSpeed)); // Process events while-you-wait!
|
|
}
|
|
}
|
|
pNewNote = nullptr;
|
|
|
|
MFC::ShowCursor(false);
|
|
MFC::SetCursor(HOldCursor);
|
|
|
|
bPlayingBackSeries = false;
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
}//end PlayBackSeries
|
|
|
|
|
|
bool CMainWindow::wait_awhile(int nHundSecs) { // Given time is in hundreths of sec
|
|
uint32 goal;
|
|
MSG msg;
|
|
|
|
goal = (nHundSecs * 10) + GetTickCount(); // time is in millisecs
|
|
while (goal > GetTickCount()) {
|
|
pause();
|
|
|
|
if (PeekMessage(&msg, m_hWnd, 0, WM_MOUSEMOVE, PM_REMOVE)) { // Remove any messages except
|
|
if (msg.message == WM_CLOSE || msg.message == WM_QUIT) //...quit & close, which get
|
|
break; //...sent to the queue
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
if (PeekMessage(&msg, m_hWnd, WM_PARENTNOTIFY, 0xFFFF, PM_REMOVE)) {
|
|
if (msg.message == WM_CLOSE || msg.message == WM_QUIT)
|
|
break;
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
} // spin yer wheels 'til nSecs pass
|
|
|
|
return true;
|
|
}//end wait_awhile()
|
|
|
|
void CMainWindow::OnClose() {
|
|
|
|
CDC *pDC;
|
|
CBrush myBrush;
|
|
CRect myRect;
|
|
int i;
|
|
|
|
if (pGameInfo->bPlayingMetagame)
|
|
pGameInfo->lScore = (long)(nNoteCount - 1); // Hitting MAX increments NoteCount to MAX + 1
|
|
//...so return is correct
|
|
|
|
pDC = GetDC();
|
|
myRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
|
|
myBrush.CreateStockObject(BLACK_BRUSH);
|
|
(*pDC).FillRect(&myRect, &myBrush);
|
|
ReleaseDC(pDC);
|
|
|
|
CNote::FlushNoteList(); // Delete list from memory
|
|
CSound::clearSounds(); // Make sure there's no sounds on return
|
|
|
|
if (m_pSignText != nullptr)
|
|
delete m_pSignText;
|
|
|
|
for (i = 0; i < (MAX_BUTTONS * 2); i++) {
|
|
if (pMusicians[i] != nullptr) {
|
|
//pMusicians[i]->DeleteObject;
|
|
delete pMusicians[i]; // Bitmap for Not_playing and Not_there
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MAX_BUTTONS; i++) {
|
|
if (pAnimSprite[i] != nullptr) {
|
|
pAnimSprite[i]->EraseSprite(pDC);
|
|
delete pAnimSprite[i];
|
|
pAnimSprite[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
if (m_pScrollButton != nullptr)
|
|
delete m_pScrollButton;
|
|
|
|
if (pGamePalette != nullptr) {
|
|
pGamePalette->DeleteObject();
|
|
delete pGamePalette;
|
|
}
|
|
|
|
CFrameWnd::OnClose();
|
|
|
|
MFC::PostMessage(ghParentWnd, WM_PARENTNOTIFY, WM_DESTROY, 0L);
|
|
}
|
|
|
|
void CALLBACK GetSubOptions(CWnd* pParentWind) {
|
|
COptnDlg OptionsDlg(pParentWind, pGamePalette); // Call Specific Game
|
|
|
|
OptionsDlg.m_bPlayGame = m_bPlayGame;
|
|
OptionsDlg.m_nNumButtons = m_nNumButtons;
|
|
OptionsDlg.m_nSpeed = tempSpeed;
|
|
|
|
if (OptionsDlg.DoModal() == IDOK) { // save values set in dialog box
|
|
tempPlayGame = OptionsDlg.m_bPlayGame;; // get new time limit,
|
|
tempNumButtons = OptionsDlg.m_nNumButtons; //...new rows, and cols
|
|
tempSpeed = OptionsDlg.m_nSpeed;
|
|
}
|
|
}
|
|
|
|
//////////// Additional Sound Notify routines //////////////
|
|
|
|
LRESULT CMainWindow::OnMCINotify(WPARAM wParam, LPARAM lParam) {
|
|
CSound *pSound;
|
|
|
|
pSound = CSound::OnMCIStopped(wParam, lParam);
|
|
if (pSound != nullptr)
|
|
OnSoundNotify(pSound);
|
|
return 0;
|
|
}
|
|
|
|
|
|
LRESULT CMainWindow::OnMMIONotify(WPARAM wParam, LPARAM lParam) {
|
|
CSound *pSound;
|
|
|
|
pSound = CSound::OnMMIOStopped(wParam, lParam);
|
|
if (pSound != nullptr)
|
|
OnSoundNotify(pSound);
|
|
return 0;
|
|
}
|
|
|
|
void CMainWindow::OnSoundNotify(CSound *pSound) {
|
|
//
|
|
// Add your code to process explicit notification of a sound "done" event here.
|
|
// pSound is a pointer to a CSound object for which you requested SOUND_NOTIFY.
|
|
//
|
|
|
|
}
|
|
|
|
// CMainWindow message map:
|
|
// Associate messages with member functions.
|
|
//
|
|
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
|
|
//{{AFX_MSG_MAP( CMainWindow )
|
|
ON_WM_PAINT()
|
|
ON_WM_CHAR()
|
|
ON_WM_SYSCHAR()
|
|
ON_WM_SYSKEYDOWN()
|
|
ON_WM_KEYDOWN()
|
|
// ON_WM_KEYUP()
|
|
ON_WM_TIMER()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_CLOSE()
|
|
ON_WM_ACTIVATE()
|
|
ON_MESSAGE(MM_MCINOTIFY, CMainWindow::OnMCINotify)
|
|
ON_MESSAGE(MM_WOM_DONE, CMainWindow::OnMMIONotify)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
} // namespace Garfunkle
|
|
} // namespace HodjNPodj
|
|
} // namespace Bagel
|