QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3019|回复: 11

请进,sdl+opengl,我差不多就译完了,

[复制链接]
发表于 2005-7-2 12:25:57 | 显示全部楼层 |阅读模式
Tutorial 01 Version 0.2
Welcome to the first (and hopefully not the last) of my tutorials. My focus with this and any other tutorials you will be seeing on this site is cross compatibility between Windows and Linux thru the use of SDL.
欢迎来到我的首个教程,在这个和其它的教程,你会看到交叉兼容Windows和LINUX平台(linux平台下用sdl来达到目的!)

Update:although the code should compile under all platforms supported by SDL (Mac OS X has been reported to compile it unchanged), I can only test it on Linux and Windows, so I can only guarantee the code to work on those platforms.

虽然这里的代码用SDL写,可以支持在所有平台下编译,我只在LINUX和Windows下测试,所以我只能确保它们在这些平台下可以正常工作。

Ok, lets start!

    Open up your favorite text editor, for the record, my favorite is XEmacs for Linux as well as Windows coding, yours might be a different one, for example Emacs or Vi, of course you could also use an IDE such as KDevelop, Dev-C++ or Visual C++, no matter your preference, you should be familiar enough with your environment to start an empty project, so, please do so now .

打开你喜欢的文本编辑器来编写(程序),我喜欢的是LINUX的XEmacs,你可以喜欢别的,例如:Emacs、Vi,当然,你可能用一个IDE──如KDEVELOP,你你有足够的熟悉你的系统环境从而开始一个空的工程。

    We start with the header files of course, as we would with any other program, remember we are aiming here at 100% cross platform compatibility so we have to be aware of the quirks of each platform, for one, we know that Linux does not have a windows.h file, so we must not include it, luckily for us, SDL.h includes windows.h under Windows.

我们从头文件开始。当然,像我们处理其它工程一样,记住我们的目标是让我们的工程能100%能够兼容平台,所以我不得不意识到每个平台的的古怪举动。举个例来说:我们知道LINUX没有windows.h文件,所以我们一定不能include。我们幸运的是SDL.h includes了windowsr windows.h文件

    We need to include the GL headers too, again SDL comes to the rescue, we just need to include SDL_opengl.h
    We must also remember that the Linux file system is case sensitive, so, every header we include must be typed with the appropriate case.
我们也要include DL头文件,再一次,SDL给了帮助,我们仅仅要include SDL_opengl.h头文件,我们也必需记住linux文件系统是小写敏感的,所以每一个头文件要用适当的大小写。

#include "SDL.h"
#include "SDL_opengl.h"

    I'd like to point something out here, some people include the headers as #include "SDL/SDL.h" or even #include <SDL/SDL.h>, heck! I used the later one before, but if you look up the SDL FAQ, you will find that "The most portable way to include SDL headers is to use quotes around the header name: #include "SDL.h" ", so there you have it.

我在这里要指出一点,有的人在include这个头文件如:#include "SDL/SDL.h" 或 #include <SDL/SDL.h>,我以前是用后面一种,但如何你查阅SDL FAQ时,会发现"The most portable way to include SDL headers is to use quotes aroundthe header name: #include "SDL.h" 很多情况下,include SDL头文件时,用双引号包围头文件:#include "SDL.h""

    Next we have the declaration and definition of the main function, it is really important that we use the version that takes into account the arguments even if we are not using them, this is because SDL calls this version of the main function inside WinMain, so if its not defined as taking arguments, we will get an undefined symbol error at link time under Windows.

我们可以看到主函数的声明和定义,即使我们不使用传入的参数,他们也非常重要。所以如果他们没有被定义就会再连接窗口中出现没有定义的语法错误,因为sdl调用了在Winmain中的此版本的main函数。

Notes: It is perfectly safe to declare main with no arguments under Linux. Also, you might skip the declaration of main on either OS.:int main(int argc, char *argv[]);
这是一个在LINUX下完整的没有参数的main函数声明,并且,你在其它的系统可能跳跃这个main函数声明。int main(int argc, char *argv[]);

///////////////////////////////////////////

