多人游戏活动的示例代码
本主题旨在充当多人游戏活动客户端 API 基本用法的快速入门指南。 本主题将讨论如何管理活动、发送邀请和将玩家添加到“最近互动玩家”列表中。
活动
设置活动
每当游戏开始或加入多人游戏时,都应该创建一个活动。 这样做使 shell 和游戏中的其他玩家都可以看到该玩家的活动,并允许其他玩家有机会加入正在进行的游戏。 如果有玩家想加入游戏的某一活动但该活动尚未运行,则将激活该活动并向其传递连接字符串。
游戏应随着参与者加入或离开而更新活动。 这将为其他玩家提供更丰富的活动视图,并告诉他们活动是否已满。
有关活动字段的信息,请参阅 活动内容。
下面是设置活动的代码示例。 这同时适用于创建活动和更新现有活动。
auto async = std::make_unique<XAsyncBlock>();
async->queue = queue;
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // Take ownership of XAsyncBlock.
HRESULT hr = XAsyncGetStatus(async, false);
};
XblMultiplayerActivityInfo info{};
info.connectionString = "dummyConnectionString";
info.joinRestriction = XblMultiplayerActivityJoinRestriction::Followed;
info.maxPlayers = 10;
info.currentPlayers = 1;
info.groupId = "dummyGroupId";
HRESULT hr = XblMultiplayerActivitySetActivityAsync(
xblContext,
&info,
false,
async.get()
);
if (SUCCEEDED(hr))
{
async.release();
}
有关详细信息,请参阅以下内容:
- XAsyncBlock
- XAsyncGetStatus
- XblMultiplayerActivityInfo
- XblMultiplayerActivityJoinRestriction
- XblMultiplayerActivitySetActivityAsync
获取活动
游戏可能希望了解其他用户的活动。 例如,游戏可能希望通过一个游戏内 UI 显示游戏中玩家的朋友及其活动。
下面是检索活动的代码示例。
auto async = std::make_unique<XAsyncBlock>();
async->queue = queue;
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // Take ownership of XAsyncBlock.
size_t resultSize{};
HRESULT hr = XblMultiplayerActivityGetActivityResultSize(async, &resultSize);
if (SUCCEEDED(hr))
{
std::vector<uint8_t> buffer(resultSize);
XblMultiplayerActivityInfo* activityInfo{};
size_t resultCount{};
hr = XblMultiplayerActivityGetActivityResult(async, buffer.size(), buffer.data(), &activityInfo, &resultCount, nullptr);
if (SUCCEEDED(hr))
{
// ...
}
}
};
HRESULT hr = XblMultiplayerActivityGetActivityAsync(
xblContext,
&xuid,
1,
async.get()
);
if (SUCCEEDED(hr))
{
async.release();
}
有关详细信息,请参阅以下内容:
- XAsyncBlock
- XblMultiplayerActivityGetActivityResultSize
- XblMultiplayerActivityInfo
- XblMultiplayerActivityGetActivityResult
- XblMultiplayerActivityGetActivityAsync
删除活动
当玩家结束或离开多人游戏活动时,游戏应使用以下代码删除活动。
auto async = std::make_unique<XAsyncBlock>();
async->queue = queue;
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // Take ownership of XAsyncBlock.
HRESULT hr = XAsyncGetStatus(async, false);
};
HRESULT hr = XblMultiplayerActivityDeleteActivityAsync(xblContext, async.get());
if (SUCCEEDED(hr))
{
async.release();
}
有关详细信息,请参阅以下内容:
邀请
在没有 UI 的情况下发送邀请
玩家可能希望直接向一个或多个其他玩家发送邀请。 发送邀请前,游戏应确保已设置活动。 这可确保 shell 和游戏之间的连续性,因为 shell 将根据当前活动发送邀请。
若要在没有 UI 的情况下发送邀请,在使用 XblMultiplayerActivitySetActivityAsync 设置活动后(请参阅上面的示例),游戏应调用 XblMultiplayerActivitySendInvitesAsync API,并传递要邀请的一批玩家和当前活动中使用的相同连接字符串。
有关邀请内容的信息,请参阅发送请求,让其他玩家加入多人游戏体验。
在没有 UI 的情况下发送邀请的代码示例如下所示。
auto async = std::make_unique<XAsyncBlock>();
async->queue = queue;
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // Take ownership of XAsyncBlock.
HRESULT hr = XAsyncGetStatus(async, false);
};
HRESULT hr = XblMultiplayerActivitySendInvitesAsync(
xblContext,
&xuid,
1,
true, // Setting false will send the invite to only players on the sender's platform.
"dummyConnectionString",
async.get()
);
if (SUCCEEDED(hr))
{
async.release();
}
有关详细信息,请参阅以下内容:
使用 UI 发送邀请
玩家可能希望直接向一个或多个其他玩家发送邀请。 发送邀请前,游戏应确保已设置活动。 这可确保 shell 和游戏之间的连续性,因为 shell 将根据当前活动发送邀请。
若要使用 UI 发送邀请,在使用 XblMultiplayerActivitySetActivityAsync 设置活动后(请参阅上面的示例),游戏应调用 XGameUiShowMultiplayerActivityGameInviteAsync API 传递请求用户。 它将使用游戏的当前活动,并使用其连接字符串和设置邀请玩家。
有关邀请内容的信息,请参阅发送请求,让其他玩家加入多人游戏体验。
使用 UI 发送邀请的代码示例如下所示。
auto async = std::make_unique<XAsyncBlock>();
async->queue = queue;
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // Take ownership of XAsyncBlock.
HRESULT hr = XGameUiShowMultiplayerActivityGameInviteResult(async);
if (hrAsync == S_OK)
{
// Handle success
}
else
{
// Likely will only happen during development - usually indicates
// an invalid user was passed in or that there is no multiplayer activity set
}
};
HRESULT hr = XGameUiShowMultiplayerActivityGameInviteAsync(
async.get()
requestingUser
);
if (SUCCEEDED(hr))
{
async.release();
}
有关详细信息,请参阅以下内容:
- XAsyncBlock
- XAsyncGetStatus
- XGameUiShowMultiplayerActivityGameInviteAsync
- XGameUiShowMultiplayerActivityGameInviteResult
接收邀请
若要在玩家接受邀请时得到通知,游戏可以使用 XGameInviteRegisterForEvent
注册邀请通知。 每次接受邀请时,都会通过注册的回调将格式化的 URI 传递给游戏。 可以解析该 URI 以确定邀请的发送者、接收者和连接字符串。 连接字符串特定于游戏,在创建多人活动时设置。 对于使用多人活动服务的游戏,URI 的完整格式如下所示。
平台 | 格式 |
---|---|
主机上的 Microsoft Game Development Kit (GDK) 或 Xbox One 软件开发工具包 | ms-xbl-<titleId>://inviteAccept?invitedUser=<xuid>&sender=<xuid>&connectionString=<connectionString> |
电脑上的 Microsoft Game Development Kit (GDK) 或 通用 Windows 平台 (UWP) | ms-xbl-multiplayer://inviteAccept?invitedUser=<xuid>&sender=<xuid>&connectionString=<connectionString> |
不再需要邀请通知时,可使用 XGameInviteUnregisterForEvent
注销回调。
用于注册和处理已接受邀请的代码示例如下所示。
void CALLBACK MyXGameInviteEventCallback(
_In_opt_ void* context,
_In_ const char* inviteUri)
{
if (inviteUri != nullptr)
{
std::string uri{ inviteUri };
size_t invitedUserBegin = uri.find("invitedUser=");
size_t senderBegin = uri.find("sender=");
std::string invitedUser = uri.substr(invitedUserBegin, uri.find('&', invitedUserBegin) - invitedUserBegin);
std::string sender = uri.substr(senderBegin, uri.find('&', senderBegin) - senderBegin);
std::string connectionString = uri.substr(uri.find("connectionString="));
// ...
}
}
XTaskQueueRegistrationToken token = { 0 };
HRESULT hr = XGameInviteRegisterForEvent(
queue,
nullptr,
MyXGameInviteEventCallback,
&token
);
// ...
bool result = XGameInviteUnregisterForEvent(token, true);
有关详细信息,请参阅以下内容:
最近互动玩家
游戏应提交与当前用户有过有意义交互的其他玩家的列表,以便更新用户最近互动过的玩家列表。 该列表是单向的,这意味着每个玩家的客户端只负责更新自己用户的列表,而玩家的列表不会相互影响。
例如,假设一组玩家出现在游戏前的大厅中,并被匹配在一起。 开始匹配时,每个玩家会将大厅中的所有其他 xuids
更新到自己的列表中。 如果有新用户要加入,则可以单独写入该用户。
注意
你可以决定哪些交互是有意义的。 对于一款游戏,可以是在大厅中出现。 对于另一款游戏,可以是一个玩家向另一个玩家射击。 对于第三款游戏,可以只是在屏幕上看到另一个玩家。
在某些情况下,可能不希望一组玩家在匹配会话开始前被看到,因此可以等到希望他们彼此可见时再写入玩家列表。 若要刷新客户端最近互动玩家列表,且需要立即强制刷新,可调用 XblMultiplayerActivityFlushRecentPlayersAsync
。 否则,最近互动的玩家列表将每 5 秒自动刷新一次。
下面是关于更新最近互动的玩家列表和刷新更新的代码示例。
更新最近互动的玩家
XblMultiplayerActivityRecentPlayerUpdate update{ xuid };
HRESULT hr = XblMultiplayerActivityUpdateRecentPlayers(xblContext, &update, 1);
有关详细信息,请参阅以下内容:
刷新最近互动的玩家
auto async = std::make_unique<XAsyncBlock>();
async->queue = queue;
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // Take ownership of XAsyncBlock.
HRESULT hr = XAsyncGetStatus(async, false);
};
HRESULT hr = XblMultiplayerActivityFlushRecentPlayersAsync(xblContext, async.get());
if (SUCCEEDED(hr))
{
async.release();
}
有关详细信息,请参阅以下内容: