• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            tbwshc

            tbw

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              95 Posts :: 8 Stories :: 3 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(4)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            這里我們提出一種游戲循環的概念,游戲循環是將原先程序中的消息循環加以修改,方法是判斷其中的內容目前是否有要處理的消息,如果有則進行處理,否則按照設定的時間間隔來重繪畫面。下面是接下來一段游戲循環的程序代碼:
               
                //游戲循環
               
                while( msg.message!=WM_QUIT )               //注釋點1(詳細內容見下)
               
                {
               
                if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )       //注釋點2(詳細內容見下)
               
                {
               
                TranslateMessage( &msg );
               
                DispatchMessage( &msg );
               
                }
               
                else
               
                {
               
                tNow = GetTickCount();                        //注釋點3
               
                if(tNow-tPre >= 100)                   //注釋點4
               
                MyPaint(hdc);
               
                }
               
                }
               
                我們來講解一下游戲循環片段中的幾個重點。
               
                <1>注釋點1:當收到的msg.message不是窗口結束消息WM_QUIT,則繼續運行循環,其中msg是一個MSG的消息結構,其結構成員message則是一個消息類型的代號。
               
                <2>注釋點2:使用PeekMessage()函數來檢測目前是否有需要處理的消息,若檢測到消息(包含WM_QUIT消息)則會返回一個非“0”值,否則返回“0”.因此在游戲循環中,若檢測到消息便進行消息的處理,否則運行else敘述之后的程序代碼。這里我們要注意的是,PeekMessage()函數不能用原先消息循環的條件GetMessage()取代,因為GetMessage()函數只有在取得WM_QUIT消息時才會返回“0”,其他時候則是返回非“0”值或“-1”(發生錯誤時)
               
                <3>注釋點3:GetTickCount()函數會取得系統開始運行到目前所經過的時間,單位是毫秒(milliseconds)。  之前我理解錯了,在這里感謝worldy的指出我的錯誤。
               
                DWORD GetTickCount()    //取得系統開始到目前經過的時間
               
                這里取得時間的目的主要是可以搭配接下來的判斷式,用來調整游戲運行的速度,使得游戲不會因為運行計算機速度的不同而跑得太快或者太慢。

                
                <4>注釋點4:if條件式中,“tPre”記錄前次繪圖的時間,而“tNow-tRre”則是計算上次繪圖到這次循環運行之間相差多少時間。這里設置為若相差40個單位時間以上則再次進行繪圖的操作,通過這個數值的控制可以調整游戲運行的速度。這里設定40個單位時間(微秒)的原因是,因為每隔40個單位進行一次繪圖的操作,那么1秒鐘大約重繪窗口1000/40=25次剛好可以達到期望值。
               
                由于循環的運行速度遠比定時器發出時間信號來得快,因此使用游戲循環可以更精準地控制程序運行速度并提高每秒鐘畫面重繪的次數。
               
                了解了游戲循環使用的基本概念之后,接下來的范例將以游戲循環的方法進行窗口的連續貼圖,更精確地制作游戲動畫效果。
               
                #include “stdafx.h”
               
                #include <stdio.h>
               
                //全局變量聲明
               
                HINSTANCE hInst;
               
                HBITMAP man[7];
               
                HDC  hdc,mdc;
               
                HWND    hWnd;
               
                DWORD   tPre,tNow,tCheck;                 //聲明三個函數來記錄時間,tPre記錄上一次繪圖的時間,tNow記錄此次準備繪圖的時間,tCheck記錄每秒開始的時間
               
                int  num,frame,fps;                    //num用來記錄圖號,frame用來累加每次畫面更新的次數,fps(frame per second)用來記錄每秒畫面更新的次數
               
                //全局函數的聲明
               
                ATOM     MyRegisterClass
               
                (HINSTANCE hInstance);
               
                BOOL     InitInstance
               
                (HINSTANCE, int);
               
                LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM,
               
                LPARAM);
               
                void     MyPaint(HDC hdc);
               
                //***WinMain函數,程序入口點函數**************************************
               
                int APIENTRY WinMain(HINSTANCE hInstance,
               
                HINSTANCE hPrevInstance,
               
                LPSTR     lpCmdLine,
               
                int       nCmdShow)
               
                {
               
                MSG msg;
               
                MyRegisterClass(hInstance);
               
                //運行初始化函數
               
                if (!InitInstance (hInstance, nCmdShow))
               
                {
               
                return FALSE;
               
                }
               
                GetMessage(&msg,NULL,NULL,NULL);   //感謝xiaoxiangp的提醒,需要在進入消息循環之前初始化msg,避免了死循環發生的可能性。
               
                //游戲循環
               
                while( msg.message!=WM_QUIT )
               
                {
               
                if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )
               
                {
               
                TranslateMessage( &msg );
               
                DispatchMessage( &msg );
               
                }
               
                else
               
                {
               
                tNow = GetTickCount();
               
                if(tNow-tPre >= 100)        //當此次循環運行與上次繪圖時間相差0.1秒時再進行重繪操作
               
                MyPaint(hdc);
               
                }
               
                }
               
                return msg.wParam;
               
                }
               
                //****設計一個窗口類,類似填空題,使用窗口結構體*************************
               
                ATOM MyRegisterClass(HINSTANCE hInstance)
               
                {
               
                WNDCLASSEX wcex;
               
                wcex.cbSize = sizeof(WNDCLASSEX);
               
                wcex.style   = CS_HREDRAW |
               
                CS_VREDRAW;
               
                wcex.lpfnWndProc    = (WNDPROC)WndProc;
               
                wcex.cbClsExtra  = 0;
               
                wcex.cbWndExtra  = 0;
               
                wcex.hInstance   = hInstance;
               
                wcex.hIcon   = NULL;
               
                wcex.hCursor     = NULL;
               
                wcex.hCursor     = LoadCursor(NULL,
               
                IDC_ARROW);
               
                wcex.hbrBackground  = (HBRUSH)
               
                (COLOR_WINDOW+1);
               
                wcex.lpszMenuName   = NULL;
               
                wcex.lpszClassName  = “canvas”;
               
                wcex.hIconSm     = NULL;
               
                return RegisterClassEx(&wcex);
               
                }
               
                //****初始化函數*************************************
               
                // 從文件加載位圖
               
                BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
               
                {
               
                char filename[20] = “”;
               
                int i;
               
                hInst = hInstance;
               
                hWnd = CreateWindow(“canvas”, “動畫演示” ,
               
                WS_OVERLAPPEDWINDOW,
               
                CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
               
                NULL, NULL, hInstance, NULL);
               
                if (!hWnd)
               
                {
               
                return FALSE;
               
                }
               
                MoveWindow(hWnd,10,10,600,450,true);
               
                ShowWindow(hWnd, nCmdShow);
               
                UpdateWindow(hWnd);
               
                hdc = GetDC(hWnd);
               
                mdc = CreateCompatibleDC(hdc);
               
                //載入各個人物位圖
               
                for(i=0;i<7;i++)
               
                {
               
                sprintf(filename,“man%d.bmp”,i);
               
                man[i] = (HBITMAP)LoadImage
               
                (NULL,filename,IMAGE_BITMAP,640,480,LR_LOADFROMFILE);
               
                }
               
                num = 0;
               
                frame = 0;
               
                MyPaint(hdc);
               
                return TRUE;
               
                }
               
                //****自定義繪圖函數*********************************
               
                // 1.計算與顯示每秒畫面更新次數
               
                // 2.按照圖號順序進行窗口貼圖
               
                void MyPaint(HDC hdc)
               
                {
               
                char str[40] = “”;
               
                if(num == 7)
               
                num = 0;
               
                frame++;            //畫面更新次數加1
               
                if(tNow - tCheck >= 1000)               //tbw判斷此次繪圖時間由前一秒算起是否已經達到1秒鐘的時間間隔。若是,則將目前的‘frame’值賦給“fps”,表示這一秒內所更新的畫面次數,然后將“frame”值回0,并重設下次計算每秒畫面數的起始時間“iCheck”.
               
                {
               
                fps = frame;
               
                frame = 0;
               
                tCheck = tNow;
               
                }
               
                SelectObject(mdc,man[num]);         //選用要更新的圖案到mdc中,再輸出顯示每秒畫面更新次數的字符串到mdc上,最后將mdc的內容貼到窗口中。
               
                sprintf(str,“每秒顯示 %d個畫面”,fps);
               
                TextOut(mdc,0,0,str,strlen(str));
               
                BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY);
               
                tPre = GetTickCount();     //記錄此次繪圖時間,供下次游戲循環中判斷是否已經達到畫面更新操作設定的時間間隔。
               
                num++;
               
                }
               
                //******消息處理函數*********************************
               
                LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
               
                WPARAM wParam, LPARAM lParam)
               
                {
               
                int i;
               
                switch (message)
               
                {
               
                case WM_DESTROY:     //窗口結束消息
               
                DeleteDC(mdc);
               
                for(i=0;i<7;i++)
               
                DeleteObject(man[i]);
               
                ReleaseDC(hWnd,hdc);
               
                PostQuitMessage(0);
               
                break;
               
                default:     //其他消息
               
                return DefWindowProc(hWnd,
               
                message, wParam, lParam);
               
                }
               
                return 0;
               
                }
               
                程序的運行結果如下圖:
            posted on 2012-09-16 14:07 tbwshc 閱讀(116) 評論(0)  編輯 收藏 引用
            一本久久久久久久| 久久久一本精品99久久精品66| 伊人久久大香线蕉精品| 精品无码人妻久久久久久| 人妻中文久久久久| 久久人爽人人爽人人片AV| 国产精品永久久久久久久久久| 午夜精品久久久久9999高清| 久久综合给合久久狠狠狠97色 | 一本大道久久香蕉成人网| AV无码久久久久不卡蜜桃| 国产成人久久777777| 人妻无码中文久久久久专区| 国产午夜精品理论片久久| 国内精品伊人久久久久AV影院| 狠狠色伊人久久精品综合网 | 色欲久久久天天天综合网 | 久久久久久久久久久精品尤物| 国产午夜免费高清久久影院| 亚洲午夜精品久久久久久app| 国产精品一久久香蕉国产线看 | 999久久久无码国产精品| 伊人久久五月天| 久久久久亚洲AV成人网人人网站 | 国产精品美女久久福利网站| 日韩亚洲欧美久久久www综合网| 99久久精品免费看国产一区二区三区 | 国产精品久久久久久影院| 中文字幕久久波多野结衣av| 欧美精品福利视频一区二区三区久久久精品 | 久久午夜无码鲁丝片午夜精品| 97精品国产91久久久久久| 久久亚洲精品无码AV红樱桃| 思思久久好好热精品国产| 人妻丰满?V无码久久不卡| 国产精品99久久久久久www| 亚洲国产成人久久精品影视| 日本精品久久久中文字幕| 欧美精品一本久久男人的天堂| 欧美综合天天夜夜久久| 国产精品伦理久久久久久|