int main(int argc, char *argv[])
{

The first thing we need to do inside main is initialize the video system, we do it as we usually do, with the SDL_Init function and we check for errors.

在main内部,我们首先做的事是:要初始化video system(视频系统),我们经常用SDL_Init()函数各完成初始化工作和检查错误,如下面的做法:

if(SDL_Init(SDL_INIT_VIDEO)<0) // 尝试初始化系统
{
    fprintf( stderr, "Video initialization failed: %s\n",SDL_GetError()); // 如果有错,找出错误用SDL_GetError()函数
    return -1
}

Next we have to set the Open GL  with the function SDL_GL_SetAttribute,we make as many calls to this function as needed, for now, we will be just setting the color and depth frame buffer as well as tell SDL that we want double buffering, if you need to set a stencil buffer or something else I recommend you check the function reference here.
下一步,我们用这个函数(SDL_GL_SetAttribute)来设置Open GL的属性,根据我们的要求,会调用这个函数很多次。现在,我来设置color和depth frame buffer深度缓冲,告诉SDL你要双倍缓冲。如果你想设置一个stencil buffer(模版缓冲,不知是不是呢!)或其它,我推荐你在这里检查这个函数的参数。


SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); // Set red frame buffer size
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); // Set green frame buffer size
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); // Set blue frame buffer size
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); // Set depth frame buffer size设置深度缓冲
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER,1); // Tell SDL we want Double buffering设置双倍缓冲


Now we set the video mode with SDL_SetVideoMode, here you decide of you want full screen or windowed mode, usually on these kind of tutorials we would use a message box to ask the user what mode does he/she wants, but since there is no message box function on SDL and we don't want to break cross compatibility or have to mess with #ifdef WIN32 macros, we will just set the program to start full screen.

现在我们来用SDL_SetVideoMode设置video mode(视频模式),这里你决定你想full screen(全屏)还是windowed mode(窗口模式),在这教程里,我们通常会用一个对话框问用户他们想用哪种。但是自从在SDL里没有前面所说的对话框和我们不想破坏(程序的)兼容性,或因使用#ifdef WIN32宏,变得mess (紊乱),我们只设置这个程序以全屏模式开始。

We need to pass the SDL_OPENGL and SDL_FULLSCREEN flags to SDL_SetVideoMode, if you want window mode, just omit the SDL_FULLSCREEN flag.

我们要通过在SDL_SetVideoMode函数里调用用 SDL_OPENGL 和  SDL_FULLSCREEN 这样的属性标记命令,如果想用窗口模式,只要省略这个SDL_FULLSCREEN属性标记命令。

We also pass the resolution (or size of the window) we want to use, here we will use 800x600, and we pass 0 as the bpp parameter, which means use the current display bits per pixel.

我们同样地通过我们想要的分辨率,这里我们用800x600,和0 bpp parameter(bpp参数,当前显示的第一象素多少bits),

if(SDL_SetVideoMode(800,600,0,SDL_OPENGL|SDL_FULLSCREEN) == 0 )
{
    fprintf( stderr, "Video mode set failed: %s\n",SDL_GetError()); // why did it failed?
    SDL_Quit(); // Release whatever SDL grabbed during SDL_Init
    return -1;
}

Next, we move on to the actual Open GL initialization part, we have to set the Open GL state machine to the state we want to start with.

下一步,我们继续前进(研究)实际的Open GL初始化部分。我们设置
Open GL开始的状态。

glViewport(0,0,800,600); // set the view port to take the whole screen设置视口坐标和大小(在这里取得全部的屏幕大小)
glMatrixMode(GL_PROJECTION); // switch to the Projection Matrix翻转投影矩阵
glLoadIdentity(); // reset Projection Matrix重设投影矩阵
gluPerspective(45.0f,800.0f/600.0f, 0.1f ,100.0f); // set our view to perspective设置我们的视角
glMatrixMode(GL_MODELVIEW); // switch to the Model View Matrix翻转模型矩阵
glLoadIdentity(); // reset Model View Matrix重置模型视图矩阵
glClearColor(0.0f,0.0f,0.0f,0.0f); // Set our Clear Color to Black设置清除颜色为黑色
glShadeModel(GL_SMOOTH); // Enable Smooth Shading打开光滑底纹
glClearDepth(1.0f); // Set the depth buffer设置深度缓冲
glEnable(GL_DEPTH_TEST); // Enables Depth Testing打开深度测试
glDepthFunc(GL_LEQUAL); // Type of depth test
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Use really nice perspective calculations 应用和蔼的透视计算的结果

