从零开始做3D地图编辑器基于QT与OGRE.docx

上传人:b****5 文档编号:12369585 上传时间:2023-04-18 格式:DOCX 页数:29 大小:158.85KB
下载 相关 举报
从零开始做3D地图编辑器基于QT与OGRE.docx_第1页
第1页 / 共29页
从零开始做3D地图编辑器基于QT与OGRE.docx_第2页
第2页 / 共29页
从零开始做3D地图编辑器基于QT与OGRE.docx_第3页
第3页 / 共29页
从零开始做3D地图编辑器基于QT与OGRE.docx_第4页
第4页 / 共29页
从零开始做3D地图编辑器基于QT与OGRE.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

从零开始做3D地图编辑器基于QT与OGRE.docx

《从零开始做3D地图编辑器基于QT与OGRE.docx》由会员分享,可在线阅读,更多相关《从零开始做3D地图编辑器基于QT与OGRE.docx(29页珍藏版)》请在冰豆网上搜索。

从零开始做3D地图编辑器基于QT与OGRE.docx

从零开始做3D地图编辑器基于QT与OGRE

第一章基础知识

注:

文章里面有不少个人见解,欢迎大家一起互相讨论。

希望高人能给予相应理解与意见建议。

在实际3D游戏开发中,编辑器是极其重要的一个部分,一个优秀健壮的编辑器,可以使项目事半功倍,而相反,一款BUG超多(随时会挂)又不注重操作习惯(完全基于快捷键,又没有详细的使用说明)的编辑器,不仅会使项目事倍功半,而且会削弱开发人员的积极性,甚至让开发人员对项目产生排斥情绪。

编辑器在游戏里面应用很广泛,一般都有地图编辑器(关卡、世界)、粒子编辑器、动画编辑器、字体编辑器(单机里面较多)、UI编辑器、材质编辑器、脚本编辑器等等,编辑器设计制作方法也大致可分为两个趋势,一种是倾向于做大而全的世界编辑器,一种是做小而精的功能编辑器,在这里我不想讨论这两者的利与弊,我只能说,只要这个解决方案可以解决我们当前的问题,那么它就是一个适合现阶段的解决方案,但并不一定是最好的解决方案。

一、工具

现在制作编辑器,流行以下几种方式:

1、 使用C#制作基于WinForm的编辑器。

2、 制作基于MFC的编辑器。

3、 制作基于WxWidgets的编辑器。

4、 制作基于QT的编辑器。

基于C#来制作编辑器,在制作一些小工具上面很有利,比如说打包工具,加密器等等和图形关系不大的工具,它的优势在于它的简单易用,但是当你涉及到图形这一块的时候,如果引擎支持不C#,那么使用XNA、ManageDX都不是很好的一种解决方案(除非你的游戏就是基于两者),导入动态链接库的方法又会比较麻烦,C#和C++之间还是有不小的区别。

基于MFC做编辑器,在以前基本是首选,它的优势在于文档应用特别多,你遇到问题的时候,基本上网络上都能找到解决方案,但是它相对门槛高,一个初学者经常会被它折磨得兴趣殆尽,应用也很麻烦,特别是在多窗口应用上面,所以以前我用MFC做编辑器都是基于Dialog来做。

WxWidgets和QT都是跨平台的GUI库,目前来说还算主流,我个人倾向于QT,WxWidgets了解不多,QT目前由诺基亚负责,有自己的IDE、设计工具、详细的例子、比较充实的文档、与VS的结合还算完美,还有一些第三方的库支持,网络上的资料也还多,是个发展潜力不错的GUI库。

因为我将要做一个3D地图编辑器,在图形这一块也有不少选择,OGRE与Irrlicht等,我选择使用OGRE,当然你也可以选择自己的引擎。

OGRE是一个开源的图形渲染引擎,它的材质脚本还是很强大的,简单易用、目的性明确,让你的Shader容易应用与修改。

早期的版本在地形这一块做得不够,所以早期做OGRE的地形编辑时一般会选择ETM,PLSM等库,新的1.7版本对地形这一块增强不少,而我也会在编辑器里面应用它地形编辑的功能。

二、工具安装指南

1、OGRE下载与编译

OGRE官方网站:

http:

//www.ogre3d.org

下载最高版本的OGRE(1.7.1),有两种方式:

