이 멀티 파트 자습서에서는 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 편을 즐겁게하고 그것이 도움이되기를 바랐다. 질문이나 제안 사항에 대한 의견이 있으시면 아래 의견에 저희에게 알려주십시오.
댓글 없음:
댓글 쓰기