您的位置:首页 > 大数据 > 人工智能

minetest源码解析四:game界面刷新绘制流程及核心函数介绍

2017-08-11 23:02 585 查看
game界面刷新绘制流程及核心函数介绍 

一 流程图



二 流程图中涉及到的核心函数介绍

1.Draw "Loading"screen

绘制点击start game之后的界面。

主要涉及函数

draw_load_screen(text, device, font,0,0);

场景绘制(绘制云)、driver->draw2DRectangle(视频驱动指针直接绘制)、GUI绘制(文字)

2.创建 texture source、shader source、item definition manager、node definition manager

初始化创建。

texture source:shader source:

item definition manager:界面上items(从服务端线程在不断获取出来,底下物品栏中)

node definition manager:界面上的场景node(从服务端线程在不断获取出来的可视范围内)

主要涉及函数

draw_load_screen(text, device, font,0,0);

场景绘制(绘制云)、driver->draw2DRectangle(视频驱动指针直接绘制)、GUI绘制(文字)

3.Create server

创建服务器。进行服务器地址的分解等等,并创建Server实例。

主要涉及函数

server = newServer(map_dir, gamespec, simple_singleplayer_mode, bind_addr.isIPv6());

server->start(bind_addr);

4.Create Client

创建客户端。先解析地址,设置连接地址,创建Client实例。

代码中这之前的do while循环可以直接去除

主要涉及函数

Client client(device, playername.c_str(), password, draw_control, tsrc, shsrc, itemdef, nodedef, sound, &eventmgr, connect_address.isIPv6());

5.Connet to the server

连接服务器。

主要涉及函数

client.connect(connect_address);

6.Wait for server to accept connection

这里主要通过一个循环不断更新以及获取状态信息(client.getState())。

主要涉及函数

while(device->run())