第一种方式是直接下载SDK,下载的SDK可以直接使用,但是由于编译环境不同,可能会缺少一些DX的DLL,你得在网络下另外下载缺少的DLL,下载方法是从网站左侧的DownLoad里面选择SDK,然后选择相应VS的版本,我们推荐使用VS2008,因为QT针对2008做了一个AddIn。

第二种方式是下载源代码进行编译。

个人觉得使用OGRE应该使用自己编译的库,毕竟有什么需要的时候还可以自己修改,自己编译需要注意几点:

1、除了OGRE源码外,你需要额外下载MicrosoftVisualC++DependenciesPackage,并把它解压到OGRE目录(你自己的OGRE目录)后编译。

        2、你需要下载CMAKE,官方网站是www.cmake.org。

下载一个最新版本就行。

3、你机器需要安装DX的SDK,不然OIS和DX的渲染系统插件无法编译。

4、使用Cmake生成OgreVS解决方案的时候要记得指定Dependencies目录(在Cmake提醒你的时候指定)。

此过程可以参考

用VS打开生成的解决方案,

然后直接编译就可以获得dll和lib.

2、QT下载

QT官方网站:

下载QT也有两种方式,一种是纯SDK(QtSDKforWindows*(287MB)),另外一种是针对VS2008的库(Qtlibraries4.6.2forWindows(VS2008,194MB)),这两者有一定的区别,前者带有更多的工具(IDE等)。

我推荐下载针对VS2008的库,下载安装完之后,还需要下载一个Addin,这个Addin比较难找,在Otherdownloads里面下载VisualStudioAdd-in(44MB)。

安装完Add-In之后,打开VS2008应该就可以找到QT的模板了。

QT4projects下面有一些选项,选择新建一个QTApplication。

新建完编译通过,运行发现这是一个基本窗口。

如果编译OIS没有成功,请在项目属性里面填入DX的include和lib路径。

三、开始之前的配置

我看到过很多同志在做项目时,直接新建项目后立马就直接开始编程,使用的是VS默认目录,结果在Debug的时候老是找不到dll,找不到资源,然后又花了一堆的时间去查找问题,白白地浪费了不少时间,更有甚者就在此时便失去了继续向下的动力,觉得这个东西太难理解了(一遇挫折就跑)。

所以我觉得在每次开始项目前都应该好好地把解决方案配置一下。

我做项目的时候喜欢这种方式,项目目录下面存在以下几个目录。

 

Bin目录不难理解,里面放的是生成的可执行文件,下面又分了Debug、Release、Data(Media)等目录,Debug、Release里面放的是执行文件和dll,命名的时候Debug要命名为_d.exe.因为资源文件是共用的,所以资源不应该放在Debug或Release下面,直接放Bin下面就行了。

Docs目录里面放的是相关文档。

Objs目录里面存放编译过程中的中间文件,临时文件。

Scripts目录里面存放解决方案,Sln或其他格式。

SDKS目录存放第三方库,比如OGRE,Boost,Lua等。

Tools目录存放着制作时的一些工具。

剩下那个目录一般改名为Src或source.

为什么目录要这样分?

Bin文件夹分出来有利于你程序的发布,调试。

把Objs从source分出来,有利于你的源代码版本控制,备份。

把解决方案单独拿出来,有利于你的跨平台或换IDE,SDKS拿出来很重要,因为有可能两年后你的引擎或者底层更新或者大改动过,但是你又需要把两年前的游戏重新编译,如果没有备份好,结果自然不难想像。

同样,工具也是这样,比如说加密器算法经常改动,你不备份好你的东西以后都没有办法修改了。

接下来要调整VS来适应这一套目录结构。

第一件事,用文本工具打开修改sln,把它指向source目录里面的工程文件。

#VisualStudio2008

Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")="Test","..\Source\Test.vcproj","{83E01383-8BC1-404F-9C25-A9AFFCDBB210}"

EndProject

像上面那样修改为你的工程名.

之后用新的解决方案打开项目,在VS里项目名上右键打开属性。

之后的第一件事情就是修改工作目录,很多同志就是因为没有设定这个目录导致找不到DLL,它在配置属性中调试一栏里面,修改成你当前的Bin所在目录,最好设置为相对目录,Debug模式下是../Bin/Debug,对应的Release下面是../Bin/Release。

接着在常规里面修改中间目录和输出目录,我们都修改成../Objs/Debug和../Objs/Release。

之后在链接器>常规里面修改输出文件,修改成..\bin\Debug\$(ProjectName)_d.exe和../Bin/Release/$(ProjectName).exe。

