2020-08-13 12:00:20 +02:00
---
id: 5e601c775ac9d0ecd8b94aff
2021-07-15 13:04:11 +05:30
title: 安全的实时多人游戏
2020-08-13 12:00:20 +02:00
challengeType: 4
2021-07-15 13:04:11 +05:30
forumTopicId: 462375
2021-01-13 03:31:00 +01:00
dashedName: secure-real-time-multiplayer-game
2020-08-13 12:00:20 +02:00
---
2020-12-16 00:37:30 -07:00
# --description--
2021-07-15 13:04:11 +05:30
使用 HTML Canvas API 和 [Socket.io ](https://socket.io/ ) 开发一个 2D 实时多人游戏,其功能与此类似:< https: // secure-real-time-multiplayer-game . freecodecamp . rocks /> 。 在这个项目中,你将使用以下方法之一编写你的代码:
2020-08-13 12:00:20 +02:00
2021-07-15 13:04:11 +05:30
- 克隆[这个 GitHub repo ](https://github.com/freeCodeCamp/boilerplate-project-secure-real-time-multiplayer-game/ ),并在本地完成你的项目。
- 使用[我们的 Replit 初始项目 ](https://replit.com/github/freeCodeCamp/boilerplate-project-secure-real-time-multiplayer-game )来完成你的项目。
- 使用您选择的站点生成器来完成项目。 需要确定包含了我们 GitHub 仓库的所有文件。
2020-08-13 12:00:20 +02:00
2021-07-15 13:04:11 +05:30
完成本项目后,请将一个正常运行的 demo( 项目演示) 托管在可以公开访问的平台。 然后在 `Solution Link` 框中提交你的项目 URL。 此外,还可以将项目的源码提交到 `GitHub Link` 中。
# --instructions--
**注意** : `helmet@^3.21.3` 是用户故事所必需的。 这意味着你需要使用以前版本的 Helmet 的文档,了解如何实现用户故事的信息。
2020-12-16 00:37:30 -07:00
# --hints--
2021-07-15 13:04:11 +05:30
提交自己的项目,而不是示例的 URL。
2021-02-06 04:42:36 +00:00
```js
(getUserInput) => {
assert(
!/.*\/secure-real-time-multiplayer-game\.freecodecamp\.rocks/.test(
getUserInput('url')
)
);
};
```
2021-07-15 13:04:11 +05:30
多个玩家可以连接到一台服务器游玩。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
每个玩家都有头像。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
每个玩家都由在 `Player.mjs` 中创建的 `Player` 类对象来代表。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
至少,每个玩家对象应该包含一个唯一的 `id` 、一个 `score` ,以及代表玩家当前位置的 `x` 和 `y` 坐标。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
游戏至少有一种类型的可收藏物品。 在 `Collectible.mjs` 中完成 `Collectible` 类来实现这一点。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
至少,每个由 `Collectible` 类创建的可收集物品对象应该包含一个唯一的 `id` 、一个 `value` ,以及代表该物品当前位置的 `x` 和 `y` 坐标。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
玩家可以使用 WASD 或方向键移动头像。 完成 `Player.mjs` 中的 `movePlayer` 方法来实现这一功能。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
`movePlayer` 方法应该接受两个参数:一个是 “up”、“down”、“left” 或 “right” 的字符串,另一个是玩家角色位置应该改变的像素数量。 `movePlayer` 应该调整它所调用的玩家对象的 `x` 和 `y` 坐标。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
用玩家的分数来计算他们相对其他玩家的名次。 在 `Player` 类中完成 `calculateRank` 方法来实现这个。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
`calculateRank` 方法应该接受一个代表所有在线玩家的对象数组,并返回字符串 `Rank: currentRanking/totalPlayers` 。 例如,在一局有两个玩家的游戏中,如果玩家 A 的分数是 3, 玩家 B 的分数是 5, 那么玩家 A 的 `calculateRank` 应该返回 `Rank: 2/2` 。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
玩家可以与可收集物品发生碰撞。 完成 `Player.mjs` 中的 `collision` 方法来实现这一点。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
`collision` 方法应该接受一个可收集物品的对象作为参数。 如果玩家的头像与物品相交,`collision` 方法应该返回 `true` 。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
所有玩家都保持游戏状态同步。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
玩家可以随时断开与游戏的连接。
2020-12-16 00:37:30 -07:00
```js
```
2021-07-15 13:04:11 +05:30
阻止客户端试图猜测/嗅探 MIME 类型。
2020-12-16 00:37:30 -07:00
```js
2021-07-15 13:04:11 +05:30
async (getUserInput) => {
const data = await fetch(getUserInput('url') + '/_api/app-info');
const parsed = await data.json();
assert.equal(parsed.headers['x-content-type-options'], 'nosniff');
};
2020-12-16 00:37:30 -07:00
```
2021-07-15 13:04:11 +05:30
防止跨站脚本( XSS) 攻击。
2020-12-16 00:37:30 -07:00
```js
2021-07-15 13:04:11 +05:30
async (getUserInput) => {
const data = await fetch(getUserInput('url') + '/_api/app-info');
const parsed = await data.json();
assert.equal(parsed.headers['x-xss-protection'], '1; mode=block');
};
2020-12-16 00:37:30 -07:00
```
2021-07-15 13:04:11 +05:30
客户端没有缓存任何网站内容。
2020-12-16 00:37:30 -07:00
```js
2021-07-15 13:04:11 +05:30
async (getUserInput) => {
const data = await fetch(getUserInput('url') + '/_api/app-info');
const parsed = await data.json();
assert.equal(parsed.headers['surrogate-control'], 'no-store');
assert.equal(
parsed.headers['cache-control'],
'no-store, no-cache, must-revalidate, proxy-revalidate'
);
assert.equal(parsed.headers['pragma'], 'no-cache');
assert.equal(parsed.headers['expires'], '0');
};
2020-12-16 00:37:30 -07:00
```
2021-07-15 13:04:11 +05:30
请求头显示该网站是由 “PHP 7.4.3” 驱动的,尽管实际并非如此(作为一种安全防御措施)。
2020-12-16 00:37:30 -07:00
```js
2021-07-15 13:04:11 +05:30
async (getUserInput) => {
const data = await fetch(getUserInput('url') + '/_api/app-info');
const parsed = await data.json();
assert.equal(parsed.headers['x-powered-by'], 'PHP 7.4.3');
};
2020-12-16 00:37:30 -07:00
```
# --solutions--
2021-01-13 03:31:00 +01:00
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```