zoukankan      html  css  js  c++  java
  • 《Direct3D中的2D编程》随书源码在vs2019中编译通过

    《Direct3D中的2D编程》讲如何使用Direct3D来实现被淘汰掉的directdraw所能实现的功能

    即讲了如何把已淘汰的DirectDraw里实现的功能转化为Direct3D的等价形式

    《Direct3D中的2D编程》用的已经是很古老的DX8,讲当微软将directdraw从DX8中去掉时,那些游戏程序员要如何从directdraw中迁移到directx3D中去绘制2D图形

    本人试验环境:win10, vs2019 社区版,下载安装 Microsoft DirectX SDK (June 2010)

    因为下载的是DX2010, 而此书作者用的是DX8,懒得再折腾在本机中换成DX8,于是做了下面这样一个小试验,最后编译通过

    ===============当时安装Microsoft DirectX SDK 2010的注意事项===================================

    Microsoft DirectX SDK 2010 版本下载 http://www.microsoft.com/en-us/download/details.aspx?id=6812

    Version:
    Date Published:
    9.29.1962
    6/7/2010
    File name:
    File size:
    DXSDK_Jun10.exe
    571.7 MB

    下载好后,先安装Microsoft DirectX SDK (June 2010),安装包名字叫DXSDK_Jun10.exe,

    如果安装完毕前出错,则卸载电脑中vc++2010的86和x64 redistribution (10.0.xxx ,xxx 高于30319,大概就是这个数字,总之开头是30,后面3位数记不清),再重新安装一遍Microsoft DirectX SDK (June 2010) ,

    然后在VS2019的编译按钮旁边,下拉框选择【Debug】 【x86】,然后点击左侧栏的项目名称,打开 项目-属性-配置属性-VC++目录 (或直接按ALT+F7  打开VC++目录)
    把下面两个目录分别添加进包含目录和库目录,注意前提是 Microsoft DirectX SDK (June 2010)安装包一定要安装在D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)

    包含目录:D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;
    库目录: D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;

    原因:编译时vs2019需要寻找的链接文件 d3dx9.lib 和d3d9.lib 就在D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86 目录下

    而编译时vs2019需要包含的头文件 d3d9.h (direct3D的头文件)就在 D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include 目录下

    ==========================================================================================

    找来《Direct3D中的2D编程》一书的随书源码的第一个例子程序,编译,一堆报错,好吧,于是开始修改例子源码


    // WindowsProject1.cpp : 定义应用程序的入口点。
    //来自于《Direct3D中的2D编程》一书的随书源码 D:\C++入门2021.12.29\游戏编程入门第4版及随书源码\Direct3D中的2D编程\2DIn3D\chap01\Example01_1
    //Example1_1
    //main.cpp
    //Ernest Pazera
    //04OCT2001
    //TGO-01-C
    //Libs: d3d8.lib       (这里表示作者用的是DX8)


    //该书用的是DX8,无法编译通过,会报错,需修改源代码中以下这些内容
    // 头文件#include "d3d8.h" 修改为 #include "d3d9.h" //include direct3d9 stuff
    //添加 #pragma comment(lib,"d3d9.lib")
    // 将源码中 Direct3DCreate8(D3D_SDK_VERSION) 改为 Direct3DCreate9(D3D_SDK_VERSION)
    // 将三处字符串中的IDirect3D8 都改为 IDirect3D9,这样程序运行结果会在输出的文本文件中显示是IDirect3D9 对象产生了,释放了
    // 另外,按ALT+F7 配置属性-高级-字符集中将 Unicode字符集改为多字节字符集

    //把D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include; 添加到项目属性-VC++目录的包含目录中

    //把D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86; 添加到项目属性-VC++目录的库目录中

    // 特别注意:如果你编译时候选择【x64】,那么应该需要把    D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64;    添加到项目属性-VC++目录的库目录中

    //如果你选择【release】编译,也需要同样进行VC++目录中的包含目录和库目录的设置,方法同上 

    修改完毕,此时无任何语法错误显示,且点击能顺利编译链接成功的源码如下:

    #include <windows.h> //include windows stuff
    #include <stdio.h> //standard input/output
    #include "d3d9.h" //include direct3d9 stuff

    #pragma comment(lib,"d3d9.lib") // 一定要加这一句,否则报错: LNK2019 无法解析的外部符号 _Direct3DCreate9@4,函数 "void __cdecl Prog_Init(void)" (?Prog_Init@@YAXXZ) 中引用了该符号 WindowsProject1 D:\c++_test\2DIn3D\WindowsProject1\WindowsProject1.obj 1

    #pragma warning( disable : 4996)
    //或将pragma warning( disable : 4996)替换为 #define _CRT_SECURE_NO_WARNINGS
    //用以解决error C4996: 'freopen': This function or variable may be unsafe. Consider using freopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 的安全检查错误的方法
    //参考这篇帖子 https://blog.csdn.net/dan15188387481/article/details/49622783


    //constants
    //window class name
    const char* WINDOWCLASS = "3D42DGP";
    //window title
    const char* WINDOWTITLE = "Example 1.1 (TGO-01-C): Creating and Destroying an IDirect3D8 object";

    //globals
    //instance handle
    HINSTANCE g_hInstance = NULL;
    //window handle
    HWND g_hWnd = NULL;
    //IDirect3D8 pointer
    IDirect3D9* g_pd3d = NULL;

    //function prototypes
    //winmain
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
    //window procedure
    LRESULT CALLBACK TheWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    //initialization
    void Prog_Init();
    //clean up
    void Prog_Done();


    //window procedure
    LRESULT CALLBACK TheWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    //which message did we get?
    switch (uMsg)
    {
    case WM_DESTROY: //window being destroyed
    {
    //quit

    PostQuitMessage(0);

    //message handled, return 0

    return (0);

    } break;
    default: //all other messages, send to default handler
    return (DefWindowProc(hWnd, uMsg, wParam, lParam));
    }
    }

    //winmain
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
    //grab instance handle
    g_hInstance = hInstance;

    //redirect stderr and stdout output
    freopen("stderr.txt", "w", stderr);   // 添加 #pragma warning( disable : 4996),否则vs2019会抱怨,说你用的函数不够安全,需要用添加_s版本的同名函数
    freopen("stdout.txt", "w", stdout);  // 添加 #pragma warning( disable : 4996),否则vs2019会抱怨,说你用的函数不够安全,需要用添加_s版本的同名函数

    //fill in window class
    WNDCLASSEX wc;
    wc.cbClsExtra = 0; //no extra class information
    wc.cbSize = sizeof(WNDCLASSEX); //size of structure
    wc.cbWndExtra = 0; //no extra window information
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //black brush
    wc.hCursor = NULL; //no cursor
    wc.hIcon = NULL; //no icon
    wc.hIconSm = NULL; //no small icon
    wc.hInstance = g_hInstance; //instance handle
    wc.lpfnWndProc = TheWindowProc; //window procedure
    wc.lpszClassName = WINDOWCLASS; //name of class
    wc.lpszMenuName = NULL; //no menu
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC; //class styles

    //register window class
    RegisterClassEx(&wc);

    //create window
    g_hWnd = CreateWindowEx(0, WINDOWCLASS, WINDOWTITLE, WS_OVERLAPPEDWINDOW, 0, 0, 320, 240, NULL, NULL, g_hInstance, NULL);

    //show the window
    ShowWindow(g_hWnd, nShowCmd);

    //initialization
    Prog_Init();

    MSG msg;
    //message pump
    for (; ; )
    {
    //check for a message
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
    //message exists

    //check for quit message
    if (msg.message == WM_QUIT) break;

    //translate the message
    TranslateMessage(&msg);

    //dispatch the message
    DispatchMessage(&msg);
    }
    }

    //clean up
    Prog_Done();

    //exit
    return (msg.wParam);
    }

    //initialization
    void Prog_Init()
    {
    //create the IDirect3D8 object
    g_pd3d = Direct3DCreate9(D3D_SDK_VERSION);

    //error check
    if (g_pd3d)
    {
    //success
    fprintf(stdout, "IDirect3D9 object created successfully.\n");
    }
    else
    {
    //failure
    fprintf(stderr, "IDirect3D9 object creation failed.\n");
    }
    }

    //clean up
    void Prog_Done()
    {
    //safe release of IDirect3D8 object
    if (g_pd3d)
    {
    //release
    g_pd3d->Release();

    //set to null
    g_pd3d = NULL;

    //report action
    fprintf(stdout, "IDirect3D9 object released.\n");
    }
    }

    总结:虽然这是一本古老的书,但到现在为止,很多想学习windows下游戏开发的热爱者,还是会随便从网上当一本游戏编程书籍,很大概率就会下到一本什么书呢,一本里面写满DirectDraw的函数的书!而这种技术已经淘汰很久很久了,完全跟不上时代!

    但是,这类书中又有很多有参考价值的部分,比如算法,空间几何,那些图形学,AI,以及其他乱七八糟的好东西,这样,这本书你到底看还是不看?食之无味弃之可惜,但又如蚊子叮铁牛无从下嘴,因为连第一个例子都无法编译通过。。。

    现在明白了,是被过气的directdraw 给坑了,那么,

    你可以选择学习虽然老一点,但仍具有一定实用性的DX9或DX10,而此时你最需要的就是一本教你如何从directdraw迁移到Direcx3D的使用方法的书,把老书中源码修改一下,能够编译通过跑起来,老书的剩余价值便可充分利用了

    ps: 虽然这是一个很小白很小白的试验小例子,但却很重要,因为很大概率的,如果你连书中第一个例子都搞不定,又缺乏最基本的DirectX和DirectDraw之间关系的背景知识,那么极有可能你会就此失去对windows游戏开发的兴趣,从而错失领略一个无比瑰丽迷人领域的宝贵机会!

  • 相关阅读:
    程序员修神之路--容器技术为什么会这么流行
    程序员修神之路--kubernetes是微服务发展的必然产物
    程序员修神之路--有状态的服务其实可以做更多的事情
    程序员修神之路--要想做好微服务架构,并非易事!
    程序员修神之路--为什么有了SOA,我们还用微服务?
    程序员过关斩将--数据库的乐观锁和悲观锁并非真实的锁
    程序员修神之路--设计一套RPC框架并非易事
    计算机的诞生和简史
    记一次Linux修改MySQL配置不生效的问题
    为什么大多数公司都不重视技术?
  • 原文地址:https://www.cnblogs.com/Thermo/p/15757856.html
Copyright © 2011-2022 走看看