使用quake3的关卡编辑器,可以制造场景,设立玩家的出发点等等。
doom3则是将这个代码中model模型变成了lwo,md5,ma文件等等
image使用了dds图像了,material比quake的shader语言更加的丰富了
quake3关卡编辑器如图所示
(1)
quake3关卡编辑器的的brush如下
图片选自 http://wiki.splashdamage.com/index.php/Brush_Basics
、
(2)
patch,来做曲面的
这一篇主要乃是关卡编辑器代码的一些大致上的了解。
1、坐标系统
《QUAKE》中使用了标准的“左手系”坐标,如图所表示。“左手
”的意思是指你把左手半握拳,大拇指树起来的话,大拇指就表示了Z
轴,其余四个手指是从X轴指向Y轴。
有一些物体当然是摆放得比较随意,比较斜一点,这时就要用到
一个“角度”的概念了。《QUAKE》中的角度是如下设定的:
0-359: 普通角度
-1: 上
-2: 下
2、刷子(Brush)
刷子是《QUAKE》的地图中两个最重要的概念之一。每一个刷子都
定义了一个单独的区域。每一个区域都被看成是四个以上相互交叉的
面形成的。而每一个面又是由不在同一直线上的三个点定义的。注意
的是这三个点必须是按照顺时针的顺序排列。不过笔者至今没有弄清
楚为什么这些老外要把它叫做“BRUSH”。每一个刷子的声明
(Statement。注意!我们开始涉及到C语言的概念了!)都应是如下
形式:
{
( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0
( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0
( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0
( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0
( 0 0 64 ) ( 1 0 64 ) ( 0 1 64 ) GROUND1_6 0 0 0 1.0 1.0
( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0
}
也许您第一次看到它们的时候会觉得有些脑子发晕,反正我是。其
实这一大堆东西就是定义了一个从点(128,128,64)到点(256,384,
268)的长方体。每一行的意思如下:
128 0 0
128 1 0
128 0 1
GROUND1_6
0
0
0
1.0
1.0
第一点
第二点
第三点
材质
x_off
y_off
旋转角度
X轴范围
Y轴范围
解释:
第一点、第二点和第三点:这三点定义了一个面,所以当然不能是
在同一条直线上。每一个面只能被定义一次。
材质:所使用MIP材质的名字(MIP将会在以后讲到)
x_off:材质的X轴偏移,必须是16的倍数
y_off:材质的Y轴偏移,同样必须是16的倍数
旋转角度:材质旋转的角度,单位是度。
X轴范围:材质在X轴方向上的长度范围
Y轴范围:材质在Y轴方向上的长度范围
3、*.MAP文件基础知识
其实MAP文件的结构挺简单的,它就是一个文本文件。所有的
《QUAKE》编辑器都应该同时支持UNIX和DOS两种文本格式。
MAP文件是对《QUAKE》的关卡建造格式的说明。建议在改动
时尽量修改MAP文件,因为所有的id Software发布的工具都是针
对MAP文件做改动的。注意其实MAP文件都是一组“未编译”的数
据,只有在它转换为*.BSP文件之后才可以被《QUAKE》所认识。
转换是用专门的BSP转换工具来完成的,比如QBSP.exe。另外,MAP
文件还要由专门的光影处理器处理过,这样《QUAKE》才能计算出
在某个地方的光线强度。否则的话在游戏中会以最强光线显示这
部分地图。最后,为了使此地图在游戏中运行时速度更快和不出
错,还要用VIS这样的工具进行处理。总之,《QUAKE》总的地图
设计是一件非常费时间的事,比当年设计《DOOM》的地图要复杂
得多,即使你现在用的机器比那时候快了很多,但是可能你花费
的时间会更多。
MAP文件通常的结构如下:
{
entity
{
brush (optional)
}
}
...
在MAP文件中可以加进注释,方法和C++中是一样的,用“//”
表示后面是注释的内容。
在MAP文件中可以使用很多种实体(entity)和刷子的组合。
但是所有的MAP文件都要有一个worldspawn的实体,它通常都是
文件的第一个入口,里面定义了所有这个关卡中常用的刷子。每
一个MAP文件中只能有一个worldspawn实体。其构造如下:
"classname" "worldspawn" // 表示这是建造本关卡的QUAKEC函数开始!
"wad" "DIRPATH" // 表示使用哪一个图形文件,即*.WAD文件
"message" "TITLE" // 本关的名字
"worldtype" "#" // 本关的类型,0表示为中世纪的,1表示古巴比伦式
(这是基本模式), 2表示金属
"sounds" "#" // 决定放哪一首CD音轨
下面是一个简单的MAP文件示例:
{
"sounds" "1"
"classname" "worldspawn"
"wad" "/gfx/base.wad"
"worldtype" "0"
{
( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0
( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0
( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0
( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0
( 0 0 64 ) ( 1 0 64 ) ( 0 1 64 ) GROUND1_6 0 0 0 1.0 1.0
( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0
}
}
{
"classname" "info_player_start"
"origin" "256 384 160"
}
你可以看到,所有的刷子都包括在实物里了。其实MAP文件中
最复杂的部分是在于实物,这也是我们下面要进一步讨论的。
二、实物(entity)的基本知识
1、基本结构
实物是在MAP文件中另外一个重要的组成部分。实物当然可以
理解为一个东西,但是不完全是。有时它是一个触发的机关,有时
它是活动的暗门。一个实物的结构通常如下:
{
"classname" "light"
"origin" "0 128 64"
"light" "255"
}
这就是普通的实物结构的声明。“普通”的意思是说它还没有
和刷子结构联系起来。当两者联系起来之后的声明形式如下:
{
"classname" "func_door"
"angle" "0"
"speed" "16"
"targetname" "t1"
"sounds" "1"
"wait" "16"
{
( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0
( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0
( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0
( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0
( 0 0 64 ) ( 1 0 64 ) ( 0 1 64 ) GROUND1_6 0 0 0 1.0 1.0
( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0
}
}
注意,和实物相结合的刷子有一个“原始”标签,它是用来对在关
卡中的位置作一些偏移。
在接下来的部分中,我将给大家介绍一下实物的结构及其中的各个
选项。各个入口(entry)其实可以按任意次序排列,另外还有很多的
可选项。
2、spawnflag标签
spawnflag标签是一个附加的标签,就是说即使一个实体中已经有了
一个原始标签后也可以再加上一个SPAWNFLAG标签。它是用来说明一些额
外的属性:
1 - 额外的生命或弹药(比如生命超过100等)
2 - 超高生命
256 - 表示普通难度以上
512 - 困难难度以上
1792 - 这个值仅仅在死亡模式中才使用。
3、实物的语法
在《QUAKE》中,实物(entity)可以定义怪兽、物品,
另外还可以定义即将发生某种事件的位置。它们其实和DOOM
中的THINGS和LINEDEF这两种类型相对应。
实物的定义当中包括了一系列的项目:此实物是什么东
西,它什么时候出现,在什么位置出现等。每一条项目的后
面都跟有一些对它各方面的详细规定。每一个实物的定义都
有一个“类名(class name),类名就是在QUAKEC中的函数
名,它与“代码堆(code lump)”有很密切的关系。在对它
们作出说明的时候,我用到了“特性(specfics)”和“内
容”这两个词,也许他们并不是很确切,不过id并没有规定
他们叫什么,而且国外的玩家在说明他们的时候用的两个单
词也不是很容易恰当地翻译过来,就用他们吧!
特 性 内 容 说 明
"classname" "name" // 定义实物的类型,是必须要求的选项
"origin" "X Y Z" // 定义其在空间中开始放置的位置坐标
"angle" "#" // 此实物面对的方向或是移动的方向,有时用角度来表示
"light" "#" // 这是在光影类名中要使用的数值
"target" "t#" // 对应一个目标名
"targetname" "t#" // 就象是DOOM中的linedef标签
"killtarget" "#" // 当此角色击中你的时候带给你的伤害力
"spawnflags" "#" // 用来说明一个非缺省的实物
"style" "#" // 同上,是用来说明一个非缺省的实物
"message" "string" // 当事件被触发的时候显示的信息,用/n表示信息结束
"mangle" "X Y Z" // 指出中断镜头的视角
{BRUSH INFO} // 这是在描述触发事件、门或是平台等的实物中加进的刷子,它
用一对括号圈起来
下面是仅在描述游戏中的怪物角色的实物使用的特性:
"speed" "#" // 此角色的移动速度
"wait" "#" // 在反复移动间的停顿时间,用秒或十分之几表示
"lip" "#" // 此特性和调整角色的开始位置有关
"dmg" "#" // 表示当此角色击中你的时候带来的伤害力
"health" "#" // 在此角色在被触发以前的伤害力
"delay" "#" // 事件触发以前的时间
"sounds" "#" // 此角色的声音
"wad" "wadfile" // 此关卡中的材质使用的wad2 图象文件
"height" "#" // 一个平台可以上升的高度
实际使用中的结构如下:
{
"specific1" "arg1" // 第一个特性,通常就是类名
"specific2" "arg2" // 第二个
... // 其它特性...
{
<INSERT BRUSH INFO HERE> // 这部分是对于描述门、触发器或是平台的实物中加
进的刷子
}
}
在最后《QUAKE》中使用的*.bsp文件中的怪物数目取决
于一个叫model structure(角色结构)的结构中的数目,而
这个数目又来自原始的*.map文件中定义的数目。worldspawn
模块则定义了整个关卡的内容。
《QUAKE》中的怪物角色是定义在一个长方体中的,这个
长方体用两个对角点的坐标定义。因此可以想象,《QUAKE》
中的角色是始终和地面平行的。不过如果这么推理的话如果
角色出现在一个斜坡上就有些不合理了……
4、全部实物列表(对《QUAKE》1.01版)
air_bubbles : 上升的气泡
ambient_drip : 滴水的声音
ambient_drone : 机器的声音
ambient_comp_hum : 电脑的背景声效
ambient_swamp1 : 青蛙的呱呱声
ambient_swamp2 : 这种声效和上面的青蛙叫声很接近
func_door : 门
func_door_secret : 这是一种通过触发来打开的门
func_wall : ……一堵可以移动的墙?
func_button : 一个按钮
func_train : 平台,但是是那种会沿着固定的轨道移动的平台
func_plat : 升降机
func_dm_only : 这是一种只在deathmatch中出现的升降机
info_null : 这——什么都不是
info_intermission : 一种静止的镜头
info_player_start : 主玩家扮演的角色出现的位置,只能有一个。主玩家就
是在联网中建立新游戏的那个
info_player_deathmatch : 开始一个死亡模式,这个实物可以有多个
info_player_coop : 开始一个合作模式,它也可以有多个
info_player_start2 : ? 开始另外一个游戏?
info_teleport_destination : 给角色一个传送的目的地
所有的项目都有一个目标标签(target tag)。当目标标签被碰到后将触发某个特定事件。
item_cells : 雷电枪的弹药
item_rockets : 火箭炮和榴弹的弹药
item_shells : 射钉枪和超级射钉枪的弹药
item_spikes : 步枪和双筒猎枪的弹药
item_health : 救护包
item_artifact_envirosuit : 生化防护衣
item_artifact_super_damage : 四倍攻击力
item_artifact_invulnerability : 无限防护力
item_artifact_invisibility : 隐形戒指
item_armorInv : 红色装甲
item_armor2 : 黄色装甲
item_armor1 : 绿色装甲
item_key1 : 银色装甲
item_key2 : 金钥匙
item_sigil : 过关符号
light : 预设的光线,但是没有可见的光源。
light_torch_small_walltorch : 墙上的小火炬
light_flame_large_yellow : 黄色的大火焰
light_flame_small_yellow : 黄色小火焰
light_flame_small_white : 白色小火焰
light_fluoro : 荧光灯,发出嗡嗡声
light_fluorospark : 荧光灯,发出滋滋声
misc_fireball : 小火球
misc_explobox : 炸药包
path_corner : 用来定义轨道平台的路径
trap_spikeshooter : 发射钉子的机关
trap_shooter : 这是一种不用触发就一直向外发射钉子的机关
trigger_teleport : 升降机,由walkover的值触发
trigger_changelevel : 改变关卡
trigger_setskill : 改变难度
trigger_counter : 在被触发到指定的次数以后激发某个事件
trigger_once : 只能使用一次的触发事件(比如打开一道门)
trigger_multiple : 可重复触发的触发事件(比如
在关卡编辑器开始时,使用mfc来初始化这个opengl这个驱动等等的处理
检测鼠标,键盘的输入,滑动等等
我自己自个划分的有 界面层 ,操作层,介质层
界面层
专门画显示界面的
xy,z视图的对话框的处理
例如画三个视图的,一个显示3D的画面
设备层
鼠标,键盘按键的操作
操作层
对于这个介质的处理,平移,旋转,缩放,选择等等的处理
在各个介质里定义这个所对应的方法,者也
介质层
这个主要是关卡编辑器中加载创建的物体者也!
主要可以分为
3d max做出来了这个模型,
photoshop做出来了纹理图片了者也
这些东西在关卡编辑器中,被整合了进来了
关卡编辑器负责的整个的场景的营造,和怪物的摆放,还有玩家的位置的摆放处理了者也
q3ase做出来了这个游戏中的脚本了者也
最后这个引擎加载上了全部的游戏资源,赖在游戏中进行处理了
quake3的关卡编辑器,其实就像是在创建一个项目时,在安装下来了这个关卡编辑器后,会有这个baseq3这个文件包,里面包含了
texture(图片)
(模型),
maps(地图文件包的位置,里面包含了三张地图,
q3dm7smple1,q3dm1sample.map,q3dm1等等地图了)
script文件包,(shader文件)
基本上一个关卡中可以用到的模型,纹理图像,等等
shader文件来表示这个模型对应的entity的名字,和图像的名字
其实就像使用torque关卡编辑器一样,很快将穿件一个游戏的资源全部的组合在了一块了者也
以下另一部分东西者也
对于点的处理
点构成了线,线构成面,面构成了体,最最基本的思想了
以下是对于点的操作,最为基本之基本了者也
class idPointListInterface {
public:
idPointListInterface() {
selectedPoints.Clear();
};
~idPointListInterface() {};
virtual int numPoints() {
return 0;
}
virtual void addPoint(const float x, const float y, const float z) {}
virtual void addPoint(const idVec3_t &v) {}
virtual void removePoint(int index) {}
virtual idVec3_t *getPoint(int index) { return NULL; }
int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
idVec3_t origin(ox, oy, oz);
idVec3_t dir(dx, dy, dz);
return selectPointByRay(origin, dir, single);
}
int selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) {
int i, besti, count;
float d, bestd;
idVec3_t temp, temp2;
// find the point closest to the ray
besti = -1;
bestd = 8;
count = numPoints();
for (i=0; i < count; i++) {
temp = *getPoint(i);
temp2 = temp;
temp -= origin;
d = DotProduct(temp, direction);
__VectorMA (origin, d, direction, temp);
temp2 -= temp;
d = temp2.Length();
if (d <= bestd) {
bestd = d;
besti = i;
}
}
if (besti >= 0) {
selectPoint(besti, single);
}
return besti;
}
int isPointSelected(int index) {
int count = selectedPoints.Num();
for (int i = 0; i < count; i++) {
if (selectedPoints[i] == index) {
return i;
}
}
return -1;
}
int selectPoint(int index, bool single) {
if (index >= 0 && index < numPoints()) {
if (single) {
deselectAll();
} else {
if (isPointSelected(index) >= 0) {
selectedPoints.Remove(index);
}
}
return selectedPoints.Append(index);
}
return -1;
}
void selectAll() {
selectedPoints.Clear();
for (int i = 0; i < numPoints(); i++) {
selectedPoints.Append(i);
}
}
void deselectAll() {
selectedPoints.Clear();
}
int numSelectedPoints();
idVec3_t *getSelectedPoint(int index) {
assert(index >= 0 && index < numSelectedPoints());
return getPoint(selectedPoints[index]);
}
virtual void updateSelection(float x, float y, float z) {
idVec3_t move(x, y, z);
updateSelection(move);
}
virtual void updateSelection(const idVec3_t &move) {
int count = selectedPoints.Num();
for (int i = 0; i < count; i++) {
*getPoint(selectedPoints[i]) += move;
}
}
void drawSelection() {
int count = selectedPoints.Num();
for (int i = 0; i < count; i++) {
glBox(red, *getPoint(selectedPoints[i]), 4);
}
}
protected:
idList<int> selectedPoints;
};
对于这个点的列表的处理了者也
float idVec3_t::toYaw( void ) {
float yaw;
if ( ( y == 0 ) && ( x == 0 ) ) {
yaw = 0;
} else {
yaw = atan2( y, x ) * 180 / M_PI;
if ( yaw < 0 ) {
yaw += 360;
}
}
return yaw;
}
这个乃是Paich这个角度的处理
float idVec3_t::toPitch( void ) {
float forward;
float pitch;
if ( ( x == 0 ) && ( y == 0 ) ) {
if ( z > 0 ) {
pitch = 90;
} else {
pitch = 270;
}
} else {
forward = ( float )idSqrt( x * x + y * y );
pitch = atan2( z, forward ) * 180 / M_PI;
if ( pitch < 0 ) {
pitch += 360;
}
}
return pitch;
}
/*
angles_t idVec3_t::toAngles( void ) {
float forward;
float yaw;
float pitch;
if ( ( x == 0 ) && ( y == 0 ) ) {
yaw = 0;
if ( z > 0 ) {
pitch = 90;
} else {
pitch = 270;
}
} else {
yaw = atan2( y, x ) * 180 / M_PI;
if ( yaw < 0 ) {
yaw += 360;
}
forward = ( float )idSqrt( x * x + y * y );
pitch = atan2( z, forward ) * 180 / M_PI;
if ( pitch < 0 ) {
pitch += 360;
}
}
return angles_t( -pitch, yaw, 0 );
}
*/
idVec3_t LerpVector( idVec3_t &w1, idVec3_t &w2, const float t ) {
float omega, cosom, sinom, scale0, scale1;
cosom = w1 * w2;
if ( ( 1.0 - cosom ) > LERP_DELTA ) {
omega = acos( cosom );
sinom = sin( omega );
scale0 = sin( ( 1.0 - t ) * omega ) / sinom;
scale1 = sin( t * omega ) / sinom;
} else {
scale0 = 1.0 - t;
scale1 = t;
}
return ( w1 * scale0 + w2 * scale1 );
}
/*
=============
idVec3_t::string
This is just a convenience function
for printing vectors
=============
*/
char *idVec3_t::string( void ) {
static int index = 0;
static char str[ 8 ][ 36 ];
char *s;
// use an array so that multiple toString's won't collide
s = str[ index ];
index = (index + 1)&7;
sprintf( s, "%.2f %.2f %.2f", x, y, z );
return s;
}
brush类
(1)房间等等,基本几何体 ,方状,箱子状的物体,主要使用brush来处理
info_player_start : 主玩家扮演的角色出现的位置,只能有一个。主玩家就
是在联网中建立新游戏的那个,玩家在游戏中出现的位置了者也
info_player_deathmatch : 玩家死亡之后重生的位置了
path_corner : 用来定义轨道平台的路径
触发器的调用函数了者也
func_door : 门
func_wall : ……一堵可以移动的墙?
func_button : 一个按钮
func_train : 平台,但是是那种会沿着固定的轨道移动的平台
func_plat : 升降机
// entity 0
{
"classname" "worldspawn"
// brush 0
{
( 104 24 0 ) ( 104 24 8 ) ( 104 112 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0
( 120 56 0 ) ( 120 56 8 ) ( 96 56 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0
( 96 176 0 ) ( 96 176 8 ) ( 96 88 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0
( 96 0 0 ) ( 96 0 8 ) ( 104 0 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0
( 104 56 8 ) ( 104 0 8 ) ( 96 0 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0
( 96 56 0 ) ( 96 0 0 ) ( 104 0 0 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0
}
brush这个可以是3面的,4面,5面,6面的等等
构成brush的多边形用这个winding来表示
对于brush的创建,(挖空,csg组合等等)
struct brush
brush可以用来创建房间,台阶,等等很多地方体结构的东西,可以是3面体,4面体,5面体,6面体
等等
构成的,不明白node为什么有surface这个构成
构成了brush的面为这个side
struct side
{
winding*w; //构成了这个brush的side的凸多边性
int NumberWinding;//一个side面被分割成多少个凸多边形
};
这个winding乃是指得是凸多边形,这个是构成面的东西,可以把面分割成了无数个winding了,
构成这个一个面的墙壁照片,纹理!这个纹理图片可以是bmp图片,也可以是这个tga,jpg图片,
在经过对于纹理的平移,旋转,缩放等等的处理,来使得纹理图片贴在墙上的
我们可以替换纹理图片,
在quake3关卡编辑器中设置纹理的过滤方式,例如线性过滤,双线性过滤,各向异性过滤等等,过滤
对于brush各个面上side生成纹理的坐标算法,这样子我们才能把这个贴图添加到了brush上的每个面上了
那是通过3维点的点的处理等等
我们也可以设置这个side面的属性,例如是岩浆,液体,
runscrip,运行这个brush的脚本的处理者也
这个surface的系数者也,
entity的处理了者也
小的物体,entity (例如,触发器,md3模型,声音,武器,子弹 ,等等
都作为了这个entity这个的)
model
md3模型的处理
加载表示物体的md3 model,预先把3dmax,做成的3ds模型,ase模型等等
转化为了md3模型,
然后加入到了编辑器中,通过平移,旋转,缩放,等等安放到了合适的位置者也,
和合适的角度
entity物体
entity这个结构包含了各种属性
例如,实体的名字,target的属性等等的处理了
主要是指的这个声音,路径点,模型,武器,健康包等等游戏中用到的各种资源文件者也
关在卡编辑器中,我们可以指明白每个物体的名称,对应的模型的路径,是什么
(例如门,灯,楼梯,等等)位置,角度,方向者也
entity这个主要就是这个起点,位置,角度,这个物体的属性等等的处理了者也
,对应的模型,
(比如quake3游戏中那些静态的网格模型,骷髅灯,跳台)
声音(像doom3中经常有这个怪物的声音,非常的恐怖的哪一种等等)
等等
,关联的纹理,名字者也、
地形的处理等等
加载上了高度图来处理这个地形的!
(3
)地形,主要是将一张alpha地图加载上了,加载高度图,然后把这张地图最后映射到了山体上了,这样子,
来得到了山体的高度了,这个我也不太懂这个怎么来做的
比如我看到的堆顶点的方式来制造的这个者也
对于地形上,加上了顶点者也
计算这个地形的尺寸了者也
对于地形上插入了这个brush,就像是这个在山地上加入了这个一个房间一样,
我们要给这个山体加上了纹理者也,
如果选择到了这个brush添加到了这个上面,那么调用这个brush里的函数者也
对于山体的命名这个,
对于山体地形的制造,这个乃是使用的这个mesh网格点的的方式来制造的这个,
最后写入了这个地形的文件了者也
(5)
对于声音的处理了
声音在quake3中这个乃是作为entity的一部分来处理的
wav设置这个声音方面,加载声音等等的处理
在doom3中的这个
(4)
天空体 ,我们必须加上了这个表示天空的位置,属性,这样子就等于做上了这个天空盒子
例如天空盒的高度,云的高度
这个触发器,以及其他的playersart等等,还有其他的东西,使用了一个红色的小箱子,来表示了者也
路径点的设置,这样子,机器人就能按照我们给出的路径进行移动了,
重生点,这样,死后重生的位置等等,用于死后的重生
还有第一次出生的位置等等的设置,这样子在游戏开始后,我们就能够在这个这个位置上把照相机的
位置放到了这里了者也
shader脚本
表示所有的物体的属性的文件,
并非是现在的cg,glsl,hlsl等等文件了者也!
有关entity物体的属性,brush的属性用来表示他们属性的文件,称为shader文件,
这个文件保存了物体的位置,
brush的位置,还有这个brush各个面上的属性,例如各个面上的纹理的名字,面上的属性(液体,岩浆,等等)
的处理者也
shader属性文件类
保存这个场景以内物体的属性者也,例如这个brush的位置,方向,纹理坐标者也
等等
quake3使用shader脚本来表示物体的属性,entity,纹理,灯光,等等的信息者也
例如entity的起点者也,名称,等等的信息的处理者也
等等,随着我自己看quake3的代码的深入很多时候真的很佩服这个引擎的功能之多者也
shader脚本,(表示纹理的阶段)
textures/sfx/metalbridge06_bounce
{
//q3map_surfacelight 2000
surfaceparm nodamage
q3map_lightimage textures/sfx/jumppadsmall.tga
q3map_surfacelight 400
{
map textures/sfx/metalbridge06_bounce.tga
rgbGen identity
}
{
clampmap textures/sfx/jumppadsmall.tga
blendfunc gl_one gl_one //纹理的 混合方式
tcMod stretch sin 1.2 .8 0 1.5
rgbGen wave square .5 .5 .25 1.5
}
// END
}
quake3关卡编辑器可以加载jpeg图像,pk3图像,因为有这两个的库存在的者也,我们解压加载pke3文件,寻找路径者也
这一部分应该移除到了这个shader脚本之外的
可以控制水波wave是由三角形,四边形,等等其他的属性,把他们保存下来,
在渲染时,根据这个水波的类型,来进行渲染者也
水波在渲染时使用什么图元来进行显示呢?例如这个triangle等等的处理者也
天空盒的参数等等
裁剪面方式(裁剪前面,裁剪后面,)
纹理的参数等等,
例如
textures/liquids/lava //表示的纹理是液体里面的岩浆
{
deformVertexes wave sin 0 3 0 0.1//表示这个岩浆的属性者也
tessSize 64
{
map textures/common/lava.tga //岩浆图像的路径者也
}
}
根据这个shader这个脚本制定的很多方面来执行命令者也
雾的颜色,(rgb等等),deform这个的属性,表示brush这个的形式者也
quake3关卡编辑器可以加载jpeg图像,pk3图像,因为有这两个的库存在的者也,我们解压加载pke3文件,寻找路径
代码中发现了brush的合并,想减,这个者也,对于brush的脚本进行运行
设置光源的属性,
Item图标者也
选择与撤销怎么来实现的呢?
(3)变换这个视图模式,例如三视图画图,只有一个xyz视图,来进行画图者也
设置这些物体,不过是最后编译时显示出来者也,其实并没有什么的
最后编译成的这个map地图格式是什么样子呢?
在编辑器中主要是windows的消息机制,把玩家所做的操作等等,来保存下来,在一
画出来几种视图,来使得这个显示等等,
对于这个shader这个部分的处理者也
选择brush的时候的处理,