{

// Update client and server

client.step(dtime);

server->step(dtime);

// End condition

if(client.getState() ==LC_Init)

// Break conditions

if(client.accessDenied())

if(input->wasKeyDown(EscapeKey))

// Display status

wchar_t* text =wgettext("Connecting
to server...");

draw_load_screen(text, device, font, dtime,100);

}

7.Wait until content has been received

主要在一个循环体去获取客户端item 和node是否reveived(client.mediaReceived() &&client.itemdefReceived()
&&client.nodedefReceived())。

主要涉及函数

while(device->run())

{

// Update client and server

client.step(dtime);

server->step(dtime);

// End condition

if(client.mediaReceived() && client.itemdefReceived()
&& client.nodedefReceived())

// Break conditions

if(client.accessDenied())

if(client.getState() <LC_Init)

if(input->wasKeyDown(EscapeKey))

// Display status

if (!client.itemdefReceived())

wchar_t* text =wgettext("Item
definitions...");

elseif (!client.nodedefReceived())

wchar_t* text =wgettext("Node
definitions...");

else

message << gettext("Media...");

}

8.Update cached texture,mesh,materials

Update cached texture,mesh,materials:所有内容全部接受到之后。

主要涉及函数

client.afterContentReceived(device,font);

更新texture以及mesh、materials的。

9.Create the camera node

minetest->camera.h

创建一个Camera的实例。管理玩家、场景中的nodes、视距以及右下角舞动的工具。

主要涉及函数

Camera camera(smgr, draw_control, gamedef);

10.Create Clouds

minetest->clouds.h

创建一个Clouds的实例。Clouds是一个ScenceNode,所以它绘制时需要场景管理器绘制。

主要涉及函数

clouds = newClouds(smgr->getRootSceneNode(), smgr, -1,time(0));

11.Create Clouds

minetest->clouds.h

创建一个Clouds的实例。Clouds是一个ScenceNode,所以它绘制时需要场景管理器绘制。

主要涉及函数

clouds = newClouds(smgr->getRootSceneNode(), smgr, -1,time(0));

12.Create Sky

minetest->sky.h

创建一个Sky的实例。Sky是一个ScenceNode,所以它绘制时需要场景管理器绘制。

主要涉及函数

new Sky(smgr->getRootSceneNode(), smgr, -1,
client.getEnv().getLocalPlayer());

13.Add some gui stuff

主要是加入了一些左上角显示的debug信息等,这种一般是在gui环境中加入staticText控件。

14.HUD object

minetest->hud.h

创建一个Hud的实例。主要这个对象中都是封装了一些绘制函数。

主要涉及函数

Hud hud(driver, smgr, guienv, font, text_height, gamedef, player, &local_inventory);

15.处理一些game中回调

譬如若点击esc退出后,选择了菜单中的Exit to Menu,退出game循环了。

if(g_gamecallback->disconnect_requested)

{

g_gamecallback->disconnect_requested =false;

break;

}

或者访问受限,退出game循环了。

if(client.accessDenied())

{

break;

}

16.游戏过程中依据按键启动菜单判断

按下按键,按键这个事件主要是鬼火引擎IEventReceiver去截取的,RealInputHandler这个对象去判断根据不同的key分别执行不同的函数。
自己去截取,RealInputHandler这个对象去判断根据不同的key分别执行不同的函数。

input = newRealInputHandler();

RealInputHandler::InputHandler

如果窗口没有激活或者一些menu正在激活,需要input->clear().

主要涉及函数

create_formspec_menu(¤t_formspec, &client, gamedef, tsrc, device, fs_src, txt_dst);

17.滚轮选择底下物品栏Item

按下按键,按键这个事件主要是通过RealInputHandler这个对象截获的。根据不同的key分别执行不同的函数。

input = newRealInputHandler();

RealInputHandler::InputHandler

主要涉及函数

create_formspec_menu(¤t_formspec, &client, gamedef, tsrc, device, fs_src, txt_dst);

18.客户端设置玩家Control

minetest->player.h

PlayerControl control(input->isKeyDown(getKeySetting("keymap_forward")),

input->isKeyDown(getKeySetting("keymap_backward")),

                 …)

client.setPlayerControl(control);

19.服务端、客户端运行 step

server->step(dtime);

client.step(dtime); 这个比较重要,有获取数据,事件获取、环境处理等等。minetest->client.cpp

主要涉及函数

void Client::step(float dtime)

{



ReceiveAll();



}

void Client::ProcessData(u8 *data,u32
datasize, u16 sender_peer_id);处理从服务器端不断获取的数据

这里的ProcessData可能会更改ClientEvent的type。

20.读取客户端event

这里的事件不是key、鼠标这些事件,而是把这些响应之后执行的事件,如玩家移动、加粒子等。

ClientEvent event = client.getClientEvent();

if(event.type ==CE_NONE)

break;

else if(event.type ==CE_PLAYER_DAMAGE
&& client.getHP() !=0)

else if(event.type ==CE_PLAYER_FORCE_MOVE)

else if(event.type ==CE_DEATHSCREEN)

else if (event.type ==CE_SHOW_FORMSPEC)

else if(event.type ==CE_SPAWN_PARTICLE)

else if(event.type ==CE_ADD_PARTICLESPAWNER)

else if(event.type ==CE_DELETE_PARTICLESPAWNER)

else if (event.type ==CE_HUDADD)

else if (event.type ==CE_HUDRM)

else if (event.type ==CE_HUDCHANGE)

else if (event.type ==CE_SET_SKY)

else if (event.type ==CE_OVERRIDE_DAY_NIGHT_RATIO)

涉及主要函数

void Client::ProcessData(u8 *data,u32
datasize, u16 sender_peer_id)

{



ToClientCommand command = (ToClientCommand)readU16(&data[0]);



}

21.更新camera

camera.update(player, dtime, busytime, tool_reload_ratio,current_camera_mode, client.getEnv());

Camera更新:计算不同camera mode的玩家眼睛偏移、计算camera自己位置、自己target位置。Wielded tool的位置、更新视野范围等等。

界面、挥舞的工具、视角等等。

client.getEnv().getClientMap().updateCamera(camera_position,camera_direction,
camera_fov, camera_offset);

ClientMap 更新camera的位置、方向、偏移等等。

如果注释掉地图不显示出来

22.创建PointedThing对象

minetest->util->pointedthing.h

PointedThing pointed =getPointedThing(

// input

&client, player_position, camera_direction,

camera_position, shootline, d,

playeritem_def.liquids_pointable, !ldown_for_dig,

camera_offset,

// output

hilightboxes,

selected_object);

这个对象中有个PointedThingType type,这个类型一般有POINTEDTHING_NOTHING、POINTEDTHING_NODE、POINTEDTHING_OBJECT。

23.底下物品栏更新

client.selectPlayerItem(new_playeritem) 客户端切换选择的物品

client.getLocalInventory(local_inventory);客户端获取本地物品

camera.wield(item, client.getPlayerItem());camera的右下角挥舞的node更新

24.更新block绘制列表

200ms或者camera的方向改变时,更新列表。

client.getEnv().getClientMap().updateDrawList(driver);

这里更新需要绘制的block,如果注释掉了,地图就显示不出来了。

25.绘制云、sky

直接调用引擎的场景管理器绘制.

26.选中block的提示框绘制

show_hud

hud.drawSelectionBoxes(hilightboxes);

27.camera wield 工具绘制

show_hud

camera.drawWieldedTool();

28.Crosshair绘制

show_hud

hud.drawCrosshair();

29.底下物品栏绘制

show_hud

hud.drawHotbar(client.getPlayerItem());

之前这句代码必须执行过client.getLocalInventory(local_inventory);客户端获取本地物品,否则是绘制不出来的。

30.生命值绘制

show_hud

hud.drawLuaElements(camera.getOffset());

31.gui绘制

包括debug的staticText,聊天的staticText,以及某些key按下弹出的界面。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息