Now we are ready for our game's main loop, we use SDL_PollEvent as we would if we were writing the usual SDL application, here is also where we would be calling a GameMain Function, but for now, lets just clear up the screen.

现在我们准备为我们的游戏的main函数的循环,我们用SDL_PollEvent函数(与我们平时写的SDL函数一样格式) 完成main函数的循环,原本我们应该调用一下GameMain函数,但是现在,让我们仅仅清结我们的屏幕.

We use SDL_GL_SwapBuffers to swap our buffers.

你们有SDL_GL_SwapBuffers函数来实现 交换缓冲功能

Note: I am defining some variables here, in real life you should define them early at the start of the function definition, but for learning purposes, I feel its better to define them here, where they are used.

我在这里义一些变量,在你自己编写程序时,你应该把它们(集中)定义在函数定义的最前面,但是由于学习教程的需要,我觉得把这些变量在使用前才定作出定义.


bool bRunning = true;
SDL_Event event;
while(bRunning)
{
    if(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_QUIT: // test to see if the user closed the app检查程序是否关闭
                bRunning = false;
            break;
            case SDL_KEYDOWN: /* Handle a KEYDOWN event 键盘按下事件*/
                if(event.key.keysym.sym==SDLK_ESCAPE)
                bRunning = false; // quit if ESCAPE is pressed
            break;
        }//switch的右花括号
    }//if(SDL_PollEvent(&event))的右花括号

    /* here we would call our main rendering function for now we just refresh the Window.我们现在只需要调用自己的主渲染函数来刷新窗口。*/

         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear screen and depth buffer清结屏幕和深度缓冲
    glLoadIdentity(); // reset current model view matrix重置当前模型视图矩阵
    SDL_GL_SwapBuffers(); // finally we swap our buffers交换缓冲
}


Everything left to do is to return from our main function, no fancy
stuff, we just return 0, meaning everything went fine.
剩下的事情就是return我们的main函数,不用多想,我们仅仅返加回0,意味所有事被都完成.

return 0;
}

And that's it! not so hard was it? now save all your work and get ready to compile your first SDL-OpenGL application.
这样好像不难吧!现在保存和准备编译你的第一个SDL_opengl程序.

Now, here a "preferred" compiler issue arises, keeping with the 100% cross compatibility guideline and because its my preferred compiler, I am going to explain how to create a simple makefile to compile with GCC, short for the GNU Compiler Collection, however, since I realize that most of the people out there are using Visual C++ for Windows compiling I am going to first give some advice for that particular compiler.

现在,这里一个"首选的"编译器,保持了100%的兼容和这还是我首选的编译器,我将会说明如何创建一个简单的makefile用GCC进行编译,使“GNU”编译收集器所花时间更少,因为我意识到有许多的人不使用“Visual C++”来“Windows”编译,这正是我首先对这种特别编译器提出建议。   

Visual C++ advice

As I said before, you should be familiar enough with your IDE to be able to set and compile your projects, and for the most part the settings that Visual C++ defaults to are good enough for a start, but when it comes to SDL, the defaults are not quite enough (your project wont even compile without some project setting tweaks).

正如我以前所说的,你可能对你的IDE(集成开发如KDEVELOP)有足够的了解以至有能力设置和编译你的程序,和Visual C++ 的大部分的设置是默认的(这对于刚接触的是什么好的.),但是来到SDL时,这些默认设置不是很完全(你的程序习惯于在没有其它程序setting tweaks下编译)

So, first of all you have to make sure you have  set up SDL properly, there is a tutorial here just for doing that, and from the SDL FAQ we find that the Visual C++ development package contains the document "VisualC.html" which explains the process, oh, by the way you can get that SDL "SDK" from this page.

所以,首先你要确保你正确地安装SDL,在这教程里,(我们)仅仅只要这些,你可以到SDL FAQ找到Visual C++ development页面包含的"VisualC.html"文档说明.

Read that, basically all you have to do is copy some files over, set an include directory, add SDL.lib and SDLmain.lib to your extra libs and then set your project to use the Multi threaded C libraries under the linking settings.