然后在C/C++>常规中把你要的include添加进去,在链接器>附加库中把你要的lib目录添加进去。

完成这些我们就配置完了。

附:

Ogre1.7.1的配置要注意:

由于Ogre使用了boost,所以一定要把Ogre自带的Boost目录放进SDKs中,如果要使用OIS,还得包含OIS的头文件路径,库文件和OGRE放在一起,所以不用再设置。

另:

如果是在IDE中新建QTApplication,QT头文件与库的相关配置会自动帮你设置好。

你只需要在它的基础上把其他库添加好就行了。

四、QT基本知识

回到QT,先在VS中新建一个QTApplication,项目里面有几个目录:

1、             FormFiles目录,它里面放的是使用QTdesigner制作的基于XML的布局文件,双击它就会自动进入QTdesigner。

2、             GeneratedFiles目录,它里面放的是一些临时生成的文件,这些文件用来处理QT的信号和槽等机制。

3、             ResourceFiles目录,它里面放的是基于XML的资源文件,你可以在窗体里面使用它们。

4、             HeaderFiles和SourceFiles这两个和VS默认是一样的。

理解了目录结构之后,先来试着写一个HelloWorld,先把除了main.cpp之外的所有文件移除(使用QTdesigner会提高制作效率,但是会让QT入门门槛变高)!

打开main.cpp,仅保留以下代码:

viewplaincopytoclipboardprint?

#include   

  

intmain(intargc,char*argv[])   

  

{   

  

        QApplicationa(argc,argv);         

  

        returna.exec();   

  

}  

#include

intmain(intargc,char*argv[])

{

        QApplicationa(argc,argv);     

        returna.exec();

}

 

编译通过。

运行没有任何反应,因为还没有往里面增加任何东西。

在代码中,Main函数是C语言的入口,之后申请的QApplication用来管理控制流和主要设置,这是核心,一定要保留。

按钮是GUI中最基本的一个控件,先看看怎么增加一个按钮。

使用按钮控件必须先包含头文件:

viewplaincopytoclipboardprint?

#include  

#include

然后在QApplicationa(argc,argv);与returna.exec();中间插入下面代码:

viewplaincopytoclipboardprint?

QPushButtonbutton("HELLO");   

  

        button.setGeometry(100,100,300,300);   

  

        button.show();  

QPushButtonbutton("HELLO");

        button.setGeometry(100,100,300,300);

        button.show();

 代码第一行是申请一个按钮,并把按钮的Caption标题设为HELLO,第二行表示这个按钮出现在屏幕坐标(100,100)的位置,宽高为(300,300),最后一行是显示这个按钮,你可以尝试把它去掉看看效果(官方助手里有QPushButton的更多资料,请自行查看)。

编译出来,发现屏幕上出现一个框,框里面有一个按钮,按钮可以点击,但是没有任何反应,因为还没有为这个按钮增加任何的槽(Slot)。

在MFC对控件的处理一般是通过事件机制,而在QT中是使用信号(Signal)和槽(Slot)机制,其实你也可以把它理解为事件机制。

简单理解信号其实就是输入,而槽就是输出,拿按钮打比方,在一次点击中,这个点击,就是一个信号,而点击后的反馈,就是槽。

每一个控件都拥有一些默认的Signal和Slot,这些都可以在官方提供的助手中查看。

绑定Signal和slot是使用静态函数connect。

函数原型是:

viewplaincopytoclipboardprint?

Boolconnect(constQObject*sender,constchar*signal,constQObject*receiver,constchar*method,Qt:

:

ConnectionTypetype=Qt:

:

AutoConnection)  

Boolconnect(constQObject*sender,constchar*signal,constQObject*receiver,constchar*method,Qt:

:

ConnectionTypetype=Qt:

:

AutoConnection)

其中sender是发送者,而receiver是接收者,signal是信号,而method就是slot,type里面提供了几种绑定方式,可以详细查看助手。

        先看一个例子,在上面代码中加入点击按钮后关闭应用程序的效果。

很简单,只需要在

viewplaincopytoclipboardprint?

button.setGeometry(100,100,300,300);  

button.setGeometry(100,100,300,300);

后面加入

viewplaincopytoclipboardprint?

QObject:

:

connect(&button,SIGNAL(clicked()),&a,SLOT(quit()));  

QObject:

:

connect(&button,SIGNAL(clicked()),&a,SLOT(quit()));

编译运行,点击后窗体关闭。

这是使用默认槽的例子,有时候需要点击按钮之后执行自定义的效果,那么就需要使用自定义槽了。

        下面是一个使用自定义Slot的例子,鼠标点击按钮之后,文本框文字会改变。

先加入一个QLabel控件,你先加入头文件:

viewplaincopytoclipboardprint?

#include  

#include

然后在connect前加入

viewplaincopytoclipboardprint?

QLabellabel("World");   

  

        label.setGeometry(50,50,300,300);  

QLabellabel("World");

        label.setGeometry(50,50,300,300);

 

先尝试编译一下,结果label没有出现在窗体里面!

它当然不会出现在窗体里面,因为我们只是对Button使用了Show()函数,尝试加入label.show(),结果出现了两个窗体,一个里面有按钮,另一个里面有一个label。

那么怎么把它们放在一起呢?

        通过上面的测试发现,调用一次show就会产生一个窗口,那么是不是只调用一次show就行了?

把函数里面代码改为:

viewplaincopytoclipboardprint?

QApplicationa(argc,argv);   

  

        QWidgetwindow;   

  

        QPushButtonbutton("HELLO");   

  

        button.setGeometry(100,100,300,300);   

  

        QLabellabel("World");   

  

        label.setGeometry(50,50,300,300);   

  

        QHBoxLayoutlayout;   

  

        Layout.addWidget(&button);   

  

        Layout.addWidget(&label);   

  

        QObject:

:

connect(&button,SIGNAL(clicked()),&window,SLOT(close()));   

  

        window.setLayout(&layout);   

  

        window.show();          

  

        returna.exec();  

QApplicationa(argc,argv);

        QWidgetwindow;

        QPushButtonbutton("HELLO");

        button.setGeometry(100,100,300,300);

        QLabellabel("World");

        label.setGeometry(50,50,300,300);

        QHBoxLayoutlayout;

        Layout.addWidget(&button);

        Layout.addWidget(&label);

        QObject:

:

connect(&button,SIGNAL(clicked()),&window,SLOT(close()));

        window.setLayout(&layout);

        window.show();      

        returna.exec();

附上此时的头文件列表:

viewplaincopytoclipboardprint?

#include  

 

#include  

 

#include  

 

#include  

 

#include  

#include

#include

#include

#include

#include

 

一开始,我就申请了一个QWidget,QWidget类是QT中所有用户界面对象的基类,它本身并没有什么实际意义,在这里你可以把它看成一个窗体容器,然后又添加了一个

QHBoxLayoutlayout;QHBoxLayout这是个可以对子widget进行特定布局的控件,通过它可以把按钮和label并排,之后把窗体的layout设为指定的layout,然后调用show()。

调试运行,终于两个控件都出现了。

回到之前的话题,自定义槽。

在QT中所有自定义槽都需要先编译成moc,才可以被使用。

不过你放心,这个过程由QT自动完成,当然你也可以手动进行编译,QT的Bin目录里面有moc.exe,参照说明进行使用。

你应该可以看到我已经偷偷把按钮的点击信号转向了窗体的close槽。

为什么要这样做呢,因为我们需要把自定义槽函数定义放在头文件里。

第一步,先把window封装起来,我新建一个MainWidget类,继承自QWidget类,类的头文件如下:

viewplaincopytoclipboardprint?

#ifndef_MAIN_WIDGET_H_  

 

#define_MAIN_WIDGET_H_  

 

#include  

 

#include  

 

#include  

 

#include   

  

classMainWidget:

publicQWidget   

  

{   

  

public:

   

  

        MainWidget();   

  

        ~MainWidget();   

  

    

  

protected:

                    

  

    

  

private:

       

  

        QLabel*                              m_pLabel;   

  

        QPushButton*         m_pButton;   

  

        QHBoxLayout*                  m_pLayout;   

  

};  

 

#endif   

  

CPP如下:

  

 

#include"MainWidget.h"   

  

MainWidget:

:

MainWidget()   

  

{   

  

        m_pLabel=newQLabel("World");   

  

        m_pLabel->setGeometry(50,50,300,300);   

  

        m_pButton=newQPushButton("HELLO");   

  

        m_pButton->setGeometry(100,100,300,300);   

  

        m_pLayout=newQHBoxLayout();   

  

        m_pLayout->addWidget(m_pButton);   

  

        m_pLayout->addWidget(m_pLabel);   

  

        connect(m_pButton,SIGNAL(clicked()),t

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 教育学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1