home *** CD-ROM | disk | FTP | other *** search
/ Speelhal Klassiekers - Hits des Salles de Jeux / Arcade.bin / games / Xonix32 / SRC / GAMEWND.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-24  |  12.2 KB  |  492 lines

  1.  
  2. //===========================
  3. // GameWnd.cpp
  4. // by SA VanNess
  5. // 08 Mar 97
  6. // for the Win32 platform
  7. //===========================
  8. // Arcade Frame Window
  9. // Class implementation
  10. //===========================
  11. // Copyright (C) 1997  SA VanNess
  12. // <savanness@pipeline.com>
  13. //
  14. // For copyright information, see the file gnu_license.txt included
  15. // with this source code distribution.
  16. //
  17. // This program is free software; you can redistribute it and/or modify
  18. // it under the terms of the GNU General Public License as published by
  19. // the Free Software Foundation; either version 2 of the License, or
  20. // (at your option) any later version.
  21. //
  22. // This program is distributed in the hope that it will be useful,
  23. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25. // GNU General Public License for more details.
  26. //
  27. // You should have received a copy of the GNU General Public License
  28. // along with this program; if not, write to the Free Software
  29. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30. //===========================
  31.  
  32. #include <afxwin.h>
  33. #include <afxcmn.h>
  34. #include <afxres.h>
  35.  
  36. #include "resource.h"
  37. #include "macros.h"
  38. #include "xonix32.h"
  39. #include "hiscores.h"
  40. #include "gamedlg.h"
  41. #include "gamewnd.h"
  42.  
  43. //Hires timing conversion function
  44. double LI2Double(LARGE_INTEGER *pli)
  45. { return (((double)pli->HighPart*(double)0xffffffff)+(double)pli->LowPart); }
  46.  
  47. //===========================
  48. // CGameWnd constr/destr
  49.  
  50. //-----------------
  51. CGameWnd::CGameWnd(CString sClassName, char *pszCmdLine)
  52. {
  53. //Game object not constructed yet!
  54. m_pGame = NULL;
  55.  
  56. //Init vars
  57. m_iInitLevel = 1;
  58. m_bPaused = m_bRunning = FALSE;
  59. m_iRefreshDelay = 1000/NOM_FPS;
  60. m_iGameSpdDelay = 1000/NOM_FPS;
  61. m_iClockDelay = 1000; //1 sec
  62.  
  63. if (!QueryPerformanceFrequency(&m_liTemp))
  64.    {
  65.    ::MessageBox(NULL,"Xonix32 requires hi-resolution timing support.\n"
  66.                 "See the ReadMe.txt file for more info.","Error!",MB_OK|MB_ICONSTOP);
  67.    ExitProcess(1);
  68.    }
  69. m_dFreq = LI2Double(&m_liTemp);
  70. QueryPerformanceCounter(&m_liTemp); m_dPrevGameTime = LI2Double(&m_liTemp);
  71. QueryPerformanceCounter(&m_liTemp); m_dPrevAnimTime = LI2Double(&m_liTemp);
  72.  
  73. //Process command-line info
  74. switch (pszCmdLine[0])
  75.    {
  76.    case 'S':
  77.    case 's':
  78.    m_iWndSizeX = 400;
  79.    m_iWndSizeY = 300;
  80.    break;
  81.  
  82.    case 'L':
  83.    case 'l':
  84.    m_iWndSizeX = 640;
  85.    m_iWndSizeY = 480;
  86.    break;
  87.  
  88.    default:
  89.    m_iWndSizeX = 520;
  90.    m_iWndSizeY = 390;
  91.    break;
  92.    }
  93.  
  94. //Create m_iWndSizeX*m_iWndSizeY window in center of screen
  95. UINT iMaxX = GetSystemMetrics(SM_CXSCREEN);
  96. UINT iMaxY = GetSystemMetrics(SM_CYSCREEN);
  97. CRect rcMainWin(iMaxX/2-m_iWndSizeX/2,iMaxY/2-m_iWndSizeY/2,iMaxX/2+m_iWndSizeX/2,iMaxY/2+m_iWndSizeY/2);
  98.  
  99. Create(sClassName,GAME_TITLE,(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPCHILDREN),
  100.        rcMainWin,NULL,MAKEINTRESOURCE(IDR_MENU1));
  101.  
  102. //Init common controls
  103. InitCommonControls();
  104.  
  105. //Attach the menu-resource to a CMenu object
  106. m_menu.Attach(::GetMenu(m_hWnd));
  107.  
  108. //Setup the status bar
  109. CRect rcTemp(0,0,0,0);
  110. m_sbarc.Create((WS_CHILD|WS_VISIBLE|CBRS_BOTTOM),rcTemp,this,AFX_IDW_STATUS_BAR);
  111. m_sbarc.SetSimple(TRUE);
  112. m_sbarc.SetText("Welcome to " GAME_TITLE "!  Press [F2] to start a new game...",255,0);
  113.  
  114. //Adjust the "virtual" client rectangle to disinclude the status bar
  115. GetClientRect(&m_rcCli);
  116. m_sbarc.GetWindowRect(rcTemp);
  117. m_rcCli.bottom -= (rcTemp.bottom-rcTemp.top);
  118.  
  119. //Create device context for direct output to client area
  120. m_pdcCli = new CClientDC(this);
  121. m_pdcCli->SetBkColor(RGB_BLACK);
  122. m_pdcCli->SetBkMode(TRANSPARENT);
  123.  
  124. //Create GDI objs
  125. m_gFontFSys.CreateStockObject(SYSTEM_FIXED_FONT);
  126.  
  127. // Load high score table data from disk
  128. m_lstHighScores.Load();
  129.  
  130. //Seed the random number generator
  131. #ifdef RELEASE
  132. srand(time(NULL));
  133. #endif //release
  134. }
  135.  
  136. //-----------------
  137. CGameWnd::~CGameWnd()
  138. {
  139. // Save high score table data to disk
  140. m_lstHighScores.Save();
  141.  
  142. // Free allocations
  143. delete m_pdcCli;
  144. }
  145.  
  146. //===========================
  147. // Primary game functions
  148.  
  149. //-----------------
  150. BOOL CGameWnd::MainLoop()
  151. {
  152. if (m_bPaused || !m_bRunning) return FALSE;
  153.  
  154. QueryPerformanceCounter(&m_liTemp); m_dGameTime = LI2Double(&m_liTemp);
  155.  
  156. if ((UINT)((1000.0*(m_dGameTime-m_dPrevGameTime))/m_dFreq) >= m_iGameSpdDelay)
  157.    {
  158.    //Run a single game timeslice
  159.    if (!m_pGame->RunGame()) GameOver();
  160.  
  161.    //Reset timer gate
  162.    m_dPrevGameTime = m_dGameTime;
  163.    }
  164.  
  165. return m_bRunning;
  166. }
  167.  
  168. //-----------------
  169. BOOL CGameWnd::AnimLoop()
  170. {
  171. if (m_bPaused || !m_bRunning) return FALSE;
  172.  
  173. QueryPerformanceCounter(&m_liTemp); m_dAnimTime = LI2Double(&m_liTemp);
  174.  
  175. if ((UINT)((1000.0*(m_dAnimTime-m_dPrevAnimTime))/m_dFreq) >= m_iRefreshDelay)
  176.    {
  177.    //Calculate FPS from iDT
  178. #ifdef BENCH_FPS
  179.    m_fFPS = (float)(m_dFreq/(m_dAnimTime-m_dPrevAnimTime));
  180. #endif //bench_fps
  181.  
  182.    //Blit from shadow bmp to client area
  183.    m_pGame->Paint();
  184.  
  185.    //Reset timer gate
  186.    m_dPrevAnimTime = m_dAnimTime;
  187.  
  188.    //Adjust refresh delay to match system load
  189.    QueryPerformanceCounter(&m_liTemp); m_dAnimTime = LI2Double(&m_liTemp);
  190.    UINT iDT = (UINT)((1000.0*(m_dAnimTime-m_dPrevAnimTime))/m_dFreq);
  191.  
  192.    iDT = MIN(iDT,(1000/MIN_FPS));
  193.    if (iDT > m_iRefreshDelay+5) m_iRefreshDelay += 10;
  194.    if (iDT < m_iRefreshDelay-5) m_iRefreshDelay -= 10;
  195.    m_iRefreshDelay = MAX(m_iRefreshDelay,m_iGameSpdDelay); //upper limit for refresh rate
  196.    m_iRefreshDelay = MIN(m_iRefreshDelay,m_iGameSpdDelay*3); //lower limit for refresh rate
  197.    }
  198.  
  199. return m_bRunning;
  200. }
  201.  
  202. //-----------------
  203. void CGameWnd::GameOver()
  204. {
  205. // Unpause game
  206. if (m_bPaused) OnGamePause();
  207.  
  208. // Stop game
  209. UINT iScore = m_pGame->GameOver();
  210. KillTimer(IDT_GAMECLK);
  211. m_bRunning = m_bPaused = FALSE;
  212.  
  213. // Scan high score data
  214. UINT iSlot = 0;
  215. while(m_lstHighScores.GetScore(iSlot) >= iScore && iSlot < 10) iSlot++;
  216. if (iSlot < 10) //then we have a new high score!
  217.    {
  218.    CNewHighScoreDialog dlgNewHighScore(IDD_NEWHIGHSCORE);
  219.    strcpy(dlgNewHighScore.m_szName,m_lstHighScores.GetName(iSlot));
  220.    dlgNewHighScore.DoModal();
  221.    m_lstHighScores.Insert(iSlot,dlgNewHighScore.m_szName,iScore);
  222.  
  223.    // Display new high score data
  224.    OnViewScores();
  225.    }
  226. }
  227.  
  228. //===========================
  229. // CGameWnd system handlers
  230.  
  231. //-----------------
  232. afx_msg void CGameWnd::OnActivateApp(BOOL bActive, HTASK hTask)
  233. {
  234. //Auto-pause!
  235. if (!bActive && !m_bPaused && m_bRunning) OnGamePause();
  236.  
  237. //Restore title bar
  238. if (m_bPaused)
  239.    SetWindowText(GAME_TITLE" - Paused");
  240. else
  241.    SetWindowText(GAME_TITLE);
  242. }
  243.  
  244. //-----------------
  245. afx_msg BOOL CGameWnd::OnEraseBkgnd(CDC *pDC)
  246. {
  247. //Avoid unnecessary flicker by overriding this default implementation!
  248. return TRUE;
  249. }
  250.  
  251. //-----------------
  252. afx_msg void CGameWnd::OnPaint()
  253. {
  254. CPaintDC DC(this);
  255.  
  256. //If game obj not constructed yet, return
  257. if (!m_pGame)
  258.    return;
  259.  
  260. //Game-dependent implementation
  261. m_pGame->Paint();
  262.  
  263. //Display pause overlay
  264. if (m_bPaused)
  265.    {
  266.    //Create the pause display
  267.    CRect rcTemp(&m_rcCli);
  268.    rcTemp.DeflateRect(m_rcCli.right/2-80,m_rcCli.bottom/2-24);
  269.    m_pdcCli->FillSolidRect(rcTemp,RGB_GREY);
  270.    CFont *pOldFont = m_pdcCli->SelectObject(&m_gFontFSys);
  271.     m_pdcCli->SetTextAlign(TA_BASELINE|TA_CENTER);
  272.     m_pdcCli->SetTextColor(RGB_YELLOW2);
  273.     m_pdcCli->TextOut((m_rcCli.right/2),(m_rcCli.bottom/2)-2,CString("P A U S E D"));
  274.     m_pdcCli->TextOut((m_rcCli.right/2),(m_rcCli.bottom/2)+12,CString("Press F3 to Resume"));
  275.    m_pdcCli->SelectObject(pOldFont);
  276.    }
  277. }
  278.  
  279. //-----------------
  280. afx_msg void CGameWnd::OnTimer(UINT nIDEvent)
  281. {
  282. switch (nIDEvent)
  283.    {
  284.    case IDT_GAMECLK:
  285.    if (m_bRunning && !m_bPaused)
  286.       m_pGame->UpdateSB();
  287.    break;
  288.    } //end of switch-block
  289. }
  290.  
  291.  
  292. //===========================
  293. // CGameWnd UI handlers
  294.  
  295. //-----------------
  296. afx_msg void CGameWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  297. {
  298. //Ignore repeated keystrokes
  299. if (nFlags&0x4000) return;
  300.  
  301. switch (nChar)
  302.    {
  303.    case VK_ESCAPE: //the "boss" key
  304.    ShowWindow(SW_MINIMIZE);
  305.    SetWindowText("Microsoft Excel");
  306.    break;
  307.  
  308.    // Menu hotkey map
  309.    case VK_F1: OnHelpAbout(); break;
  310.    case VK_F2: OnGameNew(); break;
  311.    case VK_F3: OnGamePause(); break;
  312.    case VK_F4: OnGameEnd(); break;
  313.    case VK_F5: OnOptionsSpeed(); break;
  314.    case VK_F6: OnOptionsLevel(); break;
  315.    case VK_F7: OnViewScores(); break;
  316.  
  317.    default: //call game-specific handler
  318.    m_pGame->HandleKbd(nChar);
  319.    break;
  320.    } //end of switch block
  321. }
  322.  
  323.  
  324. //===========================
  325. // CGameWnd menu handlers
  326.  
  327. //-----------------
  328. afx_msg void CGameWnd::OnGameNew()
  329. {
  330. if (m_bRunning)
  331.    {
  332.    if (MessageBox("Start a new game?","Confirm Quit Request...",MB_OKCANCEL|MB_ICONQUESTION) == IDOK)
  333.       GameOver();
  334.    else
  335.       return;
  336.    }
  337.  
  338. //Initialize new game
  339. m_bRunning = TRUE;
  340. m_bPaused = FALSE;
  341. m_pGame->NewGame(m_iInitLevel);
  342.  
  343. //Start game timers
  344. SetTimer(IDT_GAMECLK,m_iClockDelay,NULL);
  345. }
  346.  
  347. //-----------------
  348. afx_msg void CGameWnd::OnGamePause()
  349. {
  350. if (!m_bRunning) return;
  351.  
  352. if (m_bPaused) //then resume
  353.    {
  354.    //Restore title bar
  355.    SetWindowText(GAME_TITLE);
  356.    
  357.    //Notify game logic
  358.    m_pGame->PauseGame(FALSE);
  359.  
  360.    //Restart timers
  361.    SetTimer(IDT_GAMECLK,m_iClockDelay,NULL);
  362.  
  363.    //Clear pause display
  364.    m_bPaused = FALSE;
  365.    Invalidate();
  366.    }
  367. else //(!m_bPaused) then pause
  368.    {
  369.    //Set pause display
  370.    m_bPaused = TRUE;
  371.    Invalidate();
  372.  
  373.    //Kill timers
  374.    KillTimer(IDT_GAMECLK);
  375.  
  376.    //Notify game logic
  377.    m_pGame->PauseGame(TRUE);
  378.  
  379.    //Update title bar
  380.    if (!IsIconic()) SetWindowText(GAME_TITLE" - Paused");
  381.    }
  382. }
  383.  
  384. //-----------------
  385. afx_msg void CGameWnd::OnGamePauseUpdate(CCmdUI *pCmdUI)
  386. {
  387. pCmdUI->Enable((m_bRunning)?TRUE:FALSE);
  388. pCmdUI->SetText((m_bPaused)?"&Resume\tF3":"&Pause\tF3");
  389. }
  390.  
  391. //-----------------
  392. afx_msg void CGameWnd::OnGameEnd()
  393. {
  394. if (!m_bRunning) return;
  395.  
  396. if (MessageBox("Abort current game?","Confirm Quit Request...",MB_OKCANCEL|MB_ICONQUESTION) == IDOK)
  397.    GameOver();
  398. }
  399.  
  400. //-----------------
  401. afx_msg void CGameWnd::OnGameEndUpdate(CCmdUI *pCmdUI)
  402. {
  403. pCmdUI->Enable((m_bRunning)?TRUE:FALSE);
  404. }
  405.  
  406. //-----------------
  407. afx_msg void CGameWnd::OnOptionsSpeed()
  408. {
  409. if (m_bRunning) return;
  410.  
  411. CSpeedDialog dlgSpeed(IDD_OPT_SPEED);
  412. dlgSpeed.m_iSpeed = MIN(MAX_FPS,MAX(MIN_FPS,(1000/m_iGameSpdDelay)));
  413. if (dlgSpeed.DoModal() == IDOK)
  414.    {
  415.    m_iGameSpdDelay = m_iRefreshDelay = 1000/dlgSpeed.m_iSpeed;
  416.    m_iClockDelay = 1000*NOM_FPS/dlgSpeed.m_iSpeed;
  417.    }
  418. }
  419.  
  420. //-----------------
  421. afx_msg void CGameWnd::OnOptionsSpeedUpdate(CCmdUI *pCmdUI)
  422. {
  423. pCmdUI->Enable((m_bRunning)?FALSE:TRUE);
  424. }
  425.  
  426. //-----------------
  427. afx_msg void CGameWnd::OnOptionsLevel()
  428. {
  429. if (m_bRunning) return;
  430.  
  431. CLevelDialog dlgLevel(IDD_OPT_LEVEL);
  432. dlgLevel.m_iLevel = m_iInitLevel;
  433. if (dlgLevel.DoModal() == IDOK)
  434.    m_iInitLevel = dlgLevel.m_iLevel;
  435. }
  436.  
  437. //-----------------
  438. afx_msg void CGameWnd::OnOptionsLevelUpdate(CCmdUI *pCmdUI)
  439. {
  440. pCmdUI->Enable((m_bRunning)?FALSE:TRUE);
  441. }
  442.  
  443. //-----------------
  444. afx_msg void CGameWnd::OnViewScores()
  445. {
  446. if (m_bRunning) return;
  447.  
  448. CHighScoreDialog dlgScores(IDD_HIGH_SCORES);
  449. dlgScores.m_plstScoreData = &m_lstHighScores;
  450. dlgScores.DoModal();
  451. }
  452.  
  453. //-----------------
  454. afx_msg void CGameWnd::OnViewScoresUpdate(CCmdUI *pCmdUI)
  455. {
  456. pCmdUI->Enable((m_bRunning)?FALSE:TRUE);
  457. }
  458.  
  459. //-----------------
  460. afx_msg void CGameWnd::OnHelpAbout()
  461. {
  462. CDialog dlgAbout(IDD_HELP_ABOUT);
  463. dlgAbout.DoModal();
  464. }
  465.  
  466. //===========================
  467. // CGameWnd message map
  468.  
  469. //-----------------
  470. BEGIN_MESSAGE_MAP(CGameWnd, CFrameWnd)
  471.    ON_WM_ACTIVATEAPP()
  472.    ON_WM_ERASEBKGND()
  473.    ON_WM_PAINT()
  474.    ON_WM_TIMER()
  475.  
  476.    ON_WM_KEYDOWN()
  477.  
  478.    ON_COMMAND(ID_GAME_NEW,OnGameNew)
  479.    ON_COMMAND(ID_GAME_PAUSE,OnGamePause)
  480.    ON_UPDATE_COMMAND_UI(ID_GAME_PAUSE,OnGamePauseUpdate)
  481.    ON_COMMAND(ID_GAME_END,OnGameEnd)
  482.    ON_UPDATE_COMMAND_UI(ID_GAME_END,OnGameEndUpdate)
  483.    ON_COMMAND(ID_OPTIONS_SPEED,OnOptionsSpeed)
  484.    ON_UPDATE_COMMAND_UI(ID_OPTIONS_SPEED,OnOptionsSpeedUpdate)
  485.    ON_COMMAND(ID_OPTIONS_LEVEL,OnOptionsLevel)
  486.    ON_UPDATE_COMMAND_UI(ID_OPTIONS_LEVEL,OnOptionsLevelUpdate)
  487.    ON_COMMAND(ID_VIEW_SCORES,OnViewScores)
  488.    ON_UPDATE_COMMAND_UI(ID_VIEW_SCORES,OnViewScoresUpdate)
  489.    ON_COMMAND(ID_HELP_ABOUT,OnHelpAbout)
  490. END_MESSAGE_MAP()
  491.  
  492.