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

来源:互联网 发布:pid算法实例c语言 编辑:程序博客网 时间:2024/05/29 16:21

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以及meshmaterials的。



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(&current_formspec, &client, gamedef, tsrc, device, fs_src, txt_dst);



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


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

input = newRealInputHandler();

RealInputHandler::InputHandler

主要涉及函数

create_formspec_menu(&current_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_NOTHINGPOINTEDTHING_NODEPOINTEDTHING_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绘制

包括debugstaticText,聊天的staticText,以及某些key按下弹出的界面。



阅读全文
0 0
原创粉丝点击