Artoirus
- Blog
- Archives
XNA教程-3D游戏-01-3D游戏教程简介
在之前,我把所有的2D视频教程都用文字重新写了一遍,也完成了2D教程中完成的那个例子,应该说,如果是XNA变成从无到有的话,那收获已经颇为丰富了。并且,教程中所有的More Details(原视频教程的页面)我也都进行了翻译,一部分还加上了一些自己的说明。应该说,无论是机械的完成代码学会技能,还是了解一些XNA提供的实质性内容,都起到了很大的作用。
之后正好面临我的期末考试,一个学期也就这么几天读书的,总要成全我吧。所以加上复习和考试,暂停了那么几天博客的更新,也算是之前一星期之后的小小的休息吧。现在回家放暑假,休息了几天之后,我决定继续开始3D的教程了,利用之前在2D学到的东西,我们应该可以轻松的进入3D的学习了。
在3D的教程中,我们将完成一个2D教程中的demo中的3D版本。我们要完成一些类似的东西,也会接触一些新的东西。
- 建立自己的3D环境 —- 毕竟是3D游戏了,所以不单单是像2D一样画一个背景就好了,我们需要建造自己的3D外太空环境。
- 添加加农炮 —- 同样内容相似的,我们需要一个可以旋转的加农炮,只是这次的旋转是在3D环境中了。
- 添加炮弹 —- 加农炮设计的炮弹,也将在3D环境中处理,当然其实也就是初速度稍许不同,接触到之后就会发觉到2D教程的作用了。
- 添加敌方UFO —- 还是类似的,UFO从屏幕的远端向近端飞来,而不是右侧飞到左侧了哦。
- 碰撞检测 —- 3D的碰撞检测。
- 添加声效 —- 之前2D的游戏是没有声音的,这一次的3D中我们将加入声音,者是新的内容,会十分有趣的。
大致的内容就是这样。当然,如果你没有看2D的教程,直接开始3D的也是可以的,只是和2D对比的部分直接略去就可以了。另外,本教程使用XNA Game Studio 3.1开发,如果你是使用的是之前的版本,或者是未来的某个版本,那么其中也许会有一些不同之处。如果你刚刚开始,那么就赶快装上Game Studio开始吧。
相关链接:
- XNA教程-2D游戏-索引
- XNA Creators Club 教程原址
- XNA Game Studio 3.1 介绍及下载地址
- 环境配置及安装的简单介绍请看《XNA Game Studio 3.1 Available》
Demo效果图:
Comments
Copyright © 2013 Arthur Wang
2.
Artoirus
- Blog
- Archives
XNA教程-3D游戏-02-创建游戏工程
进行了之前的工作,搭建了环境之后,现在就要进入实际开发过程了。我想过程和2D也许存在着一些区别,但是还是相对比较依赖2D教程的,尤其像这一章和3D的确是别无二致,不过我这里还是按照步骤说一下。(参考:《XNA教程-2D游戏-Chapter2-创建游戏工程》)
使用GS3.1+VS2008是基于.NET Framework 3.5的,否则一些新特性将不会被用到,如果你的开发使用其他环境,那么也许会不一样。
具体涉及到一些可能和2D教程重复的东西,看过2D的直接跳过就好。
第一步、Visual Studio简单介绍
安装高于Visual Studio 2005 Express的版本,并且装好XNA Game Studio(2.0以上)。那么如果安装成功的话,在VS的新建对话框中应该可以看到这么几项(GS3.1+VS2008,不保证其他版本有一样的工程)
- Windows Game (3.1) —- XNA Game For Windows游戏的开发,很多游戏打着这个标志
- Windows Game Library (3.1) —- Windows游戏类库
- Xbox 360 Game (3.1) —- Xbox360游戏
- Xbox 360 Game Library (3.1) —- Xbox360游戏类库
- Zune Game (3.1) —- Zune游戏
- Zune Game Library (3.1) —- Zune游戏类库
- Content Pipeline Extension Library (3.1) —- Content管道扩展库
- Platformer Starter Kit (3.1) —- 一个游戏示例(提供windows x360 zune三种版本都有)
第二步、新建工程,获取资源
根据刚才介绍的新建,建立相应的工程。
比如我新建一个Windows Game (3.1)工程,并且取名为TChapter2,那么我们可以得到一些IDE为我们创建的文件,具体情况如下。
- Content —- 就是一切我们需要的游戏资源,在XNA中存在Content Pipeline这个概念,而这里的所有资源可以之后在Content管道中直接调用加载。
- Game1.cs —- 游戏逻辑代码。
- Game.ico —- 不用多说,一个Xbox360的手柄样式的ico图标。
- GameThumbnail.png —- 正如他的名字,是一个缩略图,当然要你自己画的啦。
- Program.cs —- 就是程序的入口Main方法了。
第三步、下载资源
接下去本章很重要的一部就是下载必须的游戏素材。这里提供官方链接,下载解压缩后就可以看到我们本教程的例子要用到的全部素材了。
【点击下载官方素材】
Comments
Copyright © 2013 Arthur Wang
3.
Artoirus
- Blog
- Archives
XNA教程-3D游戏-03-添加Asset
到了这里其实还是和2D的教程是重叠的,这里我们要做的是添加asset们。所以这里你要问自己三个问题:
- 你已经建立了工程(project)了吗?—- 点我补课
- 你已经下载了上一部分要求下载的资源了吗?—- 点我下载
- 你知道什么是asset吗?你看过之前2D教程的添加asset内容吗?—- 点我补课(重点浏览链接指向的文章的后半部分,讲解什么是asset)
三个问题过关的,再来看我的这里的屁话。放假回家,所以把编译一个XNA游戏都要3分钟的windows xp给格掉了(关注我的twitter的一定知道了),所以把windows 7的引导也格掉了。因为找不到之前安装windows 7的那张光盘,所以一下子没有修复引导,所以这一次的教程就先用XP完成了。装了3、4的系统,终于把一个一个的东西下载下来给装上了,现在可以继续了。
OK言归正传,看看这一次要做的是如何简单。和2D类似的右键添加等等工作,就能完成了。
第一步、添加models到工程的content中
Content中的asset可以在content pipeline中被我们调用。这是一个非常方便的设计,当然这也使得我们这一步的工作显得非常重要,你可以从磁盘去读取一些你需要的资源,但是让他在content管道中,会大大方便你的管理。
2D教程中,我们加入一些.tga资源到Content/Sprites中,我们右键新建文件夹,然后添加存在的资源等等这样完成了这部工作,那么这一次和视频一样,我们偷懒一下。直接把解压缩出来的models文件夹拖到VS2008的树状Solution Explorer的Content目录上,来完成这一步工作。
添加进来之后,我们看到了一些.fbx文件和.tga文件,fbx就是我们的模型,而tga是这些模型对应的贴图,不会被我们实际的工作主动调用到,他们只要在他们应该在的磁盘位置上就可以了,在我们调用模型的时候,相关联的贴图会自动被寻找,所以把他们排除我们的工程吧。右键选择所有的.tga文件,选择”Exclude From Project”将其排除工程。
第二步、添加audio到工程的content中
这还分成两步看起来有点傻,一样的,把解压缩出来的audio文件夹也一并拖到Solution Explorer的Content目录上。展开Audio文件夹,右键点击Waves目录,选择”Exlude From Project”,把这些.wav文件全部排除在工程之内。因为对于声音的asset处理会有很大的不同,所以这里我们暂时先这样处理就好。
准备就绪之后,就可以开始代码阶段的工作了。
【官方工程下载】
Comments
Copyright © 2013 Arthur Wang
4.
Artoirus
- Blog
- Archives
XNA教程-3D游戏-04-绘制3D地表
安装好环境、建立了XNA工程、添加了要用到的模型以及贴图,那么接下来要做的就是实际的代码了,而一上来就和2D大为不同的是,我们要直接创建我们的”宇宙环境”。要知道,在2D游戏中,我们游戏的”世界”是整个一张图,就是背景,简单的2D游戏就是这样。而3D则不然,即便是这个环境,那么也是需要我们用模型自己创建的,而这将会是一个非常复杂的工作,究竟如何复杂,看到下面的所有内容你就明白了。
从2D到3D,应该说当前我们在做的是一个非常困难的转换时期,我们要完成第一个3D的绘制,那么就必须了解很多很多只有在3D游戏中才会出现的概念。但是,简单的说,在代码上我们要完成的工作还是类似的,比如2D中,我们先声明了sprite;然后loadContent,或者load确定它的位置等信息;最后我们draw把它绘制出来。那么一样的,3D也是声明、初始化、绘制三个工作。只是2D中无论是初始化还是绘制都是相对简单的,3D就要复杂的多的多,跟着步骤走吧。
第一步、创建模型,确定视角
似乎看了标题就有些茫然,有很多的概念要讲,不过和2D教程一样,先直接说代码怎么写,回头再讲大道理。(本文后面将会有官方解释的翻译内容)
1、声明场景模型
代码找到Game1类中最前面,SpriteBatch spriteBatch;这一行的下方,在这里我们先插入这样两行代码。
Model terrainModel; Vector3 terrainPosition = Vector3.Zero;
这里用到了XNA Framework提供的Model类,以及Vector类。
显然,terrainModel这样的命名让人比较容易理解,就是场景模型,这是我们的场景或者说是地面模型,都一样,就是我们的大环境。
而terrainPostision就更加容易理解了,是terrain的位置,究竟整个地表是怎样的一个位置。这里我们用Vector3这个类来描述。Vector3是一个3维的向量,就像Vector2是X,Y两个轴的向量一样,Vector3实质上就是把Vector2扩展到X,Y,Z,3个轴的向量。初始化为Vector3.Zero,即在整个3维坐标系的原点上。
和2D游戏不同,我们2D游戏所有涉及到的坐标都是在屏幕范围内的。我们知道屏幕向右是X轴正方向,向下是Y轴正方向,所以所有的坐标都是在这样一个坐标系上想象的。而3D游戏则不同,我们必须把这些位置都想象在自己的脑海中,因为屏幕看见的什么只是你3D世界的一角,你必须在整个思维中存在你的自己的一个三维世界,它所在的一个三维坐标系和它的所有坐标。然后我们再讨论从什么视角(什么坐标)去看这个世界。
2、声明镜头
说明一下,这里的镜头英文应当是camera,翻译成相机这样子比较好。不过也许很多像我一样的游戏玩家会知道,一般我们评价一个游戏,会说镜头能控制不能控制等等,所以我想这个词会更加容易被接受。我的文章里的镜头,指的就是camera。可以想象你的眼睛就是你看这个现实世界的camera。
在刚才两行代码下面,继续写以下内容。
Vector3 cameraPosition = new Vector3(0.0f, 60.0f, 160.0f); Vector3 cameraLookAt= new Vector3(0.0f, 50.0f, 0.0f); Matrix cameraProjectionMatrix; Matrix cameraViewMatrix;
详细说一下我们做了什么。
- cameraPosition:这是镜头所在的位置,比如我们的眼睛在脸上这样的描述。这里是(0, 60, 160)这样一个位置。
- cameraLookAt:镜头的焦点。可以想象一下terrain被放在Y轴也就是高度轴的0上,镜头被放在Z轴也就是深度轴的160的位置,高度是60的位置,而它看着Y轴上50的那点,连成的直线就是你的视线了。
- cameraProjectionMatrix:镜头投影矩阵。
- cameraViewMatrix:镜头视角矩阵。关于两个矩阵,先不详细讲了。图形学中涉及到了任意点的变换可以使用矩阵,矩阵变换是一个图形学非常重要的概念。稍微讲一下。
矩阵变换一般情况下有平移、缩放、旋转。各种复杂的变化都可以由很多这样的操作完成。其他还有诸如投影、切割等等。所有的变化都可以最终表示成为一个矩阵,这就是变换矩阵。不详细讲,举3个例子。
例一:平移 W(wx,wy,wz)
例二:缩放 T(tx,ty,tz)
例三:绕X轴旋转alpha度
当然在XNA framework里封装的Matrix类不是一个简单的矩阵的实现了,还加上了很多智能的功能,当然也包括变换,至于如何使用这样一个Matrix,以及我们声明的Matrix是做什么样的变换的,看下去。
3、初始化变换矩阵
我们要初始化声明的资源,那么就要找到LoadContent()方法,在其中TODO的位置加上这样两句。
cameraViewMatrix = Matrix.CreateLookAt( cameraPosition, cameraLookAt, Vector3.Up); cameraProjectionMatrix = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(45.0f), graphics.GraphicsDevice.Viewport.AspectRatio, 1.0f, 10000.0f);
这里做的工作是实例化两个Matrix,但是这里用到了Matrix类中的CreateLookAt和CreatePerspectiveFieldOfView方法。说下参数的意思。
- CreateLookAt:
- cameraPosition:Vector3,镜头所在位置
- cameraLookAt:Vector3,镜头焦点坐标
- Vector3.Up:Vector3,按照MSDN所说传入”上”就好,当然你可以试一下其他方向……
- CreatePerspectiveFieldView:
- MathHelper.ToRadians(45.0f):float,视角大小
- graphics.GraphicsDevice.Viewport.AspectRatio:float,窗口的比率,”宽”比上”长”的比率
- 1.0f:float,镜头最小深度(近处)
- 10000.0f:float,镜头最大深度(远处)(恐怕真三国无双和GTA这样的游戏里面这个参数的体会会比较深刻)
初始化完毕,就可以接下去继续了。
第二步、编写模型绘制方法
因为游戏中将会出现很多很多的模型,虽然每一个模型都有其特殊的地方,但是每一个模型都将拥有一个默认的绘制方式。而,即便采用默认的方式,绘制模型也将会涉及到很多操作,所以将本来可以在draw方法中完成的内容单独的写一个方法来完成。方法传入的参数为模型和其所在的位置,这样我们的方法就可以把它用一样的操作绘制出来。
这里涉及到一个ModelMesh的类,每一个Model都一个很多的ModelMesh的集合,因此我们需要单独绘制每一个mesh。至于ModelMesh和Model的概念,在后面会加上说明。(本文后面将会有官方解释的翻译内容)
具体方法是,在Game1类中重新写一个方法,当然是任意位置的,代码具体如下。
void DrawModel(Model model, Vector3 modelPosition) { foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.PreferPerPixelLighting = true; effect.World = Matrix.CreateTranslation(modelPosition); effect.Projection = cameraProjectionMatrix; effect.View = cameraViewMatrix; } mesh.Draw(); } }
如参正如之前所说,一个是Model类,一个是Vector3类,分别表示要绘制的模型和其所在的位置。
- 第一个foreach循环是遍历Model中所有的ModelMesh,单独处理每一个。
- 第二个foreach循环是遍历ModelMesh中的Effects,单独处理每一个效果的处理。具体看看做了一些什么
- EnableDefaultLighting():设定光源为默认光源。
- effect.PreferPerPixelLighting = true;:在支持Pixel Shader Model 2.0的情况下,开启每个像素按光源渲染的效果。
- effect.World = Matrix.CreateTranslation(modelPosition);:创建传入模型的矩阵变换
- effect.Projection = cameraProjectionMatrix;:设定投影变换矩阵。
- effect.View = cameraViewMatrix;:设定视角变换矩阵。
这样,我们就完成了绘制方法的编写。但是不要忘了,我们还没有加载需要绘制的模型,也没有在draw方法中调用这个方法,所以看接下去的两步,完成这两个工作。
第三步、加载模型
载入模型才能画,载入模型的方法和2D的一模一样,只是一个操作的是Sprite,一个操作的是Model,但是我们知道LoadContent方法是支持范型的,那么显然我们的工作就变得非常的简单了。
找到LoadContent方法,在之前添加的代码下面加上如下代码。
terrainModel = Content.Load
(@"Modelsterrain");
这样,这一步就简简单单的完成了。
第四步、绘制模型
之前第二步完成的工作就大大简化了这一步我们的代码了。而这一步我们就只要调用之前我们写的drawModel方法,并且传入我们的模型和位置就可以了。
在Draw方法的TODO处,加入以下代码:
DrawModel(terrainModel, terrainPosition);
还等什么呢?现在就是编译运行的时候了!效果图。
下面加了4张修改了参数之后的图,方便理解一些参数。[点击放大]
- cameraViewMatrix实例化,CreateLookAt时,修改第三个参数为Vector3.Down
- cameraPosition声明并实例化时,修改为Vector3(0.0f, 100.0f, 160.0f)
- cameraProjectionMatrix实例化,CreatePerspectiveFieldOfView时,修改第一个参数为90.0f
- cameraProjectionMatrix实例化,CreatePerspectiveFieldOfView时,修改第四个参数为5000.0f
【官方源代码下载】
那么下面就贴翻译的内容,也算是比较重要的东西了,2D和3D游戏的概念上的区别。
(以下翻译为本人原传,未经允许严禁转载。另外,因本人能力有限难免出错,请高手指正。原址点击这里。)
1、3D世界:2D游戏和3D游戏之间的区别
如果你学习过第一个教程(创建2D游戏),那么你已经变得习惯用2D空间来思维了。位置、方向和动作可以全都用Vector2和一个单独的旋转角度来表示。
这个教程介绍了在三维的概念,和其一系列的新的对象。从根本上,3D世界区别于2D世界的就是新增的第三个坐标轴—-Z轴,或者说是深度。在XNA Game Studio中,2D世界实质上是一个特殊的,受限制的3D世界的版本—-你将会在本教程读到的计算也同样在2D中可以读到。
在XNA Game Studio这哦你,3D的变化意味着,取代在平面世界中画静态的Texture2D对象的是绘制用Model类表示的3D模型。Model类是被叫做网络(mesh)的许多有联系的3D点的集合,在整个世界中,最终渲染在屏幕上的对象,取决于对象的位置和方向,和镜头的位置和方向。
这过程也许初看十分复杂,但其实在3D世界编程,只依靠一些非常基本的元素。想象一个点在3D空间中,一个点有一个X坐标,一个Y坐标,和一个Z坐标。非常类似2D空间中的一个点,3D空间中的一个点也可以使用一个向量来移动,但是在3D空间中,我们使用包含Z坐标的Vector3类。
然而,使用一个叫做矩阵的数学结构体,可以使3D点做更多的事情。这些结构体,在XNA Framework中表示为Matrix类,它描述了一系列可以应用于点的变换、点的集合、或一个响亮。使用矩阵,3D对象可以移动、旋转、切割、以及(通过使用被叫做视点矩阵和投影矩阵的特殊的矩阵)绘制成一个可以显示在屏幕上的2D图像。
想象有一系列我们想画在屏幕上的3D世界中的点。它们拥有相对于被叫做原点的中心点的位置和方向信息。如果没有任何的变换,这些点只是存在于他们自己的空间,被叫做”对象空间”。
当你加载一系列的点,并且把它们添加到你的3D世界中,你可能会想给他们一个在3D世界中的位置,用来旋转或切割他们。这些行动的产物被叫做世界变换矩阵。应用了这样的矩阵的点,就被想象成在”世界空间”中(而不是对象空间中)了。
来渲染在用户屏幕上的点,需要一些附加的信息。没有要绘制的2D场景的角度和位置,是不可能把整个3D常见转换到2D图像的。使用一个视点是必要的,也被称作镜头,只需绘制它所看到的3D场景。在准备这次绘制时,镜头信息会被计算到一个视角矩阵中,把3D点的方向和位置都和镜头联系起来。之后,这些3D点就被想象成在”视觉空间”中了。
用2D绘制一个3D场景最后还需要一些其他信息。像视点的视角和领域的信息,控制着3D点如何绘制在2D计算机屏幕上。这些信息存储在一个投影矩阵中,应用之后,把3D坐标的系统中的点转换到2D坐标系统中,2D坐标系统被成为”屏幕空间”,这样点被绘制成像素。
如果要套用这个概念到3D点的集合所组成的网络(mesh)上(可以是3D表示的任何东西,一个飞船、一个人、或一只恐龙),你只需用到一些在XNA Framework中的基本的对象来制作你的游戏—-Mesh类,Matrix类和Vector类。
2、创建一个模型绘制方法
绘制一个3D模型到屏幕上是一个复杂的工作。它包括了庞大数据量的多边形的绘制,而它们经常被构造成许多不同的方式。有些可能是基于艺术效果的,而有些也许是倾向于程序化的。绘制同时也是必要的工作。每个游戏中可见的3D对象都是需要经过一个绘制过程的。
毫无悬念的,不是只有一种组织一个模型绘制方法的方式。参数、界限以及绘制算法对每个游戏来说都是不同的,取决于游戏的需求和涉及的技术。在这样的情况下,XNA Framewrok没有尝试去提供一个单独的模型绘制方法。取而代之的是提供一些元素,而把组织它们的工作留给了程序员来做。
一个Model类是XNA Framework中表示3D模型的一个基本对象,但是它比最初的模型要复杂许多。一个模型由一个或多个ModelMesh对象以一个集合的形式组成。每个ModelMesh对象是一系列组成网络(mesh)的顶点的集合,它们可以在同一个模型中被单独的移动。
一个坦克的模型是一个很好的例子。坦克的身体也许是一个ModelMesh,坦克的炮台也许是另外一个。虽然你绘制的是整个坦克,但是你可能需要分开移动坦克的不同部分。你可以使用ModelMesh对象的集合来移动不同的部分。
ModelMesh包含了一个绘制方法。每绘制一个ModelMesh到屏幕上需要调用这个方法一次。然而如果你没有实现设定变换和MedelMesh上的光的属性,那么你什么也看不到。
变换(决定了ModelMesh在世界中的定向,并且最终,物体是否出现或是出现在屏幕的哪里)和光()没有被应用到ModelMesh层面。相对的,每个ModelMesh有一些Effect和它联系在一起。一个Effect对象可以想成提供给可视设备的说明,关于如何绘制一个ModelMesh。
在很多游戏中,Effect对象是由很多复杂的顶点和像素遮罩(shader)组成的。在XNA Game Studio中也可以实现,并且对于高级图形效果来说十分重要。但是在简单的渲染中,XNA Framework Content Pipline(内容管道)提供了一个简单的机制来完成基本的光和绘制效果 —- BasicEffect类。
每个通过content pipline加载的ModelMesh接受了一个或多个BasicEffect对象,它们可以在不处理像素或顶点遮罩(shader)的情况下简单的处理变换和光源效果。所有这些BasicEffect类需要一系列表示世界(World)矩阵,视点(View)矩阵和投影(Projection)矩阵的Matrix类,和一些光照的参数。可以调用BasicEffect.EnableDefaultLighting()方法获得默认的参数。
在BasicEffect的参数被设置后,剩下的就只有调用ModelMesh.Draw方法,使用之前为BasicEffect设置的参数,来绘制ModelMesh到屏幕上了。
Comments
Copyright © 2013 Arthur Wang
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/177912.html原文链接:https://javaforall.net

