打印

最近研究心得

[复制链接]
12920|83
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
农民讲习所|  楼主 | 2008-1-2 10:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近研究Directx9.0做的游戏,发觉就是标准的前后台,呵呵。

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      "D3D Tutorial", NULL };
    RegisterClassEx( &wc );

    // Create the application's window
    HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              GetDesktopWindow(), NULL, wc.hInstance, NULL );

    // Initialize Direct3D
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // Create the vertex buffer
        if( SUCCEEDED( InitVB() ) )
        {
            // Show the window
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // Enter the message loop
            MSG msg;
            ZeroMemory( &msg, sizeof(msg) );

            while( msg.message!=WM_QUIT )        //此处循环,包含WINDOW系统使用的消息处理和游戏的主循环
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();       //此处就是游戏的主循环处,单片机中的main主循环
            }
        }
    }

    UnregisterClass( "D3D Tutorial", wc.hInstance );
    return 0;
}

相关帖子

来自 2楼
hotpower| | 2008-1-2 23:37 | 只看该作者

俺总觉得IceAge每句话都是真理~~~

int CVICALLBACK WriteThreadCallBack (HotCommStruct * HotCommStructPtr)
{
    memset (&HotCommStructPtr->HotCommWriteEvent, 0, sizeof(OVERLAPPED));
    HotCommStructPtr->HotCommWriteEvent.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
    if (HotCommStructPtr->HotCommWriteEvent.hEvent == 0)
    {
        HotCommRequestHangupEvent (HotCommStructPtr);
        goto EndWriteThread;
    }
    HotCommStructPtr->CompleteOneWriteRequire = TRUE;
    while(HotCommStructPtr->WriteThreadExec)
    {
        //取出HandleWriteCommData()发送过来的设备写入消息命令,消息处理后退出队列
        if (!PeekMessage (&HotCommStructPtr->WriteThreadMsg,//写线程的消息结构指针
                                             0,//消息被检查的窗口句柄
                                             0,//首个被检查的消息
                                             0,//最后1个被检查的消息 
                                             PM_REMOVE))//消息处理后将其消息退出队列
        {
            HotCommStructPtr->SendDataEmpty = TRUE;//发送缓冲区数据空 
            if (HotCommStructPtr->CompleteOneWriteRequire)
            {
                if (!PostThreadMessage ((DWORD)HotCommStructPtr->HotCommThreadFunctionId,
                                    (UINT)HOTCOMM_SENDDATAEMPTY,//用户发送数据区空
                                    (WPARAM)HotCommStructPtr->CommPort,//当前串口号
                                    (LPARAM)0))//
                {//发送消息失败
//                    HotCommStructPtr->CommError = -8;//串口未打开
//////                    HotCommErrorEvent (HotCommStructPtr, -8);//发送串口打开错误消息
//                    HotCommRequestHangupEvent (HotCommStructPtr);
//                    goto EndWriteThread;//千万不能退出
                }
            }
            HotCommStructPtr->CompleteOneWriteRequire = FALSE;
            HotCommStructPtr->dwWriteHandleSignaled = MsgWaitForMultipleObjects ((DWORD)1, 
                                                                                 (HANDLE)&HotCommStructPtr->hCloseEvent, 
                                                                                 (BOOL)FALSE, 
                                                                                 (DWORD)INFINITE, 
                                                                                 (DWORD)QS_ALLINPUT);
            switch (HotCommStructPtr->dwWriteHandleSignaled)
            {
                case WAIT_OBJECT_0://关闭串口事件发生
                    goto EndWriteThread;
                case WAIT_OBJECT_0 + 1:
                    continue;
                case WAIT_FAILED:
                    HotCommRequestHangupEvent (HotCommStructPtr);
                    goto EndWriteThread;
                default:
                    HotCommRequestHangupEvent (HotCommStructPtr);
                    goto EndWriteThread; 
            }
        }
        if (WaitForSingleObject (HotCommStructPtr->hCloseEvent, 0) != WAIT_TIMEOUT)
        {
            goto EndWriteThread;
        }
        if (HotCommStructPtr->WriteThreadMsg.hwnd != 0)
        {
            //将虚拟键消息转换为字符消息,字符消息被寄送到调用线程的消息队列里,
            //下次线程调用GetMessage()或PeekMessage()时被读出
            TranslateMessage (&HotCommStructPtr->WriteThreadMsg);
            //调度一个消息给窗口
            DispatchMessage (&HotCommStructPtr->WriteThreadMsg);
            continue;
        }
        switch (HotCommStructPtr->WriteThreadMsg.message)
        {
            //执行设备写入消息命令
            case HOTCOMM_SENDDATA:
                if (!(HandleWriteData (HotCommStructPtr, (void *)HotCommStructPtr->WriteThreadMsg.lParam, (DWORD)HotCommStructPtr->WriteThreadMsg.wParam)))
                {//发送失败
                    HotCommRequestHangupEvent (HotCommStructPtr);
//                    goto EndWriteThread;//不应该退出线程,这里是SPCOMM的不是了!!!
                }
                else
                {
                    HotCommStructPtr->CompleteOneWriteRequire = TRUE;//用户成功接收到数据
                }
                PostThreadMessage ((DWORD)HotCommStructPtr->HotCommThreadFunctionId,
                                    (UINT)HOTCOMM_SENDSUCCEED,//用户发送数据成功 
                                    (WPARAM)HotCommStructPtr->CommPort,
                                    (LPARAM)HotCommStructPtr);

                break;
        }
    }
EndWriteThread:
    PurgeComm(HotCommStructPtr->hCommFile, PURGE_TXABORT  //中断所有未完成的写操作 
                                         + PURGE_TXCLEAR);//清空输出缓冲区
    CloseHandle(HotCommStructPtr->HotCommWriteEvent.hEvent);
    return 0;
}

