多くの開発者は、socket.ioライブラリに基づいてマルチユーザーオンラインサーバーの開発を始めています。このライブラリを使用すると、クライアントとサーバー間のデータ交換をリアルタイムで非常に簡単に実装できますが、サーバーとクライアントの相互作用のすべてのロジックとインターフェイス、およびスケーリングとトラフィック最適化のアーキテクチャを検討して実装する必要があります。
ネットワークコンポーネント(サーバーとクライアント間の通信)については考えられないが、すぐにゲームロジックとクライアントUIの開発に集中するmagxライブラリについてお話ししたいと思います。
マルチプレイヤーゲームのアーキテクチャを設計する場合、通常、2つのアプローチが考慮されます。1つは権限のあるサーバー、もう1つは権限のない(権限のあるクライアント)です。これらのアプローチは両方ともmagxライブラリによってサポートされています。より単純なアプローチ、つまり非権威者から始めましょう。
権限のないサーバー
その本質は、サーバーが各プレーヤーの入力結果を制御しないことです。クライアントは、プレーヤーが入力したアクションとゲームロジックをローカルで個別に追跡し、その後、特定のアクションの結果をサーバーに送信します。その後、サーバーは実行されたすべてのアクションを他のクライアントのゲーム状態と同期します。
サーバーはクライアント間の通信のみを担当し、クライアントが行う追加の計算を行わないため、アーキテクチャの観点から実装する方が簡単です。
magxライブラリを使用すると、このようなサーバーを数行のコードで実装できます。
import * as http from "http"
import { Server, RelayRoom } from "magx"
const server = http.createServer()
const magx = new Server(server)
magx.define("relay", RelayRoom)
// start server
const port = process.env.PORT || 3001
server.listen(port, () => {
console.info(`Server started on http://localhost:${port}`)
})
ここで、クライアントをこのサーバーに接続して対話を開始するには、jsライブラリをインストールするだけです。
npm install --save magx-client
そしてそれをプロジェクトに接続します:
import { Client } from "magx-client"
または、HTMLで使用するための直接リンクを使用することもできます。
<script src="https://cdn.jsdelivr.net/npm/magx-client@0.7.1/dist/magx.js"></script>
接続後、ほんの数行でサーバーとの接続と相互作用を構成できます。
// authenticate to server
await client.authenticate()
// create or join room
const rooms = await client.getRooms("relay")
room = rooms.length
? await client.joinRoom(rooms[0].id)
: await client.createRoom("relay")
console.log("you joined room", name)
// handle state patches
room.onPatch((patch) => updateState(patch))
// handle state snapshot
room.onSnapshot((snapshot) => setState(snapshot))
// handle joined players
room.onMessage("player_join", (id) => console.log("player join", id))
// handle left players
room.onMessage("player_leave", (id) => console.log("player leave", id))
クライアントと権限のないサーバー間の相互作用を構築する方法の詳細な例は、magx-examplesプロジェクトの対応する例に記載されています。
信頼できるサーバー
, , - .
- . , , , , .
, . , (cheating).
. magx , (worker). , .
/ . — . Mosx — , magx - , .
, . mosx — @mx.Object, , @mx. :
@mx.Object
export class Player {
@mx public x = Math.floor(Math.random() * 400)
@mx public y = Math.floor(Math.random() * 400)
}
@mx.Object
export class State {
@mx public players = new Map<string, Player>()
public createPlayer(id: string) {
this.players.set(id, new Player())
}
public removePlayer(id: string) {
this.players.delete(id)
}
public movePlayer(id: string, movement: any) {
const player = this.players.get(id)
if (!player) { return }
player.x += movement.x ? movement.x * 10 : 0
player.y += movement.y ? movement.y * 10 : 0
}
}
, — Map() . (Array) (number, string, boolean) .
. :
export class MosxStateRoom extends Room<State> {
public createState(): any {
// create state
return new State()
}
public createPatchTracker(state: State) {
// create state change tracker
return Mosx.createTracker(state)
}
public onCreate(params: any) {
console.log("MosxStateRoom created!", params)
}
public onMessage(client: Client, type: string, data: any) {
if (type === "move") {
console.log(`MosxStateRoom received message from ${client.id}`, data)
this.state.movePlayer(client.id, data)
}
}
public onJoin(client: Client, params: any) {
console.log(`Player ${client.id} joined MosxStateRoom`, params)
client.send("hello", "world")
this.state.createPlayer(client.id)
}
public onLeave(client: Client) {
this.state.removePlayer(client.id)
}
public onClose() {
console.log("MosxStateRoom closed!")
}
}
— .
const magx = new Server(server, params)
magx.define("mosx-state", MosxStateRoom)
?
:
Mosx
Magx
- API.
- :
- ( webockets)
- ( )
- ( )
- ( )
- ビルトインルーム:ロビーとリレー(権限のないサーバー用)
- JSMagx-サーバーを操作するためのクライアントライブラリ
- サーバールームとそのクライアントを管理し、ステータスを表示するための監視コンソールmagx-monitor
- Typescriptの完全サポート
- 最小の依存関係(notepack.ioライブラリの場合-ネットワークトラフィックを削減するため)
このプロジェクトは非常に若く、コミュニティの注目がプロジェクトのより早い発展に役立つことを願っています。