NodeJs Express и socket.io.

Фронтенд розробка JavaScript. -> Гра шахові танки.

Домашнє завдання.

Створити розраховану на багато користувачів гру.

Гра є полем з квадратних шахових клітин.

Розмір поля може встановлюватись у налаштуваннях.

Приклад налаштувань гри

{
    fps: 25,
    width: 20,
    height: 20,
    size: 50,
}

fps - кількість кадрів у с.

width, height - кількість клітин по вертикалі та горизонталі

size – розмір клітини в пікселях.

1 реліз

Серверна частина.

  1. Створити двомірний масив із клітинами.

Формат масиву.

   scene = [
        [
            [  x: number, 
               y: number, 
               color: string, 
               borderColor: string, 
               border: number, 
               power: number[0-100]  
               actor: object
            ],
            [x: number, y: number, ...],
            []
            ...
        ],
        [],
        ...

    ]

При підключенні користувача на сцені розставити для нього фігури у шаховому порядку білі зверху праворуч, чорні внизу ліворуч (у кутах) для першого та другого користувача.

Якщо користувачів більше 3 нічого не робимо.

Формат об’єкта фігури.

actor = {
   color: string[black|white],
   name: [pone|rook|quin|king|bishop|knight],
   power: number[0-100],
   strenght: number[0-100],
   position: {x,y},
   image: string
}
  1. Реалізувати подію переміщення.

Вхідні дані.

{
    action: 'move',
    from: {
        x: number,
        y: number,
    },
    to: {
        x: number,
        y: number,
    }

}

Події переміщати фігуру.

  1. З частотою fps передавати на клієнт по вебсокет цей об’єкт сцени.

    { data: scene, action: ‘render’ }

Клієнтська сторона.

  1. З’єднається із сервером.

  2. Реалізувати функцію малювання клітин на полотні canvas.

  3. Реалізувати малювання об’єктів фігур.

  4. Реалізувати переміщення фігури з надсиланням повідомлення на сервер.

2 реліз

Серверна частина.

  1. На сцену додати нового актора – танк замість ферзя.

  2. Додати в сцену масив із кульками.

    { data: scene, action: ‘render’, tanks: [{color: string, image: string position: {x,y}},…], bullets: [{color: string, image: string position: {x,y}},…] }

  3. Реалізувати подію повороту танка на 45 градусів.

  4. Реалізувати подію пересування танка у 8 напрямах.

  5. Реалізувати подію пострілу.

  6. Переміщення кульки з видаленням поля при досягненні краю.

Клієнтська частина

  1. Відображення танка

  2. Відображення куль.

3 реліз

Серверна частина.

  1. Відпрацювати колізію кульки з фігурою.

  2. Відпрацювати колізію танка із фігурою.

Фронтенд розробка JavaScript. -> Використання express та web-socket-ів для обміну клієнт-сервер.

NodeJS початок. Використання express та web-socket-ів для обміну клієнт-сервер.

Ставимо реакт.

npm install react react-dom --save

Ставимо express.

npm install express --save

Ставимо typescript.

npm install typescript --save

Встановимо типи для nodejs

npm install @types/node --save

Створюємо конфігурацію в tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES5",
        "outDir": "dist",
        "rootDir": "src"
    },
    "exclude": [
        "node_modules"
    ]
}

Запуск білдера.

node ./node_modules/typescript/bin/tsc --watch

Встановимо nodemon

npm install --save nodemon

Налаштуємо його конфігурацію у nodemon.json

{
    "verbose": false,
    "ignore": ["node_modules"],
    "watch": ["src/*"],
    "ext": "*"
}

Необхідно відстежувати вихідний код у src, а не відкомпільований у dist!

Створимо простий сервер.

var express = require('express');
const app = require('express')();
const server = require('http').createServer(app);
app.use(express.static('.'));

server.listen(5000, () => {
    console.log('Listening 5000');
});

Запуск

node_modules/nodemon/bin/nodemon.js dist/server/index.js

Простий шаблон сторінки.

