3346 lines
76 KiB
C++
3346 lines
76 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/dibdoc.h"
|
|
#include "bagel/hodjnpodj/hnplibs/sprite.h"
|
|
#include "bagel/hodjnpodj/hnplibs/stdinc.h"
|
|
#include "bagel/hodjnpodj/globals.h"
|
|
#include "bagel/hodjnpodj/hnplibs/mainmenu.h"
|
|
#include "bagel/boflib/misc.h"
|
|
#include "bagel/hodjnpodj/hnplibs/cmessbox.h"
|
|
#include "bagel/boflib/error.h"
|
|
#include "bagel/hodjnpodj/hnplibs/bitmaps.h"
|
|
#include "bagel/hodjnpodj/hnplibs/rules.h"
|
|
#include "bagel/hodjnpodj/hnplibs/gamedll.h"
|
|
#include "bagel/boflib/llist.h"
|
|
#include "bagel/hodjnpodj/archeroids/main.h"
|
|
#include "bagel/hodjnpodj/archeroids/usercfg.h"
|
|
#include "bagel/hodjnpodj/hodjnpodj.h"
|
|
|
|
namespace Bagel {
|
|
namespace HodjNPodj {
|
|
namespace Archeroids {
|
|
|
|
#define ARROWS 1
|
|
|
|
//
|
|
// This mini-game's main screen bitmap
|
|
//
|
|
#define MINI_GAME_MAP ".\\ART\\FIELD.BMP"
|
|
const char *INI_SECTION = "Archeroids";
|
|
|
|
//
|
|
// Button ID constants
|
|
//
|
|
#define IDC_MENU 100
|
|
#define IDC_LIVES 101
|
|
#define IDC_SCORE 102
|
|
#define IDC_WAVE 103
|
|
|
|
//
|
|
// Bitmap IDs: Single Cel
|
|
//
|
|
#define IDB_HAY 103
|
|
//
|
|
// Multi-Cel
|
|
//
|
|
#define IDB_BADWALK 107
|
|
#define IDB_BADSHOOT 108
|
|
#define IDB_HODJSHOOT 109
|
|
#define IDB_HODJWALK 110
|
|
#define IDB_BAD_ARROWS 111
|
|
#define IDB_GOOD_ARROWS 112
|
|
#define IDB_HAYBURNING 113
|
|
#define IDB_BADDIE 114
|
|
#define IDB_HODJDIE 115
|
|
#define IDB_HEART 116
|
|
|
|
#define N_BADWALK_CELLS 4
|
|
#define N_BADSHOOT_CELLS 3
|
|
#define N_HODJSHOOT_CELLS 3
|
|
#define N_HODJWALK_CELLS 4
|
|
#define N_BAD_ARROWS_CELLS 3
|
|
#define N_GOOD_ARROWS_CELLS 3
|
|
#define N_HAYBURNING_CELLS 3
|
|
#define N_BADDIE_CELLS 6
|
|
#define N_HODJDIE_CELLS 6
|
|
|
|
#define TIMER_ID 10
|
|
|
|
#define ARROW_SPEED 24
|
|
#define ARROW_MOVES_PER_CYCLE 2
|
|
#define MAX_GOOD_ARROWS 3
|
|
#define MAX_BAD_ARROWS 5
|
|
#define BAD_ARROW_LENGTH 29
|
|
#define BAD_ARROW_WIDTH 9
|
|
#define GOOD_ARROW_LENGTH 29
|
|
#define GOOD_ARROW_WIDTH 9
|
|
#define GOODGUY_START_X 23
|
|
#define GOODGUY_START_Y 100
|
|
#define HEART_START_X (GAME_LEFT_BORDER_WIDTH + 2)
|
|
#define HEART_START_Y 372
|
|
#define HEART_SPACING 4
|
|
#define SPEED_FACTOR 25
|
|
#define N_HAY 4
|
|
#define N_SECTIONS_PER_HAY 50
|
|
#define N_WAVES 10
|
|
#define DEFAULT_ARROW_SPEED 50
|
|
#define BADGUYMOVE_Y 16
|
|
#define BADGUYMOVE_X 23
|
|
#define GOODGUYMOVE_Y 8
|
|
#define BADGUYSIZE_X 59
|
|
#define BADGUYSIZE_Y 48
|
|
#define END_GAME_AXIS 80
|
|
#define HAY_AXIS 140
|
|
#define LEVEL1 (GAME_WIDTH-(GAME_RIGHT_BORDER_WIDTH+BADGUYSIZE_X))
|
|
#define LEVEL2 (LEVEL1-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define LEVEL3 (LEVEL2-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define LEVEL4 (LEVEL3-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define LEVEL5 (LEVEL4-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define LEVEL6 (LEVEL5-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define LEVEL7 (LEVEL6-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define LEVEL8 (LEVEL7-(BADGUYSIZE_X+BADGUYMOVE_X))
|
|
#define ROW1 (GAME_TOP_BORDER_WIDTH+BADGUYMOVE_Y)
|
|
#define ROW2 (ROW1+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
#define ROW3 (ROW2+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
#define ROW4 (ROW3+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
#define ROW5 (ROW4+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
#define ROW6 (ROW5+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
#define ROW7 (ROW6+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
#define ROW8 (ROW7+(BADGUYSIZE_Y+BADGUYMOVE_Y))
|
|
|
|
// Game Sounds
|
|
//
|
|
#define WAV_DEATH ".\\SOUND\\DEATH.WAV"
|
|
#define WAV_GAMEOVER ".\\SOUND\\GAMEOVER.WAV"
|
|
#define WAV_WINWAVE ".\\SOUND\\WINWAVE.WAV"
|
|
#define WAV_NARRATION ".\\SOUND\\ARCH.WAV"
|
|
#define MID_SOUNDTRACK ".\\SOUND\\ARCH.MID"
|
|
|
|
// Local prototypes
|
|
//
|
|
void CALLBACK GetGameParams(CWnd *);
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
CPalette *pGamePalette;
|
|
LPGAMESTRUCT pGameParams;
|
|
|
|
extern HWND ghParentWnd;
|
|
|
|
STATIC int aBales[N_HAY];
|
|
|
|
STATIC const POINT aHayPosition[N_HAY][N_SECTIONS_PER_HAY] = {
|
|
{ {100, 60}, {108, 60}, {116, 60}, {124, 60}, {132, 60},
|
|
{100, 66}, {108, 66}, {116, 66}, {124, 66}, {132, 66},
|
|
{100, 72}, {108, 72}, {116, 72}, {124, 72}, {132, 72},
|
|
{100, 78}, {108, 78}, {116, 78}, {124, 78}, {132, 78},
|
|
{100, 84}, {108, 84}, {116, 84}, {124, 84}, {132, 84},
|
|
{100, 90}, {108, 90}, {116, 90}, {124, 90}, {132, 90},
|
|
{100, 96}, {108, 96}, {116, 96}, {124, 96}, {132, 96},
|
|
{100, 102}, {108, 102}, {116, 102}, {124, 102}, {132, 102},
|
|
{100, 108}, {108, 108}, {116, 108}, {124, 108}, {132, 108},
|
|
{100, 114}, {108, 114}, {116, 114}, {124, 114}, {132, 114}
|
|
},
|
|
|
|
{ {100, 160}, {108, 160}, {116, 160}, {124, 160}, {132, 160},
|
|
{100, 166}, {108, 166}, {116, 166}, {124, 166}, {132, 166},
|
|
{100, 172}, {108, 172}, {116, 172}, {124, 172}, {132, 172},
|
|
{100, 178}, {108, 178}, {116, 178}, {124, 178}, {132, 178},
|
|
{100, 184}, {108, 184}, {116, 184}, {124, 184}, {132, 184},
|
|
{100, 190}, {108, 190}, {116, 190}, {124, 190}, {132, 190},
|
|
{100, 196}, {108, 196}, {116, 196}, {124, 196}, {132, 196},
|
|
{100, 202}, {108, 202}, {116, 202}, {124, 202}, {132, 202},
|
|
{100, 208}, {108, 208}, {116, 208}, {124, 208}, {132, 208},
|
|
{100, 214}, {108, 214}, {116, 214}, {124, 214}, {132, 214}
|
|
},
|
|
|
|
{ {100, 260}, {108, 260}, {116, 260}, {124, 260}, {132, 260},
|
|
{100, 266}, {108, 266}, {116, 266}, {124, 266}, {132, 266},
|
|
{100, 272}, {108, 272}, {116, 272}, {124, 272}, {132, 272},
|
|
{100, 278}, {108, 278}, {116, 278}, {124, 278}, {132, 278},
|
|
{100, 284}, {108, 284}, {116, 284}, {124, 284}, {132, 284},
|
|
{100, 290}, {108, 290}, {116, 290}, {124, 290}, {132, 290},
|
|
{100, 296}, {108, 296}, {116, 296}, {124, 296}, {132, 296},
|
|
{100, 302}, {108, 302}, {116, 302}, {124, 302}, {132, 302},
|
|
{100, 308}, {108, 308}, {116, 308}, {124, 308}, {132, 308},
|
|
{100, 314}, {108, 314}, {116, 314}, {124, 314}, {132, 314}
|
|
},
|
|
|
|
{ {100, 360}, {108, 360}, {116, 360}, {124, 360}, {132, 360},
|
|
{100, 366}, {108, 366}, {116, 366}, {124, 366}, {132, 366},
|
|
{100, 372}, {108, 372}, {116, 372}, {124, 372}, {132, 372},
|
|
{100, 378}, {108, 378}, {116, 378}, {124, 378}, {132, 378},
|
|
{100, 384}, {108, 384}, {116, 384}, {124, 384}, {132, 384},
|
|
{100, 390}, {108, 390}, {116, 390}, {124, 390}, {132, 390},
|
|
{100, 396}, {108, 396}, {116, 396}, {124, 396}, {132, 396},
|
|
{100, 402}, {108, 402}, {116, 402}, {124, 402}, {132, 402},
|
|
{100, 408}, {108, 408}, {116, 408}, {124, 408}, {132, 408},
|
|
{100, 414}, {108, 414}, {116, 414}, {124, 414}, {132, 414}
|
|
}
|
|
};
|
|
|
|
STATIC POINT aHayPosUse[N_HAY][N_SECTIONS_PER_HAY];
|
|
|
|
//
|
|
// Position data for bad guys for each wave
|
|
//
|
|
STATIC const POINT aBadGuyPosition[N_WAVES][BADGUYS_MAX] = {
|
|
|
|
{ {LEVEL4, ROW3}, {LEVEL4, ROW4}, {LEVEL4, ROW5}, {LEVEL4, ROW6}, // Wave 1
|
|
{LEVEL3, ROW3}, {LEVEL3, ROW4}, {LEVEL3, ROW5}, {LEVEL3, ROW6},
|
|
{LEVEL2, ROW3}, {LEVEL2, ROW4}, {LEVEL2, ROW5}, {LEVEL2, ROW6},
|
|
{LEVEL1, ROW3}, {LEVEL1, ROW4}, {LEVEL1, ROW5}, {LEVEL1, ROW6}
|
|
},
|
|
|
|
{ {LEVEL4, ROW2}, {LEVEL4, ROW4}, {LEVEL4, ROW5}, {LEVEL4, ROW7}, // Wave 2
|
|
{LEVEL3, ROW2}, {LEVEL3, ROW4}, {LEVEL3, ROW5}, {LEVEL3, ROW7},
|
|
{LEVEL2, ROW2}, {LEVEL2, ROW4}, {LEVEL2, ROW5}, {LEVEL2, ROW7},
|
|
{LEVEL1, ROW2}, {LEVEL1, ROW4}, {LEVEL1, ROW5}, {LEVEL1, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW2}, {LEVEL4, ROW3}, {LEVEL4, ROW6}, {LEVEL4, ROW7}, // Wave 3
|
|
{LEVEL3, ROW3}, {LEVEL3, ROW4}, {LEVEL3, ROW5}, {LEVEL3, ROW6},
|
|
{LEVEL2, ROW2}, {LEVEL2, ROW3}, {LEVEL2, ROW4}, {LEVEL2, ROW5},
|
|
{LEVEL2, ROW6}, {LEVEL2, ROW7}, {LEVEL1, ROW2}, {LEVEL1, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW4}, {LEVEL4, ROW5}, {LEVEL4, ROW3}, {LEVEL4, ROW6}, // Wave 4
|
|
{LEVEL3, ROW5}, {LEVEL3, ROW4}, {LEVEL3, ROW2}, {LEVEL3, ROW3},
|
|
{LEVEL3, ROW6}, {LEVEL3, ROW7}, {LEVEL2, ROW2}, {LEVEL2, ROW3},
|
|
{LEVEL2, ROW6}, {LEVEL2, ROW7}, {LEVEL1, ROW2}, {LEVEL1, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW1}, {LEVEL4, ROW2}, {LEVEL4, ROW3}, {LEVEL4, ROW5}, // Wave 5
|
|
{LEVEL4, ROW6}, {LEVEL4, ROW7}, {LEVEL3, ROW1}, {LEVEL3, ROW3},
|
|
{LEVEL3, ROW5}, {LEVEL3, ROW7}, {LEVEL2, ROW1}, {LEVEL2, ROW2},
|
|
{LEVEL2, ROW3}, {LEVEL2, ROW5}, {LEVEL2, ROW6}, {LEVEL2, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW3}, {LEVEL4, ROW4}, {LEVEL4, ROW6}, {LEVEL4, ROW7}, // Wave 6
|
|
{LEVEL3, ROW3}, {LEVEL3, ROW4}, {LEVEL3, ROW6}, {LEVEL3, ROW7},
|
|
{LEVEL2, ROW2}, {LEVEL2, ROW3}, {LEVEL2, ROW5}, {LEVEL2, ROW6},
|
|
{LEVEL1, ROW2}, {LEVEL1, ROW3}, {LEVEL1, ROW5}, {LEVEL1, ROW6}
|
|
},
|
|
|
|
{ {LEVEL4, ROW2}, {LEVEL4, ROW4}, {LEVEL4, ROW5}, {LEVEL4, ROW7}, // Wave 7
|
|
{LEVEL3, ROW2}, {LEVEL3, ROW3}, {LEVEL3, ROW6}, {LEVEL3, ROW7},
|
|
{LEVEL2, ROW2}, {LEVEL2, ROW3}, {LEVEL2, ROW6}, {LEVEL2, ROW7},
|
|
{LEVEL1, ROW2}, {LEVEL1, ROW4}, {LEVEL1, ROW5}, {LEVEL1, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW2}, {LEVEL4, ROW3}, {LEVEL4, ROW4}, {LEVEL4, ROW5}, // Wave 8
|
|
{LEVEL4, ROW6}, {LEVEL3, ROW1}, {LEVEL3, ROW3}, {LEVEL3, ROW5},
|
|
{LEVEL3, ROW7}, {LEVEL2, ROW2}, {LEVEL2, ROW4}, {LEVEL2, ROW6},
|
|
{LEVEL1, ROW1}, {LEVEL1, ROW3}, {LEVEL1, ROW5}, {LEVEL1, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW2}, {LEVEL4, ROW3}, {LEVEL4, ROW4}, {LEVEL4, ROW5}, // Wave 9
|
|
{LEVEL4, ROW6}, {LEVEL3, ROW2}, {LEVEL3, ROW6}, {LEVEL2, ROW2},
|
|
{LEVEL2, ROW6}, {LEVEL1, ROW1}, {LEVEL1, ROW2}, {LEVEL1, ROW3},
|
|
{LEVEL1, ROW4}, {LEVEL1, ROW5}, {LEVEL1, ROW6}, {LEVEL1, ROW7}
|
|
},
|
|
|
|
{ {LEVEL4, ROW1}, {LEVEL4, ROW3}, {LEVEL4, ROW5}, {LEVEL4, ROW7}, // Wave 10
|
|
{LEVEL3, ROW1}, {LEVEL3, ROW3}, {LEVEL3, ROW5}, {LEVEL3, ROW7},
|
|
{LEVEL2, ROW1}, {LEVEL2, ROW3}, {LEVEL2, ROW5}, {LEVEL2, ROW7},
|
|
{LEVEL1, ROW1}, {LEVEL1, ROW3}, {LEVEL1, ROW5}, {LEVEL1, ROW7}
|
|
}
|
|
};
|
|
|
|
|
|
CMainWindow::CMainWindow() {
|
|
CString WndClass;
|
|
CRect tmpRect;
|
|
CBitmap *pSplashScreen;
|
|
CDC *pDC;
|
|
ERROR_CODE errCode;
|
|
bool bSuccess;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
// Initialize data
|
|
//
|
|
m_pHayList = m_pBadGuyList = nullptr;
|
|
m_pBadArrowList = m_pGoodArrowList = nullptr;
|
|
m_pScrollSprite = nullptr;
|
|
m_pGamePalette = nullptr;
|
|
m_pFXList = nullptr;
|
|
m_pHodj = nullptr;
|
|
m_bTimerActive = false;
|
|
m_bGameActive = false;
|
|
m_bJoyActive = false;
|
|
m_bMoveMode = false;
|
|
m_bInMenu = false;
|
|
m_pMasterBadArrow = nullptr;
|
|
m_pMasterGoodArrow = nullptr;
|
|
m_pMasterBurn = nullptr;
|
|
m_pMasterBadWalk = nullptr;
|
|
m_pMasterBadShoot = nullptr;
|
|
m_pMasterBadDie = nullptr;
|
|
m_pMasterGoodWalk = nullptr;
|
|
m_pMasterGoodShoot = nullptr;
|
|
m_pMasterGoodDie = nullptr;
|
|
m_pMasterHeart = nullptr;
|
|
|
|
m_pSoundTrack = nullptr;
|
|
m_pBadDieSound = nullptr;
|
|
m_pBoltSound = nullptr;
|
|
m_pArrowSound = nullptr;
|
|
m_pBurnSound = nullptr;
|
|
m_hBadDieRes = nullptr;
|
|
m_hBoltRes = nullptr;
|
|
m_hArrowRes = nullptr;
|
|
m_hBurnRes = nullptr;
|
|
|
|
// make sure score is initially zero
|
|
pGameParams->lScore = 0;
|
|
|
|
// no animations if playing on a 386
|
|
m_bAnimationsOn = !(GetWinFlags() & WF_CPU386);
|
|
|
|
// Set the coordinates for the "Start New Game" button
|
|
//
|
|
m_rNewGameButton.SetRect(15, 4, 233, 20);
|
|
|
|
// 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);
|
|
|
|
// Acquire the shared palette for our game from the splash screen art
|
|
//
|
|
if (FileExists(MINI_GAME_MAP)) {
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
pSplashScreen = FetchBitmap(pDC, &m_pGamePalette, MINI_GAME_MAP);
|
|
bSuccess = CSprite::SetBackdrop(pDC, m_pGamePalette, pSplashScreen);
|
|
assert(bSuccess);
|
|
pGamePalette = m_pGamePalette;
|
|
ReleaseDC(pDC);
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_FFIND;
|
|
}
|
|
|
|
// Center our window on the screen
|
|
//
|
|
tmpRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
|
|
#ifndef DEBUG
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
tmpRect.left = (pDC->GetDeviceCaps(HORZRES) - GAME_WIDTH) / 2;
|
|
tmpRect.top = (pDC->GetDeviceCaps(VERTRES) - GAME_HEIGHT) / 2;
|
|
tmpRect.right = tmpRect.left + GAME_WIDTH;
|
|
tmpRect.bottom = tmpRect.top + GAME_HEIGHT;
|
|
ReleaseDC(pDC);
|
|
}
|
|
#endif
|
|
|
|
// get mouse anchor point
|
|
//
|
|
m_ptAnchor.x = GAME_WIDTH / 2 + tmpRect.left;
|
|
m_ptAnchor.y = GAME_HEIGHT / 2 + tmpRect.top;
|
|
|
|
// 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 -- Archeroids", WS_POPUP, tmpRect, nullptr, 0);
|
|
|
|
BeginWaitCursor();
|
|
ShowWindow(SW_SHOWNORMAL);
|
|
PaintScreen();
|
|
EndWaitCursor();
|
|
|
|
// limit the mouse cursor to the bounds of this game
|
|
ClipCursor(&tmpRect);
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
//
|
|
// build our main menu button
|
|
//
|
|
if ((m_pScrollSprite = new CSprite) != nullptr) {
|
|
|
|
m_pScrollSprite->SharePalette(m_pGamePalette);
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
bSuccess = m_pScrollSprite->LoadResourceSprite(pDC, IDB_SCROLBTN);
|
|
if (!bSuccess)
|
|
errCode = ERR_UNKNOWN;
|
|
|
|
ReleaseDC(pDC);
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
m_pScrollSprite->SetMasked(true);
|
|
m_pScrollSprite->SetMobile(true);
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
|
|
// only continue if there was no error
|
|
//
|
|
if (errCode == ERR_NONE) {
|
|
|
|
BeginWaitCursor();
|
|
|
|
// Seed the random number generator
|
|
//srand((unsigned int)time(nullptr));
|
|
|
|
errCode = LoadMasterSprites();
|
|
|
|
if (!errCode)
|
|
errCode = LoadMasterSounds();
|
|
|
|
InitializeJoystick();
|
|
|
|
EndWaitCursor();
|
|
|
|
if (pGameParams->bMusicEnabled) {
|
|
m_pSoundTrack = new CSound(this, MID_SOUNDTRACK, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END);
|
|
assert(m_pSoundTrack != nullptr);
|
|
m_pSoundTrack->midiLoopPlaySegment(6400, 37680, 0, FMT_MILLISEC); //6320
|
|
} // end if m_pSoundTrack
|
|
|
|
|
|
// if we are not playing from the metagame
|
|
//
|
|
if (!pGameParams->bPlayingMetagame) {
|
|
|
|
// Automatically bring up the main menu
|
|
//
|
|
PostMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
|
|
}
|
|
}
|
|
|
|
HandleError(errCode);
|
|
}
|
|
|
|
|
|
void CMainWindow::InitializeJoystick() {
|
|
JOYINFO joyInfo;
|
|
|
|
if (joySetCapture(m_hWnd, JOYSTICKID1, 10000, true) == JOYERR_NOERROR) {
|
|
//
|
|
// Calibrate the joystick
|
|
//
|
|
joySetThreshold(JOYSTICKID1, 5000);
|
|
joyGetPos(JOYSTICKID1, &joyInfo);
|
|
m_nJoyLast = joyInfo.wYpos;
|
|
m_bJoyActive = true;
|
|
|
|
} else {
|
|
//CMessageBox dlgNoJoystick((CWnd *)this, m_pGamePalette, "Warning! No Joystick", "Driver Installed");
|
|
}
|
|
}
|
|
|
|
|
|
ERROR_CODE CMainWindow::LoadMasterSprites() {
|
|
CDC *pDC;
|
|
ERROR_CODE errCode;
|
|
|
|
errCode = ERR_NONE;
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
if ((m_pMasterGoodDie = new CSprite) != nullptr) {
|
|
|
|
if (m_pMasterGoodDie->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterGoodDie->LoadResourceCels(pDC, IDB_HODJDIE, N_HODJDIE_CELLS)) {
|
|
|
|
m_pMasterGoodDie->SetTypeCode(200);
|
|
m_pMasterGoodDie->SetMasked(true);
|
|
m_pMasterGoodDie->SetMobile(true);
|
|
m_pMasterGoodDie->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
#if 0
|
|
if (errCode == ERR_NONE) {
|
|
|
|
if ((m_pMasterGoodShoot = new CSprite) != nullptr) {
|
|
|
|
if (m_pMasterGoodShoot->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterGoodShoot->LoadResourceCels(pDC, IDB_HODJSHOOT, N_HODJSHOOT_CELLS) != false) {
|
|
|
|
m_pMasterGoodShoot->SetTypeCode(200);
|
|
m_pMasterGoodShoot->SetMasked(true);
|
|
m_pMasterGoodShoot->SetMobile(true);
|
|
m_pMasterGoodShoot->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
#endif
|
|
if (errCode == ERR_NONE) {
|
|
if ((m_pMasterGoodWalk = new CSprite) != nullptr) {
|
|
|
|
if (m_pMasterGoodWalk->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterGoodWalk->LoadResourceCels(pDC, IDB_HODJWALK, N_HODJWALK_CELLS) != false) {
|
|
|
|
m_pMasterGoodWalk->SetTypeCode(200);
|
|
m_pMasterGoodWalk->SetMasked(true);
|
|
m_pMasterGoodWalk->SetMobile(true);
|
|
m_pMasterGoodWalk->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
if ((m_pMasterBadDie = new CSprite) != nullptr) {
|
|
|
|
if (m_pMasterBadDie->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterBadDie->LoadResourceCels(pDC, IDB_BADDIE, N_BADDIE_CELLS) != false) {
|
|
|
|
m_pMasterBadDie->SetTypeCode(false);
|
|
m_pMasterBadDie->SetMasked(true);
|
|
m_pMasterBadDie->SetMobile(true);
|
|
m_pMasterBadDie->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
#if 0
|
|
if (errCode == ERR_NONE) {
|
|
|
|
if ((m_pMasterBadShoot = new CSprite) != nullptr) {
|
|
|
|
if (m_pMasterBadShoot->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterBadShoot->LoadResourceCels(pDC, IDB_BADSHOOT, N_BADSHOOT_CELLS) != false) {
|
|
|
|
m_pMasterBadShoot->SetTypeCode(false);
|
|
m_pMasterBadShoot->SetMasked(true);
|
|
m_pMasterBadShoot->SetMobile(true);
|
|
m_pMasterBadShoot->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
#endif
|
|
if ((m_pMasterBadWalk = new CSprite) != nullptr) {
|
|
|
|
if (m_pMasterBadWalk->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterBadWalk->LoadResourceCels(pDC, IDB_BADWALK, N_BADWALK_CELLS) != false) {
|
|
|
|
m_pMasterBadWalk->SetTypeCode(false);
|
|
m_pMasterBadWalk->SetMasked(true);
|
|
m_pMasterBadWalk->SetMobile(true);
|
|
m_pMasterBadWalk->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
|
|
// Create the master burning hay
|
|
//
|
|
if ((m_pMasterBurn = new CSprite) != nullptr) {
|
|
|
|
// attach arrow to the Game Palette
|
|
//
|
|
if (m_pMasterBurn->SharePalette(m_pGamePalette) != false) {
|
|
|
|
if (m_pMasterBurn->LoadResourceCels(pDC, IDB_HAYBURNING, N_HAYBURNING_CELLS) != false) {
|
|
|
|
m_pMasterBurn->SetTypeCode(300);
|
|
m_pMasterBurn->SetMasked(true);
|
|
m_pMasterBurn->SetMobile(true);
|
|
m_pMasterBurn->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
// Create the master bad arrow
|
|
//
|
|
if ((m_pMasterBadArrow = new CSprite) != nullptr) {
|
|
|
|
// attach arrow to the Game Palette
|
|
//
|
|
if (m_pMasterBadArrow->SharePalette(m_pGamePalette) != false) {
|
|
|
|
//
|
|
// load this arrow's bitmap into the sprite
|
|
//
|
|
if (m_pMasterBadArrow->LoadResourceCels(pDC, IDB_BAD_ARROWS, N_BAD_ARROWS_CELLS) != false) {
|
|
|
|
m_pMasterBadArrow->SetTypeCode(218);
|
|
m_pMasterBadArrow->SetMasked(true);
|
|
m_pMasterBadArrow->SetMobile(true);
|
|
m_pMasterBadArrow->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
// Create the master good arrow
|
|
//
|
|
if ((m_pMasterGoodArrow = new CSprite) != nullptr) {
|
|
|
|
// attach arrow to the Game Palette
|
|
//
|
|
if (m_pMasterGoodArrow->SharePalette(m_pGamePalette) != false) {
|
|
|
|
//
|
|
// load this arrow's bitmap into the sprite
|
|
//
|
|
if (m_pMasterGoodArrow->LoadResourceCels(pDC, IDB_GOOD_ARROWS, N_GOOD_ARROWS_CELLS) != false) {
|
|
|
|
m_pMasterGoodArrow->SetTypeCode(217);
|
|
m_pMasterGoodArrow->SetMasked(true);
|
|
m_pMasterGoodArrow->SetMobile(true);
|
|
m_pMasterGoodArrow->SetAnimated(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
if ((m_pMasterHeart = new CSprite) != nullptr) {
|
|
|
|
//
|
|
// load picture of heart
|
|
//
|
|
if (m_pMasterHeart->LoadResourceSprite(pDC, IDB_HEART) != false) {
|
|
|
|
// attach heart to the Game Palette
|
|
//
|
|
if (m_pMasterHeart->SharePalette(m_pGamePalette) != false) {
|
|
|
|
m_pMasterHeart->SetTypeCode(301);
|
|
m_pMasterHeart->SetMasked(true);
|
|
m_pMasterHeart->SetMobile(true);
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
void CMainWindow::ReleaseMasterSprites() {
|
|
//
|
|
// free all master sprite objects
|
|
//
|
|
|
|
if (m_pMasterHeart != nullptr) {
|
|
delete m_pMasterHeart;
|
|
m_pMasterHeart = nullptr;
|
|
}
|
|
|
|
if (m_pMasterGoodArrow != nullptr) {
|
|
delete m_pMasterGoodArrow;
|
|
m_pMasterGoodArrow = nullptr;
|
|
}
|
|
|
|
if (m_pMasterBadArrow != nullptr) {
|
|
delete m_pMasterBadArrow;
|
|
m_pMasterBadArrow = nullptr;
|
|
}
|
|
|
|
if (m_pMasterBurn != nullptr) {
|
|
delete m_pMasterBurn;
|
|
m_pMasterBurn = nullptr;
|
|
}
|
|
|
|
if (m_pMasterBadWalk != nullptr) {
|
|
delete m_pMasterBadWalk;
|
|
m_pMasterBadWalk = nullptr;
|
|
}
|
|
|
|
if (m_pMasterBadShoot != nullptr) {
|
|
delete m_pMasterBadShoot;
|
|
m_pMasterBadShoot = nullptr;
|
|
}
|
|
|
|
if (m_pMasterBadDie != nullptr) {
|
|
delete m_pMasterBadDie;
|
|
m_pMasterBadDie = nullptr;
|
|
}
|
|
|
|
if (m_pMasterGoodWalk != nullptr) {
|
|
delete m_pMasterGoodWalk;
|
|
m_pMasterGoodWalk = nullptr;
|
|
}
|
|
|
|
if (m_pMasterGoodShoot != nullptr) {
|
|
delete m_pMasterGoodShoot;
|
|
m_pMasterGoodShoot = nullptr;
|
|
}
|
|
|
|
if (m_pMasterGoodDie != nullptr) {
|
|
delete m_pMasterGoodDie;
|
|
m_pMasterGoodDie = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
ERROR_CODE CMainWindow::LoadMasterSounds() {
|
|
HANDLE hResInfo;
|
|
HINSTANCE hInst;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
hInst = (HINSTANCE)GetWindowWord(m_hWnd, GWW_HINSTANCE);
|
|
|
|
// Load and lock
|
|
//
|
|
if ((hResInfo = FindResource(hInst, "BadDieSound", "WAVE")) != nullptr) {
|
|
|
|
if ((m_hBadDieRes = LoadResource(hInst, (HRSRC)hResInfo)) != nullptr) {
|
|
|
|
if ((m_pBadDieSound = (char *)LockResource((HGLOBAL)m_hBadDieRes)) != nullptr) {
|
|
|
|
// we have now loaded at least one of the master sounds
|
|
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
// Load and lock
|
|
//
|
|
if ((hResInfo = FindResource(hInst, "BoltSound", "WAVE")) != nullptr) {
|
|
|
|
if ((m_hBoltRes = LoadResource(hInst, (HRSRC)hResInfo)) != nullptr) {
|
|
|
|
if ((m_pBoltSound = (char *)LockResource((HGLOBAL)m_hBoltRes)) == nullptr)
|
|
errCode = ERR_UNKNOWN;
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
// Load and lock
|
|
//
|
|
if ((hResInfo = FindResource(hInst, "ArrowSound", "WAVE")) != nullptr) {
|
|
|
|
if ((m_hArrowRes = LoadResource(hInst, (HRSRC)hResInfo)) != nullptr) {
|
|
|
|
if ((m_pArrowSound = (char *)LockResource((HGLOBAL)m_hArrowRes)) == nullptr)
|
|
errCode = ERR_UNKNOWN;
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
// Load and lock the hay burn sound into memory
|
|
//
|
|
if ((hResInfo = FindResource(hInst, "BurnHay", "WAVE")) != nullptr) {
|
|
|
|
if ((m_hBurnRes = LoadResource(hInst, (HRSRC)hResInfo)) != nullptr) {
|
|
|
|
if ((m_pBurnSound = (char *)LockResource((HGLOBAL)m_hBurnRes)) == nullptr)
|
|
errCode = ERR_UNKNOWN;
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
if (errCode == ERR_NONE) {
|
|
|
|
// Load and lock the extra life sound into memory
|
|
//
|
|
if ((hResInfo = FindResource(hInst, "NewLife", "WAVE")) != nullptr) {
|
|
|
|
if ((m_hExtraLifeRes = LoadResource(hInst, (HRSRC)hResInfo)) != nullptr) {
|
|
|
|
if ((m_pExtraLifeSound = (char *)LockResource((HGLOBAL)m_hExtraLifeRes)) == nullptr)
|
|
errCode = ERR_UNKNOWN;
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
} else {
|
|
errCode = ERR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
void CMainWindow::ReleaseMasterSounds() {
|
|
if (m_hExtraLifeRes != nullptr) {
|
|
FreeResource(m_hExtraLifeRes);
|
|
m_hExtraLifeRes = nullptr;
|
|
}
|
|
if (m_hBurnRes != nullptr) {
|
|
FreeResource(m_hBurnRes);
|
|
m_hBurnRes = nullptr;
|
|
}
|
|
if (m_hArrowRes != nullptr) {
|
|
FreeResource(m_hArrowRes);
|
|
m_hArrowRes = nullptr;
|
|
}
|
|
if (m_hBoltRes != nullptr) {
|
|
FreeResource(m_hBoltRes);
|
|
m_hBoltRes = nullptr;
|
|
}
|
|
if (m_hBadDieRes != nullptr) {
|
|
FreeResource(m_hBadDieRes);
|
|
m_hBadDieRes = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void CMainWindow::OnPaint() {
|
|
PAINTSTRUCT lpPaint;
|
|
|
|
Invalidate(false);
|
|
BeginPaint(&lpPaint);
|
|
PaintScreen();
|
|
EndPaint(&lpPaint);
|
|
}
|
|
|
|
|
|
void CMainWindow::PaintScreen() {
|
|
CDC *pDC;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
CSprite::RefreshBackdrop(pDC, m_pGamePalette);
|
|
|
|
if (!m_bInMenu && (m_pScrollSprite != nullptr)) {
|
|
m_pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
|
|
}
|
|
|
|
// update the on-screen sprites
|
|
errCode = RepaintSpriteList(pDC);
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
HandleError(errCode);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* RepaintSpriteList -
|
|
*
|
|
* DESCRIPTION: Longer description of this function. Continued onto next
|
|
* line like this.
|
|
*
|
|
* SAMPLE USAGE:
|
|
* errCode = RepaintSpriteList(pDC);
|
|
* CDC *pDC; pointer to current device context
|
|
*
|
|
* RETURNS: ERROR_CODE = error return code
|
|
*
|
|
*****************************************************************************/
|
|
ERROR_CODE CMainWindow::RepaintSpriteList(CDC *pDC) {
|
|
CSprite *pSprite;
|
|
ERROR_CODE errCode;
|
|
|
|
// can't use a null pointer
|
|
assert(pDC != nullptr);
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
if (pDC == nullptr) {
|
|
errCode = ERR_UNKNOWN;
|
|
} else {
|
|
|
|
//
|
|
// Paint each sprite
|
|
//
|
|
pSprite = CSprite::GetSpriteChain();
|
|
while (pSprite) {
|
|
|
|
pSprite->ClearBackground();
|
|
pSprite->RefreshSprite(pDC);
|
|
|
|
pSprite = pSprite->GetNextSprite();
|
|
}
|
|
}
|
|
return errCode;
|
|
}
|
|
|
|
|
|
bool CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) {
|
|
CMainMenu COptionsWind((CWnd *)this, m_pGamePalette, (pGameParams->bPlayingMetagame ? (NO_NEWGAME | NO_OPTIONS) : (m_bGameActive ? 0 : NO_RETURN)), GetGameParams, "arch.txt", (pGameParams->bSoundEffectsEnabled ? WAV_NARRATION : nullptr), pGameParams);
|
|
CDC *pDC;
|
|
bool bSuccess;
|
|
|
|
if (HIWORD(lParam) == BN_CLICKED) {
|
|
switch (wParam) {
|
|
|
|
//
|
|
// must bring up our menu of controls
|
|
//
|
|
case IDC_MENU:
|
|
|
|
// pause timer
|
|
GamePause();
|
|
m_bInMenu = true;
|
|
|
|
pDC = GetDC();
|
|
if (m_pScrollSprite != nullptr) {
|
|
bSuccess = m_pScrollSprite->EraseSprite(pDC);
|
|
ASSERT(bSuccess);
|
|
}
|
|
|
|
CSound::waitWaveSounds();
|
|
|
|
switch (COptionsWind.DoModal()) {
|
|
|
|
case IDC_OPTIONS_NEWGAME:
|
|
PlayGame();
|
|
break;
|
|
|
|
case IDC_OPTIONS_QUIT:
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (m_pScrollSprite != nullptr) {
|
|
bSuccess = m_pScrollSprite->PaintSprite(pDC, SCROLL_BUTTON_X, SCROLL_BUTTON_Y);
|
|
ASSERT(bSuccess);
|
|
}
|
|
ReleaseDC(pDC);
|
|
|
|
m_bInMenu = false;
|
|
|
|
if (!pGameParams->bMusicEnabled && (m_pSoundTrack != nullptr)) {
|
|
|
|
m_pSoundTrack->stop();
|
|
delete m_pSoundTrack;
|
|
m_pSoundTrack = nullptr;
|
|
|
|
} else if (pGameParams->bMusicEnabled && (m_pSoundTrack == nullptr)) {
|
|
m_pSoundTrack = new CBofSound(this, MID_SOUNDTRACK, SOUND_MIDI | SOUND_LOOP | SOUND_DONT_LOOP_TO_END);
|
|
m_pSoundTrack->midiLoopPlaySegment(6400, 37680, 0, FMT_MILLISEC);
|
|
}
|
|
|
|
// resume timer
|
|
//GameResume();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
CSprite *CMainWindow::NewLife(int iLifeIndex) {
|
|
CSize size;
|
|
CDC *pDC;
|
|
CSprite *pSprite;
|
|
|
|
pSprite = nullptr;
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
if ((pSprite = m_pMasterHeart->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
pSprite->SetZOrder(SPRITE_HINDMOST);
|
|
|
|
size = pSprite->GetSize();
|
|
|
|
// add heart to sprite list
|
|
pSprite->LinkSprite();
|
|
|
|
// set intial heart position
|
|
pSprite->PaintSprite(pDC, HEART_START_X, HEART_START_Y + (LIVES_MAX - (iLifeIndex + 1)) * (size.cy + HEART_SPACING));
|
|
}
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
return pSprite;
|
|
}
|
|
|
|
|
|
ERROR_CODE CMainWindow::CreateLives() {
|
|
int i;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
// create one heart for each live
|
|
//
|
|
for (i = 0; i < m_nInitNumLives; i++) {
|
|
|
|
// create our hearts
|
|
//
|
|
if ((m_pLives[i] = NewLife(i)) == nullptr) {
|
|
errCode = ERR_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* CreateGoodGuy -
|
|
*
|
|
* DESCRIPTION: Longer description of this function
|
|
*
|
|
*
|
|
* SAMPLE USAGE:
|
|
* errCode = CreateGoodGuy();
|
|
*
|
|
* RETURNS: ERROR_CODE = error return code
|
|
*
|
|
*****************************************************************************/
|
|
ERROR_CODE CMainWindow::CreateGoodGuy() {
|
|
CDC *pDC;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
// create our good guy sprite
|
|
//
|
|
if ((m_pHodj = m_pMasterGoodWalk->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
m_pHodj->SetZOrder(SPRITE_FOREGROUND);
|
|
m_pHodj->SetAnimated(true);
|
|
|
|
// add good guy to sprite list
|
|
m_pHodj->LinkSprite();
|
|
|
|
// set intial good guy position
|
|
m_pHodj->PaintSprite(pDC, GOODGUY_START_X, GOODGUY_START_Y);
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* CreateHay -
|
|
*
|
|
* DESCRIPTION: Longer description of this function. Continued onto next
|
|
*
|
|
*
|
|
* SAMPLE USAGE:
|
|
* errCode = CreateHay();
|
|
*
|
|
* RETURNS: ERROR_CODE = error return code.
|
|
*
|
|
*****************************************************************************/
|
|
ERROR_CODE CMainWindow::CreateHay() {
|
|
CLList *pList;
|
|
CSprite *pSprite;
|
|
CDC *pDC;
|
|
int i;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
memcpy(aHayPosUse, aHayPosition, sizeof(POINT) * N_HAY * N_SECTIONS_PER_HAY);
|
|
|
|
if ((pDC = GetDC()) == nullptr) {
|
|
errCode = ERR_UNKNOWN;
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if ((pSprite = new CSprite()) == nullptr) {
|
|
errCode = ERR_MEMORY;
|
|
break;
|
|
|
|
} else {
|
|
|
|
//
|
|
// load the hay picture
|
|
//
|
|
if (pSprite->LoadResourceSprite(pDC, IDB_HAY) == false) {
|
|
errCode = ERR_UNKNOWN;
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (pSprite->SharePalette(m_pGamePalette) == false) {
|
|
errCode = ERR_UNKNOWN;
|
|
break;
|
|
|
|
} else {
|
|
|
|
pSprite->SetTypeCode(i);
|
|
pSprite->SetMasked(true);
|
|
pSprite->SetMobile(true);
|
|
pSprite->LinkSprite(); // add hay to sprite list
|
|
|
|
pSprite->PaintSprite(pDC, 100, (i * 100) + 60); // set intial hay positions
|
|
|
|
aBales[i] = N_SECTIONS_PER_HAY;
|
|
|
|
//
|
|
// add this hay sprite to our private hay list
|
|
//
|
|
pList = new CLList(pSprite);
|
|
|
|
if (m_pHayList != nullptr) {
|
|
m_pHayList->Insert(pList);
|
|
} else {
|
|
m_pHayList = pList;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
ERROR_CODE CMainWindow::CreateBurningHay(CPoint point) {
|
|
CLList *pList;
|
|
CSprite *pSprite;
|
|
CDC *pDC;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
if ((pSprite = m_pMasterBurn->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
pSprite->SetZOrder(SPRITE_BACKGROUND);
|
|
pSprite->SetAnimated(true);
|
|
|
|
pSprite->LinkSprite(); // add burning hay to sprite list
|
|
|
|
pSprite->PaintSprite(pDC, point); // set intial hay positions
|
|
|
|
//
|
|
// add this burning hay to our special FX list
|
|
//
|
|
if ((pList = new CLList(pSprite)) != nullptr) {
|
|
|
|
if (m_pFXList != nullptr) {
|
|
m_pFXList->Insert(pList);
|
|
} else {
|
|
m_pFXList = pList;
|
|
}
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* CreateBadArrow -
|
|
*
|
|
* DESCRIPTION: Longer description of this function. Continued onto next
|
|
*
|
|
*
|
|
* SAMPLE USAGE:
|
|
* errCode = CreateBadArrow(point);
|
|
* POINT point; starting position of new arrow
|
|
*
|
|
* RETURNS: ERROR_CODE = error return code
|
|
*
|
|
*****************************************************************************/
|
|
ERROR_CODE CMainWindow::CreateBadArrow(CSprite *pBadGuy) {
|
|
CRect newRect, oldRect, overlappedRect;
|
|
CPoint point;
|
|
CSize size;
|
|
CLList *pList;
|
|
CSprite *pSprite;
|
|
CDC *pDC;
|
|
ERROR_CODE errCode;
|
|
bool bHit;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
if (ARROWS && (m_nBadArrows < MAX_BAD_ARROWS)) {
|
|
point = GetLeftMostBadGuy();
|
|
point.y = pBadGuy->GetPosition().y;
|
|
size = pBadGuy->GetSize();
|
|
point.x -= BAD_ARROW_LENGTH;
|
|
point.y += size.cy / 2 - BAD_ARROW_WIDTH / 2;
|
|
point.y -= 8;
|
|
|
|
newRect.SetRect(point.x, point.y, point.x + BAD_ARROW_LENGTH, point.y + BAD_ARROW_WIDTH);
|
|
|
|
//
|
|
// Make sure this arrow does not touch hay
|
|
//
|
|
bHit = false;
|
|
pList = m_pHayList;
|
|
while (pList != nullptr) {
|
|
oldRect = ((CSprite *)pList->getData())->GetRect();
|
|
|
|
// Check for intercection
|
|
//
|
|
if (overlappedRect.IntersectRect(oldRect, newRect)) {
|
|
bHit = true;
|
|
break;
|
|
}
|
|
pList = pList->getNext();
|
|
}
|
|
|
|
// Don't create this arrow if it interects another arrow or if it
|
|
// intersects hay
|
|
//
|
|
if (!bHit) {
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
// Animate this badguy to shoot
|
|
//
|
|
#if 0
|
|
if ((pSprite = m_pMasterBadShoot->DuplicateSprite(pDC)) != nullptr) {
|
|
int i;
|
|
|
|
pSprite->LinkSprite();
|
|
pSprite->PaintSprite(pDC, pBadGuy->GetPosition());
|
|
pBadGuy->EraseSprite(pDC);
|
|
|
|
for (i = 1; i < N_BADSHOOT_CELLS; i++) {
|
|
pSprite->PaintSprite(pDC, pBadGuy->GetPosition());
|
|
}
|
|
|
|
pBadGuy->PaintSprite(pDC, pBadGuy->GetPosition());
|
|
DeleteSprite(pSprite);
|
|
}
|
|
#endif
|
|
// Create the new arrow
|
|
//
|
|
if ((pSprite = m_pMasterBadArrow->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
pSprite->SetZOrder(SPRITE_TOPMOST);
|
|
pSprite->SetAnimated(true);
|
|
|
|
m_nBadArrows++;
|
|
|
|
pSprite->LinkSprite(); // add arrow to sprite list
|
|
|
|
pSprite->PaintSprite(pDC, point); // set intial arrow position
|
|
|
|
// Play the arrow shoot sound
|
|
//
|
|
if (pGameParams->bSoundEffectsEnabled) {
|
|
sndPlaySound(m_pBoltSound, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
|
|
}
|
|
|
|
//
|
|
// add this arrow to the aBadArrowList
|
|
//
|
|
if ((pList = new CLList(pSprite)) != nullptr) {
|
|
|
|
if (m_pBadArrowList != nullptr)
|
|
m_pBadArrowList->addToTail(pList);
|
|
else {
|
|
m_pBadArrowList = pList;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
HandleError(errCode);
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
POINT CMainWindow::GetLeftMostBadGuy() {
|
|
POINT ptTmp, ptBest;
|
|
CLList *pList;
|
|
|
|
assert(m_pBadGuyList != nullptr);
|
|
|
|
ptBest.x = 9999;
|
|
ptBest.y = 0;
|
|
|
|
pList = m_pBadGuyList->getHead();
|
|
while (pList != nullptr) {
|
|
ptTmp = ((CSprite *)pList->getData())->GetPosition();
|
|
|
|
if (ptTmp.x < ptBest.x)
|
|
ptBest = ptTmp;
|
|
|
|
pList = pList->getNext();
|
|
}
|
|
|
|
return ptBest;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* CreateGoodArrow -
|
|
*
|
|
* DESCRIPTION: Longer description of this function. Continued onto next
|
|
* line like this.
|
|
*
|
|
* SAMPLE USAGE:
|
|
* errCode = CreateGoodArrow();
|
|
*
|
|
* RETURNS: ERROR_CODE = error return code
|
|
*
|
|
*****************************************************************************/
|
|
ERROR_CODE CMainWindow::CreateGoodArrow() {
|
|
CRect newRect, oldRect, overlappedRect;
|
|
CLList *pList;
|
|
CDC *pDC;
|
|
CSize size;
|
|
ERROR_CODE errCode;
|
|
CSprite *pSprite;
|
|
POINT point;
|
|
bool bHit;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
GameResume();
|
|
|
|
if (m_nGoodArrows < MAX_GOOD_ARROWS) {
|
|
|
|
// Good guy must be valid to shoot an arrow
|
|
assert(m_pHodj != nullptr);
|
|
|
|
// Arrow is shot from end of crossbow
|
|
//
|
|
size = m_pHodj->GetSize();
|
|
point = m_pHodj->GetPosition();
|
|
point.y += 15;
|
|
point.x += size.cx - 3;
|
|
|
|
newRect.SetRect(point.x, point.y, point.x + GOOD_ARROW_LENGTH, point.y + GOOD_ARROW_WIDTH);
|
|
|
|
//
|
|
// Make sure this arrow does not touch another arrow
|
|
//
|
|
bHit = false;
|
|
pList = m_pGoodArrowList;
|
|
while (pList != nullptr) {
|
|
oldRect = ((CSprite *)pList->getData())->GetRect();
|
|
|
|
// Check for intercection
|
|
//
|
|
if (overlappedRect.IntersectRect(oldRect, newRect)) {
|
|
bHit = true;
|
|
break;
|
|
}
|
|
pList = pList->getNext();
|
|
}
|
|
|
|
//
|
|
// Don't create the arrow if it intersects another good arrow
|
|
//
|
|
if (!bHit) {
|
|
|
|
if ((pDC = GetDC()) == nullptr) {
|
|
errCode = ERR_UNKNOWN;
|
|
|
|
} else {
|
|
#if 0
|
|
if ((pSprite = m_pMasterGoodShoot->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
int i;
|
|
pSprite->LinkSprite();
|
|
pSprite->PaintSprite(pDC, m_pHodj->GetPosition());
|
|
m_pHodj->EraseSprite(pDC);
|
|
|
|
for (i = 1; i < N_HODJSHOOT_CELLS; i++) {
|
|
pSprite->PaintSprite(pDC, m_pHodj->GetPosition());
|
|
Sleep(5);
|
|
}
|
|
|
|
m_pHodj->PaintSprite(pDC, m_pHodj->GetPosition());
|
|
DeleteSprite(pSprite);
|
|
}
|
|
#endif
|
|
|
|
// Create the new arrow
|
|
//
|
|
if ((pSprite = m_pMasterGoodArrow->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
// set arrows to topmost
|
|
pSprite->SetZOrder(SPRITE_TOPMOST);
|
|
pSprite->SetAnimated(true);
|
|
|
|
m_nGoodArrows++;
|
|
|
|
pSprite->LinkSprite();
|
|
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
if (pGameParams->bSoundEffectsEnabled) {
|
|
sndPlaySound(m_pArrowSound, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
|
|
}
|
|
|
|
//
|
|
// add this arrow to the aGoodArrowList
|
|
//
|
|
pList = new CLList(pSprite);
|
|
if (m_pGoodArrowList != nullptr)
|
|
m_pGoodArrowList->addToTail(pList);
|
|
else {
|
|
m_pGoodArrowList = pList;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
}
|
|
}
|
|
}
|
|
|
|
HandleError(errCode);
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* CreateBadGuys -
|
|
*
|
|
* DESCRIPTION: Longer description of this function.
|
|
*
|
|
*
|
|
* SAMPLE USAGE:
|
|
* errCode = CreateBadGuys();
|
|
*
|
|
* RETURNS: ERROR_CODE = error return code
|
|
*
|
|
*****************************************************************************/
|
|
ERROR_CODE CMainWindow::CreateBadGuys() {
|
|
CLList *pList;
|
|
CSprite *pSprite;
|
|
CDC *pDC;
|
|
POINT point;
|
|
int i;
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
//
|
|
// create a sprite for each of the on screen bad guys
|
|
//
|
|
for (i = 0; i < m_nBadGuys; i++) {
|
|
|
|
if ((pSprite = m_pMasterBadWalk->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
pSprite->SetZOrder(SPRITE_FOREGROUND);
|
|
pSprite->SetAnimated(true);
|
|
|
|
// add badguy to sprite list
|
|
pSprite->LinkSprite();
|
|
|
|
// if this fails it will trash global memory
|
|
assert(m_nBadGuys <= BADGUYS_MAX);
|
|
|
|
// Adjust for Archer Level
|
|
//
|
|
point = aBadGuyPosition[m_nWave % N_WAVES][i];
|
|
point.x -= (m_nInitArcherLevel - 1) * BADGUYMOVE_X;
|
|
|
|
// set intial position
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
//
|
|
// add this badguy sprite to our private badguy list
|
|
//
|
|
if ((pList = new CLList(pSprite)) != nullptr) {
|
|
|
|
if (m_pBadGuyList != nullptr) {
|
|
m_pBadGuyList->Insert(pList);
|
|
} else {
|
|
m_pBadGuyList = pList;
|
|
}
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
}
|
|
ReleaseDC(pDC);
|
|
} else {
|
|
errCode = ERR_MEMORY;
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* PlayGame - one line discription
|
|
*
|
|
* DESCRIPTION: Longer description of this function. Continued onto next
|
|
*
|
|
*
|
|
* SAMPLE USAGE:
|
|
* PlayGame();
|
|
*
|
|
* RETURNS: nothing
|
|
*
|
|
*****************************************************************************/
|
|
void CMainWindow::PlayGame() {
|
|
ERROR_CODE errCode;
|
|
|
|
errCode = ERR_NONE; // assume no error
|
|
|
|
if (!m_bTimerActive) {
|
|
|
|
m_bTimerActive = true;
|
|
CWnd::SetTimer(TIMER_ID, 50, nullptr);
|
|
}
|
|
|
|
m_bNewGame = true; // a new game has been started
|
|
|
|
LoadIniSettings(); // load game defaults
|
|
|
|
GameReset(); // intilize game data
|
|
|
|
|
|
if ((errCode = CreateGoodGuy()) == ERR_NONE) { // create our good guy
|
|
|
|
if ((errCode = CreateLives()) == ERR_NONE) { // create hearts for lives
|
|
|
|
if ((errCode = CreateHay()) == ERR_NONE) { // create the hay bales
|
|
|
|
if ((errCode = CreateBadGuys()) == ERR_NONE) {
|
|
|
|
m_bGameActive = true;
|
|
|
|
FlushInputEvents();
|
|
|
|
// game starts paused
|
|
m_bPause = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
HandleError(errCode);
|
|
}
|
|
|
|
void CMainWindow::PlayNextWave() {
|
|
ERROR_CODE errCode;
|
|
|
|
// assume no error
|
|
errCode = ERR_NONE;
|
|
|
|
WaveReset();
|
|
|
|
if ((m_nWave % N_WAVES == 0) && (m_nGameSpeed > 0))
|
|
m_nGameSpeed--;
|
|
|
|
if ((errCode = CreateBadGuys()) == ERR_NONE) {
|
|
|
|
if ((errCode = CreateHay()) == ERR_NONE) {
|
|
|
|
}
|
|
}
|
|
|
|
HandleError(errCode);
|
|
}
|
|
|
|
void CMainWindow::WaveReset() {
|
|
CDC *pDC;
|
|
int i;
|
|
|
|
m_nBadGuys = m_nInitNumBadGuys; // reset # badguys
|
|
|
|
KillAnimation(); // stop all animation sequences
|
|
|
|
PruneDeadBadGuys(); // remove all dead bad guys
|
|
|
|
m_pHodj->UnlinkSprite(); // unlink good guy so we don't flush him from sprite chain
|
|
|
|
for (i = 0; i < LIVES_MAX; i++) { // unlink hearts so we don't flush them
|
|
if (m_pLives[i] != nullptr)
|
|
m_pLives[i]->UnlinkSprite();
|
|
}
|
|
|
|
if ((pDC = GetDC()) != nullptr) { // erase any sprites from the screen
|
|
CSprite::EraseSprites(pDC);
|
|
ReleaseDC(pDC);
|
|
}
|
|
CSprite::FlushSpriteChain(); // flush all sprites from the chain
|
|
|
|
for (i = 0; i < LIVES_MAX; i++) { // link the hearts back into the sprite list
|
|
if (m_pLives[i] != nullptr)
|
|
m_pLives[i]->LinkSprite();
|
|
}
|
|
m_pHodj->LinkSprite(); // link good guy back into list
|
|
|
|
m_nGoodArrows = m_nBadArrows = 0; // reset # of arrows
|
|
|
|
if (m_pHayList != nullptr) { // reset the hay list
|
|
m_pHayList->FlushList();
|
|
delete m_pHayList;
|
|
m_pHayList = nullptr;
|
|
}
|
|
if (m_pBadGuyList != nullptr) { // reset the bad guy list
|
|
m_pBadGuyList->FlushList();
|
|
delete m_pBadGuyList;
|
|
m_pBadGuyList = nullptr;
|
|
}
|
|
if (m_pBadArrowList != nullptr) { // reset the bad guy arrow list
|
|
m_pBadArrowList->FlushList();
|
|
delete m_pBadArrowList;
|
|
m_pBadArrowList = nullptr;
|
|
}
|
|
if (m_pGoodArrowList != nullptr) { // reset the good guy arrow list
|
|
m_pGoodArrowList->FlushList();
|
|
delete m_pGoodArrowList;
|
|
m_pGoodArrowList = nullptr;
|
|
}
|
|
|
|
m_nBadGuySpeed = m_nBadGuys * m_nGameSpeed * SPEED_FACTOR;// set default sprite speed
|
|
|
|
m_nState = 0; // set initial bad guy state
|
|
|
|
m_bPause = true; // game starts paused
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* GameReset - one line discription
|
|
*
|
|
* DESCRIPTION: Longer description of this function. Continued onto next
|
|
* line like this.
|
|
*
|
|
* SAMPLE USAGE:
|
|
* GameReset();
|
|
*
|
|
* RETURNS: nothing
|
|
*
|
|
*****************************************************************************/
|
|
void CMainWindow::GameReset() {
|
|
CDC *pDC;
|
|
|
|
m_bGameActive = false; // no current active game
|
|
|
|
m_bPause = false; // game starts paused
|
|
|
|
m_nGoodArrows = m_nBadArrows = 0; // reset # of arrows
|
|
|
|
m_nMoveArrows = 0; // there are no arrows to move
|
|
|
|
m_lScore = 0; // reset score to zero
|
|
|
|
m_lNewLifeScore = 400; // bonus life every 1000 points
|
|
|
|
KillAnimation(); // stop all animation sequences
|
|
|
|
PruneDeadBadGuys(); // remove all dead bad guys
|
|
|
|
memset(m_pLives, 0, sizeof(CSprite *) * LIVES_MAX); // reset hearts
|
|
|
|
if ((pDC = GetDC()) != nullptr) { // erase any sprites from the screen
|
|
CSprite::EraseSprites(pDC);
|
|
ReleaseDC(pDC);
|
|
}
|
|
CSprite::FlushSpriteChain(); // clean up after any previous game
|
|
|
|
if (m_pHayList != nullptr) { // reset the hay list
|
|
m_pHayList->FlushList();
|
|
delete m_pHayList;
|
|
m_pHayList = nullptr;
|
|
}
|
|
if (m_pBadGuyList != nullptr) { // reset the bad guy list
|
|
m_pBadGuyList->FlushList();
|
|
delete m_pBadGuyList;
|
|
m_pBadGuyList = nullptr;
|
|
}
|
|
if (m_pBadArrowList != nullptr) { // reset the bad guy arrow list
|
|
m_pBadArrowList->FlushList();
|
|
delete m_pBadArrowList;
|
|
m_pBadArrowList = nullptr;
|
|
}
|
|
if (m_pGoodArrowList != nullptr) { // reset the good guy arrow list
|
|
m_pGoodArrowList->FlushList();
|
|
delete m_pGoodArrowList;
|
|
m_pGoodArrowList = nullptr;
|
|
}
|
|
m_pHodj = nullptr; // reset our good guy
|
|
|
|
m_nBadGuys = m_nInitNumBadGuys; // reset # badguys
|
|
|
|
m_nArrowSpeed = DEFAULT_ARROW_SPEED; // set default sprite speeds
|
|
m_nBadGuySpeed = m_nBadGuys * m_nGameSpeed * SPEED_FACTOR;// set default sprite speeds
|
|
|
|
m_nState = 0; // set initial bad guy state
|
|
|
|
m_nWave = 0; // reset to Wave 1
|
|
}
|
|
|
|
void CMainWindow::KillAnimation() {
|
|
CLList *pList;
|
|
|
|
// delete the Special FX list
|
|
//
|
|
while (m_pFXList != nullptr) {
|
|
|
|
DeleteSprite((CSprite *)m_pFXList->getData());
|
|
|
|
pList = m_pFXList;
|
|
m_pFXList = m_pFXList->getNext();
|
|
delete pList;
|
|
}
|
|
}
|
|
|
|
|
|
void CMainWindow::LoadIniSettings() {
|
|
int nVal;
|
|
|
|
if (pGameParams->bPlayingMetagame) {
|
|
|
|
m_nInitNumLives = 1;
|
|
m_nInitNumBadGuys = DEFAULT_BADGUYS;
|
|
|
|
switch (pGameParams->nSkillLevel) {
|
|
|
|
case SKILLLEVEL_LOW:
|
|
|
|
m_nInitArcherLevel = 1;
|
|
m_nInitGameSpeed = 2;
|
|
break;
|
|
|
|
case SKILLLEVEL_MEDIUM:
|
|
|
|
m_nInitArcherLevel = 3;
|
|
m_nInitGameSpeed = 5;
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(pGameParams->nSkillLevel == SKILLLEVEL_HIGH);
|
|
m_nInitArcherLevel = 3;
|
|
m_nInitGameSpeed = 8;
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
|
|
// Get the game speed (1..10)
|
|
//
|
|
nVal = GetPrivateProfileInt(INI_SECTION, "GameSpeed", DEFAULT_GAME_SPEED, INI_FILENAME);
|
|
m_nInitGameSpeed = nVal;
|
|
if (nVal < SPEED_MIN || nVal > SPEED_MAX)
|
|
m_nInitGameSpeed = DEFAULT_GAME_SPEED;
|
|
|
|
// Get the Archer level (1..8)
|
|
//
|
|
nVal = GetPrivateProfileInt(INI_SECTION, "ArcherLevel", DEFAULT_ARCHER_LEVEL, INI_FILENAME);
|
|
m_nInitArcherLevel = nVal;
|
|
if (nVal < LEVEL_MIN || nVal > LEVEL_MAX)
|
|
m_nInitArcherLevel = DEFAULT_ARCHER_LEVEL;
|
|
|
|
// Get initial number of lives
|
|
//
|
|
nVal = GetPrivateProfileInt(INI_SECTION, "NumberOfLives", DEFAULT_LIVES, INI_FILENAME);
|
|
m_nInitNumLives = nVal;
|
|
if (nVal < LIVES_MIN || nVal > LIVES_MAX)
|
|
m_nInitNumLives = DEFAULT_LIVES;
|
|
|
|
// Get initial number of badguys
|
|
//
|
|
nVal = GetPrivateProfileInt(INI_SECTION, "NumberOfBadGuys", DEFAULT_BADGUYS, INI_FILENAME);
|
|
m_nInitNumBadGuys = nVal;
|
|
if (nVal < BADGUYS_MIN || nVal > BADGUYS_MAX)
|
|
m_nInitNumBadGuys = DEFAULT_BADGUYS;
|
|
|
|
// Get overide for Animations On/Off
|
|
//
|
|
nVal = GetPrivateProfileInt(INI_SECTION, "AnimationsOn", m_bAnimationsOn, INI_FILENAME);
|
|
m_bAnimationsOn = (nVal == 0 ? false : true);
|
|
}
|
|
m_nLives = m_nInitNumLives;
|
|
m_nGameSpeed = abs(SPEED_MAX - m_nInitGameSpeed);
|
|
}
|
|
|
|
|
|
void CMainWindow::OnTimer(uintptr nEventID) {
|
|
KillTimer(nEventID);
|
|
|
|
while (m_bTimerActive) {
|
|
if (MainLoop())
|
|
break;
|
|
|
|
if (CheckMessages()) {
|
|
break;
|
|
}
|
|
}
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
}
|
|
|
|
|
|
bool CMainWindow::MainLoop() {
|
|
CLList *pList, *pNext;
|
|
CSprite *pSprite;
|
|
CDC *pDC;
|
|
CRect tmpRect, newRect;
|
|
CSize size;
|
|
unsigned long t1;
|
|
|
|
// new game state is over. We are now playing the game
|
|
//
|
|
m_bNewGame = false;
|
|
|
|
if (m_bGameActive && !m_bPause) {
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
|
|
t1 = GetTickCount();
|
|
|
|
//
|
|
// Handle special effects (Animation)
|
|
//
|
|
pList = m_pFXList;
|
|
while (pList != nullptr) {
|
|
pNext = pList->getNext();
|
|
|
|
// get local pointer to this cell's sprite
|
|
pSprite = (CSprite *)pList->getData();
|
|
|
|
// paint this cell
|
|
pSprite->PaintSprite(pDC, pSprite->GetPosition());
|
|
|
|
// if animations are off or this is the last cell in animation,
|
|
// then destroy this strip
|
|
//
|
|
if (!m_bAnimationsOn || (pSprite->GetCelIndex() == pSprite->GetCelCount() - 1)) {
|
|
|
|
// if this is the head, then move the head
|
|
//
|
|
if (pList == m_pFXList)
|
|
m_pFXList = pNext;
|
|
|
|
delete pList;
|
|
|
|
DeleteSprite(pSprite);
|
|
}
|
|
|
|
pList = pNext;
|
|
}
|
|
|
|
// Handle Arrow movement
|
|
//
|
|
MoveArrows(pDC);
|
|
|
|
// Handle badguy movement.
|
|
//
|
|
if (MoveBadGuys(pDC))
|
|
return true;
|
|
|
|
if (!m_bNewGame) {
|
|
while (m_nMoveArrows < ARROW_MOVES_PER_CYCLE)
|
|
MoveArrows(pDC);
|
|
m_nMoveArrows = 0;
|
|
}
|
|
|
|
ReleaseDC(pDC);
|
|
|
|
// No governor for Cheetah on Steroids (just go fast as possible)
|
|
//
|
|
if (m_nBadGuySpeed > 0) {
|
|
while (GetTickCount() < t1 + (20 + m_nBadGuys * 20)) {
|
|
if (CheckMessages())
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool CMainWindow::MoveArrows(CDC *pDC) {
|
|
char buf1[40], buf2[40];
|
|
CLList *pList, *pNext, *pSearchList;
|
|
CSprite *pSprite, *pTmpSprite;
|
|
POINT point;
|
|
CRect tmpRect, newRect;
|
|
CSize size;
|
|
bool bHit;
|
|
|
|
assert(pDC != nullptr);
|
|
|
|
// acknowledge that we have moved the arrows one more time
|
|
m_nMoveArrows++;
|
|
|
|
//
|
|
// parse Bad Guy arrow list and move each one left
|
|
//
|
|
pList = m_pBadArrowList;
|
|
while (pList != nullptr) {
|
|
pSprite = (CSprite *)pList->getData();
|
|
point = pSprite->GetPosition();
|
|
point.x -= ARROW_SPEED;
|
|
|
|
// save pointer to next arrow
|
|
pNext = pList->getNext();
|
|
|
|
if (point.x > (0 + GAME_LEFT_BORDER_WIDTH)) {
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
if (point.x < HAY_AXIS) {
|
|
|
|
if (pSprite->InterceptOccurred()) {
|
|
|
|
bHit = false;
|
|
|
|
pSearchList = m_pHayList;
|
|
while (pSearchList != nullptr) {
|
|
|
|
newRect = pSprite->GetRect();
|
|
//newRect.right = newRect.left + 2;
|
|
pTmpSprite = (CSprite *)pSearchList->getData();
|
|
if (tmpRect.IntersectRect(newRect, pTmpSprite->GetRect())) {
|
|
|
|
if (pSprite->TestInterception(pDC, pTmpSprite)) {
|
|
|
|
DestroyBadArrow(pList);
|
|
DestroyHay(pSearchList, tmpRect, pDC, true);
|
|
bHit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pSearchList = pSearchList->getNext();
|
|
}
|
|
|
|
if (!bHit) {
|
|
|
|
if (pSprite->TestInterception(pDC, m_pHodj)) {
|
|
DestroyBadArrow(pList);
|
|
LoseLife(pDC, true);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
DestroyBadArrow(pList);
|
|
}
|
|
|
|
// go to next in list
|
|
pList = pNext;
|
|
}
|
|
|
|
//
|
|
// parse Good Guy arrow list and move each one right
|
|
//
|
|
pList = m_pGoodArrowList;
|
|
while (pList != nullptr) {
|
|
pSprite = (CSprite *)pList->getData();
|
|
size = pSprite->GetSize();
|
|
|
|
// calc new arrow location
|
|
//
|
|
point = pSprite->GetPosition();
|
|
point.x += ARROW_SPEED;
|
|
|
|
// save pointer to next arrow
|
|
pNext = pList->getNext();
|
|
|
|
// If arrow did not leave the playing field
|
|
//
|
|
if (point.x < GAME_WIDTH - (size.cx + GAME_RIGHT_BORDER_WIDTH)) {
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
// If arrow hit something, then check to see what it was
|
|
//
|
|
if (pSprite->InterceptOccurred()) {
|
|
|
|
bHit = false;
|
|
|
|
if (point.x < HAY_AXIS) {
|
|
|
|
pSearchList = m_pHayList;
|
|
while (pSearchList != nullptr) {
|
|
|
|
newRect = pSprite->GetRect();
|
|
//newRect.left = newRect.right - 2;
|
|
pTmpSprite = (CSprite *)pSearchList->getData();
|
|
if (tmpRect.IntersectRect(newRect, pTmpSprite->GetRect())) {
|
|
|
|
if (pSprite->TestInterception(pDC, pTmpSprite)) {
|
|
|
|
DestroyGoodArrow(pList);
|
|
DestroyHay(pSearchList, tmpRect, pDC, true);
|
|
bHit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pSearchList = pSearchList->getNext();
|
|
}
|
|
}
|
|
|
|
if (!bHit) {
|
|
//
|
|
// check for hitting bad guy as a secondary hit
|
|
//
|
|
pSearchList = m_pBadGuyList;
|
|
while (pSearchList != nullptr) {
|
|
|
|
// if badguy is not already dead
|
|
//
|
|
pTmpSprite = (CSprite *)pSearchList->getData();
|
|
if (pTmpSprite->GetTypeCode() == false) {
|
|
|
|
if (pSprite->TestInterception(pDC, pTmpSprite)) {
|
|
|
|
DestroyGoodArrow(pList);
|
|
DestroyBadGuy(pSearchList, pDC);
|
|
|
|
//
|
|
// Are all the bad guys dead?
|
|
//
|
|
if (m_nBadGuys == 0) {
|
|
pNext = nullptr;
|
|
GamePause();
|
|
++m_nWave;
|
|
|
|
if (pGameParams->bSoundEffectsEnabled)
|
|
sndPlaySound(WAV_WINWAVE, SND_SYNC);
|
|
|
|
if (pGameParams->bPlayingMetagame) {
|
|
Common::sprintf_s(buf1, "You have defeated");
|
|
Common::sprintf_s(buf2, "all of the archers.");
|
|
|
|
} else {
|
|
Common::sprintf_s(buf1, "Wave %d completed.", m_nWave);
|
|
Common::sprintf_s(buf2, "Score: %ld Lives: %d", m_lScore, m_nLives);
|
|
}
|
|
|
|
FlushInputEvents();
|
|
CMessageBox dlgWaveComplete((CWnd *)this, m_pGamePalette, buf1, buf2);
|
|
|
|
if (pGameParams->bPlayingMetagame) {
|
|
|
|
pGameParams->lScore = 1;
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
} else {
|
|
PlayNextWave();
|
|
}
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
pSearchList = pSearchList->getNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
DestroyGoodArrow(pList);
|
|
}
|
|
|
|
// go to next in list
|
|
pList = pNext;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CMainWindow::CheckMessages() {
|
|
JOYINFO joyInfo;
|
|
MSG msg;
|
|
bool bEndTask = false;
|
|
|
|
assert(m_bTimerActive);
|
|
|
|
// check for joystick movement
|
|
//
|
|
if (m_bJoyActive) {
|
|
joyGetPos(JOYSTICKID1, &joyInfo);
|
|
OnJoyStick(joyInfo.wButtons, (long)joyInfo.wYpos << 16);
|
|
}
|
|
|
|
if (PeekMessage(&msg, nullptr, MM_MCINOTIFY, MM_MCINOTIFY, PM_REMOVE)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
|
|
|
if (msg.message == WM_CLOSE || msg.message == WM_QUIT) {
|
|
m_bTimerActive = false;
|
|
bEndTask = true;
|
|
} else {
|
|
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
return bEndTask;
|
|
}
|
|
|
|
bool CMainWindow::MoveBadGuys(CDC *pDC) {
|
|
CRect tmpRect;
|
|
POINT point;
|
|
CLList *pList, *pSearchList, *pSearchNext;
|
|
CSprite *pSprite;
|
|
int i, n;
|
|
|
|
if (!m_bGameActive)
|
|
return true;
|
|
|
|
// can't access a null pointer
|
|
assert(pDC != nullptr);
|
|
assert(m_bTimerActive);
|
|
|
|
if (!m_bPause && (m_nBadGuys > 0) && (m_pBadGuyList != nullptr) && !m_bNewGame) {
|
|
|
|
PruneDeadBadGuys();
|
|
|
|
//
|
|
// There are 4 bad guy states
|
|
// 0 Bad guys move up while in this state
|
|
// 1 & 3 Bad guys move left 1 level when in this state
|
|
// 2 Bad guys move down while in this state
|
|
//
|
|
n = (m_nBadGuys / ARROW_MOVES_PER_CYCLE);
|
|
switch (m_nState) {
|
|
|
|
//
|
|
// move all bad guys up
|
|
//
|
|
case 0:
|
|
|
|
//
|
|
// parse Bad Guy list and move each one up
|
|
//
|
|
i = 0;
|
|
pList = m_pBadGuyList;
|
|
while (pList != nullptr) {
|
|
pSprite = (CSprite *)pList->getData();
|
|
|
|
assert(pSprite != nullptr);
|
|
|
|
// as long as this badguy is not dead then move him
|
|
//
|
|
if (pSprite->GetTypeCode() == false) {
|
|
|
|
point = pSprite->GetPosition();
|
|
point.y -= BADGUYMOVE_Y - m_nGameSpeed;
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
//
|
|
// if any are gonna hit the top border, then set
|
|
// to state 1 (time to move left 1 level)
|
|
//
|
|
if (point.y < (0 + GAME_TOP_BORDER_WIDTH + BADGUYMOVE_Y - m_nGameSpeed)) {
|
|
if (m_nState == 0)
|
|
m_nState = 1;
|
|
}
|
|
|
|
if (point.x < HAY_AXIS) {
|
|
|
|
if (pSprite->InterceptOccurred()) {
|
|
|
|
//
|
|
// Test badguy vs hay
|
|
//
|
|
pSearchList = m_pHayList;
|
|
while (pSearchList != nullptr) {
|
|
pSearchNext = pSearchList->getNext();
|
|
|
|
if (tmpRect.IntersectRect(pSprite->GetRect(), ((CSprite *)pSearchList->getData())->GetRect())) {
|
|
|
|
point.x = tmpRect.left;
|
|
point.y = tmpRect.top;
|
|
DestroyHay(pSearchList, tmpRect, pDC, false);
|
|
break;
|
|
}
|
|
pSearchList = pSearchNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((brand() & 0x001f) == 0) {
|
|
CreateBadArrow(pSprite);
|
|
}
|
|
|
|
if (CheckMessages())
|
|
return true;
|
|
|
|
if (m_bNewGame)
|
|
return false;
|
|
|
|
if (n > 0) {
|
|
if ((i % n) == n - 1) {
|
|
if (MoveArrows(pDC)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
pList = pList->getNext();
|
|
}
|
|
break;
|
|
|
|
//
|
|
// move all bad guys down
|
|
//
|
|
case 2:
|
|
|
|
//
|
|
// parse Bad Guy list and move each one down
|
|
//
|
|
i = 0;
|
|
pList = m_pBadGuyList;
|
|
while (pList != nullptr) {
|
|
pSprite = (CSprite *)pList->getData();
|
|
|
|
assert(pSprite != nullptr);
|
|
|
|
// as long as this badguy is not dead then move him
|
|
//
|
|
if (pSprite->GetTypeCode() == false) {
|
|
|
|
point = pSprite->GetPosition();
|
|
point.y += BADGUYMOVE_Y - m_nGameSpeed;
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
//
|
|
// if any hit are gonna hit the top border, then set
|
|
// to state 1 (time to move left 1 level)
|
|
//
|
|
if (point.y > GAME_HEIGHT - (GAME_BOTTOM_BORDER_WIDTH + BADGUYMOVE_Y + BADGUYSIZE_Y - m_nGameSpeed)) {
|
|
if (m_nState == 2)
|
|
m_nState = 3;
|
|
}
|
|
|
|
if (point.x < HAY_AXIS) {
|
|
|
|
if (pSprite->InterceptOccurred()) {
|
|
|
|
//
|
|
// Test badguy vs hay
|
|
//
|
|
pSearchList = m_pHayList;
|
|
while (pSearchList != nullptr) {
|
|
pSearchNext = pSearchList->getNext();
|
|
|
|
if (tmpRect.IntersectRect(pSprite->GetRect(), ((CSprite *)pSearchList->getData())->GetRect())) {
|
|
|
|
point.x = tmpRect.left;
|
|
point.y = tmpRect.top;
|
|
DestroyHay(pSearchList, tmpRect, pDC, false);
|
|
break;
|
|
}
|
|
pSearchList = pSearchNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Crossbow shoots arrow from center of badguy
|
|
//
|
|
if ((brand() & 0x001f) == 0) {
|
|
CreateBadArrow(pSprite);
|
|
}
|
|
|
|
if (CheckMessages())
|
|
return true;
|
|
|
|
if (m_bNewGame)
|
|
return false;
|
|
|
|
if (n > 0) {
|
|
if ((i % n) == n - 1) {
|
|
if (MoveArrows(pDC)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
pList = pList->getNext();
|
|
}
|
|
break;
|
|
|
|
//
|
|
// move all bad guys left 1 level
|
|
//
|
|
case 1:
|
|
case 3:
|
|
|
|
// test speed
|
|
//ErrorLog("SPEED.LOG", "%ld", GetTickCount()/1000);
|
|
|
|
//
|
|
// parse Bad Guy list and move each one left 1 level
|
|
//
|
|
i = 0;
|
|
pList = m_pBadGuyList;
|
|
while (pList != nullptr) {
|
|
pSprite = (CSprite *)pList->getData();
|
|
|
|
assert(pSprite != nullptr);
|
|
|
|
// as long as this badguy is not dead then move him
|
|
//
|
|
if (pSprite->GetTypeCode() == false) {
|
|
|
|
point = pSprite->GetPosition();
|
|
point.x -= BADGUYMOVE_X;
|
|
pSprite->PaintSprite(pDC, point);
|
|
|
|
//
|
|
// Test badguy vs good guy
|
|
//
|
|
if (point.x < END_GAME_AXIS) {
|
|
|
|
LoseLife(pDC, false);
|
|
break;
|
|
|
|
} else if (point.x < HAY_AXIS) {
|
|
|
|
if (pSprite->InterceptOccurred()) {
|
|
|
|
//
|
|
// Test badguy vs hay
|
|
//
|
|
pSearchList = m_pHayList;
|
|
while (pSearchList != nullptr) {
|
|
pSearchNext = pSearchList->getNext();
|
|
|
|
if (tmpRect.IntersectRect(pSprite->GetRect(), ((CSprite *)pSearchList->getData())->GetRect())) {
|
|
|
|
point.x = tmpRect.left;
|
|
point.y = tmpRect.top;
|
|
DestroyHay(pSearchList, tmpRect, pDC, false);
|
|
break;
|
|
}
|
|
pSearchList = pSearchNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Crossbow shoots arrow from center of badguy
|
|
//
|
|
if ((brand() & 0x001f) == 0) {
|
|
CreateBadArrow(pSprite);
|
|
}
|
|
|
|
if (CheckMessages())
|
|
return true;
|
|
|
|
if (m_bNewGame)
|
|
return false;
|
|
|
|
if (n > 0) {
|
|
if ((i % n) == n - 1) {
|
|
if (MoveArrows(pDC)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
pList = pList->getNext();
|
|
}
|
|
|
|
// goto next state
|
|
//
|
|
m_nState++;
|
|
m_nState %= 4;
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
PruneDeadBadGuys();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void CMainWindow::LoseLife(CDC *pDC, bool bAnimate) {
|
|
char szTmpBuf[40];
|
|
CSprite *pSprite;
|
|
//CSound *pSound;
|
|
CLList *pList, *pNext;
|
|
POINT point;
|
|
int i;
|
|
|
|
// validate the device context
|
|
assert(pDC != nullptr);
|
|
|
|
GamePause(); // stop the timer while we process stuff
|
|
|
|
--m_nLives; // one less life
|
|
|
|
DeleteSprite(m_pLives[m_nLives]); // remove 1 heart
|
|
m_pLives[m_nLives] = nullptr;
|
|
|
|
// play the death sound
|
|
//
|
|
if (pGameParams->bSoundEffectsEnabled) {
|
|
//pSound = new CSound((CWnd *)this, WAV_DEATH, SOUND_WAVE | SOUND_ASYNCH | SOUND_AUTODELETE);
|
|
sndPlaySound(WAV_DEATH, SND_ASYNC);
|
|
}
|
|
|
|
//CSound::waitWaveSounds();
|
|
|
|
if (bAnimate) {
|
|
|
|
if ((pSprite = m_pMasterGoodDie->DuplicateSprite(pDC)) != nullptr) {
|
|
|
|
pSprite->SetAnimated(true);
|
|
pSprite->LinkSprite();
|
|
pSprite->PaintSprite(pDC, m_pHodj->GetPosition());
|
|
|
|
m_pHodj->EraseSprite(pDC);
|
|
|
|
for (i = 1; i < N_HODJDIE_CELLS; i++) {
|
|
pSprite->PaintSprite(pDC, m_pHodj->GetPosition());
|
|
pause();
|
|
Sleep(300);
|
|
}
|
|
DeleteSprite(pSprite);
|
|
}
|
|
}
|
|
|
|
if (m_nLives > 0) {
|
|
|
|
FlushInputEvents();
|
|
|
|
// Inform user that he has lost a life
|
|
//
|
|
Common::sprintf_s(szTmpBuf, "You have %d li%s left.", m_nLives, m_nLives != 1 ? "ves" : "fe");
|
|
CMessageBox dlgLoseLife((CWnd *)this, m_pGamePalette, "That Hurts!", szTmpBuf);
|
|
|
|
//
|
|
// Need to erase all on-screen arrows
|
|
//
|
|
pList = m_pBadArrowList; // destroy all bad arrows
|
|
while (pList != nullptr) {
|
|
pNext = pList->getNext();
|
|
DestroyBadArrow(pList);
|
|
pList = pNext;
|
|
}
|
|
pList = m_pGoodArrowList; // destroy all good arrows
|
|
while (pList != nullptr) {
|
|
pNext = pList->getNext();
|
|
DestroyGoodArrow(pList);
|
|
pList = pNext;
|
|
}
|
|
|
|
KillAnimation(); // terminate any animation sequences
|
|
|
|
PruneDeadBadGuys();
|
|
|
|
//
|
|
// Need to reset bad guys to top of screen
|
|
//
|
|
i = 0;
|
|
pList = m_pBadGuyList;
|
|
while (pList != nullptr) {
|
|
pSprite = (CSprite *)pList->getData();
|
|
|
|
assert(pSprite != nullptr);
|
|
|
|
point = aBadGuyPosition[m_nWave % N_WAVES][i];
|
|
point.x -= (m_nInitArcherLevel - 1) * BADGUYMOVE_X;
|
|
pSprite->PaintSprite(pDC, point);
|
|
i++;
|
|
pList = pList->getNext();
|
|
}
|
|
m_pHodj->PaintSprite(pDC, m_pHodj->GetPosition());
|
|
|
|
PostMessage(WM_RBUTTONUP, 0, 0);
|
|
|
|
//GameResume(); // resume the timer
|
|
} else {
|
|
|
|
// Game Over
|
|
//
|
|
if (pGameParams->bSoundEffectsEnabled)
|
|
sndPlaySound(WAV_GAMEOVER, SND_SYNC);
|
|
|
|
FlushInputEvents();
|
|
|
|
Common::sprintf_s(szTmpBuf, "Score: %ld.", m_lScore);
|
|
CMessageBox dlgGameOver((CWnd *)this, m_pGamePalette, "Game over.", szTmpBuf);
|
|
GameReset();
|
|
|
|
if (pGameParams->bPlayingMetagame) {
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMainWindow::PruneDeadBadGuys() {
|
|
CLList *pList, *pNext;
|
|
CSprite *pSprite;
|
|
|
|
pList = m_pBadGuyList;
|
|
while (pList != nullptr) {
|
|
|
|
pNext = pList->getNext();
|
|
|
|
pSprite = (CSprite *)(pList->getData());
|
|
assert(pSprite != nullptr);
|
|
|
|
if (pSprite->GetTypeCode() == 1) {
|
|
delete pSprite;
|
|
|
|
// if this is the 1st bad guy in the list, then move the head
|
|
//
|
|
if (pList == m_pBadGuyList)
|
|
m_pBadGuyList = pNext;
|
|
|
|
delete pList;
|
|
}
|
|
|
|
pList = pNext;
|
|
}
|
|
}
|
|
|
|
void CMainWindow::DestroyBadGuy(CLList *pList, CDC *pDC) {
|
|
CSprite *pSprite, *pNewSprite;
|
|
CLList *pNewList;
|
|
POINT point;
|
|
int i;
|
|
|
|
// can't access null pointers
|
|
assert(pList != nullptr);
|
|
assert(pDC != nullptr);
|
|
|
|
// can't delete a non existant bad guy
|
|
assert(m_nBadGuys != 0);
|
|
|
|
// one less bad guy
|
|
m_nBadGuys--;
|
|
|
|
// Update the score
|
|
//
|
|
pSprite = (CSprite *)pList->getData();
|
|
|
|
assert(pSprite != nullptr);
|
|
|
|
point = pSprite->GetPosition();
|
|
m_lScore += ((LEVEL1 - point.x) / BADGUYMOVE_X) + 1;
|
|
|
|
// add code to give player extra life every 400, 800, 1600 etc. points
|
|
//
|
|
if ((m_nLives <= 4) && (m_lScore >= m_lNewLifeScore)) {
|
|
|
|
// play the You get a new life sound
|
|
if (pGameParams->bSoundEffectsEnabled) {
|
|
sndPlaySound(m_pExtraLifeSound, SND_MEMORY | SND_SYNC | SND_NODEFAULT);
|
|
}
|
|
|
|
m_lNewLifeScore += m_lNewLifeScore;
|
|
m_pLives[m_nLives] = NewLife(m_nLives);
|
|
m_nLives++;
|
|
}
|
|
|
|
// increase bad guy speed
|
|
//
|
|
m_nBadGuySpeed = m_nBadGuys * m_nGameSpeed * SPEED_FACTOR;
|
|
|
|
// Play the Bad Guy gets killed sound
|
|
//
|
|
if (pGameParams->bSoundEffectsEnabled) {
|
|
sndPlaySound(m_pBadDieSound, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
|
|
}
|
|
|
|
// indicate that this badguy is dead
|
|
pSprite->SetTypeCode(true);
|
|
|
|
//
|
|
// perform some animation to kill a bad guy
|
|
//
|
|
if ((pNewSprite = m_pMasterBadDie->DuplicateSprite(pDC)) != nullptr) {
|
|
pNewSprite->SetZOrder(SPRITE_BACKGROUND);
|
|
pNewSprite->SetAnimated(true);
|
|
pNewSprite->LinkSprite();
|
|
pNewSprite->PaintSprite(pDC, point);
|
|
}
|
|
|
|
pSprite->EraseSprite(pDC);
|
|
pSprite->UnlinkSprite();
|
|
|
|
//
|
|
// if this is not the last bad guy, the set up an animation event
|
|
//
|
|
if (m_nBadGuys != 0) {
|
|
|
|
if ((pNewList = new CLList) != nullptr) {
|
|
|
|
pNewList->PutData(pNewSprite);
|
|
|
|
if (m_pFXList == nullptr)
|
|
m_pFXList = pNewList;
|
|
else
|
|
m_pFXList->Insert(pNewList);
|
|
}
|
|
|
|
} else if (pNewSprite) {
|
|
KillAnimation();
|
|
|
|
//
|
|
// since this is the last bad guy, then do the animation inline
|
|
//
|
|
for (i = 1; i < N_BADDIE_CELLS; i++) {
|
|
|
|
pNewSprite->PaintSprite(pDC, pNewSprite->GetPosition());
|
|
Sleep(300);
|
|
}
|
|
DeleteSprite(pNewSprite);
|
|
}
|
|
}
|
|
|
|
void CMainWindow::DestroyHay(CLList *pList, CRect rect, CDC *pDC, bool bAnimate) {
|
|
CSprite *pSprite;
|
|
CRect tmpRect, overlappedRect;
|
|
POINT ptTmp, point;
|
|
int i, nID;
|
|
|
|
// can't access null pointers
|
|
assert(pList != nullptr);
|
|
assert(pDC != nullptr);
|
|
|
|
pSprite = (CSprite *)pList->getData();
|
|
assert(pSprite != nullptr);
|
|
|
|
point = pSprite->GetPosition();
|
|
nID = pSprite->GetTypeCode();
|
|
|
|
// can't hit an empty bale
|
|
assert(aBales[nID] > 0);
|
|
|
|
// find and crop all sections of hay that need to be cropped
|
|
//
|
|
for (i = 0; i < N_SECTIONS_PER_HAY; i++) {
|
|
ptTmp = aHayPosUse[nID][i];
|
|
|
|
if (ptTmp.x != 0) {
|
|
|
|
tmpRect.SetRect(ptTmp.x, ptTmp.y, ptTmp.x + 8 - 1, ptTmp.y + 6 - 1);
|
|
|
|
if (overlappedRect.IntersectRect(tmpRect, rect)) {
|
|
tmpRect.left -= point.x;
|
|
tmpRect.top -= point.y;
|
|
tmpRect.right -= point.x - 1;
|
|
tmpRect.bottom -= point.y - 1;
|
|
pSprite->CropImage(pDC, &tmpRect);
|
|
aHayPosUse[nID][i].x = 0;
|
|
aHayPosUse[nID][i].y = 0;
|
|
|
|
// one less bale in this hay
|
|
--aBales[nID];
|
|
|
|
if (aBales[nID] != 0) {
|
|
pSprite->PaintSprite(pDC, pSprite->GetPosition());
|
|
|
|
} else {
|
|
//
|
|
// All sections have been removed from this Bale
|
|
//
|
|
DeleteSprite(pSprite);
|
|
if (pList == m_pHayList)
|
|
m_pHayList = m_pHayList->getNext();
|
|
|
|
delete pList;
|
|
break;
|
|
}
|
|
|
|
if (bAnimate) {
|
|
CreateBurningHay(ptTmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bAnimate) {
|
|
|
|
// sound effect for when hay is struck by flaming arrow
|
|
if (pGameParams->bSoundEffectsEnabled) {
|
|
sndPlaySound(m_pBurnSound, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMainWindow::DestroyGoodArrow(CLList *pList) {
|
|
// can't access a null pointer
|
|
assert(pList != nullptr);
|
|
|
|
// can't delete a non-existant arrow
|
|
assert(m_nGoodArrows > 0);
|
|
|
|
// one less arrow
|
|
m_nGoodArrows--;
|
|
|
|
// Delete the actual sprite
|
|
//
|
|
DeleteSprite((CSprite *)pList->getData());
|
|
|
|
// if this is the 1st arrow in the list, then move the head
|
|
//
|
|
if (pList == m_pGoodArrowList)
|
|
m_pGoodArrowList = pList->getNext();
|
|
|
|
delete pList;
|
|
}
|
|
|
|
|
|
void CMainWindow::DestroyBadArrow(CLList *pList) {
|
|
// can't access a null pointer
|
|
assert(pList != nullptr);
|
|
|
|
// can't delete a non-existant arrow
|
|
assert(m_nBadArrows > 0);
|
|
|
|
// one less arrow
|
|
m_nBadArrows--;
|
|
|
|
// Delete the actual sprite
|
|
//
|
|
DeleteSprite((CSprite *)pList->getData());
|
|
|
|
// if this is the 1st arrow in the list, then move the head
|
|
//
|
|
if (pList == m_pBadArrowList)
|
|
m_pBadArrowList = pList->getNext();
|
|
|
|
delete pList;
|
|
}
|
|
|
|
|
|
void CMainWindow::DeleteSprite(CSprite *pSprite) {
|
|
CDC *pDC;
|
|
|
|
// can't delete a null pointer
|
|
assert(pSprite != nullptr);
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
pSprite->EraseSprite(pDC); // erase it from screen
|
|
ReleaseDC(pDC);
|
|
}
|
|
pSprite->UnlinkSprite(); // unlink it
|
|
|
|
delete pSprite; // delete it
|
|
}
|
|
|
|
|
|
|
|
void CMainWindow::OnLButtonDown(unsigned int nFlags, CPoint point) {
|
|
CRect cTestRect;
|
|
|
|
cTestRect = m_pScrollSprite->GetRect();
|
|
|
|
if (cTestRect.PtInRect(point)) {
|
|
SendMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
|
|
|
|
// User clicked on the Title - NewGame button
|
|
//
|
|
} else if (m_rNewGameButton.PtInRect(point) && !m_bMoveMode) {
|
|
|
|
// if we are not playing from the metagame
|
|
//
|
|
if (!pGameParams->bPlayingMetagame) {
|
|
|
|
// start a new game
|
|
PlayGame();
|
|
}
|
|
|
|
// User is trying to shoot an arrow
|
|
//
|
|
} else {
|
|
|
|
if (m_bGameActive)
|
|
CreateGoodArrow();
|
|
}
|
|
|
|
CFrameWnd::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CMainWindow::OnSysKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
switch (nChar) {
|
|
|
|
// User has hit ALT_F4 so close down this App
|
|
//
|
|
case VK_F4:
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
default:
|
|
CFrameWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CMainWindow::OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
switch (nChar) {
|
|
|
|
// Shoot an arrow
|
|
//
|
|
case VK_RETURN:
|
|
case VK_SPACE:
|
|
if (m_bGameActive) {
|
|
CreateGoodArrow();
|
|
}
|
|
break;
|
|
|
|
// Move good-guy up
|
|
//
|
|
case VK_UP:
|
|
MoveHodj(-GOODGUYMOVE_Y);
|
|
break;
|
|
|
|
// Move good-guy down
|
|
//
|
|
case VK_DOWN:
|
|
MoveHodj(GOODGUYMOVE_Y);
|
|
break;
|
|
|
|
//
|
|
// Bring up the Rules
|
|
//
|
|
case VK_F1: {
|
|
GamePause();
|
|
CSound::waitWaveSounds();
|
|
CRules RulesDlg(this, "arch.txt", m_pGamePalette, (pGameParams->bSoundEffectsEnabled ? WAV_NARRATION : nullptr));
|
|
RulesDlg.DoModal();
|
|
|
|
GameResume();
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Bring up the options menu
|
|
//
|
|
case VK_F2:
|
|
SendMessage(WM_COMMAND, IDC_MENU, BN_CLICKED);
|
|
break;
|
|
|
|
default:
|
|
CFrameWnd::OnChar(nChar, nRepCnt, nFlags);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CMainWindow::OnSysChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
|
|
// terminate app on ALT_Q
|
|
//
|
|
if ((nChar == 'q') && (nFlags & 0x2000)) {
|
|
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
|
|
} else {
|
|
|
|
// default action
|
|
CFrameWnd ::OnSysChar(nChar, nRepCnt, nFlags);
|
|
}
|
|
}
|
|
|
|
void CMainWindow::MoveHodj(int y) {
|
|
POINT point;
|
|
CDC *pDC;
|
|
|
|
//
|
|
// As long as the game is active, move hodj
|
|
//
|
|
if (m_bGameActive) {
|
|
|
|
// if Hodj actually moved
|
|
//
|
|
if (y != 0) {
|
|
|
|
GameResume();
|
|
|
|
// something is wrong if hodj does not exist
|
|
assert(m_pHodj != nullptr);
|
|
|
|
// limit his movement
|
|
//
|
|
if (y > GOODGUYMOVE_Y * 2) {
|
|
y = GOODGUYMOVE_Y * 2;
|
|
|
|
} else if (y < GOODGUYMOVE_Y * -2) {
|
|
y = GOODGUYMOVE_Y * -2;
|
|
}
|
|
|
|
point = m_pHodj->GetPosition();
|
|
point.y += y;
|
|
|
|
if (point.y > GAME_HEIGHT - (GAME_BOTTOM_BORDER_WIDTH + m_pHodj->GetSize().cy)) {
|
|
point.y = GAME_HEIGHT - (GAME_BOTTOM_BORDER_WIDTH + m_pHodj->GetSize().cy);
|
|
|
|
} else if (point.y < GAME_TOP_BORDER_WIDTH) {
|
|
point.y = GAME_TOP_BORDER_WIDTH;
|
|
}
|
|
|
|
if ((pDC = GetDC()) != nullptr) {
|
|
m_pHodj->PaintSprite(pDC, point);
|
|
ReleaseDC(pDC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CMainWindow::HandleError(ERROR_CODE errCode) {
|
|
//
|
|
// Exit this application on fatal errors
|
|
//
|
|
if (errCode != ERR_NONE) {
|
|
|
|
// pause the current game (if any)
|
|
GamePause();
|
|
|
|
// Display Error Message to the user
|
|
MessageBox(errList[errCode], "Fatal Error!", MB_OK | MB_ICONSTOP);
|
|
|
|
// Force this application to terminate
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
|
|
// Don't allow a repaint (remove all WM_PAINT messages)
|
|
ValidateRect(nullptr);
|
|
}
|
|
}
|
|
|
|
|
|
void CMainWindow::OnClose() {
|
|
CBrush myBrush;
|
|
CRect myRect;
|
|
CDC *pDC;
|
|
|
|
ClipCursor(nullptr); // release mouse limits
|
|
|
|
CSound::clearSounds(); // stop and delete all CSounds
|
|
|
|
ReleaseMasterSounds(); // release pre-loaded WAVs
|
|
|
|
ReleaseMasterSprites(); // delete all master sprite objects
|
|
|
|
KillTimer(TIMER_ID); // kill the timer (if any)
|
|
|
|
ReleaseCapture(); // release the capture of mouse events
|
|
|
|
GameReset(); // perform clean-up
|
|
|
|
if (m_bJoyActive) // release the joystick
|
|
joyReleaseCapture(JOYSTICKID1);
|
|
|
|
|
|
if (m_pScrollSprite != nullptr) { // release sprite scroll button
|
|
delete m_pScrollSprite;
|
|
m_pScrollSprite = nullptr;
|
|
}
|
|
|
|
CSprite::ClearBackdrop(); // free the off screen bitmap
|
|
|
|
if (m_pGamePalette != nullptr) { // need to de-allocate the palette
|
|
m_pGamePalette->DeleteObject();
|
|
delete m_pGamePalette;
|
|
m_pGamePalette = nullptr;
|
|
}
|
|
|
|
if ((pDC = GetDC()) != nullptr) { // paint black
|
|
|
|
myRect.SetRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
|
|
myBrush.CreateStockObject(BLACK_BRUSH);
|
|
pDC->FillRect(&myRect, &myBrush);
|
|
ReleaseDC(pDC);
|
|
}
|
|
|
|
DestroyWindow(); // destruct the main window
|
|
|
|
MFC::PostMessage(ghParentWnd, WM_PARENTNOTIFY, WM_DESTROY, 0L);
|
|
}
|
|
|
|
|
|
long CMainWindow::OnJoyStick(unsigned int wParam, long lParam) {
|
|
long nThreshold;
|
|
|
|
if (m_bGameActive) {
|
|
|
|
if (wParam & JOY_BUTTON1) {
|
|
CreateGoodArrow();
|
|
}
|
|
|
|
nThreshold = m_nJoyLast;
|
|
nThreshold -= (unsigned int)HIWORD(lParam);
|
|
|
|
if (nThreshold > 5000) {
|
|
MoveHodj(-GOODGUYMOVE_Y);
|
|
|
|
/*if (nThreshold > 20000)
|
|
MoveHodj(-GOODGUYMOVE_Y);*/
|
|
}
|
|
|
|
if (nThreshold < -5000) {
|
|
MoveHodj(GOODGUYMOVE_Y);
|
|
|
|
/*if (nThreshold < -20000)
|
|
MoveHodj(GOODGUYMOVE_Y);*/
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CMainWindow::GamePause() {
|
|
m_bPause = true;
|
|
if (m_bMoveMode) {
|
|
m_bMoveMode = false;
|
|
MFC::SetCursor(LoadCursor(nullptr, IDC_ARROW));
|
|
}
|
|
}
|
|
|
|
|
|
void CMainWindow::GameResume() {
|
|
m_bPause = false;
|
|
|
|
if (m_bMoveMode)
|
|
SetCursor(nullptr);
|
|
}
|
|
|
|
void CMainWindow::OnActivate(unsigned int nState, CWnd *, bool) {
|
|
if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
|
|
SetFocus();
|
|
}
|
|
|
|
|
|
void CMainWindow::OnRButtonUp(unsigned int, CPoint) {
|
|
//
|
|
// Toggle Good Guy Move Mode
|
|
//
|
|
if (m_bGameActive) {
|
|
m_bMoveMode = (m_bMoveMode ? false : true);
|
|
|
|
if (m_bMoveMode) {
|
|
GameResume();
|
|
|
|
// hide the cursor
|
|
SetCursor(nullptr);
|
|
|
|
// move cursor to anchor point
|
|
SetCursorPos(m_ptAnchor.x, m_ptAnchor.y);
|
|
} else {
|
|
|
|
GamePause();
|
|
|
|
// unhide the cursor
|
|
SetCursor(LoadCursor(nullptr, IDC_ARROW));
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMainWindow::OnMouseMove(unsigned int, CPoint point) {
|
|
//
|
|
// If the Right mouse button is down when we move the mouse, then
|
|
// the user is moving the good guy, otherwise it is a normal mouse move.
|
|
//
|
|
if (m_bGameActive && !m_bPause && m_bMoveMode) {
|
|
|
|
GetCursorPos(&point);
|
|
|
|
// Move good guy according to how the mouse was moved
|
|
//
|
|
MoveHodj(point.y - m_ptAnchor.y);
|
|
|
|
// reset cursor position
|
|
//
|
|
SetCursorPos(m_ptAnchor.x, m_ptAnchor.y);
|
|
|
|
} else {
|
|
|
|
SetCursor(LoadCursor(nullptr, IDC_ARROW));
|
|
}
|
|
}
|
|
|
|
//////////// 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 *) {
|
|
//
|
|
// 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.
|
|
//
|
|
}
|
|
|
|
void CMainWindow::FlushInputEvents() {
|
|
MSG msg;
|
|
|
|
// find and remove all keyboard events
|
|
//
|
|
while (true) {
|
|
if (!PeekMessage(&msg, nullptr, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
|
|
break;
|
|
}
|
|
|
|
// find and remove all mouse events
|
|
//
|
|
while (true) {
|
|
if (!PeekMessage(&msg, nullptr, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// CMainWindow message map:
|
|
// Associate messages with member functions.
|
|
//
|
|
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
|
|
ON_WM_PAINT()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_SYSKEYDOWN()
|
|
ON_WM_SYSCHAR()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_TIMER()
|
|
ON_WM_CLOSE()
|
|
ON_WM_ACTIVATE()
|
|
ON_WM_RBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_MESSAGE(MM_MCINOTIFY, CMainWindow::OnMCINotify)
|
|
ON_MESSAGE(MM_WOM_DONE, CMainWindow::OnMMIONotify)
|
|
//ON_MESSAGE(MM_JOY1MOVE, OnJoyStick)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
void CALLBACK GetGameParams(CWnd *pParentWnd) {
|
|
//
|
|
// Our user preference dialog box is self contained in this object
|
|
//
|
|
CUserCfgDlg dlgUserCfg(pParentWnd, pGamePalette, IDD_USERCFG);
|
|
}
|
|
|
|
} // namespace Archeroids
|
|
} // namespace HodjNPodj
|
|
} // namespace Bagel
|