使用特权

评论回复
来自 3楼
农民讲习所|  楼主 | 2008-1-7 14:23 | 只看该作者

在WINDOW上玩MCU的结果

观察串口打开、关闭、发送、接收,可以使用串口侦听软件,比如:http://www.sudt.com的SerialTrace,这个不错。

完全按照裸奔方式设计的仿MCU的WINDOW程序,以后可能只要会MCU就可设计WINDOW程序,可能......

有关MCU部分,RainLib_Base.lib, RainLib_Unsiversal.lib, RainLib_Driver.lib被封装好,按MCU玩WINDOW游戏程序,很简单了。

代码:main.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Main.h"

#include "..\WinTools\RainLib_WinTools.h"
#include "..\Base\RainLib_Base.h"
#include "..\Unsiversal\RainLib_Unsiversal.h"
#include "..\Driver\RainLib_Driver.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
struct CommunicateQueue *psCommunicateQueue_Uart8;          //串口1

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

//main.c必须提供
void _stdcall CallBack_5msInterrupt( void )
{
}

//main.c必须提供
void _stdcall CallBack_20msInterrupt( void )
{
}

//---------------------------------------------------------------------------
//窗口初始化
//---------------------------------------------------------------------------
void __fastcall TForm1::MainFormInit( void )
{
    this->ClientWidth = Ini_Read( "LCD", "ScreenWidth", 640 );
    this->ClientHeight = Ini_Read( "LCD", "ScreenHeight", 480 );
}

