2015 рдореЗрдВ рдЬрд╛рд░реА,
Agar.io рдЦреЗрд▓реЛрдВ рдХреА рдирдИ рд╢реИрд▓реА рдХреЗ рдкреВрд░реНрд╡рдЬ рдмрди рдЧрдП
редio , рдХреА рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рдХрд╛рдлреА рдмрдврд╝ рдЧрдИ рд╣реИред рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреА рд╡реГрджреНрдзрд┐ .io рдЦреЗрд▓ рдЬреЛ рдореИрдВрдиреЗ рдЦреБрдж рдЕрдиреБрднрд╡ рдХрд┐рдП рд╣реИрдВ: рдкрд┐рдЫрд▓реЗ рддреАрди рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдореИрдВрдиреЗ
рдЗрд╕ рд╢реИрд▓реА рдХреЗ рджреЛ рдЧреЗрдо рдмрдирд╛рдП рдФрд░ рдмреЗрдЪреЗ рд╣реИрдВред ред
рдпрджрд┐ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рдХрднреА рдЗрд╕ рддрд░рд╣ рдХреЗ рдЦреЗрд▓реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╕реБрдирд╛ рд╣реИ: рдпреЗ рдореБрдлреНрдд рдорд▓реНрдЯреАрдкреНрд▓реЗрдпрд░ рд╡реЗрдм рдЧреЗрдо рд╣реИрдВ рдЬреЛ (рдХреЛрдИ рдЦрд╛рддрд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ) рдореЗрдВ рднрд╛рдЧ рд▓реЗрдирд╛ рдЖрд╕рд╛рди рд╣реИред рдЖрдорддреМрд░ рдкрд░ рд╡реЗ рдХрдИ рд╡рд┐рд░реЛрдзреА рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рдПрдХ рд╣реА рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдзрдХреЗрд▓ рджреЗрддреЗ рд╣реИрдВред
.Io рд╢реИрд▓реА рдХреЗ рдЕрдиреНрдп рдкреНрд░рд╕рд┐рджреНрдз рдЦреЗрд▓ рд╣реИрдВ:
Slither.io рдФрд░
Diep.io.рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ, рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдПрдВрдЧреЗ рдХрд┐
рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рдПрдХ .io рдЧреЗрдо рдХреИрд╕реЗ
рдмрдирд╛рдпрд╛ рдЬрд╛рдП ред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдХреЗрд╡рд▓ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЬреНрдЮрд╛рди рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛: рдЖрдкрдХреЛ
ES6 рд╕рд┐рдВрдЯреИрдХреНрд╕,
this
рдФрд░
рдкреНрд░реЙрдорд┐рд╕ рдЬреИрд╕реА рдЪреАрдЬреЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рднрд▓реЗ рд╣реА рдЖрдк рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рдлрд┐рд░ рднреА рдЖрдк рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреЛрд╕реНрдЯ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЦреЗрд▓ рдЙрджрд╛рд╣рд░рдг .io
рдЖрдкрдХреЛ рд╕реАрдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
рдПрдХ рдЙрджрд╛рд╣рд░рдг .io рдЧреЗрдо рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░реЗрдВрдЧреЗред рдЗрд╕реЗ рдЦреЗрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛ!
рдЦреЗрд▓ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ: рдЖрдк рдПрдХ рдореИрджрд╛рди рдореЗрдВ рдПрдХ рдЬрд╣рд╛рдЬ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдЕрдиреНрдп рдЦрд┐рд▓рд╛рдбрд╝реА рд╣реИрдВред рдЖрдкрдХрд╛ рдЬрд╣рд╛рдЬ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЧреЛрд▓реЗ рджрд╛рдЧрддрд╛ рд╣реИ рдФрд░ рдЖрдк рдЕрдиреНрдп рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рдорд╛рд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рдЙрдирдХреЗ рдЧреЛрд▓реЗ рд╕реЗ рдмрдЪрддреЗ рд╣реИрдВред
1. рдЕрд╡рд▓реЛрдХрди / рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕рдВрд░рдЪрдирд╛
рдореИрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЦреЗрд▓ рдХреЗ рд▓рд┐рдП рд╕реНрд░реЛрдд рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ рддрд╛рдХрд┐ рдЖрдк рдореЗрд░рд╛ рдЕрдиреБрд╕рд░рдг рдХрд░ рд╕рдХреЗрдВред
рдЙрджрд╛рд╣рд░рдг рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:
- рдПрдХреНрд╕рдкреНрд░реЗрд╕ Node.js рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ рд╣реИ рдЬреЛ рдЧреЗрдо рдХреЗ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддрд╛ рд╣реИред
- socket.io - рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рдмреАрдЪ рдбреЗрдЯрд╛ рдХреЗ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реЗрдмрд╕реЛрдХреЗрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реАред
- рд╡реЗрдмрдкреИрдХ рдПрдХ рдореЙрдбреНрдпреВрд▓ рдореИрдиреЗрдЬрд░ рд╣реИред рдЖрдк рдпрд╣рд╛рдВ рд╡реЗрдмрдкреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
рдпрд╣рд╛рдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:
public/ assets/ ... src/ client/ css/ ... html/ index.html index.js ... server/ server.js ... shared/ constants.js
рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ /
public/
рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд╕рдм рдХреБрдЫ рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдк рд╕реЗ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
public/assets/
рдореЗрдВ рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдЫрд╡рд┐рдпрд╛рдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
src /
рд╕рднреА рд╕реНрд░реЛрдд рдХреЛрдб
src/
folder рдореЗрдВ рд╣реИред рдирд╛рдо
client/
рдФрд░
server/
рдЦреБрдж рдХреЗ рд▓рд┐рдП рдмреЛрд▓рддреЗ рд╣реИрдВ, рдФрд░
shared/
рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рджреЛрдиреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЖрдпрд╛рдд рдХреА рдЧрдИ рдПрдХ рд╕реНрдерд┐рд░ рдлрд╝рд╛рдЗрд▓ рд╣реЛрддреА рд╣реИред
2. рдЕрд╕реЗрдВрдмрд▓реА / рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреИрд░рд╛рдореАрдЯрд░
рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП
рд╡реЗрдмрдкреИрдХ рдореЙрдбреНрдпреВрд▓ рдкреНрд░рдмрдВрдзрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЖрдЗрдП рд╣рдорд╛рд░реЗ рд╡реЗрдмрдкреИрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
webpack.common.js:
const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry: { game: './src/client/index.js', }, output: { filename: '[name].[contenthash].js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ['@babel/preset-env'], }, }, }, { test: /\.css$/, use: [ { loader: MiniCssExtractPlugin.loader, }, 'css-loader', ], }, ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].[contenthash].css', }), new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/client/html/index.html', }), ], };
рдпрд╣рд╛рдБ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд╛рдЗрдиреЗрдВ рд╣реИрдВ:
src/client/index.js
рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ (JS) рдХреЗ рд▓рд┐рдП рдЗрдирдкреБрдЯ рдмрд┐рдВрджреБ рд╣реИред рд╡реЗрдмрдкреИрдХ рдпрд╣рд╛рдВ рд╕реЗ рд╢реБрд░реВ рд╣реЛрдЧрд╛ рдФрд░ рдЕрдиреНрдп рдЖрдпрд╛рддрд┐рдд рдлрд╛рдЗрд▓реЛрдВ рдХреА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░реЗрдЧрд╛ред- рд╣рдорд╛рд░реЗ рд╡реЗрдмрдкреИрдХ рдЕрд╕реЗрдВрдмрд▓реА рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ JS
dist/
рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реЛрдЧрд╛ред рдореИрдВ рдЗрд╕ рдлрд╛рдЗрд▓ рдХреЛ рд╣рдорд╛рд░реЗ рдЬреЗрдПрд╕ рдкреИрдХреЗрдЬ рдХрд╣реВрдВрдЧрд╛ред - рд╣рдо рдмреИрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ @ рдЬреЗрд╕реНрд╕реЗрд▓ / рдкреНрд░реАрд╕реЗрдЯ-рдПрдирд╡реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреБрд░рд╛рдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдЬреЗрдПрд╕ рдХреЛрдб рдХреЛ рдЯреНрд░рд╛рдВрд╕рдкрд╛рдЗрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
- рд╣рдо рдЬреЗрдПрд╕ рдлрд╛рдЗрд▓реЛрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдВрджрд░реНрднрд┐рдд рд╕рднреА рд╕реАрдПрд╕рдПрд╕ рдХреЛ рдирд┐рдХрд╛рд▓рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕реНрдерд╛рди рдкрд░ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рд╕реАрдПрд╕рдПрд╕ рдкреИрдХреЗрдЬ рдХрд╣реВрдВрдЧрд╛ред
рдЖрдкрдиреЗ рдЕрдЬреАрдм рдкреИрдХреЗрдЬ рдлрд╝рд╛рдЗрд▓ рдирд╛рдореЛрдВ рдкрд░ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
'[name].[contenthash].ext'
ред рд╡реЗ рд╡реЗрдмрдкреИрдХ
рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдирд╛рдореЛрдВ рдХрд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХрд░рддреЗ рд╣реИрдВ :
[name]
рдХреЛ рдЗрдирдкреБрдЯ рдмрд┐рдВрджреБ рдХреЗ рдирд╛рдо рд╕реЗ рдмрджрд▓рд╛ рдЬрд╛рдПрдЧрд╛ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдПрдХ
game
), рдФрд░
[contenthash]
рдХреЛ рдлрд╝рд╛рдЗрд▓ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╣реИрд╢ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдо
рд╣реИрд╢рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ
рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ - рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░реЛрдВ рдХреЛ рд╣рдорд╛рд░реЗ рдЬреЗрдПрд╕ рдкреИрдХреЗрдЬреЛрдВ рдХреЛ рдЕрдирд┐рд╢реНрдЪрд┐рдд рдХрд╛рд▓ рдХреЗ рд▓рд┐рдП рдХреИрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐
рдпрджрд┐ рдкреИрдХреЗрдЬ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ (
contenthash
рдкрд░рд┐рд╡рд░реНрддрди)ред рд╕рдорд╛рдкреНрдд рдкрд░рд┐рдгрд╛рдо рдлреЙрд░реНрдо
game.dbeee76e91a97d0c7207.js
рдХрд╛ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рд╣реЛрдЧрд╛ред
webpack.common.js
рдлрд╝рд╛рдЗрд▓ рдЖрдзрд╛рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рд╡рд┐рдХрд╛рд╕ рдФрд░ рддреИрдпрд╛рд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╡рд┐рдХрд╛рд╕ рд╡рд┐рдиреНрдпрд╛рд╕:
webpack.dev.js
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common, { mode: 'development', });
рджрдХреНрд╖рддрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд┐рдХрд╛рд╕
webpack.dev.js
рдореЗрдВ
webpack.dev.js
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ
webpack.dev.js
, рдФрд░ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рддреИрдирд╛рдд рд╣реЛрдиреЗ рдкрд░ рдкреИрдХреЗрдЬ рдЖрдХрд╛рд░реЛрдВ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
webpack.prod.js
рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ рд╣реИрдВред
рд╕реНрдерд╛рдиреАрдп рд╕реЗрдЯрд┐рдВрдЧ
рдореИрдВ рдПрдХ рд╕реНрдерд╛рдиреАрдп рдорд╢реАрди рдкрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ рддрд╛рдХрд┐ рдЖрдк рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ рд╕реВрдЪреАрдмрджреНрдз рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░ рд╕рдХреЗрдВред рд╕реЗрдЯрдЕрдк рд╕рд░рд▓ рд╣реИ: рдкрд╣рд▓реЗ,
рдиреЛрдб рдФрд░
рдПрдирдкреАрдПрдо рдХреЛ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдЧреЗ рдЖрдкрдХреЛ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
$ git clone https:
рдФрд░ рдЖрдк рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВ! рд╡рд┐рдХрд╛рд╕ рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдЪрд▓рд╛рдПрдВ
$ npm run develop
рдФрд░
рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
: рд╡реЗрдм рдмреНрд░рд╛рдЙрдЬрд░ рдореЗрдВ
3000 ред рдХреЛрдб рдмрджрд▓рддреЗ рд╣реА рдЬреЗрдПрд╕ рдФрд░ рд╕реАрдПрд╕рдПрд╕ рдкреИрдХреЗрдЬреЛрдВ рдХрд╛ рд╡рд┐рдХрд╛рд╕ рд╕рд░реНрд╡рд░ рдЕрдкрдиреЗ рдЖрдк рдлрд┐рд░ рд╕реЗ рддреИрдпрд╛рд░ рд╣реЛ рдЬрд╛рдПрдЧрд╛ - рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреГрд╖реНрда рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ!
3. рдЧреНрд░рд╛рд╣рдХ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ
рдЪрд▓реЛ рдЦреЗрд▓ рдХреЛрдб рдХреЗ рд▓рд┐рдП рд╣реА рдиреАрдЪреЗ рдЖрддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ
index.html
рдкреЗрдЬ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрдм рдЖрдк рд╕рд╛рдЗрдЯ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЗрд╕реЗ рдкрд╣рд▓реЗ рд▓реЛрдб рдХрд░реЗрдЧрд╛ред рд╣рдорд╛рд░рд╛ рдкреГрд╖реНрда рдХрд╛рдлреА рд╕рд░рд▓ рд╣реЛрдЧрд╛:
index.html
<! DOCTYPE html>
<Html>
<Head>
<рд╢реАрд░реНрд╖рдХ> рдПрдХ рдЙрджрд╛рд╣рд░рдг .io рдЦреЗрд▓ </ рд╢реАрд░реНрд╖рдХ>
<рд▓рд┐рдВрдХ рдкреНрд░рдХрд╛рд░ = "рдЯреЗрдХреНрд╕реНрдЯ / рд╕реАрдПрд╕рдПрд╕" rel = "рд╕реНрдЯрд╛рдЗрд▓рд╢реАрдЯ" href = "/ game.bundle.css">
</ Head>
<Body>
<рдХреИрдирд╡рд╛рд╕ рдЖрдИрдбреА = "рдЧреЗрдо-рдХреИрдирд╡рд╛рд╕"> </ рдХреИрдирд╡рд╛рд╕>
<script async src = "/ game.bundle.js"> </ script>
<div id = "play-menu" рд╡рд░реНрдЧ = "рдЫрд┐рдкрд╛ рд╣реБрдЖ">
<рдЗрдирдкреБрдЯ рдкреНрд░рдХрд╛рд░ = "рдЯреЗрдХреНрд╕реНрдЯ" рдЖрдИрдбреА = "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо-рдЗрдирдкреБрдЯ" рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░ = "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо" />
<рдмрдЯрди рдЖрдИрдбреА = "рдкреНрд▓реЗ-рдмрдЯрди"> рдкреНрд▓реЗ </ рдмрдЯрди>
</ Div>
</ Body>
</ Html>
рдпрд╣ рдХреЛрдб рдЙрджрд╛рд╣рд░рдг рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рд╕рд░рд▓ рд╣реИ, рдореИрдВ рдкреЛрд╕реНрдЯ рдХреЗ рдХрдИ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рднреА рдРрд╕рд╛ рд╣реА рдХрд░реВрдВрдЧрд╛ред рдкреВрд░реНрдг рдХреЛрдб рд╣рдореЗрд╢рд╛ Github рдкрд░ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредрд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣реИ:
- рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдХреИрдирд╡рд╕ (
<canvas>
) <canvas>
рдЬреЛ рд╣рдо рдЧреЗрдо рдХреЛ рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред - рд╣рдорд╛рд░реЗ рд╕реАрдПрд╕рдПрд╕ рдкреИрдХреЗрдЬ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП
<link>
ред <script>
рд╣рдорд╛рд░реЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреИрдХреЗрдЬ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдПред- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо
<input>
рдФрд░ "рдкреНрд▓реЗ" ( <button>
) <button>
рд╕рд╛рде рдореБрдЦреНрдп рдореЗрдиреВред
рд╣реЛрдо рдкреЗрдЬ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрдЧрд╛, рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рдХреЗ рдЬреЗрдПрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдЧрд╛:
src/client/index.js
ред
index.js
import { connect, play } from './networking'; import { startRendering, stopRendering } from './render'; import { startCapturingInput, stopCapturingInput } from './input'; import { downloadAssets } from './assets'; import { initState } from './state'; import { setLeaderboardHidden } from './leaderboard'; import './css/main.css'; const playMenu = document.getElementById('play-menu'); const playButton = document.getElementById('play-button'); const usernameInput = document.getElementById('username-input'); Promise.all([ connect(), downloadAssets(), ]).then(() => { playMenu.classList.remove('hidden'); usernameInput.focus(); playButton.onclick = () => {
рдпрд╣ рдЬрдЯрд┐рд▓ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣рд╛рдВ рдмрд╣реБрдд рд╕рд╛рд░реА рдХреНрд░рд┐рдпрд╛рдПрдВ рдирд╣реАрдВ рд╣реЛ рд░рд╣реА рд╣реИрдВ:
- рдХрдИ рдЕрдиреНрдп рдЬреЗрдПрд╕ рдлрд╛рдЗрд▓реЗрдВ рдЖрдпрд╛рдд рдХрд░реЗрдВред
- рдЖрдпрд╛рдд рд╕реАрдПрд╕рдПрд╕ (рддрд╛рдХрд┐ рд╡реЗрдмрдкреИрдХ рд╣рдорд╛рд░реЗ рд╕реАрдПрд╕рдПрд╕ рдкреИрдХреЗрдЬ рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░рдирд╛ рдЬрд╛рдирддрд╛ рд╣реИ)ред
- рд╕рд░реНрд╡рд░ рд╕реЗ рдХрдиреЗрдХреНрд╢рди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рдирд┐рдВрдЧ
connect()
рдФрд░ рдЧреЗрдо рдХреЛ рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдЫрд╡рд┐рдпрд╛рдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд╛рдЙрдирд▓реЛрдбрдЕрд╕реИрдЯ downloadAssets()
рдЪрд▓ рд░рд╣рд╛ рд╣реИред - рдЪрд░рдг 3 рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж , рдореБрдЦреНрдп рдореЗрдиреВ (
playMenu
) playMenu
рдЬрд╛рддрд╛ playMenu
ред - PLAY рдмрдЯрди рджрдмрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ред рдЬрдм рдмрдЯрди рджрдмрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреЛрдб рдЧреЗрдо рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЛ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЦреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред
рд╣рдорд╛рд░реЗ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд░реНрд╡рд░ рд▓реЙрдЬрд┐рдХ рдХрд╛ рдореБрдЦреНрдп "рдорд╛рдВрд╕" рдЙрди рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╣реИ, рдЬрд┐рдиреНрд╣реЗрдВ
index.js
рдлрд╝рд╛рдЗрд▓ рджреНрд╡рд╛рд░рд╛ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЕрдм рд╣рдо рдЙрди рд╕рднреА рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
4. рдЧреНрд░рд╛рд╣рдХ рдбреЗрдЯрд╛ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди
рдЗрд╕ рдЧреЗрдо рдореЗрдВ рд╣рдо рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕рдВрдЪрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕рд┐рджреНрдз
рд╕реЙрдХреЗрдЯ.рдЖрдИрдУ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред Socket.io рдиреЗ
WebSockets рдХреЗ рд▓рд┐рдП рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рдорд░реНрдерди рджрд┐рдпрд╛ рд╣реИ, рдЬреЛ рджреЛ-рддрд░рдлрд╝рд╛ рд╕рдВрдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреВрд▓ рд╣реИрдВ: рд╣рдо рд╕рд░реНрд╡рд░ рдХреЛ рд╕рдВрджреЗрд╢ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ
рдФрд░ рд╕рд░реНрд╡рд░ рд╣рдореЗрдВ рдЙрд╕реА рдХрдиреЗрдХреНрд╢рди рдкрд░ рд╕рдВрджреЗрд╢ рднреЗрдЬ рд╕рдХрддрд╛ рд╣реИред
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ
src/client/networking.js
рдлрд╝рд╛рдЗрд▓ рд╣реЛрдЧреА рдЬреЛ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде
рд╕рднреА рд╕рдВрдЪрд╛рд░реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓реЗрдЧреА:
networking.js
import io from 'socket.io-client'; import { processGameUpdate } from './state'; const Constants = require('../shared/constants'); const socket = io(`ws://${window.location.host}`); const connectedPromise = new Promise(resolve => { socket.on('connect', () => { console.log('Connected to server!'); resolve(); }); }); export const connect = onGameOver => ( connectedPromise.then(() => {
рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдпрд╣ рдХреЛрдб рднреА рдереЛрдбрд╝рд╛ рдХрдо рд╣реИредрдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рддреАрди рдореБрдЦреНрдп рдХреНрд░рд┐рдпрд╛рдПрдВ рд╣реИрдВ:
- рд╣рдо рд╕рд░реНрд╡рд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВред
connectedPromise
рдХреА рдЕрдиреБрдорддрд┐ рдХреЗрд╡рд▓ рддрднреА рд╣реИ рдЬрдм рд╣рдордиреЗ рдХрдиреЗрдХреНрд╢рди рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рд╣реЛред - рдпрджрд┐ рдХрдиреЗрдХреНрд╢рди рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕реНрдерд╛рдкрд┐рдд рд╣реИ, рддреЛ рд╣рдо рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ (
processGameUpdate()
рдФрд░ onGameOver()
) рдкрдВрдЬреАрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред - рд╣рдо
play()
рдФрд░ updateDirection()
рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреЗ play()
рддрд╛рдХрд┐ рдЕрдиреНрдп рдлрд╛рдЗрд▓реЗрдВ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХреЗрдВред
5. рдХреНрд▓рд╛рдЗрдВрдЯ рд░реЗрдВрдбрд░рд┐рдВрдЧ
рдпрд╣ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдЪрд┐рддреНрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ!
... рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдРрд╕рд╛ рдХрд░ рд╕рдХреЗрдВ, рд╣рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рднреА рдЪрд┐рддреНрд░реЛрдВ (рд╕рдВрд╕рд╛рдзрдиреЛрдВ) рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рд╕рдВрд╕рд╛рдзрди рдкреНрд░рдмрдВрдзрдХ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
assets.js
const ASSET_NAMES = ['ship.svg', 'bullet.svg']; const assets = {}; const downloadPromise = Promise.all(ASSET_NAMES.map(downloadAsset)); function downloadAsset(assetName) { return new Promise(resolve => { const asset = new Image(); asset.onload = () => { console.log(`Downloaded ${assetName}`); assets[assetName] = asset; resolve(); }; asset.src = `/assets/${assetName}`; }); } export const downloadAssets = () => downloadPromise; export const getAsset = assetName => assets[assetName];
рд╕рдВрд╕рд╛рдзрди рдкреНрд░рдмрдВрдзрди рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЗрддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ! рдореБрдЦреНрдп рдмрд┐рдВрджреБ
assets
рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╣реИ, рдЬреЛ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдХреБрдВрдЬреА рдХреЛ
Image
рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдореВрд▓реНрдп рдореЗрдВ рдмрд╛рдВрдз рджреЗрдЧрд╛ред рдЬрдм рд╕рдВрд╕рд╛рдзрди рд▓реЛрдб рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рддреНрд╡рд░рд┐рдд рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддрд┐ рдХреЗ рд▓рд┐рдП
assets
рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВред рдЬрдм рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рдбрд╛рдЙрдирд▓реЛрдбрд┐рдВрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреА рдЬрд╛рдПрдЧреА (рдЕрд░реНрдерд╛рдд,
рд╕рднреА рд╕рдВрд╕рд╛рдзрди рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ), рд╣рдо
downloadPromise
рд╕рдХреНрд╖рдо рдХрд░рддреЗ рд╣реИрдВред
рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдкреНрд░рддрд┐рдкрд╛рджрди рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдо рд╡реЗрдм рдкреЗрдЬ рдкрд░ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдХреИрдирд╡рд╕ (
<canvas>
) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рдорд╛рд░рд╛ рдЦреЗрд▓ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдмрд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
- рдкреГрд╖реНрдарднреВрдорд┐
- рдЦрд┐рд▓рд╛рдбрд╝реА рдЬрд╣рд╛рдЬ
- рдЦреЗрд▓ рдореЗрдВ рдЕрдиреНрдп рдЦрд┐рд▓рд╛рдбрд╝реА
- рдЧреЛрд▓рд╛рдмрд╛рд░реВрдж
рдпрд╣рд╛рдБ
src/client/render.js
рдХреЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕реНрдирд┐рдкреЗрдЯ рджрд┐рдП рдЧрдП рд╣реИрдВ рдЬреЛ рдКрдкрд░ рд╕реВрдЪреАрдмрджреНрдз рдЪрд╛рд░ рдмрд┐рдВрджреБрдУрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВ:
render.js
import { getAsset } from './assets'; import { getCurrentState } from './state'; const Constants = require('../shared/constants'); const { PLAYER_RADIUS, PLAYER_MAX_HP, BULLET_RADIUS, MAP_SIZE } = Constants;
рдЗрд╕ рдХреЛрдб рдХреЛ рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рднреА рдЫреЛрдЯрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИредrender()
рдЗрд╕ рдлрд╛рдЗрд▓ рдХрд╛ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рд╣реИред
startRendering()
рдФрд░
stopRendering()
60 FPS рдкрд░ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдЪрдХреНрд░ рдХреА рд╕рдХреНрд░рд┐рдпрддрд╛ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕рд╣рд╛рдпрдХ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (рдЙрджрд╛ред
renderBullet()
) рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдБ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИ:
render.js
function renderBullet(me, bullet) { const { x, y } = bullet; context.drawImage( getAsset('bullet.svg'), canvas.width / 2 + x - me.x - BULLET_RADIUS, canvas.height / 2 + y - me.y - BULLET_RADIUS, BULLET_RADIUS * 2, BULLET_RADIUS * 2, ); }
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо
getAsset()
рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдкрд╣рд▓реЗ
asset.js
рдореЗрдВ рджреЗрдЦрд╛ рдЧрдпрд╛ рдерд╛ред
asset.js
!
рдпрджрд┐ рдЖрдк рдЕрдиреНрдп рд╕рд╣рд╛рдпрдХ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдмрд╛рдХреА src / client / render.js рдкрдврд╝реЗрдВ ред
6. рдЧреНрд░рд╛рд╣рдХ рдЗрдирдкреБрдЯ
рдпрд╣ рдЦреЗрд▓ рдХреЛ
рдЦреЗрд▓рдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ! рдирд┐рдпрдВрддреНрд░рдг рдпреЛрдЬрдирд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реЛрдЧреА: рдЖрдк рдорд╛рдЙрд╕ (рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЖрдВрджреЛрд▓рди рдХреА рджрд┐рд╢рд╛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░реАрди (рдореЛрдмрд╛рдЗрд▓ рдбрд┐рд╡рд╛рдЗрд╕ рдкрд░) рдХреЛ рдЫреВ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдорд╛рдЙрд╕ рдФрд░ рдЯрдЪ рдИрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП
рдЗрд╡реЗрдВрдЯ рд╢реНрд░реЛрддрд╛рдУрдВ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВрдЧреЗред
src/client/input.js
рдпрд╣ рд╕рдм рдХрд░реЗрдЧрд╛:
input.js
import { updateDirection } from './networking'; function onMouseInput(e) { handleInput(e.clientX, e.clientY); } function onTouchInput(e) { const touch = e.touches[0]; handleInput(touch.clientX, touch.clientY); } function handleInput(x, y) { const dir = Math.atan2(x - window.innerWidth / 2, window.innerHeight / 2 - y); updateDirection(dir); } export function startCapturingInput() { window.addEventListener('mousemove', onMouseInput); window.addEventListener('touchmove', onTouchInput); } export function stopCapturingInput() { window.removeEventListener('mousemove', onMouseInput); window.removeEventListener('touchmove', onTouchInput); }
onMouseInput()
рдФрд░
onTouchInput()
рдИрд╡реЗрдВрдЯ рд╢реНрд░реЛрддрд╛ рд╣реИрдВ рдЬреЛ рдПрдХ рдЗрдирдкреБрдЯ рдИрд╡реЗрдВрдЯ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдорд╛рдЙрд╕ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ) рддрдм
updateDirection()
(
updateDirection()
рд╕реЗ
updateDirection()
рдХреЙрд▓
updateDirection()
ред
updateDirection()
рдПрдХ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдореИрд╕реЗрдЬрд┐рдВрдЧ рдореЗрдВ рд▓рдЧрд╛ рд╣реБрдЖ рд╣реИ рдЬреЛ рдЗрдирдкреБрдЯ рдИрд╡реЗрдВрдЯ рдХреЛ рдкреНрд░реЛрд╕реЗрд╕ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрд╕реА рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЧреЗрдо рд╕реНрдЯреЗрдЯ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред
7. рдЧреНрд░рд╛рд╣рдХ рдХреА рд╕реНрдерд┐рддрд┐
рдпрд╣ рдЕрдиреБрднрд╛рдЧ рдкреЛрд╕реНрдЯ рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╕рдмрд╕реЗ рдХрдард┐рди рд╣реИред рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдкрд╣рд▓реЗ рдкрдврд╝рдиреЗ рд╕реЗ рдирд╣реАрдВ рд╕рдордЭрддреЗ рд╣реИрдВ, рддреЛ рдирд┐рд░рд╛рд╢ рди рд╣реЛрдВ! рдЖрдк рдЗрд╕реЗ рдЫреЛрдбрд╝ рднреА рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдмрд╛рдж рдореЗрдВ рд╡рд╛рдкрд╕ рдЖ рд╕рдХрддреЗ рд╣реИрдВред
рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд░реНрд╡рд░ рдХреЛрдб рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкрд╣реЗрд▓реА рдХрд╛ рдЕрдВрддрд┐рдо рдЯреБрдХрдбрд╝рд╛
рд░рд╛рдЬреНрдп рд╣реИ ред рдХреНрд▓рд╛рдЗрдВрдЯ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдЕрдиреБрднрд╛рдЧ рд╕реЗ рдХреЛрдб рд╕реНрдирд┐рдкреЗрдЯ рдпрд╛рдж рд░рдЦреЗрдВ?
render.js
import { getCurrentState } from './state'; function render() { const { me, others, bullets } = getCurrentState();
getCurrentState()
рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдЕрдкрдбреЗрдЯ рдХреЗ рдЖрдзрд╛рд░ рдкрд░
рдХрд┐рд╕реА рднреА рд╕рдордп рдХреНрд▓рд╛рдЗрдВрдЯ
рдореЗрдВ рдЧреЗрдо рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рд╣рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣рд╛рдБ рдПрдХ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдЬреЛ рдПрдХ рд╕рд░реНрд╡рд░ рднреЗрдЬ рд╕рдХрддрд╛ рд╣реИ:
{ "t": 1555960373725, "me": { "x": 2213.8050880413657, "y": 1469.370893425012, "direction": 1.3082443894581433, "id": "AhzgAtklgo2FJvwWAADO", "hp": 100 }, "others": [], "bullets": [ { "id": "RUJfJ8Y18n", "x": 2354.029197099604, "y": 1431.6848318262666 }, { "id": "ctg5rht5s", "x": 2260.546457727445, "y": 1456.8088728920968 } ], "leaderboard": [ { "username": "Player", "score": 3 } ] }
рдкреНрд░рддреНрдпреЗрдХ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдореЗрдВ рдкрд╛рдБрдЪ рд╕рдорд╛рди рдлрд╝реАрд▓реНрдб рд╣реЛрддреЗ рд╣реИрдВ:
- t : рдпрд╣ рдЕрджреНрдпрддрди рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЙрд╕ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдкред
- рдореБрдЭреЗ : рдЗрд╕ рдЕрдкрдбреЗрдЯ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реАред
- рдЕрдиреНрдп : рдПрдХ рд╣реА рдЦреЗрд▓ рдореЗрдВ рднрд╛рдЧ рд▓реЗрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреНрдп рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреА рдПрдХ рд╕рд░рдгреАред
- рдЧреЛрд▓рд┐рдпреЛрдВ : рдЦреЗрд▓ рдореЗрдВ рдЧреЛрд▓реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреА рдПрдХ рд╕рд░рдгреАред
- рд▓реАрдбрд░рдмреЛрд░реНрдб : рд╡рд░реНрддрдорд╛рди рд▓реАрдбрд░рдмреЛрд░реНрдб рдбреЗрдЯрд╛ред рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд▓реЗрдВрдЧреЗред
7.1 рдЧреНрд░рд╛рд╣рдХ рдХреА рдЕрдиреБрднрд╡рд╣реАрди рдЕрд╡рд╕реНрдерд╛
getCurrentState()
рдХрд╛ рднреЛрд▓реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗрд╡рд▓ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдЧреЗрдо рдЕрдкрдбреЗрдЯ рд╕реЗ рд╕реАрдзреЗ рдбреЗрдЯрд╛ рд▓реМрдЯрд╛ рд╕рдХрддрд╛ рд╣реИред
рднреЛрд▓реА-state.js
let lastGameUpdate = null;
рд╕реБрдВрджрд░ рдФрд░ рд╕реНрдкрд╖реНрдЯ! рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рд╕рд░рд▓ рдерд╛ред рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╕рдорд╕реНрдпрд╛рдЧреНрд░рд╕реНрдд рд╣реИ:
рдпрд╣ рд╕рд░реНрд╡рд░ рдШрдбрд╝реА рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЛ рд░реЗрдВрдбрд░ рдХреА рдлреНрд░реЗрдо рджрд░ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИ ред
рдлреНрд░реЗрдо рджрд░ : рдлреНрд░реЗрдо рдХреА рд╕рдВрдЦреНрдпрд╛ (рдпрд╛рдиреА render()
рдХреЙрд▓) рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдпрд╛ рдПрдлрдкреАрдПрд╕ред рдЦреЗрд▓ рдЖрдорддреМрд░ рдкрд░ рдХрдо рд╕реЗ рдХрдо 60 рдПрдлрдкреАрдПрд╕ рддрдХ рдкрд╣реБрдВрдЪрддреЗ рд╣реИрдВред
рдЯрд┐рдХ рджрд░ : рд╡рд╣ рдЖрд╡реГрддреНрддрд┐ рдЬрд┐рд╕ рдкрд░ рд╕рд░реНрд╡рд░ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рднреЗрдЬрддрд╛ рд╣реИред рдЕрдХреНрд╕рд░ рдпрд╣ рдлреНрд░реЗрдо рджрд░ рд╕реЗ рдХрдо рд╣реЛрддрд╛ рд╣реИ ред рд╣рдорд╛рд░реЗ рдЦреЗрд▓ рдореЗрдВ, рд╕рд░реНрд╡рд░ 30 рдЪрдХреНрд░ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдХреА рдЖрд╡реГрддреНрддрд┐ рдкрд░ рдЪрд▓рддрд╛ рд╣реИред
рдпрджрд┐ рд╣рдо рдЧреЗрдо рдХреЗ рдирд╡реАрдирддрдо рдЕрдкрдбреЗрдЯ рдХреЛ рдХреЗрд╡рд▓ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдПрдлрдкреАрдПрд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрднреА рднреА 30 рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реЛ рдкрд╛рдПрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐
рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 30 рд╕реЗ рдЕрдзрд┐рдХ рдЕрдкрдбреЗрдЯ рдХрднреА рдирд╣реАрдВ рдорд┐рд▓рддреЗ рд╣реИрдВ ред рднрд▓реЗ рд╣реА рд╣рдо
render()
рдХреЙрд▓ рдХрд░рддреЗ
render()
рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 60 рдмрд╛рд░, рдЗрдирдореЗрдВ рд╕реЗ рдЖрдзреЗ рдХреЙрд▓ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдЪреАрдЬрд╝ рдХреЛ рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВрдЧреЗ, рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рднреЛрд▓реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕рдореЗрдВ
рджреЗрд░реА рд╣реЛрдиреЗ рдХрд╛
рдЦрддрд░рд╛ рд╣реИ ред рдПрдХ рдЖрджрд░реНрд╢ рдЗрдВрдЯрд░рдиреЗрдЯ рд╕реНрдкреАрдб рдХреЗ рд╕рд╛рде, рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╣рд░ 33 рдПрдордПрд╕ (рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 30) рдХрд╛ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдорд┐рд▓реЗрдЧрд╛:
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдХреБрдЫ рднреА рд╕рд╣реА рдирд╣реАрдВ рд╣реИред рдПрдХ рдЕрдзрд┐рдХ рдпрдерд╛рд░реНрдерд╡рд╛рджреА рдЪрд┐рддреНрд░ рд╣реЛрдЧрд╛:
рдПрдХ рднреЛрд▓реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рд╕рдмрд╕реЗ рдЦрд░рд╛рдм рд╕реНрдерд┐рддрд┐ рд╣реИ рдЬрдм рдЗрд╕рдореЗрдВ рджреЗрд░реА рд╣реЛрддреА рд╣реИред рдпрджрд┐ рдЧреЗрдо рдЕрдкрдбреЗрдЯ 50 рдПрдордПрд╕ рдХреА рджреЗрд░реА рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ
рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд 50 рдПрдордПрд╕ рдХреЗ рд▓рд┐рдП
рдзреАрдорд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ , рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрднреА рднреА рдкрд┐рдЫрд▓реЗ рдЕрдкрдбреЗрдЯ рд╕реЗ рдЧреЗрдо рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрд░рддрд╛ рд╣реИред рдЖрдк рдХрд▓реНрдкрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЗ рд▓рд┐рдП рдпрд╣ рдХрд┐рддрдирд╛ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ: рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдмреНрд░реЗрдХ рд▓рдЧрд╛рдиреЗ рдХреЗ рдХрд╛рд░рдг, рдЦреЗрд▓ рдЪрд┐рдХреЛрдЯреА рдФрд░ рдЕрд╕реНрдерд┐рд░ рдкреНрд░рддреАрдд рд╣реЛрдЧрд╛ред
7.2 рдЧреНрд░рд╛рд╣рдХ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реБрдзрд╛рд░
рд╣рдо рдЕрдиреБрднрд╡рд╣реАрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕реБрдзрд╛рд░ рдХрд░реЗрдВрдЧреЗред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо
рдПрдХ 100 рдПрдордПрд╕
рд░реЗрдВрдбрд░рд┐рдВрдЧ рджреЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА "рд╡рд░реНрддрдорд╛рди" рд╕реНрдерд┐рддрд┐ рд╣рдореЗрд╢рд╛ рд╕рд░реНрд╡рд░ рдкрд░ рдЧреЗрдо рдХреА рд╕реНрдерд┐рддрд┐ рд╕реЗ 100 рдПрдордПрд╕ рд╕реЗ рдкреАрдЫреЗ рд░рд╣ рдЬрд╛рдПрдЧреАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╕рд░реНрд╡рд░ рдкрд░ рд╕рдордп
150 рд╣реИ , рддреЛ рд╡рд╣ рд╕реНрдерд┐рддрд┐ рдЬрд┐рд╕рдореЗрдВ рд╕рд░реНрд╡рд░
50 рдХреЗ рд╕рдордп рдХрд╛ рдерд╛, рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:
рдпрд╣ рд╣рдореЗрдВ 100 рдПрдордПрд╕ рдХрд╛ рдмрдлрд░ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рд╣рдореЗрдВ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╕рдордп рддрдХ рдЬреАрд╡рд┐рдд рд░рд╣рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИ:
рдЗрд╕рдХреЗ рд▓рд┐рдП рднреБрдЧрддрд╛рди рдХрд░рдирд╛ 100 рдПрдордПрд╕
рдХреА рдирд┐рд░рдВрддрд░
рдЗрдирдкреБрдЯ рджреЗрд░реА (рдЗрдирдкреБрдЯ рд▓реИрдЧ) рд╣реЛрдЧрд╛ ред рдпрд╣ рдЪрд┐рдХрдиреА рдЧреЗрдордкреНрд▓реЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рдореВрд▓реА рдмрд▓рд┐рджрд╛рди рд╣реИ - рдЕрдзрд┐рдХрд╛рдВрд╢ рдЦрд┐рд▓рд╛рдбрд╝реА (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЖрдХрд╕реНрдорд┐рдХ рд╡рд╛рд▓реЗ) рднреА рдЗрд╕ рджреЗрд░реА рдХреЛ рдиреЛрдЯрд┐рд╕ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рд▓реЛрдЧреЛрдВ рдХреЛ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рджреЗрд░реА рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ 100 рдПрдордПрд╕ рдХреА рдирд┐рд░рдВрддрд░ рджреЗрд░реА рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред
рд╣рдо "рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдлреЛрд░рдХрд╛рд╕реНрдЯрд┐рдВрдЧ" рдирд╛рдордХ рдПрдХ рдЕрдиреНрдп рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ , рдЬреЛ рдХрдерд┐рдд рджреЗрд░реА рдХреЛ рдХрдо рдХрд░рдиреЗ рдХрд╛ рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рдФрд░ рд╕реБрдзрд╛рд░
рд░реИрдЦрд┐рдХ рдкреНрд░рдХреНрд╖реЗрдк рд╣реИ ред рд╡рд┐рд▓рдВрдм рдХрд╛ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░рдг, рд╣рдо рдЖрдорддреМрд░ рдкрд░ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд╡рд░реНрддрдорд╛рди рд╕рдордп рдХреЛ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдЕрдкрдбреЗрдЯ рд╕реЗ рдЖрдЧреЗ рдирд┐рдХрд▓ рдЬрд╛рддреЗ рд╣реИрдВред рдЬрдм
getCurrentState()
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕рдордп рд╕реЗ рдкрд╣рд▓реЗ рдФрд░ рдмрд╛рдж рдореЗрдВ рддреБрд░рдВрдд рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдХреЗ рдмреАрдЪ
рд░реИрдЦрд┐рдХ рдкреНрд░рдХреНрд╖реЗрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
рдпрд╣ рдлреНрд░реЗрдо рджрд░ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ: рдЕрдм рд╣рдо рдХрд┐рд╕реА рднреА рдЖрд╡реГрддреНрддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рд╕рд╛рде рдЕрджреНрд╡рд┐рддреАрдп рдлреНрд░реЗрдо рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!
7.3 рдПрдиреНрд╣рд╛рдВрд╕реНрдб рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реНрдерд┐рддрд┐ рд▓рд╛рдЧреВ рдХрд░рдирд╛
src/client/state.js
рдореЗрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд░реЗрдВрдбрд░рд┐рдВрдЧ рджреЗрд░реА рдФрд░ рд░реИрдЦрд┐рдХ рдкреНрд░рдХреНрд╖реЗрдк рджреЛрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдирд╣реАрдВ рд╣реИред рдХреЛрдб рдХреЛ рджреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рддреЛрдбрд╝рддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдкрд╣рд▓реЗ рдПрдХ рд╣реИ:
State.js рднрд╛рдЧ 1
const RENDER_DELAY = 100; const gameUpdates = []; let gameStart = 0; let firstServerTimestamp = 0; export function initState() { gameStart = 0; firstServerTimestamp = 0; } export function processGameUpdate(update) { if (!firstServerTimestamp) { firstServerTimestamp = update.t; gameStart = Date.now(); } gameUpdates.push(update);
рдкрд╣рд▓рд╛ рдХрджрдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╣реИ рдХрд┐
currentServerTime()
рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рджреЗрдЦрд╛, рд╣рд░ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдореЗрдВ рдПрдХ рд╕рд░реНрд╡рд░ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рд╢рд╛рдорд┐рд▓ рд╣реЛрддрд╛ рд╣реИред рд╣рдо рд╕рд░реНрд╡рд░ рдХреЗ рдкреАрдЫреЗ рдЫрд╡рд┐ 100 рдПрдордПрд╕ рдХреЛ рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░реЗрдВрдбрд░рд┐рдВрдЧ рджреЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди
рд╣рдо рдХрднреА рднреА рд╕рд░реНрд╡рд░ рдкрд░ рд╡рд░реНрддрдорд╛рди рд╕рдордп рдХреЛ рдирд╣реАрдВ рдЬрд╛рди рдкрд╛рдПрдВрдЧреЗ , рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдпрд╣ рдирд╣реАрдВ рдЬрд╛рди рд╕рдХрддреЗ рдХрд┐ рдХреЛрдИ рднреА рдЕрдкрдбреЗрдЯ рд╣рдореЗрдВ рдХрдм рддрдХ рдорд┐рд▓рд╛ред рдЗрдВрдЯрд░рдиреЗрдЯ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╣реИ рдФрд░ рдЗрд╕рдХреА рдЧрддрд┐ рдмрд╣реБрдд рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреА рд╣реИ!
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдПрдХ рдЙрдЪрд┐рдд рдЕрдиреБрдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рд╣рдо рдЗрд╕ рдмрд╛рдд рдХрд╛
рдвреЛрдВрдЧ рдХрд░реЗрдВрдЧреЗ
рдХрд┐ рдкрд╣рд▓рд╛ рдЕрдкрдбреЗрдЯ рддреБрд░рдВрдд рдЖ рдЧрдпрд╛ ред рдпрджрд┐ рдпрд╣ рд╕рдЪ рд╣реЛрддрд╛, рддреЛ рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рд╢реЗрд╖ рд╕рдордп рдореЗрдВ рд╕рд░реНрд╡рд░ рдХрд╛ рд╕рдордп рдкрддрд╛ рд╣реЛрддрд╛! рд╣рдо рдкрд╣рд▓реЗ рд╕рд░реНрд╡рд░ рдореЗрдВ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреЛ рд╕реЗрд╡ рдХрд░рддреЗ рд╣реИрдВ рдФрд░
firstServerTimestamp
рдореЗрдВ рдЙрд╕реА рд╕рдордп рдЕрдкрдиреЗ
рд▓реЛрдХрд▓ (рдХреНрд▓рд╛рдЗрдВрдЯ) рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреЛ
gameStart
ред
рдУрд╣ рд░реБрдХреЛред
рдХреНрдпрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдореЗрдВ рд╕рд░реНрд╡рд░ = рд╕рдордп рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП? рд╣рдо "рд╕рд░реНрд╡рд░ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк" рдФрд░ "рдХреНрд▓рд╛рдЗрдВрдЯ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк" рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рдХреНрдпреЛрдВ рдХрд░рддреЗ рд╣реИрдВ? рдпрд╣ рдПрдХ рдорд╣рд╛рди рдкреНрд░рд╢реНрди рд╣реИ! рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдпрд╣ рдПрдХ рд╣реА рдмрд╛рдд рдирд╣реАрдВ рд╣реИред
Date.now()
рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рд▓реМрдЯрд╛рдПрдЧрд╛, рдФрд░ рдпрд╣ рдЗрди рдорд╢реАрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рдиреАрдп рдХрд╛рд░рдХреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдХрднреА рди рдорд╛рдиреЗрдВ рдХрд┐ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рд╕рднреА рдорд╢реАрдиреЛрдВ рдкрд░ рд╕рдорд╛рди рд╣реИрдВредрдЕрдм рд╣рдо рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐
currentServerTime()
рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ: рдпрд╣
рд╡рд░реНрддрдорд╛рди рд░реЗрдВрдбрд░рд┐рдВрдЧ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдХрд╛ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рд▓реМрдЯрд╛рддрд╛ рд╣реИред
рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдпрд╣ рд╡рд░реНрддрдорд╛рди рд╕рд░реНрд╡рд░ рд╕рдордп рд╣реИ ( firstServerTimestamp <+ (Date.now() - gameStart)
) рдЛрдг рджреЗрдиреЗ рдореЗрдВ рджреЗрд░реА ( RENDER_DELAY
)редрдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдХреЛ рдХреИрд╕реЗ рд╕рдВрднрд╛рд▓рддреЗ рд╣реИрдВред рдЬрдм рд╕рд░реНрд╡рд░ рд╕реЗ рдХреЛрдИ рдЕрдкрдбреЗрдЯ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЙрд╕реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ processGameUpdate()
, рдФрд░ рд╣рдо рдирдП рдЕрдкрдбреЗрдЯ рдХреЛ рдПрдХ рдЕрд░реИ рдореЗрдВ рд╕реЗрд╡ рдХрд░рддреЗ рд╣реИрдВ gameUpdates
ред рдлрд┐рд░, рдореЗрдореЛрд░реА рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рднреА рдкреБрд░рд╛рдиреЗ рдЕрдкрдбреЗрдЯ рдХреЛ рдЖрдзрд╛рд░ рдЕрдкрдбреЗрдЯ рдореЗрдВ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВ , рдХреНрдпреЛрдВрдХрд┐ рдЕрдм рд╣рдореЗрдВ рдЙрдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИредрдПрдХ "рдмреБрдирд┐рдпрд╛рджреА рдЕрджреНрдпрддрди" рдХреНрдпрд╛ рд╣реИ? рдпрд╣ рдкрд╣рд▓рд╛ рдЕрдкрдбреЗрдЯ рд╣реИ рдЬреЛ рд╣рдо рд╡рд░реНрддрдорд╛рди рд╕рд░реНрд╡рд░ рд╕рдордп рд╕реЗ рдкреАрдЫреЗ рдХреА рдУрд░ рдмрдврд╝рддреЗ рд╣реБрдП рдкрд╛рддреЗ рд╣реИрдВ ред рдЗрд╕ рд╕рд░реНрдХрд┐рдЯ рдХреЛ рдпрд╛рдж рд░рдЦреЗрдВ?рдХреНрд▓рд╛рдЗрдВрдЯ рд░реЗрдВрдбрд░ рдЯрд╛рдЗрдо рдХреЗ рдмрд╛рдИрдВ рдУрд░ рд╕реАрдзреЗ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдПрдХ рдмреБрдирд┐рдпрд╛рджреА рдЕрдкрдбреЗрдЯ рд╣реИредрдореВрд▓ рдЕрджреНрдпрддрди рдХрд┐рд╕рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ? рд╣рдо рдЖрдзрд╛рд░ рд╕реЗ рдЕрдкрдбреЗрдЯ рдХреНрдпреЛрдВ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ? рдЗрд╕реЗ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдЕрдВрдд рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЗрдЦреЗрдВ getCurrentState()
:state.js рднрд╛рдЧ 2
export function getCurrentState() { if (!firstServerTimestamp) { return {}; } const base = getBaseUpdate(); const serverTime = currentServerTime();
рд╣рдо рддреАрди рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рддреЗ рд╣реИрдВ:base < 0
рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдореМрдЬреВрджрд╛ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдЯрд╛рдЗрдо (рдКрдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рджреЗрдЦреЗрдВ getBaseUpdate()
) рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЕрдкрдбреЗрдЯ рдирд╣реАрдВ рд╣реИ ред рдпрд╣ рд╡рд┐рд▓рдВрдм рдХреЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЗ рдХрд╛рд░рдг рдЦреЗрд▓ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╕рд╣реА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо рд╕рдмрд╕реЗ рд╣рд╛рд▓рд┐рдпрд╛ рдЕрдкрдбреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВредbase
рдпрд╣ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд╡реАрдирддрдо рдЕрдкрдбреЗрдЯ рд╣реИред рдпрд╣ рдиреЗрдЯрд╡рд░реНрдХ рд╡рд┐рд▓рдВрдмрддрд╛ рдпрд╛ рдЦрд░рд╛рдм рдЗрдВрдЯрд░рдиреЗрдЯ рдХрдиреЗрдХреНрд╢рди рдХреЗ рдХрд╛рд░рдг рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд╡реАрдирддрдо рдЕрдкрдбреЗрдЯ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рд╣реЛрддрд╛ рд╣реИред- рд╡рд░реНрддрдорд╛рди рд░реЗрдВрдбрд░рд┐рдВрдЧ рд╕рдордп рд╕реЗ рдкрд╣рд▓реЗ рдФрд░ рдмрд╛рдж рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЕрдкрдбреЗрдЯ рд╣реИ, рддрд╛рдХрд┐ рдЖрдк рдЗрдВрдЯрд░рдкреЛрд▓ рдХрд░ рд╕рдХреЗрдВ !
рдЬреЛ рдХреБрдЫ рднреА рд░рд╣рддрд╛ state.js
рд╣реИ рд╡рд╣ рд░реИрдЦрд┐рдХ рдкреНрд░рдХреНрд╖реЗрдк рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ, рдЬреЛ рдПрдХ рд╕рд░рд▓ (рд▓реЗрдХрд┐рди рдЙрдмрд╛рдК) рдЧрдгрд┐рдд рд╣реИред рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рд╕реАрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕реЗ рдЧреАрдереВрдмstate.js
рдкрд░ рдЦреЛрд▓реЗрдВ редрднрд╛рдЧ 2. рдмреИрдХреЗрдВрдб рд╕рд░реНрд╡рд░
рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рд╣рдорд╛рд░реЗ .io рдЧреЗрдо рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЪрд▓рд╛рдиреЗ рд╡рд╛рд▓реЗ Node.js рдмреИрдХрдПрдВрдб рдХреЛ рджреЗрдЦреЗрдВрдЧреЗ ред1. рд╕рд░реНрд╡рд░ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ
рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо Node.js рдХреЗ рд▓рд┐рдП рд▓реЛрдХрдкреНрд░рд┐рдп рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕реЗ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдпрд╣ рд╣рдорд╛рд░реЗ рд╕рд░реНрд╡рд░ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдлрд╝рд╛рдЗрд▓ рджреНрд╡рд╛рд░рд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ src/server/server.js
:server.js, рднрд╛рдЧ 1
const express = require('express'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackConfig = require('../../webpack.dev.js');
рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╣рдордиреЗ рд╡реЗрдмрдкреИрдХ рдкрд░ рдЪрд░реНрдЪрд╛ рдХреА рдереА? рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рд╣рдо рдЕрдкрдиреЗ рд╡реЗрдмрдкреИрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рд╣рдо рдЙрдиреНрд╣реЗрдВ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗ:- рд╡реЗрдмрдкреИрдХ-рджреЗрд╡-рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдорд╛рд░реЗ рд╡рд┐рдХрд╛рд╕ рдкреИрдХреЗрдЬреЛрдВ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВ, рдпрд╛
- рд╡реИрдзрд╛рдирд┐рдХ рд░реВрдк рд╕реЗ рдЙрд╕ рдлрд╝реЛрд▓реНрдбрд░
dist/
рдХреЛ рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП Webpack рдЙрддреНрдкрд╛рджрди рдХреА рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдХреЗ рдмрд╛рдж рд╣рдорд╛рд░реА рдлрд╛рдЗрд▓реЗрдВ рд▓рд┐рдЦреЗрдЧрд╛ред
рдПрдХ рдЕрдиреНрдп рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╛рд░реНрдп socket.ioserver.js
рд╕рд░реНрд╡рд░ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реИ , рдЬреЛ рдмрд╕ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ:server.js, рднрд╛рдЧ 2
const socketio = require('socket.io'); const Constants = require('../shared/constants');
рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕реЙрдХреЗрдЯ.рдЖрдИрдУ рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдирдП рд╕реЙрдХреЗрдЯ рдХреЗ рд▓рд┐рдП рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдЧреНрд░рд╛рд╣рдХреЛрдВ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рд╕рдВрджреЗрд╢ рдХреЛ рд╕рд┐рдВрдЧрд▓рдЯрди рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рднреЗрдЬрддреЗ рд╣реИрдВ game
:server.js, рднрд╛рдЧ 3
const Game = require('./game');
рд╣рдо .io рд╢реИрд▓реА рдХрд╛ рдПрдХ рдЧреЗрдо рдмрдирд╛рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЙрджрд╛рд╣рд░рдг Game
("рдЧреЗрдо") рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рд╕рднреА рдЦрд┐рд▓рд╛рдбрд╝реА рдПрдХ рд╣реА рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЦреЗрд▓рддреЗ рд╣реИрдВ! рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдпрд╣ рд╡рд░реНрдЧ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ Game
ред2. рдЦреЗрд▓ рд╕рд░реНрд╡рд░
рдХреНрд▓рд╛рд╕ Game
рдореЗрдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд▓реЙрдЬрд┐рдХ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рджреЛ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рд╣реИрдВ: рдЦрд┐рд▓рд╛рдбрд╝реА рдкреНрд░рдмрдВрдзрди рдФрд░ рдЦреЗрд▓ рд╕рд┐рдореБрд▓реЗрд╢рди редрдЦрд┐рд▓рд╛рдбрд╝реА рдкреНрд░рдмрдВрдзрди рдХреЗ рд╕рд╛рде - рд╣рдо рдкрд╣рд▓реЗ рдХрд╛рд░реНрдп рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВредgame.js, рднрд╛рдЧ 1
const Constants = require('../shared/constants'); const Player = require('./player'); class Game { constructor() { this.sockets = {}; this.players = {}; this.bullets = []; this.lastUpdateTime = Date.now(); this.shouldSendUpdate = false; setInterval(this.update.bind(this), 1000 / 60); } addPlayer(socket, username) { this.sockets[socket.id] = socket;
рдЗрд╕ рдЧреЗрдо рдореЗрдВ, рд╣рдо рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ id
рдЙрдирдХреЗ рд╕реЙрдХреЗрдЯ рд╕реЙрдХреЗрдЯ рдХреЗ рдХреНрд╖реЗрддреНрд░ рджреНрд╡рд╛рд░рд╛ рдкрд╣рдЪрд╛рдиреЗрдВрдЧреЗред (рдпрджрд┐ рдЖрдк рднреНрд░рдорд┐рдд рд╣реИрдВ, рддреЛ рд╡рд╛рдкрд╕ рд▓реМрдЯреЗрдВ server.js
)ред Socket.io рд╣реА рдкреНрд░рддреНрдпреЗрдХ рд╕реЙрдХреЗрдЯ рдХреЛ рдПрдХ рдЕрдиреЛрдЦрд╛ рдЕрд╕рд╛рдЗрди рдХрд░рддрд╛ рд╣реИ id
, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдореИрдВ рдЙрдирдХреА рдЦрд┐рд▓рд╛рдбрд╝реА рдЖрдИрдбреА рдХреЛ рдХреЙрд▓ рдХрд░реВрдВрдЧрд╛ редрдЗрд╕реЗ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рдЖрдЗрдП рдХрдХреНрд╖рд╛ рдореЗрдВ рдЙрджрд╛рд╣рд░рдг рдЪрд░ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ Game
:sockets
рдПрдХ рдРрд╕реА рд╡рд╕реНрддреБ рд╣реИ рдЬреЛ рдЦрд┐рд▓рд╛рдбрд╝реА рдЖрдИрдбреА рдХреЛ рдЙрд╕ рд╕реЙрдХреЗрдЯ рд╕реЗ рдмрд╛рдВрдзрддреА рд╣реИ рдЬреЛ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рд╣рдореЗрдВ рд▓рдЧрд╛рддрд╛рд░ рд╕рдордп рдХреЗ рд▓рд┐рдП рдЙрдирдХреЗ рдЦрд┐рд▓рд╛рдбрд╝реА рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рд╕реЙрдХреЗрдЯ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИредplayers
рдПрдХ рд╡рд╕реНрддреБ рд╣реИ рдЬреЛ рдПрдХ рдЦрд┐рд▓рд╛рдбрд╝реА рдЖрдИрдбреА рдХреЛ рдХреЛрдб> рдкреНрд▓реЗрдпрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдмрд╛рдВрдзрддреА рд╣реИ
bullets
рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ Bullet
рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрд░рдо рдирд╣реАрдВ рд╣реИредlastUpdateTime
- рдпрд╣ рдЙрд╕ рд╕рдордп рдХрд╛ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рд╣реИ рдЬрдм рдЧреЗрдо рдХреЛ рдЖрдЦрд┐рд░реА рдмрд╛рд░ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЬрд▓реНрдж рд╣реА рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИредshouldSendUpdate
рдПрдХ рд╕рд╣рд╛рдпрдХ рдЪрд░ рд╣реИред рд╣рдо рдЬрд▓реНрдж рд╣реА рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рднреА рджреЗрдЦреЗрдВрдЧреЗредрддрд░реАрдХреЗ addPlayer()
, removePlayer()
рдФрд░ handleInput()
рд╕рдордЭрд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИ, рд╡реЗ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ server.js
ред рдпрджрд┐ рдЖрдкрдХреЛ рдЕрдкрдиреА рд╕реНрдореГрддрд┐ рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдереЛрдбрд╝реА рдЕрдзрд┐рдХ рдорд╛рддреНрд░рд╛ рдореЗрдВ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдБредрдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдЪрдХреНрд░constructor()
рд╢реБрд░реВ рдХрд░рддреА рд╣реИ (60 рдЕрдкрдбреЗрдЯ / рдПрд╕ рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде):game.js, рднрд╛рдЧ 2
const Constants = require('../shared/constants'); const applyCollisions = require('./collisions'); class Game {
рд╡рд┐рдзрд┐ рдореЗрдВ update()
рд╕рдВрднрд╡рддрдГ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд▓реЙрдЬрд┐рдХ рдХрд╛ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣рд┐рд╕реНрд╕рд╛ рд╣реЛрддрд╛ рд╣реИред рдЖрджреЗрд╢ рдореЗрдВ, рд╣рдо рд╡рд╣ рд╕рдм рдХреБрдЫ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╡рд╣ рдХрд░рддрд╛ рд╣реИ:- рдЧрдгрдирд╛ рдХрд░рддрд╛
dt
рд╣реИ рдХрд┐ рдЖрдЦрд┐рд░реА рдХреЗ рдмрд╛рдж рдХрд┐рддрдирд╛ рд╕рдордп рдмреАрдд рдЪреБрдХрд╛ рд╣реИ update()
ред - . . ,
bullet.update()
true
, ( ). - . тАФ
player.update()
Bullet
. applyCollisions()
, , . , ( player.onDealtDamage()
), bullets
.- .
update()
. shouldSendUpdate
. update()
60 /, 30 /. , 30 / ( ).
? . 30 тАУ !
рдлрд┐рд░ update()
рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб 30 рдмрд╛рд░ рдХреЙрд▓ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ ? рдЦреЗрд▓ рдХреЗ рд╕рд┐рдореБрд▓реЗрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЕрдзрд┐рдХ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ update()
, рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рдЦреЗрд▓ рдХрд╛ рдЕрдиреБрдХрд░рдг рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдХреЙрд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рджреВрд░ рдордд рдЬрд╛рдУ update()
, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рдирд▓ рд░реВрдк рд╕реЗ рдорд╣рдВрдЧрд╛ рдХрд╛рдо рд╣реИ - 60 рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдХрд╛рдлреА рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред
рдХрдХреНрд╖рд╛ рдореЗрдВ рд╢реЗрд╖ Game
рд╕рд╣рд╛рдпрдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ update()
:game.js, рднрд╛рдЧ 3
class Game {
getLeaderboard()
рдХрд╛рдлреА рд╕рд░рд▓ - рдпрд╣ рдЕрдВрдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рдЫрд╛рдБрдЯрддрд╛ рд╣реИ, рдкрд╛рдБрдЪ рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рд╕реНрдХреЛрд░ рдХреЗ рд▓рд┐рдП рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИред рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЦреЗрд▓ рдЕрджреНрдпрддрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдПcreateUpdate()
рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ update()
ред рдЗрд╕рдХрд╛ рдореБрдЦреНрдп рдХрд╛рд░реНрдп serializeForUpdate()
рдХрдХреНрд╖рд╛рдУрдВ Player
рдФрд░ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реИ Bullet
ред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╡рд╣ рдкреНрд░рддреНрдпреЗрдХ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЛ рдХреЗрд╡рд▓ рдирд┐рдХрдЯрддрдо рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдФрд░ рдЧреЛрд▓реЗ рдкрд░ рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ - рдЦрд┐рд▓рд╛рдбрд╝реА рд╕реЗ рджреВрд░ рд╕реНрдерд┐рдд рдЦреЗрд▓ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ!3. рд╕рд░реНрд╡рд░ рдкрд░ рдЧреЗрдо рдСрдмреНрдЬреЗрдХреНрдЯ
рд╣рдорд╛рд░реЗ рдЦреЗрд▓ рдореЗрдВ, рдЧреЛрд▓реЗ рдФрд░ рдЦрд┐рд▓рд╛рдбрд╝реА рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рд╕рдорд╛рди рд╣реИрдВ: рд╡реЗ рдЕрдореВрд░реНрдд рдЧреЛрд▓ рдЪрд▓рддреА рд╣реБрдИ рдЦреЗрд▓ рд╡рд╕реНрддреБрдПрдВ рд╣реИрдВред рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдФрд░ рдЧреЛрд▓реЗ рдХреА рдЗрд╕ рд╕рдорд╛рдирддрд╛ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдЖрдзрд╛рд░ рд╡рд░реНрдЧ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ Object
:object.js
class Object { constructor(id, x, y, dir, speed) { this.id = id; this.x = x; this.y = y; this.direction = dir; this.speed = speed; } update(dt) { this.x += dt * this.speed * Math.sin(this.direction); this.y -= dt * this.speed * Math.cos(this.direction); } distanceTo(object) { const dx = this.x - object.x; const dy = this.y - object.y; return Math.sqrt(dx * dx + dy * dy); } setDirection(dir) { this.direction = dir; } serializeForUpdate() { return { id: this.id, x: this.x, y: this.y, }; } }
рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИред рдпрд╣ рд╡рд░реНрдЧ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдВрджрд░реНрдн рдмрд┐рдВрджреБ рд╣реЛрдЧрд╛ред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╡рд░реНрдЧ рдХреИрд╕реЗ Bullet
рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ Object
:bullet.js
const shortid = require('shortid'); const ObjectClass = require('./object'); const Constants = require('../shared/constants'); class Bullet extends ObjectClass { constructor(parentID, x, y, dir) { super(shortid(), x, y, dir, Constants.BULLET_SPEED); this.parentID = parentID; }
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди Bullet
рдмрд╣реБрдд рдХрдо рд╣реИ! рд╣рдордиреЗ Object
рдХреЗрд╡рд▓ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрдХреНрд╕рдЯреЗрдВрд╢рдиреЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ :- рдмреЗрддрд░рддреАрдм рдврдВрдЧ рд╕реЗ рдПрдХ рдкреНрд░рдХреНрд╖реЗрдкреНрдп рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреЗ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
id
ред - рдПрдХ рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝рдирд╛
parentID
рддрд╛рдХрд┐ рдЖрдк рдЙрд╕ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЛ рдЯреНрд░реИрдХ рдХрд░ рд╕рдХреЗрдВ рдЬрд┐рд╕рдиреЗ рдпрд╣ рдкреНрд░реЛрдЬреЗрдХреНрдЯрд╛рдЗрд▓ рдмрдирд╛рдпрд╛ рд╣реИред - рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдЬреЛрдбрд╝рдирд╛
update()
, рдЬреЛ рдмрд░рд╛рдмрд░ рд╣реИ true
рдпрджрд┐ рдкреНрд░рдХреНрд╖реЗрдкреНрдп рдХреНрд╖реЗрддреНрд░ рдХреЗ рдмрд╛рд╣рд░ рд╣реИ (рдпрд╛рдж рд░рдЦреЗрдВ, рд╣рдордиреЗ рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдереА?)ред
рдЪрд▓реЛ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ Player
:player.js
const ObjectClass = require('./object'); const Bullet = require('./bullet'); const Constants = require('../shared/constants'); class Player extends ObjectClass { constructor(id, username, x, y) { super(id, x, y, Math.random() * 2 * Math.PI, Constants.PLAYER_SPEED); this.username = username; this.hp = Constants.PLAYER_MAX_HP; this.fireCooldown = 0; this.score = 0; }
рдЦрд┐рд▓рд╛рдбрд╝реА рдЧреЛрд▓реЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╡рд░реНрдЧ рдореЗрдВ рдХреБрдЫ рдФрд░ рдХреНрд╖реЗрддреНрд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдПред рдЙрдирдХреА рдкрджреНрдзрддрд┐ update()
рдмрд╣реБрдд рдХрд╛рдо рдХрд░рддреА рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдирдП рдмрдирд╛рдП рдЧрдП рд╢реЗрд▓ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрддреА рд╣реИ рдЕрдЧрд░ рдпрд╣ рдирд╣реАрдВ рдЫреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ fireCooldown
(рдпрд╛рдж рд░рдЦреЗрдВ, рд╣рдордиреЗ рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдереА?)ред рд╡рд╣ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рднреА рдХрд░рддрд╛ рд╣реИ serializeForUpdate()
, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдЧреЗрдо рдЕрдкрдбреЗрдЯ рдореЗрдВ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХреЛрдб рд░рд┐рдкреАрдЯреЗрдмрд┐рд▓рд┐рдЯреА рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдПрдмреЗрд╕ рдХреНрд▓рд╛рд╕ Object
рд╣реЛрдирд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрджрдо рд╣реИ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╡рд░реНрдЧ рдХреЗ рдмрд┐рдирд╛, Object
рд╣рд░ рдЧреЗрдо рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдПрдХ рд╣реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП distanceTo()
, рдФрд░ рдХрдИ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рдЗрди рд╕рднреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиреЛрдВ рдХреА рдХреЙрдкреА-рдкреЗрд╕реНрдЯ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдПрдХ рдмреБрд░рд╛ рд╕рдкрдирд╛ рд╣реЛрдЧрд╛ред рд╡рд┐рд╕реНрддрд╛рд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ Object
рдмрдврд╝рдиреЗ рдкрд░ рдпрд╣ рдмрдбрд╝реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред4. рд╕рдВрдШрд░реНрд╖ рдорд╛рдиреНрдпрддрд╛
рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдмрдЪреА рд╣реИ, рдЬрдм рдпрд╣ рдкрддрд╛ рдЪрд▓реЗрдЧрд╛ рдХрд┐ рдЧреЛрд▓реЗ рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рдХрд┐рд╕ рддрд░рд╣ рдорд╛рд░рддреЗ рд╣реИрдВ! update()
рдПрдХ рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рд╕реЗ рдХреЛрдб рдХрд╛ рдпрд╣ рдЯреБрдХрдбрд╝рд╛ рдпрд╛рдж рд░рдЦреЗрдВ Game
:game.js
const applyCollisions = require('./collisions'); class Game {
рд╣рдореЗрдВ рдПрдХ рдРрд╕рд╛ рддрд░реАрдХрд╛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ applyCollisions()
рдЬреЛ рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рд╣рд┐рдЯ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдЧреЛрд▓реЗ рд▓реМрдЯрд╛рдПред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдРрд╕рд╛ рдХрд░рдирд╛ рдЗрддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐- рд╕рднреА рдЯрдХрд░рд╛рдиреЗ рд╡рд╛рд▓реА рд╡рд╕реНрддреБрдПрдВ рдордВрдбрд▓рд┐рдпрд╛рдВ рд╣реИрдВ, рдФрд░ рдЯрдХрд░рд╛рд╡ рдХреА рдорд╛рдиреНрдпрддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЖрдВрдХрдбрд╝рд╛ рд╣реИред
- рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд╡рд┐рдзрд┐ рд╣реИ
distanceTo()
рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдХрдХреНрд╖рд╛ рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ Object
ред
рдпрд╣рд╛рдВ рд╣рдорд╛рд░реА рдЯрдХреНрдХрд░ рдорд╛рдиреНрдпрддрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:collisions.js
const Constants = require('../shared/constants');
рдпрд╣ рд╕рд╛рдзрд╛рд░рдг рдЯрдХреНрдХрд░ рдХреА рдорд╛рдиреНрдпрддрд╛ рдЗрд╕ рддрдереНрдп рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ рдХрд┐ рджреЛ рд╡реГрддреНрдд рдЯрдХрд░рд╛рддреЗ рд╣реИрдВ рдпрджрд┐ рдЙрдирдХреЗ рдХреЗрдВрджреНрд░реЛрдВ рдХреЗ рдмреАрдЪ рдХреА рджреВрд░реА рдЙрдирдХреЗ рд░реЗрдбреА рдХреЗ рдпреЛрдЧ рд╕реЗ рдХрдо рд╣реЛ ред рдпрд╣рд╛рдВ рдРрд╕рд╛ рдорд╛рдорд▓рд╛ рд╣реИ рдЬрдм рджреЛ рд╕рд░реНрдХрд▓ рдХреЗ рдХреЗрдВрджреНрд░реЛрдВ рдХреЗ рдмреАрдЪ рдХреА рджреВрд░реА рдЙрдирдХреЗ рд░реЗрдбреА рдХреЗ рдпреЛрдЧ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ:рдпрд╣рд╛рдВ рдЖрдкрдХреЛ рдХреБрдЫ рдкрд╣рд▓реБрдУрдВ рдкрд░ рд╕рд╛рд╡рдзрд╛рдиреА рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:- рдкреНрд░рдХреНрд╖реЗрдкреНрдп рдЙрд╕ рдЦрд┐рд▓рд╛рдбрд╝реА рдореЗрдВ рдирд╣реАрдВ рдЧрд┐рд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рд╣реИред рдпрд╣ рддреБрд▓рдирд╛ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛
bullet.parentID
рдХреЗ рд╕рд╛рде player.id
ред - рдкреНрд░рдХреНрд╖реЗрдкреНрдп рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХрдИ рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рде рдЯрдХрд░рд╛рд╡ рдХреЗ рдЪрд░рдо рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рд┐рдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдСрдкрд░реЗрдЯрд░ рдХреА рдорджрдж рд╕реЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░реЗрдВрдЧреЗ
break
: рдЬреИрд╕реЗ рд╣реА рдПрдХ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЛ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЙрд╕реЗ рдПрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯрд╛рдЗрд▓ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рд╣реИ, рд╣рдо рдЦреЛрдЬ рдХреЛ рд░реЛрдХрддреЗ рд╣реИрдВ рдФрд░ рдЕрдЧрд▓реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯрд╛рдЗрд▓ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВред
рдЕрдВрдд
рд╡рд╣ рд╕рдм рд╣реИ! рд╣рдордиреЗ рдПрдХ .io рд╡реЗрдм рдЧреЗрдо рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЬреЛ рдХреБрдЫ рднреА рдЬрд╛рдирдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЙрд╕реЗ рдХрд╡рд░ рдХрд┐рдпрд╛ рд╣реИред рдЖрдЧреЗ рдХреНрдпрд╛ рд╣реИ?
рдЕрдкрдиреЗ рдЦреБрдж рдХреЗ .io рдЦреЗрд▓ рдХрд╛ рдирд┐рд░реНрдорд╛рдг!рд╕рднреА рд╕реИрдВрдкрд▓ рдХреЛрдб рдУрдкрди рд╕реЛрд░реНрд╕ рд╣реИрдВ рдФрд░ рдЗрдиреНрд╣реЗрдВ рдЬреАрдердм рдкрд░ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред