Socket.io로 Phaser 3에 기본 멀티 플레이어 게임 만들기 - 파트 1(Create a Basic Multiplayer Game in Phaser 3 with Socket.io – Part 1)



이 멀티 파트 자습서에서는 Phaser 3 및 Socket.io를 사용하여 간단한 멀티 플레이어 게임을 만듭니다. 멀티 플레이어 게임의 경우 클라이언트 - 서버 게임 아키텍처를 따를 것입니다. 클라이언트 - 서버 게임 아키텍처에 익숙하지 않은 경우 클라이언트는 플레이어에게 게임을 표시하고 플레이어의 입력을 처리하며 서버와 통신해야합니다. 한편, 서버는 각 클라이언트로 해당 데이터를 브로드 캐스팅해야합니다.

이 튜토리얼의 목표는 멀티 플레이어 게임을 만드는 기본 사항을 알려주는 것입니다. 다음 방법을 배우게됩니다.

- 게임을 렌더링하고 통신 할 Node.js 및 Express 서버를 설정하십시오.
- 우리의 클라이언트로 작동 할 기본 Phaser 3 게임을 설치하십시오.
- Socket.io를 사용하면 서버와 클라이언트가 통신 할 수 있습니다.

1 부 소스 코드와 관련된 모든 파일을 다운로드 할 수 있습니다.


자습서 요구 사항

이 튜토리얼에서는 Node.js와 Express를 사용하여 서버를 작성합니다. 또한 NPM을 사용하여 서버를 실행하는 데 필요한 필수 패키지를 설치합니다. 이 자습서를 수행하려면 Node.js 및 NPM을 로컬로 설치해야 하며 그렇지 않으면 이미 설치되어있는 환경에 액세스해야합니다. 또한 명령 프롬프트 (Windows) / 터미널 (Mac)을 사용하여 필수 패키지를 설치하고 노드 서버를 시작 / 중지합니다.

이러한 도구에 대한 사전 경험이 있으면 도움이되지만이 자습서에서는 필요하지 않습니다. 이 튜토리얼의 초점이 Phaser로 게임을 만들고 있으므로이 도구를 설치하는 방법은 다루지 않을 것입니다. 마지막으로 필요한 것은 코드 편집을위한 IDE 또는 텍스트 편집기입니다.

Node.js를 설치하려면 여기 링크를 클릭하고 LTS 버전을 선택하십시오. 이 자습서에서는 현재 버전을 다운로드하여 사용할 수 있지만 대부분의 사용자는 LTS 버전을 사용하는 것이 좋습니다. Node.js를 설치하면 NPM도 컴퓨터에 설치됩니다. 이러한 도구가 설치되면 다음 부분으로 넘어갈 수 있습니다.


서버 설정

우리가 할 첫 번째 일은 게임 파일을 제공 할 기본 Node.js 서버를 만드는 것입니다. 시작하려면 컴퓨터에 새 폴더를 만드십시오. 원하는 이름으로 부를 수 있습니다. 그런 다음이 폴더에서 탐색하여 server.js라는 새 파일을 만듭니다. server.js를 열고 다음 코드를 추가하십시오.

var express = require('express');
var app = express();
var server = require('http').Server(app);
 
app.use(express.static(__dirname + '/public'));
 
app.get('/', function (req, res) {
  res.sendFile(__dirname + '/index.html');
});
 
server.listen(8081, function () {
  console.log(`Listening on ${server.address().port}`);
});
위 코드에서 우리는 :

- Express 모듈을 참조했습니다. 이 모듈은 우리가 정적 파일을 렌더링하는 데 도움이되는 웹 프레임 워크입니다.
- 표현의 새로운 인스턴스를 만들고 app 이라고했습니다.
- 익스프레스는 HTTP 요청을 처리 할 수 있도록 HTTP 서버에 앱을 제공했습니다.
- Express에서 Express.static 내장 미들웨어 기능을 사용하여 정적 파일을 렌더링하도록 서버를 업데이트했습니다.
- index.html 파일을 루트 페이지로 제공하도록 서버에 지시했습니다.
- 서버가 포트 8081에서 청취를 시작했는지 확인하십시오.

서버를 실행하기 전에 서버에 필요한 모듈을 설치해야 합니다. 터미널 / 명령 프롬프트를 열고 프로젝트 폴더로 이동하십시오. 일단 거기에 다음 명령을 실행해야 합니다 : npm init -f. 이렇게하면 프로젝트 폴더에 package.json 파일이 만들어집니다. 이 파일을 사용하여 프로젝트가 의존하는 모든 패키지를 추적합니다.

이제 Express를 설치하겠습니다. 터미널에서 다음 명령을 실행하십시오. npm install --save express. 그러면 프로젝트 폴더에 node_modules라는 폴더가 만들어지고 명령에 --save 플래그를 추가하면 npm이이 패키지를 package.json 파일에 저장합니다.


클라이언트 설정

기본 서버 코드가 끝나면 클라이언트 측 코드 설정 작업을 시작합니다. 프로젝트 폴더에서 public이라는 새 폴더를 만듭니다. 이 폴더에 넣은 파일은 우리가 설정 한 서버에서 렌더링됩니다. 따라서 모든 정적 클라이언트 측 파일을이 폴더에 저장하려고합니다. 이제 공용 폴더에서 index.html이라는 새 파일을 만듭니다. index.html을 열고 다음 코드를 추가하십시오.
<!DOCTYPE html>
<html>
 
    <head>
        <meta charset="utf-8">
    </head>
 
    <body>
        <script src="//cdn.jsdelivr.net/npm/phaser@3.0.0/dist/phaser.min.js"></script>
        <script src="js/game.js"></script>
    </body>
 
</html>
위의 코드에서 간단한 HTML 페이지를 설정하고 phaser.min.js (페이저 게임 프레임 워크)와 game.js (Phaser 게임 코드)라는 두 개의 JavaScript 파일을 참조했습니다. 공용 폴더로 돌아가 js라는 새 폴더를 만들고이 폴더에 game.js.라는 새 파일을 만듭니다. game.js를 열고 다음 코드를 추가하십시오 :
var config = {
  type: Phaser.AUTO,
  parent: 'phaser-example',
  width: 800,
  height: 600,
  physics: {
    default: 'arcade',
    arcade: {
      debug: false,
      gravity: { y: 0 }
    }
  },
  scene: {
    preload: preload,
    create: create,
    update: update
  }
};
 
var game = new Phaser.Game(config);
 
function preload() {}
 
function create() {}
 
function update() {}
방금 추가 한 코드를 살펴 보겠습니다.

- Phaser 게임에 사용할 구성을 만들었습니다.
- config 객체의 type 필드에서 게임의 렌더러 유형을 설정합니다. 두 가지 주요 유형은 Canvas와 WebGL입니다. WebGL은 더 빠른 렌더러이며 더 나은 성능을 제공하지만 모든 브라우저가이를 지원하는 것은 아닙니다. 유형에 대해 AUTO를 선택하면 Phaser가 WebGL을 사용할 수있는 경우 WebGL을 사용하고 그렇지 않은 경우 Canvas를 사용합니다.
- config 객체에서, 부모 필드는 Phaser에게 id가 존재하는 기존 <canvas> 요소에서 게임을 렌더링하도록 지시하는 데 사용됩니다. 존재하지 않으면 Phaser는 우리를 위해 <canvas> 요소를 만듭니다.
- config 객체에서 우리는 게임의 볼 수있는 영역의 너비와 높이를 지정합니다.
- config 객체에서 Phaser에서 사용할 수있는 아케이드 물리를 활성화했으며 중력을 0으로 설정했습니다.
- config 객체에는 미리 정의 된 preload, update 및 create 함수를 사용할 scene 객체가 임베드되었습니다.

기본 클라이언트 측 코드 설정을 통해 서버를 테스트하고 모든 것이 올바르게 작동하는지 확인합니다. 터미널 / 명령 프롬프트로 돌아가서 node server.js 명령을 실행하면 다음 줄이 표시됩니다. Listening on 8081. 이제 웹 브라우저를 열고 http : // localhost : 8081 /로 이동하면, 웹 페이지에 블랙 박스가 보일 것입니다. 개발자 툴에서 콘솔을 열면 게임이 실행되고있는 Phaser 버전의 로그가 보일 것입니다.



Socket.IO 추가하기

서버가 이제 게임을 렌더링 할 때 Socket.IO를 게임에 추가 할 것입니다. Socket.IO에 익숙하지 않은 사용자는 웹 클라이언트와 서버 간의 실시간 양방향 통신을 가능하게하는 JavaScript 라이브러리입니다. Socket.IO를 사용하려면 클라이언트와 서버 코드를 업데이트하여 둘 사이의 통신을 가능하게해야합니다.

터미널에서 다음 명령을 실행하십시오. npm install --save socket.io. 서버가 계속 실행중인 경우 새 터미널 창을 열고 프로젝트 폴더에서 코드를 실행하거나 서버를 중지 한 다음 (Ctrl + C) 명령을 실행할 수 있습니다. 이렇게하면 Socket.IO 노드 패키지가 설치되어 package.json 파일에 저장됩니다.

이제 server.js에 var server = require ( 'http').Server (app);  아래에 다음 코드를 추가합니다.
var io = require('socket.io').listen(server);

그런 다음 server.listen 행 위에 다음 코드를 추가하십시오.
io.on('connection', function (socket) {
  console.log('a user connected');
  socket.on('disconnect', function () {
    console.log('user disconnected');
  });
});

위 코드에서 우리는 :

- socket.io 모듈을 참조하고 서버 객체를 수신하게했습니다.
- 연결 및 연결 끊김을 청취하는 논리가 추가되었습니다.

다음으로 Socket.IO 라이브러리를 포함하도록 클라이언트 측 코드를 업데이트합니다. index.html을 열고 <body> 요소의 맨 위에 다음 줄을 추가하십시오.
<script src="/socket.io/socket.io.js"></script>

이제 서버를 다시 시작하고 브라우저에서 게임을 새로 고침하면 터미널에 사용자 연결 / 연결 해제 메시지가 표시됩니다.




플레이어 추가 - 서버

이제 소켓 연결 설정을 완료 했으므로 플레이어를 게임에 추가 할 수 있습니다. 모든 플레이어의 게임을 동기화 상태로 유지하려면 사용자가 게임에 연결하거나 연결을 끊을 때 모든 플레이어에게 알릴 필요가 있습니다. 또한 새로운 플레이어가 연결되면 플레이어가 게임의 다른 모든 플레이어를 알 수있는 방법이 필요합니다. 이 모든 작업을 수행하려면 플레이어 데이터를 저장해야하며 소켓 연결을 사용하여 플레이어에게 메시지를 보냅니다.

이 자습서에서는 플레이어 데이터를 서버의 메모리에 저장합니다. 일반적으로 우리는이 데이터를 특정 유형의 데이터베이스에 저장하여 영구적으로 저장하려고합니다. 서버가 실패하면 게임 상태를 쉽게 복구 할 수 있습니다.

server.js에서 io 변수 아래에 다음 행을 추가하십시오.

var players = {};

이 오브젝트를 사용하여 현재 게임중인 모든 플레이어를 추적합니다. 그런 다음 socket.io 연결 이벤트의 콜백 함수에서 console.log ( 'a user connected') 아래에 다음 코드를 추가합니다.
// create a new player and add it to our players object
players[socket.id] = {
  rotation: 0,
  x: Math.floor(Math.random() * 700) + 50,
  y: Math.floor(Math.random() * 500) + 50,
  playerId: socket.id,
  team: (Math.floor(Math.random() * 2) == 0) ? 'red' : 'blue'
};
// send the players object to the new player
socket.emit('currentPlayers', players);
// update all other players of the new player
socket.broadcast.emit('newPlayer', players[socket.id]);
방금 추가 한 코드를 살펴 보겠습니다.

- 플레이어가 웹 소켓에 연결하면 player 데이터에 플레이어 데이터를 저장하고 socket.id를 키로 사용합니다.
- 플레이어의 회전, x 및 y 위치를 저장하고 있으며이를 클라이언트 측에서 스프라이트를 작성하고이 데이터를 사용하여 모든 플레이어 게임을 업데이트하는 데 사용합니다. 우리는 또한 playerId를 저장하여 게임에서 참조 할 수 있으며 나중에 사용할 팀 속성을 추가했습니다.
- 우리는 socket.emit과 socket.broadcast.emit을 사용하여 클라이언트 측 소켓에 이벤트를 발생시켰다. socket.emit은이 특정 소켓 (방금 연결 한 새 플레이어)으로 이벤트를 방출합니다. socket.broadcast.emit은 이벤트를 다른 모든 소켓 (기존 플레이어)에게 보냅니다.
- currentPlayers 이벤트에서 플레이어 개체를 새 플레이어로 전달합니다. 이 데이터는 새 플레이어의 게임에서 모든 플레이어 스프라이트를 채우는 데 사용됩니다.
- newPlayer 이벤트에서 우리는 새로운 플레이어의 데이터를 다른 모든 플레이어에게 전달하므로 새로운 스프라이트를 게임에 추가 할 수 있습니다.

플레이어가 연결을 끊을 때 플레이어 개체에서 해당 플레이어의 데이터를 제거해야하며이 사용자가 게임에서 해당 플레이어의 스프라이트를 제거 할 수 있도록 남겨 두는 메시지를 다른 모든 플레이어에게 보내야합니다.

socket.io disconnect 이벤트의 콜백 함수에서 아래 코드를 추가하십시오.
// remove this player from our players object
delete players[socket.id];
// emit a message to all players to remove this player
io.emit('disconnect', socket.id);

server.js 파일은 다음과 같아야합니다.
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io').listen(server);
 
var players = {};
 
app.use(express.static(__dirname + '/public'));
 
app.get('/', function (req, res) {
  res.sendFile(__dirname + '/index.html');
});
 
io.on('connection', function (socket) {
  console.log('a user connected');
  // create a new player and add it to our players object
  players[socket.id] = {
    rotation: 0,
    x: Math.floor(Math.random() * 700) + 50,
    y: Math.floor(Math.random() * 500) + 50,
    playerId: socket.id,
    team: (Math.floor(Math.random() * 2) == 0) ? 'red' : 'blue'
  };
  // send the players object to the new player
  socket.emit('currentPlayers', players);
  // update all other players of the new player
  socket.broadcast.emit('newPlayer', players[socket.id]);
 
  // when a player disconnects, remove them from our players object
  socket.on('disconnect', function () {
    console.log('user disconnected');
    // remove this player from our players object
    delete players[socket.id];
    // emit a message to all players to remove this player
    io.emit('disconnect', socket.id);
  });
});
 
server.listen(8081, function () {
  console.log(`Listening on ${server.address().port}`);
});


결론

플레이어를 추가하는 서버 코드를 사용하면이 자습서의 제 1 부를 끝까지 다룰 수 있습니다. 2 부에서는 멀티 플레이어 게임을 다음과 같이 마무리합니다.

- 게임에 플레이어를 추가하기위한 클라이언트 측 로직 추가.
- 플레이어 입력을위한 로직 추가.
- 수집 할 수집품을 플레이어에게 추가합니다.

나는 당신이이 튜토리얼의 제 1 편을 즐겁게하고 그것이 도움이되기를 바랐다. 질문이나 제안 사항에 대한 의견이 있으시면 아래 의견에 저희에게 알려주십시오.

댓글 없음:

댓글 쓰기