阅读到这里,基本上你所做的是复制一些文件,设置 include 的目录,增加SDL.lib ,
和SDLmain.lib(额外的库文件)和在连接设置的下面,设置你程序使用的多线程C语言库.

Other than setting up SDL you need to add the OpenGL libraries to be linked with your project, do that by adding OpenGL32.lib and Glu32.lib to the additional libraries space in the linking settings.

除了设置好SDL外你还要增加OpenGL库连接到你的程序中,在连接设置,通过增加OpenGL32.lib 和Glu32.lib来达到增加附加库

On to the makefile approach

Ok, first of all I want to make a quick note here, I know enough about make and makefiles to get around, but I am far from being an expert on this field, so please bear that in mind .

首先,我想在这里做个快速注解,我全面了解make和makefile相关的,但在这领域我远远没达到专家水平,因此请忍受.

There is more than one way to create a makefile, ranging from telling it to just compile and link all files in the directory into an executable, to going thru a complete multi developer-multi platform system such as the autotools system, we don't want to get that simple or that complex here, so lets set some guidelines.

不只一种方法来创建“makefile“文件,告诉它编译的范围并且连结目录里所有文件来执行,例如”the autotools system“这种可扩展的多平台系统。我们不想拿太简单或是太复杂的问题在此讨论,所以我们要做一些指导。

We want to compile an executable file which may or may not contain all source files that reside inside the directory, we want this makefile to run on (at least) Windows and Linux, and we want two ways to clean up our project, one to get rid of the object files and one to delete all object files and the executable so we can completely rebuild our source, or to get all neat for backup purposes.

The make syntax is not too different from the syntax of a programming language, basically you have variables, targets, dependencies, conditionals and some other stuff, variables are defined as variable_name = definition, and then expanded with $(var_name), you will find that most variables use all uppercase characters, so lets first define some global variables, open up your favorite editor and create a new file, give it the name "makefile" and type the following lines:

OBJS = main.o
LIBS = `sdl-config --libs`
CFLAGS = -O3 -c `sdl-config --cflags`

First we have the variable OBJS which equals main.o, this variable will hold a list of object files required to build our executable, if we had more source files we would add them to this variable separated by spaces, and if there were so many that you wanted to have a file per line, then use a back slash to let make know that the variable definition continues on the next line, in example if we had 2 files main1.o and main2.o we could use:

OBJS = main1.o main2.o

or

OBJS = main1.o \
            main2.o

Both of those are valid, but we only have one file to deal with here, so lets go on.

LIBS is also a pretty standard variable name is used to list the libraries that are needed to be linked with the object files, in this case we will only add the SDL libs with the use of the sdl-config script, a simple script that echoes the appropriate libraries, paths and flags for SDL, we will deal with the OpenGL libraries in a moment, so don't fret.

Finally CFLAGS is a list of flags to be passed at compile time, such as include directories, sdl-config takes care of those for us, and I like to feed the optimization level 3 flag to gcc ("-O3"), if you were debugging this program you would probably replace that flag with -g or -ggdb, also with a conditional you could pass a variable to make to decide which flag to use, but for now we'll just keep it simple, the -c flag tells the compiler to just compile and not link yet, this will generate an object file.

Conditionals:

Conditionals are really similar to pre compiler conditionals, and you have access to environment variables, so we will use this advantage to find out where are we running, Windows? Linux?, we need to do this because OpenGL libraries have different names on the different OS, so we will set a variable we will call OGLLIBS thru the use of conditionals.

Continue by typing the following on your makefile:

ifeq ($(OSTYPE),linux-gnu)
OGLLIBS = -lGL -lGLU
else
OGLLIBS = -lopengl32 -lglu32
endif

Pretty simple wasn't it? OSTYPE is an environment variable which on Linux, (or at least it is on Red Hat distributions) is set to linux-gnu, check yours by typing "set" on your console, typing it on cmd (also known as a DOS box in windows) will reveal that the variable is not present, but if you do it inside MSYS you will notice that OSTYPE=msys, anyway, you can use any other variable there to make the distinction between OS, I found OSTYPE to be the most appropriate, but now I am not so sure, feel free to experiment with it.

Targets:

