默然说话

一个异想天开的人做着异想天开的梦

牟勇ID:mouyong
64434次访问,排名1576好友4人,关注者6
我快乐,我存在
mouyong的文章
原创 108 篇
翻译 4 篇
转载 30 篇
评论 12 篇
默然的公告
如果要联系我,希望能说明来意,谢谢.

点击这里给我发消息

Google

最近评论
peigen:又~~~~为什么是又呢???
dcopperfield:顶下
gaoyunpeng:无意中进入到这个博客,很快就被里面的内容所吸引,感觉很有意思,不知道为什么会有这样的感觉,或许只是一种直觉上的吸引吧,一直在看博客里的文章,觉得很不错,天天等更新,哈哈,终于看到新的文章啦~
我会一直关注的~
mouyong:谢谢你的鼓励,我会更加努力。
了祝愿你实现自己的理想,达成自己的目标
wsspy007:牟老师,我发现你是我见过最好的老师了,为学生考虑最多,一切为学生着想,不知道牟老师还记得我么,张伟(无名小辈肯定你是忘记了),第一期跟杨大宇他们在一个班的,补考两次都没有及格,我现在不在昆明了,在胜利油田,这里一切都很好,一个月的薪金能顶得上昆明3-5个月的薪水,但是我不喜欢这份工作,钱固然多,但是从学校出来步入社会以后才发现,我还是应该走软件开发这条路,现在每天我只睡4-6个小时,工作12……
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 游戏编程中的人工智能(2-3)收藏

    新一篇: 游戏编程中的人工智能技术(3-1) | 旧一篇: 游戏编程中的人工智能(2-2)

     
    如何在画布上签名?下面就要解决这个问题。
    朝屏幕输出文本最简单的方法就是使用TextOut函数。下面看一下它的原型:
    BOOL TextOut(
        HDC         hdc,                
    //DC句柄
        int             nXStart,                //开始写入位置的X坐标
        int             nYStart,                //开始写入位置的Y坐标
        LPCTSTR         lpString,               //指向字符串的指针
        int             cbString                //字符串的字符数
    );
    首先向TextOut传入DC句柄,还有需要文本显示的坐标,一个字符串指针,最后是一个表示文本长度的整数。文本默认的颜色是黑色,默认的背景色是WHITE_BRUSH。
    DrawText比TextOut稍微复杂一点。它的原型如下:
    int DrawText(
        HDC         hdc,                
    //DC句柄
        LPCTSTR         lpString,       //指向待写入字符串的指针
        int             nCount,         //字符串的长度(字符个数)
        LPRECT          lpRect,         //指向格式化大小结构的指针
        UINT            uFormat         //文本书写标识
    );
    这个函数在lpRect指定的文本框里显示文本。文本根据uFormat标志设置。
    uFormat:设置文本格式化
    表2.2DrawText格式化标志
    样式
    描述
    DT_BOTTOM
    文本在文本框内底部对齐。若要使用本标志,必须同时使用DT_SINGLELINE标志
    DT_CENTER
    这个标志使文本在文本框内水平居中
    DT_LEFT
    文本左对齐
    DT_RIGHT
    文本右对齐
    DT_SINGLELINE
    在单行里显示所有文字。有回车键文字也不换行
    DT_TOP
    文本顶部对齐
    DT_WORDBREAK
    这个标志的效果类似于字的换行
    在Windows中可以自己定义背景色和前景色,还可以设置文本的透明度。为了设置文本颜色,需要利用SetTextColor函数:
    COLORREF SetTextColor(
        HDC         hdc,                
    //DC句柄
        COLORREF        crColor             //文本颜色
    );
    设置背景色用SetBkColor函数:
    COLORREF SetBkColor(
        HDC         hdc,                
    //DC句柄
        COLORREF        crColor             //背景颜色
    );
    设置完成以后,前景和背景色会一直有效,直到再次修改为止。两个函数都返回当前的颜色值,用户可以记录最初的设置,以便在必要时恢复。
    为了将文本颜色设为红色而背景设为黑色,可以执行下面这些语句。
    除了能够设置前景和背景色以外,还可以设置透明度。这把显示到屏幕上的文本的背景部分变成了透明(例如,如果文本背后是一个图案,则看起来就像是把文字直接打印到图案上一样)。
    可以用SetBkMode函数设置背景的透明度:
    int SetBkMode(
        HDC         hdc,                
    //DC句柄
        int             iBkMode         //用以指明背景模式标志
    );
    只有两个标志可用:OPAQUE(不透明)和TRANSPARENT(透明)。因此,要使用透明背景绘制文本的时候,在具体绘制之前,应设置合适的背景模式。
    GDI_Text的源代码示范了所有这些函数的使用。
    默然:这里有两个文件:main.cpp和defines.h
    首先是main.cpp
    嗯,我不逐句翻译了,只把与前面不同的地方翻译一下。
    //-----------------------------------------------------------------------
    // 
    // Name: GDI_Text示例工程
    // 
    // Author: Mat Buckland 2002
    //
    // Desc: 代码演示了文本输出
     
    //------------------------------------------------------------------------
     
    #include 
    <windows.h>
    #include 
    <time.h>
     
    #include 
    "defines.h"
     
     
     
     
    //--------------------------------- Globals ------------------------------
    //
    //------------------------------------------------------------------------
     
    char* g_szApplicationName = "The Groovy GDI - Text Output";
    char*   g_szWindowClassName = "MyWindowClass";
     
    //---------------------------- WindowProc ---------------------------------
    // 
    // This is the callback function which handles all the windows messages
    //-------------------------------------------------------------------------
     
    LRESULT CALLBACK WindowProc (HWND   hwnd,
                                 UINT   msg,
                                 WPARAM wParam,
                                 LPARAM lParam)
    {
        
    //these hold the dimensions of the client window area
         static int cxClient, cyClient;
     
        
    switch (msg)
        
    {
        
            
    //A WM_CREATE msg is sent when your application window is first
            
    //created
        case WM_CREATE:
          
    {
             
    //to get get the size of the client window first we need to create
             
    //a RECT and then ask Windows to fill in our RECT structure with
             
    //the client window size. Then we assign to cxClient and cyClient 
             
    //accordingly
                   RECT rect;
     
                   GetClientRect(hwnd, 
    &rect);
     
                   cxClient 
    = rect.right;
                   cyClient 
    = rect.bottom;
     
          }

     
          
    break;
     
        
    case WM_KEYUP:
          
    {
            
    switch(wParam)
            
    {
     
            
    case VK_ESCAPE:
              
    {
                PostQuitMessage(
    0);
              }

              
              
    break;
            }

          }

        
        
    case WM_PAINT:
          
    {
                     PAINTSTRUCT ps;
              
             BeginPaint (hwnd, 
    &ps);
     
              
    //Make the bottom part of window a pattern so you can see what
             
    //the transparency flag does
             HBRUSH PatternBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(0,0,255));
     
             HBRUSH OldBrush 
    = (HBRUSH)SelectObject(ps.hdc, PatternBrush);
     
             Rectangle(ps.hdc,
    0, cyClient/2, cxClient, cyClient);
     
             
    //替换回旧画刷
             SelectObject(ps.hdc, OldBrush);
     
             
    //首先,演示用TextOut输出演示文本
             char* text = "1. I ain't got time to bleed.";
             
             TextOut(ps.hdc, 
    55, text, strlen(text));
     
             
    //现在是DrawText.首先我们创建一个文本框
             RECT TextBox;
             TextBox.top 
    = 30;
             TextBox.left 
    = 100;
             TextBox.bottom 
    = 200;
             TextBox.right 
    = cxClient-100;
     
             
    //文本赋值
             text = "2. You take the blue pill and the story ends.You wake in your bed and believe whatever you want to believe.You take the red pill and you stay in Wonderland and I show you how deep the rabbit-hole goes.";
     
             
    //现在,画文本
             DrawText(ps.hdc, text, strlen(text), &TextBox, DT_WORDBREAK);
     
             
    //现在改变颜色,先设置文本为红色
              SetTextColor(ps.hdc, RGB(25500));
     
             
    //设置背景为黑色
             SetBkColor(ps.hdc, RGB(000));
     
             TextBox.top 
    = 200;
             TextBox.left 
    = 5;
             TextBox.bottom 
    = 300;
             TextBox.right 
    = cxClient-200;
     
             text 
    = "3. The greatest trick the devil ever pulled was convincing the world he didn't exist.";
             DrawText(ps.hdc, text, strlen(text), 
    &TextBox, DT_WORDBREAK);
     
             
    //现在,设置背景透明
             SetBkMode(ps.hdc, TRANSPARENT);
     
             TextBox.top 
    = 300;
             TextBox.left 
    = 100;
             TextBox.bottom 
    = cyClient;
             TextBox.right 
    = cxClient-50;
     
             text 
    = "4. ...I抦 42 years old. In less than a year I抣l be dead";
             DrawText(ps.hdc, text, strlen(text), 
    &TextBox, DT_WORDBREAK);
             
             EndPaint (hwnd, 
    &ps);
          }

     
          
    break;
     
        
    //has the user resized the client area?
            case WM_SIZE:
             
    {
            
    //if so we need to update our variables so that any drawing
            
    //we do using cxClient and cyClient is scaled accordingly
                 cxClient = LOWORD(lParam);
                 cyClient 
    = HIWORD(lParam);
          }

     
          
    break;
              
             
    case WM_DESTROY:
                 
    {
     
             
    // kill the application, this sends a WM_QUIT message 
                     PostQuitMessage (0);
                 }

     
           
    break;
     
         }
    //end switch
     
         
    //this is where all the messages not specifically handled by our 
             
    //winproc are sent to be processed
             return DefWindowProc (hwnd, msg, wParam, lParam);
    }

     
    //-------------------------------- WinMain -------------------------------
    //
    // The entry point of the windows program
    //------------------------------------------------------------------------
    int WINAPI WinMain (HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR     szCmdLine, 
                        
    int       iCmdShow)
    {
         
    //handle to our window
             HWND                       hWnd;
        
             
    //our window class structure
             WNDCLASSEX     winclass;
             
         
    // first fill in the window class stucture
           winclass.cbSize        = sizeof(WNDCLASSEX);
           winclass.style         
    = CS_HREDRAW | CS_VREDRAW;
         winclass.lpfnWndProc   
    = WindowProc;
         winclass.cbClsExtra    
    = 0;
         winclass.cbWndExtra    
    = 0;
         winclass.hInstance     
    = hInstance;
         winclass.hIcon         
    = LoadIcon(NULL, IDI_APPLICATION);
         winclass.hCursor       
    = LoadCursor(NULL, IDC_ARROW);
         winclass.hbrBackground 
    = (HBRUSH)GetStockObject (WHITE_BRUSH);
         winclass.lpszMenuName 
    = NULL;
         winclass.lpszClassName 
    = g_szWindowClassName;
           winclass.hIconSm       
    = LoadIcon(NULL, IDI_APPLICATION);
     
             
    //register the window class
            if (!RegisterClassEx(&winclass))
            
    {
                MessageBox(NULL, 
    "Registration Failed!""Error"0);
     
                
    //exit the application
                return 0;
            }

     
             
    //create the window and assign its ID to hwnd    
         hWnd = CreateWindowEx (NULL,                 // extended style
                                g_szWindowClassName, // window class name
                                g_szApplicationName, // window caption
                                WS_OVERLAPPEDWINDOW, // window style
                                0,                    // initial x position
                                0,                    // initial y position
                                WINDOW_WIDTH,         // initial x size
                                WINDOW_HEIGHT,        // initial y size
                                NULL,                 // parent window handle
                                NULL,                 // window menu handle
                                hInstance,            // program instance handle
                                NULL);                // creation parameters
     
         
    //make sure the window creation has gone OK
         if(!hWnd)
         
    {
           MessageBox(NULL, 
    "CreateWindowEx Failed!""Error!"0);
         }

             
         
    //make the window visible
             ShowWindow (hWnd, iCmdShow);
         UpdateWindow (hWnd);
     
         
    //this will hold any windows messages
             MSG msg;
         
             
    //entry point of our message handler
             while (GetMessage (&msg, NULL, 00))
         
    {
              TranslateMessage (
    &msg);
              DispatchMessage (
    &msg);
         }

     
         UnregisterClass( g_szWindowClassName, winclass.hInstance );
         
    return msg.wParam;
    }
    然后,是defines.h
    #ifndef DEFINES_H
    #define DEFINES_H
     
    #define WINDOW_WIDTH 400
    #define WINDOW_HEIGHT 400
     
    #endif
    在GDI_Polygon例子里,每次需要显示一个新的多边形,就得按一次空格键,这可能显得有点繁琐。但怎样才能在屏幕上连续不断地显示新的多边形来催眠用户呢?仅用GetMessage是办不到的。如果消息队列中没有消息,GetMessage就会等待,直到新的消息出现在队列中。需要这样一种消息循环,只有在需要处理消息时才去处理消息,其余的时间都让游戏代码去自动产生激动的场面。为了做到这一点,可以使用PeekMessage函数。其原型如下:
    BOOL PeekMessage(
        LPMSG           lpMsg,              
    //message结构指针
        HWND            hWnd,               //窗口句柄
        UINT            wMsgFilterMin,      //指定被检查的消息范围里的第一个message
        UINT            wMsgFilterMax,      //指定被检查的消息范围里的最后的message
        UINT            wRemoveMsg      //移走标志
    );
    最后一个参数wRemoveMsg,它的值可以是PM_NOREMOVE(消息处理后仍保留在队列中),或PM_REMOVE(消息处理后移走),通常选择后者。如果队列中有消息,PeekMessage将返回true,否则返回false。
    要创建实时的消息抽取循环,就需要更复杂一些,如果只把GetMessage替换作PeekMessage,那么,当队列中没有消息时,PeekMessage返回零,应用程序会因此而终止。下面尝试用另一种形式来修改绘制多边形的例子。
    while(PeekMessage(&msg,NULL,0,0,PM_))
    {
        TranslateMessage(
    &msg);
        DispatchMessage(
    &msg);
    }
    这样只会见到应用程序窗口闪电般地打开,接着就立即关闭。而实际中需要的是一个更为强健的设计,过程如下:
    //进入message抽取循环
    bool bDone=false;
    MSG msg;
    while(!bDone){
        
    while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){
            
    if(msg.message==WM_QUIT){
                
    //如果是quit消息,就退出循环
                bDone=true;
            }
    else{
                TranslateMessage(
    &msg);
                DispatchMessage(
    &msg);
            }

        }

        
    //下面是调用WM_PAINT绘制场景
        InvalidateRect(hWnd,NULL,TRUE);
        UpdateWindow(hWnd);
    }
    从GDI_Polygon2例子里的消息循环的运行情况中,可以发现WindowProc中的WM_PAINT部分现在包含产生新多边形的代码。这里利用了小巧的Sleep函数让程序每帧有几毫秒的延迟,这样就能实际看清每个多边形。调用Sleep时,参数表示程序应当暂停的毫秒数,暂停过后,程序接着就自动继续运行。
    默然:下面公布GDI_Ploygon2的源代码,由