文档库 最新最全的文档下载
当前位置:文档库 › flightgear

flightgear

flightgear
flightgear

基本架构,架构分析的前提是编译flightgear

在flightgear内部,命令行参数分为6种类型:BOOL、String、Double、Int、Channel、Func

其中Bool、String、Double、Int都是直接对相应的属性(可以理解为内部的变量)进行赋值;

如:--airport=ZSSS 初始化时设置机场ICAO为ZSSS(上海虹桥)

Func类型则是在初始化阶段直接调用内部函数进行处理。

如:--random-wind 初始化时调用fgOptRandomWind,设置随即风

不过有些Func类型的参数是需要输入参数的,如:--func_key=func_argv

Channel类型参数主要用于外部接口通信,一般都可以复用(如:在命令行中可以有多个--native-fdm=xxx)

这种类型的参数有大家熟知的--native-fdm、--generic、--atlas等

具体的源码解析流程见图

flightgear网络接口模块是有FGIO子系统来完成的。FGIO子系统支持各种通信协议。

通信协议包括大家常用的:Native-fdm,Native,generic,jsclient等(也即前篇介绍的channel 类型参数)

对应的参数形式:--protocol=medium,direction,hz,medium_options,...

在flightgear架构分析中提到了,对于子系统,flightgear在初始化阶段调用子系统的bind(),init(),主循环阶段调用子系统的update(),最后调用子系统的shutdown。

因此对于FGIO子系统,在程序中也主要体现在bind、init、update和shutdown这几个函数的处理上。关于FGIO的结构如下图

通信协议的具体实现在FGIO的FGProtocol列表中,FGIO在每个周期都会调用每个FGProtocol 的处理函数,关于FGProtocol的结构如下图

下面具体对generic通信进行介绍,generic是通过FGGeneric(FGProtocol子类)来完成的,结构如图所示

Flightgear多人飞行对应的参数是multiplay。

具体参数结构如下:

--multiplay=dir,freq,ip,port --callsign=your_name

其中callsign代表自己的ID

官方文档上给出的例子是:

For two players on a local network or across the internet:

----------------------------------------------------------

Player1:--multiplay=out,10,192.168.0.3,5500 --multiplay=in,10,192.168.0.2,5501

--callsign=player1

Player2:--multiplay=out,10,192.168.0.2,5501 --multiplay=in,10,192.168.0.3,5500

--callsign=player2

For multiple players on a local network:

----------------------------------------

Player1:--multiplay=out,10,255.255.255.255,5500 --multiplay=in,10,255.255.255.255,5500

--callsign=player1

Playern:--multiplay=out,10,255.255.255.255,5500 --multiplay=in,10,255.255.255.255,5500

--callsign=playern

对于局域网内,2人联机飞行是没问题的,但是多人联机,通过广播的方式通信时会报错!!!因为在程序内部不能对广播地址进行绑定。

所以文档上关于广播方式联机的例子是有误的。

原因在于,flightgear对于广播地址没有进行判断,直接按照常规地址进行绑定,所以会绑定失败。

对于局域网多人(至少3人)联机飞行,这里给大家提供3种方案:

1.自己单独在一台主机上搭建服务器,目的很简单:数据转发。所有联机的客户机把--multiplay=out,10,server_ip,5501中的地址设为服务器地址。服务器则把收到的数据发给所有的客户机。

2.通过组播方式进行通信,虽然flightgear(实质是simgear)没有对广播进行特殊处理,但是它能识别组播地址。

3.修改flightgear程序。

对于广域网多人联机飞行,由于路由器一般不支持广播和组播,因此这里提供2中方案:

1.使用flightgear提供的在线服务器,连上去即可

2.自己搭建服务器(思路与局域网方案1一致),但是服务器需要固定IP

下面来分析如果修改flightgear程序来达到联机飞行的目的:

multiplay主要是有FGMultiplayMgr子系统来管理的,根据前面分析,对于子系统的处理主要是以下几个过程:

bind()

init()

update()

shutdown()

FGMultiplayMgr的重点是init:

init进行以下几个处理:

mSocket.reset(new simgear::Socket());

mSocket->open(false)

mSocket->setBlocking(false);

mSocket->bind(rxAddress.c_str(), rxPort)

这几个处理没有判断地址的类型,因此在bind阶段就会出现广播地址绑定失败!

为了解决这个问题,可以把以上过程改成以下过程:

mSocket.reset(new simgear::Socket());

mSocket->open(false)

mSocket->setBlocking(false);

mSocket->setBroadcast(true);

mSocket->bind(“0.0.0.0.”, rxPort)

Flightgear支持4个输入方式:

鼠标输入

键盘输入

游戏杆输入

事件输入

对应的子系统分别为:FGMouseInput、FGKeyboardInput、FGJoystickInput、FGEventInput 这几种输入的处理方式大同小异,本文以键盘输入为例,分析flightgear是如何响应键盘消息,以及如何自定义键盘消息。

flightgear处理键盘消息分为以下3个过程:

1.加载配置文件,配置文件包括"preferences.xml",“(your_aircraft)-set.xml/(your_aircraft)-set-common.xml”等。其中键盘的配置信息在/input/keyboard节点内

2.FGKeyboardInput的初始化,也即flightgear注册按键响应函数

3.FGKeyboardInput 的postinit过程,也即绑定按键到对应对象(该对象实现具体的按键响应过程)

具体的流程图如下:

下面来具体看看flightgear是如何响应按键:

以777-20飞机为例,在飞机的配置文件中注册了Ctrl-L按键消息:

Ctrl-L

toggle cabin lights

property-toggle

controls/lighting/cabin-lights

处理过程如下:

1.窗口接收到按键信号

2.窗口任何查询按键注册函数

3.按键注册函数根据按键的类型,得到对应的FGButton,FGButton触发绑定对应的处理函数fire

4.在处理函数中通过

property-toggle的property-toggle查找命令,得到的命令为:do_property_toggle

5.传入该按键的属性节点处理:do_property_toggle(&property)

最后来谈谈如何注册自己的按键消息,该过程如果抛开nasal来说,过程是比较简单的:1.首先定位文件,一般来说在飞机的配置文件中注册比较合适,对于777飞机来说,可以在777-set-common.xml中注册

2.复制上面xml内容,修改按键的ascii、响应命令,如

A

toggle cabin lights

property-toggle

controls/lighting/cabin-lights

这时按键'A'也可以到达CTL-L的效果。

最后,如果大家更深入的了解,可以跟进以下几方面知识:

1.nasal脚本(flightgear内嵌编译器的一种脚本语言)

2.flightgear支持的命令以及对应的字符串

相关文档