//---------------------------------------------------------------------------
//主初始化
//---------------------------------------------------------------------------
void __fastcall TForm1::MainInit( void )
{
    WinToolsLib_Init( "RainLib.ini" );                              //INI文件名
    this->MainFormInit();

    BaseLib_Init( Ini_Read( "MSG", "BufferMax", 5000 ) );           //消息队列大小
    UnsiversalLib_Init( Ini_Read( "PACKAGE", "PackageMax", 2 ) );   //使用包解析的任务数
    DriverLib_Init( this->ClientWidth, this->ClientHeight );

    psCommunicateQueue_Uart8 = CommunicateQueue_Register( 200, 200, NULL);
    if( Uart8_Setup( 1, psCommunicateQueue_Uart8, B38400, BIT_8|STOP_1|P_NONE ) == false )
    {
        Application->MessageBoxA( "打开串口错误", "程序中断退出!", MB_OK );
        Application->Terminate();
    }

    //lcd
    U8 *p = DrvLcd_FramePagePoint(1);
    for( int i=0; i<this->ClientHeight*2; i++ )
    {
        for( int j=0; j<this->ClientWidth; j++ )
        {
            *p++ = i;           
        }
    }

    //开始运行程序
    Msg_RunInit();
    this->Show();
}

//---------------------------------------------------------------------------
//析构
//---------------------------------------------------------------------------
void __fastcall TForm1::MainDestory( void )
{
    DriverLib_Destory();
    UnsiversalLib_Destory();
    BaseLib_Destory();
    WinToolsLib_Destory();
}

//---------------------------------------------------------------------------
//主循环
//---------------------------------------------------------------------------
void __fastcall TForm1::MainLoop( void )
{
    static bool bTestLcdMove = false;
    static U8 mCounter = 0;
    static int my = 0;

    BaseLib_MainLoop();
    UnsiversalLib_MainLoop();
    DriverLib_MainLoop();
    WinToolsLib_MainLoop();

    if( sSysTimer.bSysTouch )
    {
        if( ++mCounter >= 2 )
        {
            //20ms * 2时间进入
            mCounter = 0;

            if( bTestLcdMove )
            {
                my--;
                if( my == 0 )
                {
                    bTestLcdMove = false;
                }
            }
            else {
                my++;
                if( my == (this->ClientHeight-1) )
                {
                    bTestLcdMove = true;
                }
            }

            DrvLcd_FrameOffset( my );
            DrvLcd_RefreshToForm( this->Canvas, Rect(0, 0, this->ClientWidth, this->ClientHeight) );

            //向串口发送my位置
            CommunicateQueue_Push( psCommunicateQueue_Uart8, (U8)my );
            CommunicateQueue_Push( psCommunicateQueue_Uart8, (U8)(my/256) );
        }
    }
}


RainLibMain.cpp:WINDOW调用
//---------------------------------------------------------------------------