<!DOCTYPE html>
<html>
    <head><title>TypeScript Greeter</title>
        <script src="node_modules/systemjs/dist/system.js"></script>
    </head>
    <body>
       <h1>Hello from Node!</h1>
    </body>
</html>

Встановимо універсальний завантажувач модулів.

npm install systemjs@0.19.22 --save

Фронтенд додаток.

Створюємо файл client/index.ts

console.log('Start!!!')

Додамо скрипт завантаження.

    <script>
        SystemJS.config({
            defaultJSExtensions: true
        });
        SystemJS.import('dist/client/index.js');        
    </script>

Зробимо оновлення сторінки після запуску сервера.

Ставимо лібу socket.io.

npm install socket.io @types/socket.io --save

Підключимо її на клієнта та спробуємо створити підключення.

Створюємо новий файл у client/includes/SocketConnection.ts

import { Client } from 'socket.io';
import * as io from 'socket.io';
export class SocketConnection {
    socket: any; 
    constructor(url: string) {
        this.socket = io(url, {transports:['websocket']});
    }
}

Приклад відпрацювання з’єднання та надсилання повідомлення на сервер.

this.socket = io(url, {transports:['websocket']})
.on('connect', (connection) => {
    this.socket.emit('hello',{message: 'hello message'});
})

Підключаємо та використовуємо в client/index.ts

import { SocketConnection } from './includes/SocketConnection';
var socket = new SocketConnection('ws://localhost:5000')
console.log('Start!!!')

start page

Додаємо шляхи до завантажувача.

    <script>
        SystemJS.config({
            defaultJSExtensions: true,
            map: {
                'socket.io': 'node_modules/socket.io-client/dist'
            },
            packages: {
                'socket.io': {
                    main: './socket.io.js'
                }
            }
        });
        SystemJS.import('dist/client/index.js');        
    </script>

[посилання на документацію по клієнту] (https://socket.io/docs/client-api/)

Додаємо сокет сервер на сервері.

const server = require('http').createServer(app);

// adding socket listener
const io = require('socket.io')(server, {});

Створюємо клас сокет з’єднання на сервері server/includes/SocketServer.ts

export class SocketServer {
    constructor(io: any) {
        io.on('connection', socket => { 
            console.log('Connected');
            console.log(socket.id);
         });
    }
}

Створюємо об’єкт класу SocketServer у вхідному файлі сервера server/index.ts.

// adding socket listener
const io = require('socket.io')(server, {});
var socketServer = new SocketServer(io);

Додавання шаблонизатора swig

npm install swig --save

Доопрацюємо вхідний файл сервера.

app.set('views', __dirname + '/../../src/server/tpl');
app.engine('html', require('swig').renderFile);
app.use("/", function(request, response){
    response.render("index.html");  
});

Перенесемо шаблон index.html у src/server/tpl.

Перевантаження сторінки у браузері.

Встановимо бібліотеку.

npm install livereload --save

Додамо наступне в server/index.ts.

// livereload  
const livereload = require("livereload");
const liveReloadServer = livereload.createServer();
liveReloadServer.watch(__dirname, '/../../src');   
liveReloadServer.server.once("connection", () => {
    setTimeout(() => {
      liveReloadServer.refresh("/");
    }, 1000);
  });    
const connectLivereload = require("connect-livereload");
app.use(connectLivereload());

app.use(connectLivereload()) - автоматично додасть тег скрипта на всі сторінки.

** Необхідно стежити за позицією коду та розміщувати перед підключенням шаблонизатора **

Іноді сервер livereload не завершується і залишає відкритим порт 35729.

Тому перед стартом сервера можна примусово прибивати процес порту 35729.

kill -9 $(lsof -t -i:35729)

Об’єднаний сервер NodeJs та транспілятор Typescript.

(Посилання на бібліотеку)https://www.npmjs.com/package/concurrently

npm install concurrently --save

Запустимо 2 команди, пропишемо команду start у package.json

“scripts”: { … “start”: “concurrently "./bin/run.cmd" "./bin/build.cmd"” },