home *** CD-ROM | disk | FTP | other *** search
-
- //===========================
- // GameWnd.cpp
- // by SA VanNess
- // 08 Mar 97
- // for the Win32 platform
- //===========================
- // Arcade Frame Window
- // Class implementation
- //===========================
- // Copyright (C) 1997 SA VanNess
- // <savanness@pipeline.com>
- //
- // For copyright information, see the file gnu_license.txt included
- // with this source code 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 2 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, write to the Free Software
- // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- //===========================
-
- #include <afxwin.h>
- #include <afxcmn.h>
- #include <afxres.h>
-
- #include "resource.h"
- #include "macros.h"
- #include "xonix32.h"
- #include "hiscores.h"
- #include "gamedlg.h"
- #include "gamewnd.h"
-
- //Hires timing conversion function
- double LI2Double(LARGE_INTEGER *pli)
- { return (((double)pli->HighPart*(double)0xffffffff)+(double)pli->LowPart); }
-
- //===========================
- // CGameWnd constr/destr
-
- //-----------------
- CGameWnd::CGameWnd(CString sClassName, char *pszCmdLine)
- {
- //Game object not constructed yet!
- m_pGame = NULL;
-
- //Init vars
- m_iInitLevel = 1;
- m_bPaused = m_bRunning = FALSE;
- m_iRefreshDelay = 1000/NOM_FPS;
- m_iGameSpdDelay = 1000/NOM_FPS;
- m_iClockDelay = 1000; //1 sec
-
- if (!QueryPerformanceFrequency(&m_liTemp))
- {
- ::MessageBox(NULL,"Xonix32 requires hi-resolution timing support.\n"
- "See the ReadMe.txt file for more info.","Error!",MB_OK|MB_ICONSTOP);
- ExitProcess(1);
- }
- m_dFreq = LI2Double(&m_liTemp);
- QueryPerformanceCounter(&m_liTemp); m_dPrevGameTime = LI2Double(&m_liTemp);
- QueryPerformanceCounter(&m_liTemp); m_dPrevAnimTime = LI2Double(&m_liTemp);
-
- //Process command-line info
- switch (pszCmdLine[0])
- {
- case 'S':
- case 's':
- m_iWndSizeX = 400;
- m_iWndSizeY = 300;
- break;
-
- case 'L':
- case 'l':
- m_iWndSizeX = 640;
- m_iWndSizeY = 480;
- break;
-
- default:
- m_iWndSizeX = 520;
- m_iWndSizeY = 390;
- break;
- }
-
- //Create m_iWndSizeX*m_iWndSizeY window in center of screen
- UINT iMaxX = GetSystemMetrics(SM_CXSCREEN);
- UINT iMaxY = GetSystemMetrics(SM_CYSCREEN);
- CRect rcMainWin(iMaxX/2-m_iWndSizeX/2,iMaxY/2-m_iWndSizeY/2,iMaxX/2+m_iWndSizeX/2,iMaxY/2+m_iWndSizeY/2);
-
- Create(sClassName,GAME_TITLE,(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPCHILDREN),
- rcMainWin,NULL,MAKEINTRESOURCE(IDR_MENU1));
-
- //Init common controls
- InitCommonControls();
-
- //Attach the menu-resource to a CMenu object
- m_menu.Attach(::GetMenu(m_hWnd));
-
- //Setup the status bar
- CRect rcTemp(0,0,0,0);
- m_sbarc.Create((WS_CHILD|WS_VISIBLE|CBRS_BOTTOM),rcTemp,this,AFX_IDW_STATUS_BAR);
- m_sbarc.SetSimple(TRUE);
- m_sbarc.SetText("Welcome to " GAME_TITLE "! Press [F2] to start a new game...",255,0);
-
- //Adjust the "virtual" client rectangle to disinclude the status bar
- GetClientRect(&m_rcCli);
- m_sbarc.GetWindowRect(rcTemp);
- m_rcCli.bottom -= (rcTemp.bottom-rcTemp.top);
-
- //Create device context for direct output to client area
- m_pdcCli = new CClientDC(this);
- m_pdcCli->SetBkColor(RGB_BLACK);
- m_pdcCli->SetBkMode(TRANSPARENT);
-
- //Create GDI objs
- m_gFontFSys.CreateStockObject(SYSTEM_FIXED_FONT);
-
- // Load high score table data from disk
- m_lstHighScores.Load();
-
- //Seed the random number generator
- #ifdef RELEASE
- srand(time(NULL));
- #endif //release
- }
-
- //-----------------
- CGameWnd::~CGameWnd()
- {
- // Save high score table data to disk
- m_lstHighScores.Save();
-
- // Free allocations
- delete m_pdcCli;
- }
-
- //===========================
- // Primary game functions
-
- //-----------------
- BOOL CGameWnd::MainLoop()
- {
- if (m_bPaused || !m_bRunning) return FALSE;
-
- QueryPerformanceCounter(&m_liTemp); m_dGameTime = LI2Double(&m_liTemp);
-
- if ((UINT)((1000.0*(m_dGameTime-m_dPrevGameTime))/m_dFreq) >= m_iGameSpdDelay)
- {
- //Run a single game timeslice
- if (!m_pGame->RunGame()) GameOver();
-
- //Reset timer gate
- m_dPrevGameTime = m_dGameTime;
- }
-
- return m_bRunning;
- }
-
- //-----------------
- BOOL CGameWnd::AnimLoop()
- {
- if (m_bPaused || !m_bRunning) return FALSE;
-
- QueryPerformanceCounter(&m_liTemp); m_dAnimTime = LI2Double(&m_liTemp);
-
- if ((UINT)((1000.0*(m_dAnimTime-m_dPrevAnimTime))/m_dFreq) >= m_iRefreshDelay)
- {
- //Calculate FPS from iDT
- #ifdef BENCH_FPS
- m_fFPS = (float)(m_dFreq/(m_dAnimTime-m_dPrevAnimTime));
- #endif //bench_fps
-
- //Blit from shadow bmp to client area
- m_pGame->Paint();
-
- //Reset timer gate
- m_dPrevAnimTime = m_dAnimTime;
-
- //Adjust refresh delay to match system load
- QueryPerformanceCounter(&m_liTemp); m_dAnimTime = LI2Double(&m_liTemp);
- UINT iDT = (UINT)((1000.0*(m_dAnimTime-m_dPrevAnimTime))/m_dFreq);
-
- iDT = MIN(iDT,(1000/MIN_FPS));
- if (iDT > m_iRefreshDelay+5) m_iRefreshDelay += 10;
- if (iDT < m_iRefreshDelay-5) m_iRefreshDelay -= 10;
- m_iRefreshDelay = MAX(m_iRefreshDelay,m_iGameSpdDelay); //upper limit for refresh rate
- m_iRefreshDelay = MIN(m_iRefreshDelay,m_iGameSpdDelay*3); //lower limit for refresh rate
- }
-
- return m_bRunning;
- }
-
- //-----------------
- void CGameWnd::GameOver()
- {
- // Unpause game
- if (m_bPaused) OnGamePause();
-
- // Stop game
- UINT iScore = m_pGame->GameOver();
- KillTimer(IDT_GAMECLK);
- m_bRunning = m_bPaused = FALSE;
-
- // Scan high score data
- UINT iSlot = 0;
- while(m_lstHighScores.GetScore(iSlot) >= iScore && iSlot < 10) iSlot++;
- if (iSlot < 10) //then we have a new high score!
- {
- CNewHighScoreDialog dlgNewHighScore(IDD_NEWHIGHSCORE);
- strcpy(dlgNewHighScore.m_szName,m_lstHighScores.GetName(iSlot));
- dlgNewHighScore.DoModal();
- m_lstHighScores.Insert(iSlot,dlgNewHighScore.m_szName,iScore);
-
- // Display new high score data
- OnViewScores();
- }
- }
-
- //===========================
- // CGameWnd system handlers
-
- //-----------------
- afx_msg void CGameWnd::OnActivateApp(BOOL bActive, HTASK hTask)
- {
- //Auto-pause!
- if (!bActive && !m_bPaused && m_bRunning) OnGamePause();
-
- //Restore title bar
- if (m_bPaused)
- SetWindowText(GAME_TITLE" - Paused");
- else
- SetWindowText(GAME_TITLE);
- }
-
- //-----------------
- afx_msg BOOL CGameWnd::OnEraseBkgnd(CDC *pDC)
- {
- //Avoid unnecessary flicker by overriding this default implementation!
- return TRUE;
- }
-
- //-----------------
- afx_msg void CGameWnd::OnPaint()
- {
- CPaintDC DC(this);
-
- //If game obj not constructed yet, return
- if (!m_pGame)
- return;
-
- //Game-dependent implementation
- m_pGame->Paint();
-
- //Display pause overlay
- if (m_bPaused)
- {
- //Create the pause display
- CRect rcTemp(&m_rcCli);
- rcTemp.DeflateRect(m_rcCli.right/2-80,m_rcCli.bottom/2-24);
- m_pdcCli->FillSolidRect(rcTemp,RGB_GREY);
- CFont *pOldFont = m_pdcCli->SelectObject(&m_gFontFSys);
- m_pdcCli->SetTextAlign(TA_BASELINE|TA_CENTER);
- m_pdcCli->SetTextColor(RGB_YELLOW2);
- m_pdcCli->TextOut((m_rcCli.right/2),(m_rcCli.bottom/2)-2,CString("P A U S E D"));
- m_pdcCli->TextOut((m_rcCli.right/2),(m_rcCli.bottom/2)+12,CString("Press F3 to Resume"));
- m_pdcCli->SelectObject(pOldFont);
- }
- }
-
- //-----------------
- afx_msg void CGameWnd::OnTimer(UINT nIDEvent)
- {
- switch (nIDEvent)
- {
- case IDT_GAMECLK:
- if (m_bRunning && !m_bPaused)
- m_pGame->UpdateSB();
- break;
- } //end of switch-block
- }
-
-
- //===========================
- // CGameWnd UI handlers
-
- //-----------------
- afx_msg void CGameWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- //Ignore repeated keystrokes
- if (nFlags&0x4000) return;
-
- switch (nChar)
- {
- case VK_ESCAPE: //the "boss" key
- ShowWindow(SW_MINIMIZE);
- SetWindowText("Microsoft Excel");
- break;
-
- // Menu hotkey map
- case VK_F1: OnHelpAbout(); break;
- case VK_F2: OnGameNew(); break;
- case VK_F3: OnGamePause(); break;
- case VK_F4: OnGameEnd(); break;
- case VK_F5: OnOptionsSpeed(); break;
- case VK_F6: OnOptionsLevel(); break;
- case VK_F7: OnViewScores(); break;
-
- default: //call game-specific handler
- m_pGame->HandleKbd(nChar);
- break;
- } //end of switch block
- }
-
-
- //===========================
- // CGameWnd menu handlers
-
- //-----------------
- afx_msg void CGameWnd::OnGameNew()
- {
- if (m_bRunning)
- {
- if (MessageBox("Start a new game?","Confirm Quit Request...",MB_OKCANCEL|MB_ICONQUESTION) == IDOK)
- GameOver();
- else
- return;
- }
-
- //Initialize new game
- m_bRunning = TRUE;
- m_bPaused = FALSE;
- m_pGame->NewGame(m_iInitLevel);
-
- //Start game timers
- SetTimer(IDT_GAMECLK,m_iClockDelay,NULL);
- }
-
- //-----------------
- afx_msg void CGameWnd::OnGamePause()
- {
- if (!m_bRunning) return;
-
- if (m_bPaused) //then resume
- {
- //Restore title bar
- SetWindowText(GAME_TITLE);
-
- //Notify game logic
- m_pGame->PauseGame(FALSE);
-
- //Restart timers
- SetTimer(IDT_GAMECLK,m_iClockDelay,NULL);
-
- //Clear pause display
- m_bPaused = FALSE;
- Invalidate();
- }
- else //(!m_bPaused) then pause
- {
- //Set pause display
- m_bPaused = TRUE;
- Invalidate();
-
- //Kill timers
- KillTimer(IDT_GAMECLK);
-
- //Notify game logic
- m_pGame->PauseGame(TRUE);
-
- //Update title bar
- if (!IsIconic()) SetWindowText(GAME_TITLE" - Paused");
- }
- }
-
- //-----------------
- afx_msg void CGameWnd::OnGamePauseUpdate(CCmdUI *pCmdUI)
- {
- pCmdUI->Enable((m_bRunning)?TRUE:FALSE);
- pCmdUI->SetText((m_bPaused)?"&Resume\tF3":"&Pause\tF3");
- }
-
- //-----------------
- afx_msg void CGameWnd::OnGameEnd()
- {
- if (!m_bRunning) return;
-
- if (MessageBox("Abort current game?","Confirm Quit Request...",MB_OKCANCEL|MB_ICONQUESTION) == IDOK)
- GameOver();
- }
-
- //-----------------
- afx_msg void CGameWnd::OnGameEndUpdate(CCmdUI *pCmdUI)
- {
- pCmdUI->Enable((m_bRunning)?TRUE:FALSE);
- }
-
- //-----------------
- afx_msg void CGameWnd::OnOptionsSpeed()
- {
- if (m_bRunning) return;
-
- CSpeedDialog dlgSpeed(IDD_OPT_SPEED);
- dlgSpeed.m_iSpeed = MIN(MAX_FPS,MAX(MIN_FPS,(1000/m_iGameSpdDelay)));
- if (dlgSpeed.DoModal() == IDOK)
- {
- m_iGameSpdDelay = m_iRefreshDelay = 1000/dlgSpeed.m_iSpeed;
- m_iClockDelay = 1000*NOM_FPS/dlgSpeed.m_iSpeed;
- }
- }
-
- //-----------------
- afx_msg void CGameWnd::OnOptionsSpeedUpdate(CCmdUI *pCmdUI)
- {
- pCmdUI->Enable((m_bRunning)?FALSE:TRUE);
- }
-
- //-----------------
- afx_msg void CGameWnd::OnOptionsLevel()
- {
- if (m_bRunning) return;
-
- CLevelDialog dlgLevel(IDD_OPT_LEVEL);
- dlgLevel.m_iLevel = m_iInitLevel;
- if (dlgLevel.DoModal() == IDOK)
- m_iInitLevel = dlgLevel.m_iLevel;
- }
-
- //-----------------
- afx_msg void CGameWnd::OnOptionsLevelUpdate(CCmdUI *pCmdUI)
- {
- pCmdUI->Enable((m_bRunning)?FALSE:TRUE);
- }
-
- //-----------------
- afx_msg void CGameWnd::OnViewScores()
- {
- if (m_bRunning) return;
-
- CHighScoreDialog dlgScores(IDD_HIGH_SCORES);
- dlgScores.m_plstScoreData = &m_lstHighScores;
- dlgScores.DoModal();
- }
-
- //-----------------
- afx_msg void CGameWnd::OnViewScoresUpdate(CCmdUI *pCmdUI)
- {
- pCmdUI->Enable((m_bRunning)?FALSE:TRUE);
- }
-
- //-----------------
- afx_msg void CGameWnd::OnHelpAbout()
- {
- CDialog dlgAbout(IDD_HELP_ABOUT);
- dlgAbout.DoModal();
- }
-
- //===========================
- // CGameWnd message map
-
- //-----------------
- BEGIN_MESSAGE_MAP(CGameWnd, CFrameWnd)
- ON_WM_ACTIVATEAPP()
- ON_WM_ERASEBKGND()
- ON_WM_PAINT()
- ON_WM_TIMER()
-
- ON_WM_KEYDOWN()
-
- ON_COMMAND(ID_GAME_NEW,OnGameNew)
- ON_COMMAND(ID_GAME_PAUSE,OnGamePause)
- ON_UPDATE_COMMAND_UI(ID_GAME_PAUSE,OnGamePauseUpdate)
- ON_COMMAND(ID_GAME_END,OnGameEnd)
- ON_UPDATE_COMMAND_UI(ID_GAME_END,OnGameEndUpdate)
- ON_COMMAND(ID_OPTIONS_SPEED,OnOptionsSpeed)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SPEED,OnOptionsSpeedUpdate)
- ON_COMMAND(ID_OPTIONS_LEVEL,OnOptionsLevel)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_LEVEL,OnOptionsLevelUpdate)
- ON_COMMAND(ID_VIEW_SCORES,OnViewScores)
- ON_UPDATE_COMMAND_UI(ID_VIEW_SCORES,OnViewScoresUpdate)
- ON_COMMAND(ID_HELP_ABOUT,OnHelpAbout)
- END_MESSAGE_MAP()
-
-