zoukankan      html  css  js  c++  java
  • 29 GameProject4(+GUI)

    main.h头文件包含了用于GUI系统和控件的define语句。这里将在游戏源文件中添加3个新函数,它们分别是InitializeMainMenu()、MainMenuCallback()和MainMenuRender()。其中InitializeMainMenu()由GameInitialize()函数调用,将整个GUI的主菜单加载到内存中。MainMenuRender()由GameLoop()函数调用,借助渲染系统将主菜单显示在屏幕上。函数MainMenuCallback()是GUI系统的回调函数,对按钮动作做出响应。

    main.h

    #ifndef _UGP_MAIN_H_
    #define _UGP_MAIN_H_


    #include
    "StrandedEngine/engine.h"
    #pragma comment(lib, "lib/StrandedEngine.lib")

    #define WINDOW_CLASS "StrandedGame"
    #define WINDOW_NAME "Stranded"
    #define WIN_WIDTH 800
    #define WIN_HEIGHT 600
    #define FULLSCREEN 1

    // Function Prototypes...
    bool InitializeEngine();
    void ShutdownEngine();

    // Menu functions.
    bool InitializeMainMenu();
    void MainMenuCallback(int id, int state);
    void MainMenuRender();

    // Main game functions.
    bool GameInitialize();
    void GameLoop();
    void GameShutdown();

    // Main menu defines. GUI_FRAME
    #define GUI_MAIN_SCREEN 1
    #define GUI_START_SCREEN 2
    #define GUI_CREDITS_SCREEN 3

    // ids for our GUI controls.
    #define STATIC_TEXT_ID 1
    #define BUTTON_START_ID 2
    #define BUTTON_CREDITS_ID 3
    #define BUTTON_QUIT_ID 4
    #define BUTTON_BACK_ID 5
    #define BUTTON_LEVEL_1_ID 6

    #endif

      

    main.cpp

    #include"main.h"


    // Globals...
    HWND g_hwnd;
    CRenderInterface
    *g_Render = NULL;

    // GUI ids.
    int g_mainGui = -1;
    int g_startGui = -1;
    int g_creditsGui = -1;
    int g_currentGUI = GUI_MAIN_SCREEN;

    // Font id.
    int g_arialID = -1;

    // Temp Mouse state information.
    bool LMBDown = false;
    int mouseX = 0, mouseY = 0;


    LRESULT WINAPI MsgProc(HWND hd, UINT msg, WPARAM wp, LPARAM lp)
    {
    switch(msg)
    {
    case WM_DESTROY:
    PostQuitMessage(
    0);
    return 0;
    break;

    case WM_KEYUP:
    if(wp == VK_ESCAPE) PostQuitMessage(0);
    break;

    case WM_LBUTTONDOWN:
    LMBDown
    = true;
    break;

    case WM_LBUTTONUP:
    LMBDown
    = false;
    break;

    case WM_MOUSEMOVE:
    mouseY
    = HIWORD (lp);
    mouseX
    = LOWORD (lp);
    break;
    }

    return DefWindowProc(hd, msg, wp, lp);
    }


    int WINAPI WinMain(HINSTANCE h, HINSTANCE p, LPSTR cmd, int show)
    {
    // Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc,
    0L, 0L, GetModuleHandle(NULL), NULL, NULL,
    NULL, NULL, WINDOW_CLASS, NULL };
    RegisterClassEx(
    &wc);

    // Create the application's window
    if(FULLSCREEN)
    {
    g_hwnd
    = CreateWindowEx(NULL, WINDOW_CLASS, WINDOW_NAME,
    WS_POPUP
    | WS_SYSMENU | WS_VISIBLE, 0, 0,
    WIN_WIDTH, WIN_HEIGHT,
    NULL, NULL, h, NULL);
    }
    else
    {
    g_hwnd
    = CreateWindowEx(NULL, WINDOW_CLASS, WINDOW_NAME,
    WS_OVERLAPPEDWINDOW
    | WS_VISIBLE, 0,
    0, WIN_WIDTH, WIN_HEIGHT,
    NULL, NULL, h, NULL);
    }

    if(g_hwnd)
    {
    // Show the window
    ShowWindow(g_hwnd, SW_SHOWDEFAULT);
    UpdateWindow(g_hwnd);
    }

    // Initialize the Stranded Engine.
    if(InitializeEngine())
    {
    // Initialize Stranded game.
    if(GameInitialize())
    {
    // Enter the message loop
    MSG msg;
    ZeroMemory(
    &msg, sizeof(msg));

    SetCursorPos(
    0, 0);

    while(msg.message != WM_QUIT)
    {
    if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
    TranslateMessage(
    &msg);
    DispatchMessage(
    &msg);
    }
    else
    GameLoop();
    }
    }
    }

    // Release any and all resources.
    GameShutdown();
    ShutdownEngine();

    UnregisterClass(WINDOW_CLASS, wc.hInstance);
    return 0;
    }


    bool InitializeEngine()
    {
    if(!CreateD3DRenderer(&g_Render)) return false;

    if(!g_Render->Initialize(WIN_WIDTH, WIN_HEIGHT,
    g_hwnd, FULLSCREEN))
    return false;

    g_Render
    ->SetClearCol(0, 0, 0);

    // 创建渲染静态文本用的字体
    if(!g_Render->CreateText("Arial", 0, true, 18, g_arialID))
    return false;

    return true;
    }


    void ShutdownEngine()
    {
    if(g_Render)
    {
    g_Render
    ->Shutdown();
    delete g_Render;
    g_Render
    = NULL;
    }
    }


    bool InitializeMainMenu()
    {
    // Create gui screens.
    if(!g_Render->CreateGUI(g_mainGui)) return false;
    if(!g_Render->CreateGUI(g_startGui)) return false;
    if(!g_Render->CreateGUI(g_creditsGui)) return false;

    // Load backdrops.
    if(!g_Render->AddGUIBackdrop(g_mainGui, "menu/mainMenu.jpg"))
    return false;
    if(!g_Render->AddGUIBackdrop(g_startGui, "menu/startMenu.jpg"))
    return false;
    if(!g_Render->AddGUIBackdrop(g_creditsGui,
    "menu/creditsMenu.jpg")) return false;

    // Set main screen elements.
    if(!g_Render->AddGUIStaticText(g_mainGui, STATIC_TEXT_ID,
    "Version: 1.0", PERCENT_OF(WIN_WIDTH, 0.85),
    PERCENT_OF(WIN_WIDTH,
    0.05),
    UGPCOLOR_ARGB(
    255,255,255,255), g_arialID)) return false;

    if(!g_Render->AddGUIButton(g_mainGui, BUTTON_START_ID,
    PERCENT_OF(WIN_WIDTH,
    0.05), PERCENT_OF(WIN_HEIGHT, 0.40),
    "menu/startUp.png", "menu/StartOver.png",
    "menu/startDown.png")) return false;

    if(!g_Render->AddGUIButton(g_mainGui, BUTTON_CREDITS_ID,
    PERCENT_OF(WIN_WIDTH,
    0.05), PERCENT_OF(WIN_HEIGHT, 0.50),
    "menu/creditsUp.png", "menu/creditsOver.png",
    "menu/creditsDown.png")) return false;

    if(!g_Render->AddGUIButton(g_mainGui, BUTTON_QUIT_ID,
    PERCENT_OF(WIN_WIDTH,
    0.05), PERCENT_OF(WIN_HEIGHT, 0.60),
    "menu/quitUp.png", "menu/quitOver.png",
    "menu/quitDown.png")) return false;


    // Set start screen elements.
    if(!g_Render->AddGUIButton(g_startGui, BUTTON_LEVEL_1_ID,
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.15),
    "menu/level1Up.png", "menu/level1Over.png",
    "menu/level1Down.png")) return false;

    if(!g_Render->AddGUIButton(g_startGui, BUTTON_BACK_ID,
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.80),
    "menu/backUp.png", "menu/backOver.png",
    "menu/backDown.png")) return false;


    // Set credits screen elements.
    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    "Game Design -",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.15),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Allen Sherrod",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.20),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    "Programming -",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.25),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Allen Sherrod",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.30),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    "Sound -",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.35),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Allen Sherrod",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.40),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    "Level Design -",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.45),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Allen Sherrod",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.50),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    "Speical Thanks -",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.55),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Jenifer Niles",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.60),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Bryan Davidson",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.65),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Charles River Media",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.70),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIStaticText(g_creditsGui, STATIC_TEXT_ID,
    " Readers of this book",
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.75),
    UGPCOLOR_ARGB(
    255,255,255,255),
    g_arialID))
    return false;

    if(!g_Render->AddGUIButton(g_creditsGui, BUTTON_BACK_ID,
    PERCENT_OF(WIN_WIDTH,
    0.1), PERCENT_OF(WIN_HEIGHT, 0.80),
    "menu/backUp.png", "menu/backOver.png",
    "menu/backDown.png")) return false;

    return true;
    }


    void MainMenuCallback(int id, int state)
    {
    switch(id)
    {
    case BUTTON_START_ID:
    if(state == UGP_BUTTON_DOWN)
    g_currentGUI
    = GUI_START_SCREEN;
    break;

    case BUTTON_CREDITS_ID:
    if(state == UGP_BUTTON_DOWN)
    g_currentGUI
    = GUI_CREDITS_SCREEN;
    break;

    case BUTTON_BACK_ID:
    if(state == UGP_BUTTON_DOWN)
    g_currentGUI
    = GUI_MAIN_SCREEN;
    break;

    case BUTTON_QUIT_ID:
    if(state == UGP_BUTTON_DOWN)
    PostQuitMessage(
    0);
    break;

    case BUTTON_LEVEL_1_ID:
    // Start first level.
    break;
    }
    }


    void MainMenuRender()
    {
    if(!g_Render) return;

    g_Render
    ->StartRender(1, 1, 0);

    if(g_currentGUI == GUI_MAIN_SCREEN)
    g_Render
    ->ProcessGUI(g_mainGui, LMBDown, mouseX, mouseY, MainMenuCallback);
    else if(g_currentGUI == GUI_START_SCREEN)
    g_Render
    ->ProcessGUI(g_startGui, LMBDown, mouseX, mouseY, MainMenuCallback);
    else
    g_Render
    ->ProcessGUI(g_creditsGui, LMBDown, mouseX, mouseY, MainMenuCallback);

    g_Render
    ->EndRendering();
    }


    bool GameInitialize()
    {
    if(!InitializeMainMenu()) return false;

    return true;
    }


    void GameLoop()
    {
    MainMenuRender();
    }


    void GameShutdown()
    {

    }

      

    defines.h

    #ifndef _UGP_DEFINES_H_
    #define _UGP_DEFINES_H_

    #include
    <windows.h>

    #define PERCENT_OF(a, b) (int)(a * b)

    // Boolean values.
    #define UGP_INVALID -1
    #define UGP_OK 1
    #define UGP_FAIL 0

    // Vertex formats. GUI控件矩形的灵活顶点格式
    #define GUI_FVF 2

    // Types of controls we support.
    #define UGP_GUI_STATICTEXT 1
    #define UGP_GUI_BUTTON 2
    #define UGP_GUI_BACKDROP 3

    // Mouse button states.
    #define UGP_BUTTON_UP 1
    #define UGP_BUTTON_OVER 2
    #define UGP_BUTTON_DOWN 3

    // Light type defines.
    #define LIGHT_POINT 1
    #define LIGHT_DIRECTIONAL 2
    #define LIGHT_SPOT 3

    // Window handle (need new way if porting to Mac and OpenGL).
    #define WinHWND HWND

    // Typedefs and enumerations.
    typedef long VertexType;

    enum PrimType
    {
    NULL_TYPE,
    POINT_LIST,
    TRIANGLE_LIST,
    TRIANGLE_STRIP,
    TRIANGLE_FAN,
    LINE_LIST,
    LINE_STRIP
    };

    enum RenderState
    {
    CULL_NONE,
    CULL_CW,
    CULL_CCW,
    DEPTH_NONE,
    DEPTH_READONLY,
    DEPTH_READWRITE,
    SHADE_POINTS,
    SHADE_SOLIDTRI,
    SHADE_WIRETRI,
    SHADE_WIREPOLY,
    TRANSPARENCY_NONE,
    TRANSPARENCY_ENABLE
    };

    enum TransState
    {
    TRANS_ZERO
    = 1,
    TRANS_ONE,
    TRANS_SRCCOLOR,
    TRANS_INVSRCCOLOR,
    TRANS_SRCALPHA,
    TRANS_INVSRCALPHA,
    TRANS_DSTALPHA,
    TRANS_INVDSTALPHA,
    TRANS_DSTCOLOR,
    TRANS_INVDSTCOLOR,
    TRANS_SRCALPHASAT,
    TRANS_BOTHSRCALPHA,
    TRANS_INVBOTHSRCALPHA,
    TRANS_BLENDFACTOR,
    TRANS_INVBLENDFACTOR
    };

    enum TextureState
    {
    MIN_FILTER,
    MAG_FILTER,
    MIP_FILTER
    };

    enum FilterType
    {
    POINT_TYPE,
    LINEAR_TYPE,
    ANISOTROPIC_TYPE
    };

    // Color defines.
    #define UGPCOLOR_ARGB(a,r,g,b) ((unsigned long)((((a)&0xff)<<24)|\
    (((r)
    &0xff)<<16)|(((g)&0xff)<<8)|\
    ((b)
    &0xff)))

    #endif

      

    engine.h

    #ifndef _UGP_ENGINE_H_
    #define _UGP_ENGINE_H_

    #include
    "structs.h"
    #include
    "RenderInterface.h"
    #include
    "D3DRenderer.h"
    #include
    "light.h"
    #include
    "material.h"

    #endif

      

    structs.h

    #ifndef _UGP_STRUCTS_H_
    #define _UGP_STRUCTS_H_


    // A structure for our custom vertex type.
    struct stGUIVertex
    {
    float x, y, z, rhw;
    unsigned
    long color;
    float tu, tv;
    };

    #endif

      

    GUI.h

    #ifndef _UGP_D3D_GUI_H_
    #define _UGP_D3D_GUI_H_

    #include
    "defines.h"


    struct stGUIControl
    {
    // 控件类型
    int m_type;
    // 控件id
    int m_id;
    // 控件颜色(仅用于静态文本)
    unsigned long m_color;

    // 静态文本:字体id;按钮,背景图:静态几何图形缓存中的id
    int m_listID;

    // 左上角的x,y坐标(用于静态文本和按钮)
    int m_xPos, m_yPos;

    // 按钮的宽高(仅用于按钮)
    int m_width, m_height;

    //静态文本的内容
    char *m_text;

    // 按钮弹起、按下、鼠标在按钮上时分别显示的纹理的id;
    // 当控件类型是背景图时,用m_upTex存储纹理id
    int m_upTex, m_downTex, m_overTex;
    };

    // 渲染系统将负责字体和静态几何图形缓存的创建、删除和管理。
    class CGUISystem
    {
    public:
    CGUISystem() : m_controls(
    0), m_totalControls(0), m_backDropID(-1) {}
    ~CGUISystem() { Shutdown(); }

    // 向控件链表中加一个空的控件对象
    int IncreaseControls();

    // 添加背景图
    // @texID 背景图的纹理ID
    // @staticID 存储背景图几何形状的静态缓存ID
    bool AddBackdrop(int texID, int staticID);

    // 添加静态文本控件
    // @id 控件id
    // @text 文本内容
    // @x 文本的起始x坐标
    // @y 文本的起始y坐标
    // @color 文本颜色
    // @fontID 文本用到的字体id(在字体链表中的索引)
    bool AddStaticText(int id, char *text, int x, int y, unsigned long color, int fontID);

    // @id 控件id
    // @x 左上角的x坐标
    // @y 左上角的y坐标
    // @width 按钮宽度
    // @height 按钮高度
    // @ upID 按钮弹起时的纹理id
    // @overID 鼠标在按钮上时的纹理id
    // @downID 按钮按下时的纹理id
    // @staticID 显示按钮几何形状的静态缓存ID
    bool AddButton(int id, int x, int y, int width, int height,
    int upID, int overID, int downID, unsigned int staticID);

    // 清理资源
    void Shutdown();

    stGUIControl
    *GetGUIControl(int id)
    {
    if(id < 0 || id >= m_totalControls) return NULL;
    return &m_controls[id];
    }

    int GetTotalControls()
    {
    return m_totalControls;
    }

    stGUIControl
    *GetBackDrop()
    {
    if(m_backDropID >= 0 && m_totalControls)
    return &m_controls[m_backDropID];
    return NULL;
    }

    private:
    // 控件链表头指针
    stGUIControl *m_controls;
    // 控件总数
    int m_totalControls;
    // 背景纹理的id(索引)
    int m_backDropID;
    };

    #endif

      

    GUI.cpp

    #include"GUI.h"


    int CGUISystem::IncreaseControls()
    {
    if(!m_controls)
    {
    m_controls
    = new stGUIControl[1];
    if(!m_controls) return UGP_FAIL;
    memset(
    &m_controls[0], 0, sizeof(stGUIControl));
    }
    else
    {
    stGUIControl
    *temp;
    temp
    = new stGUIControl[m_totalControls + 1];
    if(!temp) return UGP_FAIL;
    memset(temp,
    0, sizeof(stGUIControl) * (m_totalControls + 1));

    memcpy(temp, m_controls,
    sizeof(stGUIControl) * m_totalControls);

    delete[] m_controls;
    m_controls
    = temp;
    }

    return UGP_OK;
    }


    bool CGUISystem::AddBackdrop(int texID, int sID)
    {
    if(texID < 0 || sID < 0) return false;

    // 若之前没背景图则把texID当做背景图,否则直接修改原来的背景图的id
    if(m_backDropID < 0)
    {
    // Create a blank control.
    if(!IncreaseControls()) return false;

    // Fill in necessary info.
    m_controls[m_totalControls].m_type = UGP_GUI_BACKDROP;
    m_controls[m_totalControls].m_upTex
    = texID;
    m_controls[m_totalControls].m_listID
    = sID;

    // Keep track which index is backdrop.
    // Allows us to render backdrop first without
    // having to have added it first.
    m_backDropID = m_totalControls;

    // Increment total.
    m_totalControls++;
    }
    else
    {
    // Else just override the tex id and static buffer id.
    m_controls[m_backDropID].m_upTex = texID;
    m_controls[m_backDropID].m_listID
    = sID;
    }

    return true;
    }


    bool CGUISystem::AddStaticText(int id, char *text, int x, int y,
    unsigned
    long color, int fontID)
    {
    if(!text || fontID < 0) return false;

    // Create a blank control.
    if(!IncreaseControls()) return false;

    // Fill it with all the info we need for static text.
    m_controls[m_totalControls].m_type = UGP_GUI_STATICTEXT;
    m_controls[m_totalControls].m_id
    = id;
    m_controls[m_totalControls].m_color
    = color;
    m_controls[m_totalControls].m_xPos
    = x;
    m_controls[m_totalControls].m_yPos
    = y;
    m_controls[m_totalControls].m_listID
    = fontID;

    // Copy text data.
    int len = strlen(text);
    m_controls[m_totalControls].m_text
    = new char[len + 1];
    if(!m_controls[m_totalControls].m_text) return false;
    memcpy(m_controls[m_totalControls].m_text, text, len);
    m_controls[m_totalControls].m_text[len]
    = '\0';

    // Increment total.
    m_totalControls++;

    return true;
    }


    bool CGUISystem::AddButton(int id, int x, int y, int width,
    int height, int upID, int overID,
    int downID, unsigned int staticID)
    {
    // Create a blank control.
    if(!IncreaseControls()) return false;

    // Set all the data needed to render/process a button.
    m_controls[m_totalControls].m_type = UGP_GUI_BUTTON;
    m_controls[m_totalControls].m_id
    = id;
    m_controls[m_totalControls].m_xPos
    = x;
    m_controls[m_totalControls].m_yPos
    = y;
    m_controls[m_totalControls].m_width
    = width;
    m_controls[m_totalControls].m_height
    = height;
    m_controls[m_totalControls].m_upTex
    = upID;
    m_controls[m_totalControls].m_overTex
    = overID;
    m_controls[m_totalControls].m_downTex
    = downID;
    m_controls[m_totalControls].m_listID
    = staticID;

    // Increment total.
    m_totalControls++;

    return true;
    }


    void CGUISystem::Shutdown()
    {
    // Release all resources.
    for(int s = 0; s < m_totalControls; s++)
    {
    if(m_controls[s].m_text)
    {
    delete[] m_controls[s].m_text;
    m_controls[s].m_text
    = NULL;
    }
    }

    m_totalControls
    = 0;
    if(m_controls) delete[] m_controls;
    m_controls
    = NULL;
    }

      

    RenderInterface.h

    #ifndef _UGP_RENDERINTERFACE_H_
    #define _UGP_RENDERINTERFACE_H_

    #include
    "defines.h"
    #include
    "material.h"
    #include
    "light.h"
    #include
    "GUI.h"


    class CRenderInterface
    {
    public:
    CRenderInterface() : m_screenWidth(
    0),
    m_screenHeight(
    0), m_near(0), m_far(0) { }
    virtual ~CRenderInterface() {}

    virtual bool Initialize(int w, int h,
    WinHWND mainWin,
    bool fullScreen) = 0;
    virtual void OneTimeInit() = 0;
    virtual void Shutdown() = 0;


    virtual void SetClearCol(float r, float g, float b) = 0;
    virtual void StartRender(bool bColor, bool bDepth,
    bool bStencil) = 0;
    virtual void ClearBuffers(bool bColor, bool bDepth,
    bool bStencil) = 0;
    virtual void EndRendering() = 0;


    virtual void SetMaterial(stMaterial *mat) = 0;

    virtual void SetLight(stLight *light, int index) = 0;
    virtual void DisableLight(int index) = 0;


    virtual void SetDepthTesting(RenderState state) = 0;
    virtual void SetTransparency(RenderState state,
    TransState src, TransState dst)
    = 0;

    virtual int AddTexture2D(char *file, int *texId) = 0;
    virtual void SetTextureFilter(int index, int filter,
    int val) = 0;
    virtual void SetMultiTexture() = 0;
    virtual void ApplyTexture(int index, int texId) = 0;
    virtual void SaveScreenShot(char *file) = 0;

    virtual void EnablePointSprites(float size, float min,
    float a, float b, float c) = 0;
    virtual void DisablePointSprites() = 0;

    // 创建新字体
    // @font 字体名称
    // @weight 字体权重
    // @italic 是否为斜体
    // @size 字体大小
    // @id 字体在字体数组中的索引
    virtual bool CreateText(char *font, int weight, bool italic, int size, int &id) = 0;

    // 渲染静态文本
    // @id 字体的索引id
    // @x 文本起始x坐标
    // @y 文本的起始y坐标
    // @r,g,b 文本的颜色
    // @text 文本的内容
    virtual void DisplayText(int id, long x, long y, int r, int g, int b, char *text, ...) = 0;
    virtual void DisplayText(int id, long x, long y, unsigned long color, char *text, ...) = 0;

    // 创建一个新的GUI Frame
    // @id 新创建的GUI Frame在GUI数组中的索引id
    bool CreateGUI(int &id)
    {
    if(!m_guiList)
    {
    m_guiList
    = new CGUISystem[1];
    if(!m_guiList) return UGP_FAIL;
    }
    else
    {
    CGUISystem
    *temp;
    temp
    = new CGUISystem[m_totalGUIs + 1];

    memcpy(temp, m_guiList,
    sizeof(CGUISystem) * m_totalGUIs);

    delete[] m_guiList;
    m_guiList
    = temp;
    }

    id
    = m_totalGUIs;
    m_totalGUIs
    ++;

    return true;
    }

    // 向某gui中添加背景图
    // @guiId 目标gui的索引
    // @fileName 背景图索引
    virtual bool AddGUIBackdrop(int guiId, char *fileName) = 0;

    // 向某gui中添加静态文本
    // @guiId 目标gui的索引
    // @id 控件的id
    // @text 文本内容
    // @x 文本起始x坐标
    // @y 文本起始y坐标
    // @color 文本颜色
    // @fontID 用到的字体的索引id
    virtual bool AddGUIStaticText(int guiId, int id, char *text, int x, int y,
    unsigned
    long color, int fontID) = 0;

    // @guiId 目标gui的索引
    // @id 控件的id
    // @x 起始x坐标
    // @y 起始y坐标
    // @up 按钮弹起时的纹理的路径
    // @over 鼠标在按钮上时的纹理的路径
    // @down 按钮按下时的纹理的路径
    virtual bool AddGUIButton(int guiId, int id, int x, int y,
    char *up, char *over, char *down) = 0;

    // Render GUI
    // 函数以GUI对象ID为参数。并将GUI显示到屏幕上。该函数也要处理按钮状态,将GUI元素显示到屏幕上。
    // @guiId 目标gui的索引
    // @LMBDown 左键是否按下
    // @mouseX 鼠标当前位置的x坐标
    // @mouseY 鼠标当前位置的Y坐标
    // @funcPtr 回调函数指针
    // @id gui上的按钮控件的id
    // @state 按钮控件状态
    virtual void ProcessGUI(int guiID, bool LMBDown, int mouseX,
    int mouseY, void(*funcPtr)(int id, int state)) = 0;


    virtual void CalculateProjMatrix(float fov, float n,
    float f) = 0;
    virtual void CalculateOrthoMatrix(float n, float f) = 0;

    virtual int CreateStaticBuffer(VertexType, PrimType,
    int totalVerts, int totalIndices,
    int stride, void **data, unsigned int *indices,
    int *staticId) = 0;

    virtual int Render(int staticId) = 0;

    protected:
    int m_screenWidth;
    int m_screenHeight;
    bool m_fullscreen;

    // 字体总数
    int m_totalFonts;

    // GUI Frame的数组头指针
    CGUISystem *m_guiList;

    // GUI Frame的总数
    int m_totalGUIs;

    WinHWND m_mainHandle;

    float m_near;
    float m_far;
    };

    #endif

      

    D3DRenderer.h

    #ifndef _D3D_RENDERER_H_
    #define _D3D_RENDERER_H_

    #include
    <windows.h>
    #include
    <d3d9.h>
    #include
    <d3dx9.h>
    #include
    "RenderInterface.h"

    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")


    struct stD3DStaticBuffer
    {
    stD3DStaticBuffer() : vbPtr(
    0), ibPtr(0), numVerts(0),
    numIndices(
    0), stride(0), fvf(0),
    primType(NULL_TYPE) {}

    LPDIRECT3DVERTEXBUFFER9 vbPtr;
    LPDIRECT3DINDEXBUFFER9 ibPtr;
    int numVerts;
    int numIndices;
    int stride;
    unsigned
    long fvf;
    PrimType primType;
    };

    struct stD3DTexture
    {
    stD3DTexture() : fileName(
    0), image(0), width(0), height(0) {}

    char *fileName;
    int width, height;
    LPDIRECT3DTEXTURE9 image;
    };


    class CD3DRenderer : public CRenderInterface
    {
    public:
    CD3DRenderer();
    ~CD3DRenderer();

    bool Initialize(int w, int h, WinHWND mainWin,
    bool fullScreen);
    void Shutdown();

    void SetClearCol(float r, float g, float b);
    void StartRender(bool bColor, bool bDepth, bool bStencil);
    void ClearBuffers(bool bColor, bool bDepth, bool bStencil);
    void EndRendering();

    void SetMaterial(stMaterial *mat);

    void SetLight(stLight *light, int index);
    void DisableLight(int index);

    void SetDepthTesting(RenderState state);
    void SetTransparency(RenderState state, TransState src,
    TransState dst);

    int AddTexture2D(char *file, int *texId);
    void SetTextureFilter(int index, int filter, int val);
    void SetMultiTexture();
    void ApplyTexture(int index, int texId);
    void SaveScreenShot(char *file);

    void EnablePointSprites(float size, float min, float a,
    float b, float c);
    void DisablePointSprites();

    //
    bool CreateText(char *font, int weight, bool italic, int size, int &id);

    void DisplayText(int id, long x, long y, int r, int g, int b, char *text, ...);

    void DisplayText(int id, long x, long y, unsigned long color, char *text, ...);

    bool AddGUIBackdrop(int guiId, char *fileName);

    bool AddGUIStaticText(int guiId, int id, char *text, int x, int y, unsigned long color, int fontID);

    bool AddGUIButton(int guiId, int id, int x, int y, char *up, char *over, char *down);

    void ProcessGUI(int guiID, bool LMBDown, int mouseX, int mouseY, void(*funcPtr)(int id, int state));


    void CalculateProjMatrix(float fov, float n, float f);
    void CalculateOrthoMatrix(float n, float f);

    int CreateStaticBuffer(VertexType, PrimType,
    int totalVerts, int totalIndices,
    int stride, void **data, unsigned int *indices,
    int *staticId);

    int Render(int staticId);

    private:
    void OneTimeInit();


    private:
    D3DCOLOR m_Color;
    LPDIRECT3D9 m_Direct3D;
    LPDIRECT3DDEVICE9 m_Device;
    bool m_renderingScene;

    // 字体数组头指针
    LPD3DXFONT *m_fonts;
    // Total fonts in base class.

    stD3DStaticBuffer
    *m_staticBufferList;
    int m_numStaticBuffers;
    int m_activeStaticBuffer;

    stD3DTexture
    *m_textureList;
    int m_numTextures;
    };

    bool CreateD3DRenderer(CRenderInterface **pObj);

    #endif

      

    D3DRenderer.cpp

    bool CD3DRenderer::CreateText(char *font, int weight, bool italic,
    int size, int &id)
    {
    if(!m_fonts)
    {
    m_fonts
    = new LPD3DXFONT[1];
    if(!m_fonts) return UGP_FAIL;
    }
    else
    {
    LPD3DXFONT
    *temp;
    temp
    = new LPD3DXFONT[m_totalFonts + 1];

    memcpy(temp, m_fonts,
    sizeof(LPD3DXFONT) * m_totalFonts);

    delete[] m_fonts;
    m_fonts
    = temp;
    }

    if(FAILED(D3DXCreateFont(m_Device, size, 0, weight, 1, italic,
    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
    DEFAULT_QUALITY,
    DEFAULT_PITCH
    | FF_DONTCARE, font,
    &m_fonts[m_totalFonts]))) return false;

    id
    = m_totalFonts;
    m_totalFonts
    ++;

    return true;
    }


    void CD3DRenderer::DisplayText(int id, long x, long y,
    int r, int g, int b, char *text, ...)
    {
    RECT FontPosition
    = {x, y, m_screenWidth, m_screenWidth};
    char message[1024];
    va_list argList;

    if(id >= m_totalFonts) return;

    va_start(argList, text);
    vsprintf(message, text, argList);
    va_end(argList);

    m_fonts[id]
    ->DrawText(NULL, message, -1, &FontPosition, DT_SINGLELINE, D3DCOLOR_ARGB(255, r, g, b));
    }


    void CD3DRenderer::DisplayText(int id, long x, long y,
    unsigned
    long color, char *text, ...)
    {
    RECT FontPosition
    = {x, y, m_screenWidth, m_screenWidth};
    char message[1024];
    va_list argList;

    if(id >= m_totalFonts) return;

    va_start(argList, text);
    vsprintf(message, text, argList);
    va_end(argList);

    m_fonts[id]
    ->DrawText(NULL, message, -1, &FontPosition,
    DT_SINGLELINE, color);
    }


    bool CD3DRenderer::AddGUIBackdrop(int guiId, char *fileName)
    {
    if(guiId >= m_totalGUIs) return false;

    int texID = -1, staticID = -1;

    if(!AddTexture2D(fileName, &texID)) return false;

    unsigned
    long col = D3DCOLOR_XRGB(255,255,255);

    stGUIVertex obj[]
    =
    {
    {(
    float)m_screenWidth, 0, 0, 1, col, 1, 0},
    {(
    float)m_screenWidth, (float)m_screenHeight, 0, 1, col, 1, 1},
    {
    0, 0, 0, 1, col, 0, 0},
    {
    0, (float)m_screenHeight, 0, 1, col, 0, 1},
    };

    if(!CreateStaticBuffer(GUI_FVF, TRIANGLE_STRIP, 4, 0,
    sizeof(stGUIVertex), (void**)&obj, NULL,
    &staticID)) return false;

    return m_guiList[guiId].AddBackdrop(texID, staticID);
    }


    bool CD3DRenderer::AddGUIStaticText(int guiId, int id,
    char *text, int x, int y, unsigned long color, int fontID)
    {
    if(guiId >= m_totalGUIs) return false;

    return m_guiList[guiId].AddStaticText(id, text, x, y,
    color, fontID);
    }


    bool CD3DRenderer::AddGUIButton(int guiId, int id, int x,
    int y, char *up, char *over, char *down)
    {
    if(guiId >= m_totalGUIs) return false;

    int upID = -1, overID = -1, downID = -1, staticID = -1;

    if(!AddTexture2D(up, &upID)) return false;
    if(!AddTexture2D(over, &overID)) return false;
    if(!AddTexture2D(down, &downID)) return false;

    unsigned
    long col = D3DCOLOR_XRGB(255,255,255);

    int w = m_textureList[upID].width;
    int h = m_textureList[upID].height;

    stGUIVertex obj[]
    =
    {
    {(
    float)(w + x), (float)(0 + y), 0, 1, col, 1, 0},
    {(
    float)(w + x), (float)(h + y), 0, 1, col, 1, 1},
    {(
    float)(0 + x), (float)(0 + y), 0, 1, col, 0, 0},
    {(
    float)(0 + x), (float)(h + y), 0, 1, col, 0, 1},
    };

    if(!CreateStaticBuffer(GUI_FVF, TRIANGLE_STRIP, 4, 0,
    sizeof(stGUIVertex), (void**)&obj, NULL,
    &staticID)) return false;

    return m_guiList[guiId].AddButton(id, x, y, w, h, upID, overID,
    downID, staticID);
    }


    void CD3DRenderer::ProcessGUI(int guiId, bool LMBDown,
    int mouseX, int mouseY, void(*funcPtr)(int id, int state))
    {
    if(guiId >= m_totalGUIs || !m_Device) return;

    CGUISystem
    *gui = &m_guiList[guiId];
    if(!gui) return;

    // 必须先画背景图
    stGUIControl *backDrop = gui->GetBackDrop();

    // Draw backdrop first to control render order. Don't
    // want to draw this after buttons in 2D.
    if(backDrop)
    {
    // 设置纹理对象
    ApplyTexture(0, backDrop->m_upTex);
    // 渲染该纹理到m_listID对应的静态缓存对应的几何形状
    Render(backDrop->m_listID);
    // 渲染完该纹理后清空当前纹理对象
    ApplyTexture(0, -1);
    }

    // Initial button state.
    int status = UGP_BUTTON_UP;

    // 遍历GUI控件对象数组,并逐个渲染 Loop through all controls and display them.
    for(int i = 0; i < gui->GetTotalControls(); i++)
    {
    // Get the current control.
    stGUIControl *pCnt = gui->GetGUIControl(i);
    if(!pCnt) continue;

    // Take action depending on what type it is.
    switch(pCnt->m_type)
    {
    case UGP_GUI_STATICTEXT:
    DisplayText(pCnt
    ->m_listID, pCnt->m_xPos, pCnt->m_yPos, pCnt->m_color, pCnt->m_text);
    break;

    case UGP_GUI_BUTTON:
    status
    = UGP_BUTTON_UP;
    // Set alpha transparency on for the texture image.
    m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    m_Device
    ->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    m_Device
    ->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    // Check if over the button or pressing it.
    if(mouseX > pCnt->m_xPos && mouseX <
    (pCnt
    ->m_xPos + pCnt->m_width) &&
    mouseY
    > pCnt->m_yPos && mouseY <
    (pCnt
    ->m_yPos + pCnt->m_height))
    {
    if(LMBDown) status = UGP_BUTTON_DOWN;
    else status = UGP_BUTTON_OVER;
    }

    // State will depend on it's texture.
    if(status == UGP_BUTTON_UP)
    ApplyTexture(
    0, pCnt->m_upTex);
    if(status == UGP_BUTTON_OVER)
    ApplyTexture(
    0, pCnt->m_overTex);
    if(status == UGP_BUTTON_DOWN)
    ApplyTexture(
    0, pCnt->m_downTex);

    // Render button.
    Render(pCnt->m_listID);

    // Turn off alpha.
    m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,
    FALSE);
    break;
    }

    // Process control by calling the callback. 处理空间上的事件
    if(funcPtr) funcPtr(pCnt->m_id, status);
    }
    }


    void CD3DRenderer::CalculateProjMatrix(float fov, float n, float f)
    {
    if(!m_Device) return;
    D3DXMATRIX projection;

    D3DXMatrixPerspectiveFovLH(
    &projection, fov,
    (
    float)m_screenWidth/(float)m_screenHeight, n, f);

    m_Device
    ->SetTransform(D3DTS_PROJECTION, &projection);
    }


    void CD3DRenderer::CalculateOrthoMatrix(float n, float f)
    {
    if(!m_Device) return;
    D3DXMATRIX ortho;

    D3DXMatrixOrthoLH(
    &ortho, (float)m_screenWidth,
    (
    float)m_screenHeight, n, f);
    m_Device
    ->SetTransform(D3DTS_PROJECTION, &ortho);
    }


    int CD3DRenderer::CreateStaticBuffer(VertexType vType,
    PrimType primType,
    int totalVerts,
    int totalIndices, int stride, void **data,
    unsigned
    int *indices, int *staticId)
    {
    void *ptr;
    int index = m_numStaticBuffers;

    if(!m_staticBufferList)
    {
    m_staticBufferList
    = new stD3DStaticBuffer[1];
    if(!m_staticBufferList) return UGP_FAIL;
    }
    else
    {
    stD3DStaticBuffer
    *temp;
    temp
    = new stD3DStaticBuffer[m_numStaticBuffers + 1];

    memcpy(temp, m_staticBufferList,
    sizeof(stD3DStaticBuffer) * m_numStaticBuffers);

    delete[] m_staticBufferList;
    m_staticBufferList
    = temp;
    }

    m_staticBufferList[index].numVerts
    = totalVerts;
    m_staticBufferList[index].numIndices
    = totalIndices;
    m_staticBufferList[index].primType
    = primType;
    m_staticBufferList[index].stride
    = stride;
    m_staticBufferList[index].fvf
    = CreateD3DFVF(vType);

    if(totalIndices > 0)
    {
    if(FAILED(m_Device->CreateIndexBuffer(sizeof(unsigned int) *
    totalIndices, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
    D3DPOOL_DEFAULT,
    &m_staticBufferList[index].ibPtr,
    NULL)))
    return UGP_FAIL;

    if(FAILED(m_staticBufferList[index].ibPtr->Lock(0, 0,
    (
    void**)&ptr, 0))) return UGP_FAIL;

    memcpy(ptr, indices,
    sizeof(unsigned int) * totalIndices);
    m_staticBufferList[index].ibPtr
    ->Unlock();
    }
    else
    {
    m_staticBufferList[index].ibPtr
    = NULL;
    }

    if(FAILED(m_Device->CreateVertexBuffer(totalVerts * stride,
    D3DUSAGE_WRITEONLY, m_staticBufferList[index].fvf,
    D3DPOOL_DEFAULT,
    &m_staticBufferList[index].vbPtr,
    NULL)))
    return UGP_FAIL;

    if(FAILED(m_staticBufferList[index].vbPtr->Lock(0, 0,
    (
    void**)&ptr, 0))) return UGP_FAIL;

    memcpy(ptr, data, totalVerts
    * stride);
    m_staticBufferList[index].vbPtr
    ->Unlock();


    *staticId = m_numStaticBuffers;
    m_numStaticBuffers
    ++;

    return UGP_OK;
    }


    int CD3DRenderer::Render(int staticId)
    {
    if(staticId >= m_numStaticBuffers) return UGP_FAIL;

    if(m_activeStaticBuffer != staticId)
    {
    if(m_staticBufferList[staticId].ibPtr != NULL)
    m_Device
    ->SetIndices(m_staticBufferList[staticId].ibPtr);

    m_Device
    ->SetStreamSource(0,
    m_staticBufferList[staticId].vbPtr,
    0,
    m_staticBufferList[staticId].stride);

    m_Device
    ->SetFVF(m_staticBufferList[staticId].fvf);

    m_activeStaticBuffer
    = staticId;
    }

    if(m_staticBufferList[staticId].ibPtr != NULL)
    {
    switch(m_staticBufferList[staticId].primType)
    {
    case POINT_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_POINTLIST,
    0, m_staticBufferList[staticId].numVerts)))
    return UGP_FAIL;
    break;

    case TRIANGLE_LIST:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
    0, m_staticBufferList[staticId].numVerts / 3,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case TRIANGLE_STRIP:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0,
    0, m_staticBufferList[staticId].numVerts / 2,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case TRIANGLE_FAN:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0,
    0, m_staticBufferList[staticId].numVerts / 2,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case LINE_LIST:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_LINELIST, 0,
    0, m_staticBufferList[staticId].numVerts / 2,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    case LINE_STRIP:
    if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0,
    0, m_staticBufferList[staticId].numVerts,
    0, m_staticBufferList[staticId].numIndices)))
    return UGP_FAIL;
    break;

    default:
    return UGP_FAIL;
    }
    }
    else
    {
    switch(m_staticBufferList[staticId].primType)
    {
    case POINT_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_POINTLIST,
    0, m_staticBufferList[staticId].numVerts)))
    return UGP_FAIL;
    break;

    case TRIANGLE_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0,
    (
    int)(m_staticBufferList[staticId].numVerts / 3))))
    return UGP_FAIL;
    break;

    case TRIANGLE_STRIP:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0,
    (
    int)(m_staticBufferList[staticId].numVerts / 2))))
    return UGP_FAIL;
    break;

    case TRIANGLE_FAN:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0,
    (
    int)(m_staticBufferList[staticId].numVerts / 2))))
    return UGP_FAIL;
    break;

    case LINE_LIST:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_LINELIST, 0,
    m_staticBufferList[staticId].numVerts
    / 2)))
    return UGP_FAIL;
    break;

    case LINE_STRIP:
    if(FAILED(m_Device->DrawPrimitive(D3DPT_LINESTRIP, 0,
    m_staticBufferList[staticId].numVerts)))
    return UGP_FAIL;
    break;

    default:
    return UGP_FAIL;
    }
    }

    return UGP_OK;
    }

      

  • 相关阅读:
    理解OAuth 2.0
    Npoi导出word(Peanuts)
    轻松搞定javascript日期格式化问题
    史上最全的MSSQL复习笔记
    SQL经典短小代码收集
    Web系统与自控系统数据通讯架构 之 OPC DA DataChangeEventHandler 非热点数据更新策略 ,
    记一次SQL Server insert触发器操作
    记一次单机Nginx调优,效果立竿见影
    windows 显示引用账户已被锁定,且可能无法登录
    C# 使用modbus 读取PLC 寄存器地址
  • 原文地址:https://www.cnblogs.com/kex1n/p/2164078.html
Copyright © 2011-2022 走看看