A target is that, a target or a goal, something to shot for perhaps ? is something that we don't yet have, but we are getting to it, for example the object files are targets and so is our executable, targets have dependencies, or stuff we need in order to get to our target, these dependencies may be existing files or other targets, by default make will build the first target found, so we will use a dummy target to begin with, the all target:

all: Tutorial01.exe

The all target only has dependencies, and its only dependency is Tutorial01.exe, so when make finds all as the first target, it will then go on to build Tutorial01.exe, notice that if we had different executables to build we could just as well add them to the list of dependencies for all, and "make all" will indeed make all our executables.

Now that we have that lets continue with the object file target, continue with your makefile and type the following:

main.o: main.cpp
        gcc $(CFLAGS) main.cpp

That's a [tab] before "gcc" in case you are wondering, its necessary.

Basically here we are telling make that we have a target main.o, and that it depends on the existence of main.cpp, on the next line we give it instructions to actually get main.o, notice that you could add the arguments -o main.o to gcc, but this is not necessary. since gcc by default names the object file the same as the source file with an .o extension.

You would add a target like the previous one for each source file in your project.

Ok, we are halfway there, now we need a target for our executable, this isn't too different, so, continue by typing:

Tutorial01.exe: $(OBJS)
        gcc $(OBJS) $(LIBS) $(OGLLIBS) -o Tutorial01.exe

Again, there is a [tab] before "gcc". Here we have the new target Tutorial01.exe, which dependencies are the list of object files, now, you may be wondering why use a variable if you could just as well used main.o plain and simple, the reason is because the project may grow and grow, and you may want to be able to change the list of object files used right at the top of the file easily, but yes, you could have had just main.o instead of the $(OBJS) variable.

Anyway, this will cause make to look for the main.o file, which is nowhere to be found, but since there is a target that tells make how to get main.o, make will build main.o for you and then it will proceed to link Tutorial01.exe.

In this case we need -o Tutorial01.exe, otherwise the compiler will default to a.exe (a.out in Linux) and we don't want that.
 楼主| 发表于 2005-7-2 13:50:28 | 显示全部楼层
没有译完!不过在这一两天会译完的
回复

使用道具 举报

发表于 2005-7-2 15:18:01 | 显示全部楼层
楼主诚意可嘉,不过这样的译法跟没译的差不多。
回复

使用道具 举报

发表于 2005-7-2 15:45:20 | 显示全部楼层
但愿你不要用金山快译之类的软件翻译!!!那样的话简直是垃圾。
回复

使用道具 举报

 楼主| 发表于 2005-7-2 16:33:58 | 显示全部楼层
对我要一段一段的译!
回复

使用道具 举报

发表于 2005-7-2 18:41:35 | 显示全部楼层
英文对做技术的太重要了
回复

使用道具 举报

发表于 2005-7-2 21:56:29 | 显示全部楼层
把原文地址公布出来吧。:)
回复

使用道具 举报

 楼主| 发表于 2005-7-2 22:01:01 | 显示全部楼层
好像我没有保留原文的地址啊!现在还有译完!
回复

使用道具 举报

发表于 2005-7-3 09:20:12 | 显示全部楼层
谢谢楼主,呵呵!真的很厉害了,崇拜一下哈!
回复

使用道具 举报

发表于 2005-7-3 09:34:48 | 显示全部楼层
楼主,推荐你去搜索一下 Linux Game Programming,里面 Chapter 4 Mastering SDL 不错

另外。。。翻译这种事情,你不如全部翻译完成了再贴上来
回复

使用道具 举报

 楼主| 发表于 2005-7-3 13:53:20 | 显示全部楼层
[quote:45fffb275e="wolf0403"]楼主,推荐你去搜索一下 Linux Game Programming,里面 Chapter 4 Mastering SDL 不错

另外。。。翻译这种事情,你不如全部翻译完成了再贴上来[/quote]
好的,我译完这个,就去找一找,
另外,我因为要上班,做完手头上的事情先,放到论坛上以修改的方式来译:一方面,译了多少算多少,不会因工作地点的改变,而打断译的计划,另一方面:我看到有这么多的朋友支持.这也是一种动力!
回复

使用道具 举报

发表于 2005-7-4 09:06:53 | 显示全部楼层
路过支持一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-5 19:25 , Processed in 0.117019 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表