#include <vcl.h>
#include "Main.h"
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("Main.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
        Application->Initialize();
        Application->CreateForm(__classid(TForm1), &Form1);
        Form1->MainInit();            //主初始化

        MSG msg;
        ZeroMemory( &msg, sizeof(msg) );
        while( msg.message != WM_QUIT )
        {
            if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
            {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
            else
            {
                Form1->MainLoop();        //主循环
            }
        }
        Form1->MainDestory();
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}
//---------------------------------------------------------------------------

使用特权

评论回复
地板
xwj| | 2008-1-2 11:03 | 只看该作者

哈哈,老农研究的啥游戏啊?

是这样的,
越是强调性能、需要大运算量的游戏越应该分层次处理,
把不通的东西丢给不同层的“引擎”甚至四不同的硬件来处理

而应用层的东西,只需要调用api既可

使用特权

评论回复
5
农民讲习所|  楼主 | 2008-1-2 11:14 | 只看该作者

俺准备将嵌入裸奔用DIRECTX9.0移植到WINDOW上

呵呵,俺用ARM9做的程序,只要改改驱动,就可以当作游戏程序一样移植到WINDOW上,这样不用再重新开发。

使用特权

评论回复
6
yewuyi| | 2008-1-2 11:15 | 只看该作者

怎么研究上那个了?

从那看到的代码?

使用特权

评论回复
7
农民讲习所|  楼主 | 2008-1-2 11:16 | 只看该作者

俺是自下而上开发的

从农民到将军

使用特权

评论回复
8
农民讲习所|  楼主 | 2008-1-2 11:17 | 只看该作者

DirectX 9 SDK for Borland C++ Builder

最简单的3D例子:
DX9 for BCB\SAMPLES\Direct3D\Tutorials\Tut02_Vertices

可以到http://blog.csdn.net/yanjun_1982/archive/2005/09/20/485319.aspx看看入门

使用特权

评论回复
9
mohanwei| | 2008-1-2 11:24 | 只看该作者

框架基本都是前后台的。像用MFC一样,对于程序员来说

好像是“基于消息”,但是打开框架一看,就是“前后台”。

使用特权

评论回复
10
农民讲习所|  楼主 | 2008-1-2 19:57 | 只看该作者

又有新的发现

俺发现用嵌入裸奔实现的WINDOW程序,占用CPU一直在50%左右,很奇怪,不多也不少。

实现方法:将WINDOW的WinMain函数中Application->Run()用下面替换就行

  Form1->MainInit();            //主初始化
  Form1->Show();

  MSG msg;
  ZeroMemory( &msg, sizeof(msg) );
  
  while( msg.message!=WM_QUIT )
  {
     if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
     {
         TranslateMessage( &msg );
         DispatchMessage( &msg );
     }
     Form1->MainLoop();            //主循环
   }

   Form1->Destory();

   和MCU中的处理方式一模一样了。估计游戏都是这么设计的。

但为什么CPU占有率一直50%?奇怪。

使用特权

评论回复
11
ra_rabbit| | 2008-1-2 22:09 | 只看该作者

听听天书

使用特权

评论回复
12
IceAge| | 2008-1-2 23:29 | 只看该作者

50%

可能是你的 mainloop 里的没有出让 cpu.

mainloop 循环等待时也可以使用

if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE )){
   TranslateMessage( &msg );
   DispatchMessage( &msg );
}

使用特权

评论回复
13
农民讲习所|  楼主 | 2008-1-3 07:22 | 只看该作者

mainloop中很简单,就是要不出让CPU

Label1->Caption = i++;

俺原来想应该远>50%,否则游戏性能怎么提升的?难道要开线程?

使用特权

评论回复
14
fsaok| | 2008-1-3 07:38 | 只看该作者

继续关注中

使用特权

评论回复
15
aweyfan| | 2008-1-3 09:07 | 只看该作者

所长的问题是PeekMessage造成的

应当避免使用PeekMessage,而使用GetMessage,不过这样你的前后台就跑不起来了,哈哈

使用特权

评论回复
16
农民讲习所|  楼主 | 2008-1-3 09:07 | 只看该作者

有意思

俺打开Directx9.0的例子程序,发现CPU占有率都是50%,很有意思。
俺再开线程测试测试

使用特权

评论回复
17
农民讲习所|  楼主 | 2008-1-3 09:09 | 只看该作者

请教aweyfan

为什么PeekMessage会这样?估计也只能是它的原因。去看看帮助先。

使用特权

评论回复
18
aweyfan| | 2008-1-3 09:09 | 只看该作者

所长是否用双核

PeekMessage 会造成100%

使用特权

评论回复
19
农民讲习所|  楼主 | 2008-1-3 09:16 | 只看该作者

呵呵,明白了

就是双核的原因,谢谢aweyfan!

还有问题,双核下如何编程提高CPU占用率?估计这个难度高,开线程测试先。

使用特权

评论回复
20
dld2| | 2008-1-3 09:19 | 只看该作者

哈哈有意思

一个进程能同时占用两个核吗

使用特权

评论回复
21
农民讲习所|  楼主 | 2008-1-3 10:13 | 只看该作者

俺开线程测试,占用CPU98%-99%

WINDOW下主循环看来要开个线程来做才合适。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

1275

帖子

15

粉丝