2015 เจตเจฟเฉฑเจ เจฐเจฟเจฒเฉเจเจผ เจนเฉเจ
เจเฉเจเจฐ เจคเฉเจธเฉเจ เจเจนเจจเจพเจ เจเฉเจฎเจพเจ เจฌเจพเจฐเฉ เจชเจนเจฟเจฒเจพเจ เจเจฆเฉ เจจเจนเฉเจ เจธเฉเจฃเจฟเจ เจนเฉ, เจคเจพเจ เจเจน เจฎเฉเจซเจค, เจฎเจฒเจเฉเจชเจฒเฉเจ
เจฐ เจตเฉเฉฑเจฌ เจเฉเจฎเจพเจ เจนเจจ เจเฉ เจเฉเจกเจฃ เจฒเจ เจเจธเจพเจจ เจนเจจ (เจเจฟเจธเฉ เจเจพเจคเฉ เจฆเฉ เจฒเฉเฉ เจจเจนเฉเจ)เฅค เจเจน เจเจฎ เจคเฉเจฐ 'เจคเฉ เจฌเจนเฉเจค เจธเจพเจฐเฉ เจตเจฟเจฐเฉเจงเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจเฉฑเจ เจ
เจเจพเฉเฉ เจตเจฟเฉฑเจ เจเฉเฉเจนเจพ เจเจฐเจฆเฉ เจนเจจเฅค เจนเฉเจฐ เจฎเจธเจผเจนเฉเจฐ .io เจเฉเจฎเจพเจ:
เจเจธ เจชเฉเจธเจ เจตเจฟเฉฑเจ เจ
เจธเฉเจ เจเจน เจชเจคเจพ เจฒเจเจพเจตเจพเจเจเฉ เจเจฟ เจเจฟเจตเฉเจ เจธเจเฉเจฐเฉเจ เจคเฉเจ เจเฉฑเจ .io เจเฉเจฎ เจฌเจฃเจพเจ. เจ
เจเจฟเจนเจพ เจเจฐเจจ เจฒเจ, เจเจพเจตเจพเจธเจเฉเจฐเจฟเจชเจ เจฆเจพ เจธเจฟเจฐเจซ เจเจฟเจเจจ เจเจพเจซเจผเฉ เจนเฉเจตเฉเจเจพ: เจคเฉเจนเจพเจจเฉเฉฐ เจธเจฟเฉฐเจเฉเจเจธ เจตเจฐเจเฉเจเจ เจเฉเจเจผเจพเจ เจจเฉเฉฐ เจธเจฎเจเจฃ เจฆเฉ เจเจผเจฐเฉเจฐเจค เจนเฉ this
ะธ
เจเฉฑเจ .io เจเฉเจฎ เจฆเฉ เจเจฆเจพเจนเจฐเจจ
เจธเจฟเจเจฒเจพเจ เจธเจนเจพเจเจคเจพ เจฒเจ เจ
เจธเฉเจ เจนเจตเจพเจฒเจพ เจฆเฉเจตเจพเจเจเฉ
เจเฉเจก เจเจพเจซเจผเฉ เจธเจงเจพเจฐเจจ เจนเฉ: เจคเฉเจธเฉเจ เจฆเฉเจเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจฆเฉ เจจเจพเจฒ เจเฉฑเจ เจ
เจเจพเฉเฉ เจตเจฟเฉฑเจ เจเฉฑเจ เจเจนเจพเจเจผ เจจเฉเฉฐ เจจเจฟเจฏเฉฐเจคเจฐเจฟเจค เจเจฐเจฆเฉ เจนเฉ. เจคเฉเจนเจพเจกเจพ เจเจนเจพเจเจผ เจเจเฉเจฎเฉเจเจฟเจ เจนเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒเจพเจ เจจเฉเฉฐ เจซเจพเจเจฐ เจเจฐเจฆเจพ เจนเฉ เจ
เจคเฉ เจคเฉเจธเฉเจ เจฆเฉเจเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจเจจเฉเจนเจพเจ เจฆเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒเจพเจ เจคเฉเจ เจฌเจเจฆเฉ เจนเฉเจ เจฎเจพเจฐเจจ เจฆเฉ เจเฉเจธเจผเจฟเจธเจผ เจเจฐเจฆเฉ เจนเฉเฅค
1. เจธเฉฐเจเฉเจช เจเจพเจฃเจเจพเจฐเฉ/เจชเฉเจฐเฉเจเฉเจเจ เจฌเจฃเจคเจฐ
เจฎเฉเจ เจธเจฟเจซเจพเจฐเจธเจผ เจเจฐเจฆเจพ เจนเจพเจ
เจธเจฐเฉเจค เจเฉเจก เจจเฉเฉฐ เจกเจพเจเจจเจฒเฉเจก เจเจฐเฉ เจเจฆเจพเจนเจฐเจจ เจเฉเจฎ เจคเจพเจ เจเฉ เจคเฉเจธเฉเจ เจฎเฉเจฐเจพ เจ เจจเฉเจธเจฐเจฃ เจเจฐ เจธเจเฉ.
เจเจฆเจพเจนเจฐเจจ เจนเฉเจ เจฒเจฟเจเฉ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจฆเฉ เจนเฉ:
เจเจเจธเจชเฉเจฐเฉเฉฑเจธ Node.js เจฒเจ เจธเจญ เจคเฉเจ เจชเฉเจฐเจธเจฟเฉฑเจง เจตเฉเฉฑเจฌ เจซเจฐเฉเจฎเจตเจฐเจ เจนเฉ เจเฉ เจเฉเจฎ เจฆเฉ เจตเฉเฉฑเจฌ เจธเจฐเจตเจฐ เจฆเจพ เจชเฉเจฐเจฌเฉฐเจงเจจ เจเจฐเจฆเจพ เจนเฉเฅคsocket.io - เจฌเฉเจฐเจพเจเจเจผเจฐ เจ เจคเฉ เจธเจฐเจตเจฐ เจตเจฟเจเจเจพเจฐ เจกเฉเจเจพ เจฆเจพ เจเจฆเจพเจจ-เจชเฉเจฐเจฆเจพเจจ เจเจฐเจจ เจฒเจ เจตเฉเจฌเจธเจพเจเฉเจ เจฒเจพเจเจฌเฉเจฐเฉเจฐเฉเฅคเจตเฉเจฌเจชเฉเจ - เจฎเฉเจกเฉเจเจฒ เจฎเฉเจจเฉเจเจฐ. เจคเฉเจธเฉเจ เจเจธ เจฌเจพเจฐเฉ เจชเฉเฉเจน เจธเจเจฆเฉ เจนเฉ เจเจฟ เจตเฉเจฌเจชเฉเจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฟเจเจ เจเจฐเจจเฉ เจนเฉเจเฉฑเจฅเฉ .
เจชเฉเจฐเฉเจเฉเจเจ เจกเจพเจเจฐเฉเจเจเจฐเฉ เจฌเจฃเจคเจฐ เจเจธ เจคเจฐเฉเจนเจพเจ เจฆเจฟเจเจพเจ เจฆเจฟเฉฐเจฆเฉ เจนเฉ:
public/
assets/
...
src/
client/
css/
...
html/
index.html
index.js
...
server/
server.js
...
shared/
constants.js
เจเจจเจคเจ/
เจนเจฐ เจเฉเจเจผ เจซเฉเจฒเจกเจฐ เจตเจฟเฉฑเจ เจนเฉ public/
เจธเจฐเจตเจฐ เจฆเฉเจเจฐเจพ เจธเจฅเจฟเจฐ เจคเฉเจฐ 'เจคเฉ เจชเฉเจฐเจธเจพเจฐเจฟเจค เจเฉเจคเจพ เจเจพเจตเฉเจเจพเฅค IN public/assets/
เจธเจพเจกเฉ เจชเฉเจฐเฉเจเฉเจเจ เจฆเฉเจเจฐเจพ เจตเจฐเจคเฉเจเจ เจเจเจเจ เจคเจธเจตเฉเจฐเจพเจ เจธเจผเจพเจฎเจฒ เจนเจจเฅค
src /
เจธเจพเจฐเฉ เจธเจฐเฉเจค เจเฉเจก เจซเฉเจฒเจกเจฐ เจตเจฟเฉฑเจ เจนเฉ src/
. เจธเจฟเจฐเจฒเฉเจ 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
Javascript (JS) เจเจฒเจพเจเฉฐเจ เจฆเจพ เจเจเจเจฐเฉ เจชเฉเจเจเฉฐเจ เจนเฉเฅค เจตเฉเจฌเจชเฉเจ เจเฉฑเจฅเฉเจ เจธเจผเฉเจฐเฉ เจนเฉเจตเฉเจเจพ เจ เจคเฉ เจฆเฉเจเฉเจเจ เจเจฏเจพเจค เจเฉเจคเฉเจเจ เจซเจพเจเจฒเจพเจ เจจเฉเฉฐ เจฎเฉเฉ-เจฎเฉเฉ เจเฉเจ เจเจฐเฉเจเจพเฅค- เจธเจพเจกเฉ เจตเฉเจฌเจชเฉเจ เจฌเจฟเจฒเจก เจฆเจพ เจเจเจเจชเฉเฉฑเจ JS เจกเจพเจเจฐเฉเจเจเจฐเฉ เจตเจฟเฉฑเจ เจธเจฅเจฟเจค เจนเฉเจตเฉเจเจพ
dist/
. เจฎเฉเจ เจเจธ เจซเจพเจเจฒ เจจเฉเฉฐ เจธเจพเจกเฉ เจเจพเจฒ เจเจฐเจพเจเจเจพ เจเฉเจเจธ เจชเฉเจเฉเจ. - เจ
เจธเฉเจ เจตเจฐเจคเจฆเฉ เจนเจพเจ
เจฌเจพเจฌเจฒ , เจ เจคเฉ เจเจพเจธ เจคเฉเจฐ 'เจคเฉ เจธเฉฐเจฐเจเจจเจพ@babel/preset-env เจชเฉเจฐเจพเจฃเฉ เจฌเฉเจฐเจพเจเจเจผเจฐเจพเจ เจฒเจ เจธเจพเจกเฉ JS เจเฉเจก เจจเฉเฉฐ เจเฉเจฐเจพเจเจธเจชเจพเจเจฒ เจเจฐเจจ เจฒเจเฅค - เจ เจธเฉเจ JS เจซเจพเจเจฒเจพเจ เจฆเฉเจเจฐเจพ เจนเจตเจพเจฒเจพ เจฆเจฟเฉฑเจคเฉ เจธเจพเจฐเฉ CSS เจจเฉเฉฐ เจเจเจธเจเจฐเฉเจเจ เจเจฐเจจ เจ เจคเฉ เจเจนเจจเจพเจ เจจเฉเฉฐ เจเฉฑเจ เจฅเจพเจ เจคเฉ เจเฉเฉเจจ เจฒเจ เจเฉฑเจ เจชเจฒเฉฑเจเจเจจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจฆเฉ เจนเจพเจเฅค เจฎเฉเจ เจเจธเจจเฉเฉฐ เจธเจพเจกเจพ เจเจนเจพเจเจเจพ CSS เจชเฉเจเฉเจ.
เจคเฉเจธเฉเจ เจธเจผเจพเจเจฆ เจ
เจเฉเจฌ เจชเฉเจเฉเจ เจซเจพเจเจฒ เจจเจพเจฎ เจฆเฉเจเฉ เจนเฉเจฃเจเฉ '[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.prod.js
, เจเจคเจชเจพเจฆเจจ เจฒเจ เจคเฉเจจเจพเจค เจเจฐเจจ เจตเฉเจฒเฉ เจชเฉเจเฉเจ เจ
เจเจพเจฐ เจจเฉเฉฐ เจ
เจจเฉเจเฉเจฒ เจฌเจฃเจพเจเจฃ เจฒเจเฅค
เจธเจฅเจพเจจเจ เจธเฉเฉฑเจเจ เฉฑเจช
เจฎเฉเจ เจคเฉเจนเจพเจกเฉ เจธเจฅเจพเจจเจ เจฎเจธเจผเฉเจจ 'เจคเฉ เจชเฉเจฐเฉเจเฉเจเจ เจจเฉเฉฐ เจธเจฅเจพเจชเจฟเจค เจเจฐเจจ เจฆเฉ เจธเจฟเจซเจพเจฐเจธเจผ เจเจฐเจฆเจพ เจนเจพเจ เจคเจพเจ เจเฉ เจคเฉเจธเฉเจ เจเจธ เจชเฉเจธเจ เจตเจฟเฉฑเจ เจธเฉเจเฉเจฌเฉฑเจง เจเจฆเจฎเจพเจ เจฆเฉ เจชเจพเจฒเจฃเจพ เจเจฐ เจธเจเฉเฅค เจธเฉเฉฑเจเจ
เฉฑเจช เจธเจงเจพเจฐเจจ เจนเฉ: เจชเจนเจฟเจฒเจพเจ, เจธเจฟเจธเจเจฎ เจเฉเจฒ เจนเฉเจฃเจพ เจเจพเจนเฉเจฆเจพ เจนเฉ
$ git clone https://github.com/vzhou842/example-.io-game.git
$ cd example-.io-game
$ npm install
เจ เจคเฉ เจคเฉเจธเฉเจ เจเจพเจฃ เจฒเจ เจคเจฟเจเจฐ เจนเฉ! เจตเจฟเจเจพเจธ เจธเจฐเจตเจฐ เจธเจผเฉเจฐเฉ เจเจฐเจจ เจฒเจ, เจฌเฉฑเจธ เจเจฒเจพเจ
$ npm run develop
เจ
เจคเฉ เจเจชเจฃเฉ เจตเฉเฉฑเจฌ เจฌเฉเจฐเจพเจเจเจผเจฐ 'เจคเฉ เจเจพเจ
3. เจเจฒเจพเจเฉฐเจ เจเจเจเจฐเฉ เจชเฉเจเจเฉฐเจ
เจเจ เจเฉเจฎ เจเฉเจก 'เจคเฉ เจเจชเจฃเฉ เจเจช เจนเฉเจ เจพเจ เจเจคเจฐเฉเจเฅค เจชเจนเจฟเจฒเจพเจ เจธเจพเจจเฉเฉฐ เจเฉฑเจ เจชเฉฐเจจเฉ เจฆเฉ เจฒเฉเฉ เจนเฉ index.html
, เจเจฆเฉเจ เจคเฉเจธเฉเจ เจธเจพเจเจ 'เจคเฉ เจเจพเจเจฆเฉ เจนเฉ, เจคเจพเจ เจฌเฉเจฐเจพเจเจเจผเจฐ เจเจธเจจเฉเฉฐ เจชเจนเจฟเจฒเจพเจ เจฒเฉเจก เจเจฐเฉเจเจพเฅค เจธเจพเจกเจพ เจชเฉฐเจจเจพ เจเจพเจซเจผเฉ เจธเจงเจพเจฐเจจ เจนเฉเจตเฉเจเจพ:
Index.html
เจเฉฑเจ เจเจฆเจพเจนเจฐเจจ .io เจเฉเจฎ เจเฉเจกเฉ
เจเจธ เจเฉเจก เจเจฆเจพเจนเจฐเจจ เจจเฉเฉฐ เจธเจชเจธเจผเจเจคเจพ เจฒเจ เจฅเฉเฉเฉเจนเจพ เจเจฟเจนเจพ เจธเจฐเจฒ เจฌเจฃเจพเจเจ เจเจฟเจ เจนเฉ, เจ
เจคเฉ เจฎเฉเจ เจชเฉเจธเจ เจตเจฟเฉฑเจ เจนเฉเจฐ เจฌเจนเฉเจค เจธเจพเจฐเฉเจเจ เจเจฆเจพเจนเจฐเจฃเจพเจ เจจเจพเจฒ เจตเฉ เจ
เจเจฟเจนเจพ เจนเฉ เจเจฐเจพเจเจเจพเฅค เจคเฉเจธเฉเจ เจนเจฎเฉเจธเจผเจพ 'เจคเฉ เจชเฉเจฐเจพ เจเฉเจก เจฆเฉเจ เจธเจเจฆเฉ เจนเฉ
เจธเจพเจกเฉ เจเฉเจฒ:
HTML5 เจเฉเจจเจตเจธ เจคเฉฑเจค (<canvas>
), เจเจฟเจธเจฆเฉ เจตเจฐเจคเฉเจ เจ เจธเฉเจ เจเฉเจฎ เจจเฉเฉฐ เจฐเฉเจเจกเจฐ เจเจฐเจจ เจฒเจ เจเจฐเจพเจเจเฉเฅค<link>
เจธเจพเจกเฉ CSS เจชเฉเจเฉเจ เจจเฉเฉฐ เจเฉเฉเจจ เจฒเจเฅค<script>
เจธเจพเจกเฉ Javascript เจชเฉเจเฉเจ เจจเฉเฉฐ เจเฉเฉเจจ เจฒเจ.- เจเจชเจญเฉเจเจคเจพ เจจเจพเจฎ เจฆเฉ เจจเจพเจฒ เจฎเฉเฉฑเจ เจฎเฉเจจเฉ
<input>
เจ เจคเฉ "PLAY" เจฌเจเจจ (<button>
).
เจเฉฑเจ เจตเจพเจฐ เจนเฉเจฎ เจชเฉเจ เจฒเฉเจก เจนเฉเจฃ เจคเฉเจ เจฌเจพเจ
เจฆ, เจฌเฉเจฐเจพเจเจเจผเจฐ เจเจพเจตเจพเจธเจเฉเจฐเจฟเจชเจ เจเฉเจก เจจเฉเฉฐ เจเจฒเจพเจเจฃเจพ เจธเจผเฉเจฐเฉ เจเจฐ เจฆเฉเจตเฉเจเจพ, เจเจเจเจฐเฉ เจชเฉเจเจเฉฐเจ JS เจซเจพเจเจฒ เจจเจพเจฒ เจธเจผเฉเจฐเฉ เจเจฐเจฆเฉ เจนเฉเจ: 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 = () => {
// Play!
play(usernameInput.value);
playMenu.classList.add('hidden');
initState();
startCapturingInput();
startRendering();
setLeaderboardHidden(false);
};
});
เจเจน เจเฉเฉฐเจเจฒเจฆเจพเจฐ เจฒเฉฑเจ เจธเจเจฆเจพ เจนเฉ, เจชเจฐ เจ เจธเจฒ เจตเจฟเฉฑเจ เจเฉฑเจฅเฉ เจฌเจนเฉเจค เจเฉเจ เจจเจนเฉเจ เจนเฉ เจฐเจฟเจนเจพ เจนเฉ:
- เจเจ เจนเฉเจฐ JS เจซเจพเจเจฒเจพเจ เจเจฏเจพเจค เจเจฐเฉเฅค
- CSS เจเจฏเจพเจค เจเจฐเฉ (เจเจธ เจฒเจ เจตเฉเจฌเจชเฉเจ เจเจนเจจเจพเจ เจจเฉเฉฐ เจธเจพเจกเฉ CSS เจชเฉเจเฉเจ เจตเจฟเฉฑเจ เจธเจผเจพเจฎเจฒ เจเจฐเจจเจพ เจเจพเจฃเจฆเจพ เจนเฉ)เฅค
- เจเจฒเจพเจ
connect()
เจธเจฐเจตเจฐ เจจเจพเจฒ เจเฉเจจเฉเจเจธเจผเจจ เจธเจฅเจพเจชเจค เจเจฐเจจ เจ เจคเฉ เจธเจผเฉเจฐเฉ เจเจฐเจจ เจฒเจdownloadAssets()
เจเฉเจฎ เจจเฉเฉฐ เจฐเฉเจเจกเจฐ เจเจฐเจจ เจฒเจ เจฒเฉเฉเฉเจเจฆเฉเจเจ เจคเจธเจตเฉเจฐเจพเจ เจจเฉเฉฐ เจกเจพเจเจจเจฒเฉเจก เจเจฐเจจ เจฒเจเฅค - เจชเฉเจพเจ
3 เจชเฉเจฐเจพ เจเจฐเจจ เจคเฉเจ เจฌเจพเจ
เจฆ เจฎเฉเฉฑเจ เจฎเฉเจจเฉ เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจนเฉเฉฐเจฆเจพ เจนเฉ (
playMenu
). - "PLAY" เจฌเจเจจ เจเจฒเจฟเฉฑเจ เจนเฉเจเจกเจฒเจฐ เจจเฉเฉฐ เจธเฉเจ เจ เจช เจเจฐเจจเจพเฅค เจเจฆเฉเจ เจฌเจเจจ เจฆเจฌเจพเจเจ เจเจพเจเจฆเจพ เจนเฉ, เจเฉเจก เจเฉเจฎ เจจเฉเฉฐ เจธเจผเฉเจฐเฉ เจเจฐเจฆเจพ เจนเฉ เจ เจคเฉ เจธเจฐเจตเจฐ เจจเฉเฉฐ เจฆเฉฑเจธเจฆเจพ เจนเฉ เจเจฟ เจ เจธเฉเจ เจเฉเจกเจฃ เจฒเจ เจคเจฟเจเจฐ เจนเจพเจเฅค
เจธเจพเจกเฉ เจเจฒเจพเจเฉฐเจ-เจธเจฐเจตเจฐ เจคเจฐเจ เจฆเจพ เจฎเฉเฉฑเจ "เจฎเฉเจ" เจเจนเจจเจพเจ เจซเจพเจเจฒเจพเจ เจตเจฟเฉฑเจ เจนเฉ เจเฉ เจซเจพเจเจฒ เจฆเฉเจเจฐเจพ เจเจฏเจพเจค เจเฉเจคเฉเจเจ เจเจเจเจ เจธเจจ index.js
. เจนเฉเจฃ เจ
เจธเฉเจ เจเจนเจจเจพเจ เจธเจพเจฐเจฟเจเจ เจจเฉเฉฐ เจเฉเจฐเจฎ เจตเจฟเฉฑเจ เจตเฉเจเจพเจเจเฉ.
4. เจเจฒเจพเจเฉฐเจ เจกเฉเจเจพ เจฆเจพ เจเจฆเจพเจจ-เจชเฉเจฐเจฆเจพเจจ
เจเจธ เจเฉเจฎ เจตเจฟเฉฑเจ เจ
เจธเฉเจ เจธเจฐเจตเจฐ เจจเจพเจฒ เจธเฉฐเจเจพเจฐ เจเจฐเจจ เจฒเจ เจเฉฑเจ เจฎเจธเจผเจนเฉเจฐ เจฒเจพเจเจฌเฉเจฐเฉเจฐเฉ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจฆเฉ เจนเจพเจ
เจธเจพเจกเฉ เจเฉเจฒ เจเฉฑเจ เจซเจพเจเจฒ เจนเฉเจตเฉเจเฉ 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(() => {
// Register callbacks
socket.on(Constants.MSG_TYPES.GAME_UPDATE, processGameUpdate);
socket.on(Constants.MSG_TYPES.GAME_OVER, onGameOver);
})
);
export const play = username => {
socket.emit(Constants.MSG_TYPES.JOIN_GAME, username);
};
export const updateDirection = dir => {
socket.emit(Constants.MSG_TYPES.INPUT, dir);
};
เจธเจชเจธเจผเจเจคเจพ เจฒเจ เจเจน เจเฉเจก เจตเฉ เจฅเฉเฉเฉเจนเจพ เจเฉเจเจพ เจเฉเจคเจพ เจเจฟเจ เจนเฉเฅค
เจเจธ เจซเจพเจเจฒ เจตเจฟเฉฑเจ เจคเจฟเฉฐเจจ เจฎเฉเฉฑเจ เจเฉเจเจผเจพเจ เจนเฉ เจฐเจนเฉเจเจ เจนเจจ:
- เจ
เจธเฉเจ เจธเจฐเจตเจฐ เจจเจพเจฒ เจเฉเฉเจจ เจฆเฉ เจเฉเจธเจผเจฟเจธเจผ เจเจฐ เจฐเจนเฉ เจนเจพเจเฅค
connectedPromise
เจธเจฟเจฐเจซเจผ เจเจฆเฉเจ เจนเฉ เจเจเจพเจเจผเจค เจฆเจฟเฉฑเจคเฉ เจเจพเจเจฆเฉ เจนเฉ เจเจฆเฉเจ เจ เจธเฉเจ เจเฉฑเจ เจเฉเจจเฉเจเจธเจผเจจ เจธเจฅเจพเจชเจค เจเฉเจคเจพ เจนเฉเฉฐเจฆเจพ เจนเฉเฅค - เจเฉเจเจฐ เจเฉเจจเฉเจเจธเจผเจจ เจธเจซเจฒ เจนเฉเฉฐเจฆเจพ เจนเฉ, เจคเจพเจ เจ
เจธเฉเจ เจเจพเจฒเจฌเฉเจ เจซเฉฐเจเจธเจผเจจเจพเจ เจจเฉเฉฐ เจฐเจเจฟเจธเจเจฐ เจเจฐเจฆเฉ เจนเจพเจ (
processGameUpdate()
ะธonGameOver()
) เจเจนเจจเจพเจ เจธเฉเจจเฉเจนเจฟเจเจ เจฒเจ เจเฉ เจ เจธเฉเจ เจธเจฐเจตเจฐ เจคเฉเจ เจชเฉเจฐเจพเจชเจค เจเจฐ เจธเจเจฆเฉ เจนเจพเจเฅค - เจ
เจธเฉเจ เจจเจฟเจฐเจฏเจพเจค เจเจฐเจฆเฉ เจนเจพเจ
play()
ะธupdateDirection()
เจคเจพเจ เจเฉ เจนเฉเจฐ เจซเจพเจเจฒเจพเจ เจเจนเจจเจพเจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐ เจธเจเจฃเฅค
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
.
เจธเจฐเฉเจคเจพเจ เจจเฉเฉฐ เจกเจพเจเจจเจฒเฉเจก เจเจฐเจจ เจคเฉเจ เจฌเจพเจ
เจฆ, เจคเฉเจธเฉเจ เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจธเจผเฉเจฐเฉ เจเจฐ เจธเจเจฆเฉ เจนเฉเฅค เจเจฟเจตเฉเจ เจเจฟ เจชเจนเจฟเจฒเจพเจ เจเจฟเจนเจพ เจเจฟเจ เจนเฉ, เจเฉฑเจ เจตเฉเจฌ เจชเฉเจ 'เจคเฉ เจเจฟเฉฑเจเจฃ เจฒเจ เจเฉ เจ
เจธเฉเจ เจตเจฐเจคเจฆเฉ เจนเจพเจ <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;
// Get the canvas graphics context
const canvas = document.getElementById('game-canvas');
const context = canvas.getContext('2d');
// Make the canvas fullscreen
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function render() {
const { me, others, bullets } = getCurrentState();
if (!me) {
return;
}
// Draw background
renderBackground(me.x, me.y);
// Draw all bullets
bullets.forEach(renderBullet.bind(null, me));
// Draw all players
renderPlayer(me, me);
others.forEach(renderPlayer.bind(null, me));
}
// ... Helper functions here excluded
let renderInterval = null;
export function startRendering() {
renderInterval = setInterval(render, 1000 / 60);
}
export function stopRendering() {
clearInterval(renderInterval);
}
เจธเจชเจธเจผเจเจคเจพ เจฒเจ เจเจน เจเฉเจก เจตเฉ เจเฉเจเจพ เจเฉเจคเจพ เจเจฟเจ เจนเฉเฅค
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
!
เจเฉเจเจฐ เจคเฉเจธเฉเจ เจนเฉเจฐ เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจธเจนเจพเจเจ เจซเฉฐเจเจธเจผเจจเจพเจ เจฆเฉ เจชเฉเจเฉเจฒ เจเจฐเจจ เจตเจฟเฉฑเจ เจฆเจฟเจฒเจเจธเจชเฉ เจฐเฉฑเจเจฆเฉ เจนเฉ, เจคเจพเจ เจฌเจพเจเฉ เจจเฉเฉฐ เจชเฉเฉเจนเฉ
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()
(เจฆเฉ networking.js
) เจเจฆเฉเจ เจเฉฑเจ เจเจจเจชเฉเจ เจเจเจจเจพ เจตเจพเจชเจฐเจฆเฉ เจนเฉ (เจเจฆเจพเจนเจฐเจจ เจฒเจ, เจเจฆเฉเจ เจฎเจพเจเจธ เจจเฉเฉฐ เจฎเฉเจต เจเฉเจคเจพ เจเจพเจเจฆเจพ เจนเฉ)เฅค updateDirection()
เจธเจฐเจตเจฐ เจจเจพเจฒ เจธเฉเจจเฉเจนเจฟเจเจ เจฆเฉ เจเจฆเจพเจจ-เจชเฉเจฐเจฆเจพเจจ เจจเจพเจฒ เจจเจเจฟเฉฑเจ เจฆเจพ เจนเฉ, เจเฉ เจเจจเจชเฉเจ เจเจตเฉเจเจ เจฆเฉ เจชเฉเจฐเจเจฟเจฐเจฟเจ เจเจฐเจฆเจพ เจนเฉ เจ
เจคเฉ เจเจธ เจ
เจจเฉเจธเจพเจฐ เจเฉเจฎ เจธเจเฉเจ เจจเฉเฉฐ เจ
เจชเจกเฉเจ เจเจฐเจฆเจพ เจนเฉเฅค
7. เจเจพเจนเจ เจธเจฅเจฟเจคเฉ
เจชเฉเจธเจ เจฆเฉ เจชเจนเจฟเจฒเฉ เจญเจพเจ เจตเจฟเฉฑเจ เจเจน เจญเจพเจ เจธเจญ เจคเฉเจ เจเจเจพ เจนเฉเฅค เจจเจฟเจฐเจพเจธเจผ เจจเจพ เจนเฉเจตเฉ เจเฉเจเจฐ เจคเฉเจธเฉเจ เจเจธเจจเฉเฉฐ เจชเจนเจฟเจฒเฉ เจตเจพเจฐ เจชเฉเฉเจนเจฆเฉ เจธเจฎเฉเจ เจธเจฎเจ เจจเจนเฉเจ เจชเจพเจเจเจฆเฉ เจนเฉ! เจคเฉเจธเฉเจ เจเจธเจจเฉเฉฐ เจเฉฑเจก เจตเฉ เจธเจเจฆเฉ เจนเฉ เจ เจคเฉ เจฌเจพเจ เจฆ เจตเจฟเฉฑเจ เจเจธ 'เจคเฉ เจตเจพเจชเจธ เจ เจธเจเจฆเฉ เจนเฉเฅค
เจเจฒเจพเจเฉฐเจ-เจธเจฐเจตเจฐ เจเฉเจก เจจเฉเฉฐ เจชเฉเจฐเจพ เจเจฐเจจ เจฒเจ เจฒเฉเฉเฉเจเจฆเฉ เจฌเฉเจเจพเจฐเจค เจฆเจพ เจเจเจฐเฉ เจเฉเจเฉเจพ เจนเฉ เจฐเจพเจ. เจเจฒเจพเจเฉฐเจ เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจธเฉเจเจธเจผเจจ เจคเฉเจ เจเฉเจก เจธเจจเจฟเฉฑเจชเจ เจฏเจพเจฆ เจนเฉ?
render.js
import { getCurrentState } from './state';
function render() {
const { me, others, bullets } = getCurrentState();
// Do the rendering
// ...
}
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: เจธเจฐเจตเจฐ เจเจพเจเจฎเจธเจเฉเจเจช เจเจน เจฆเจฐเจธเจพเจเจเจฆเจพ เจนเฉ เจเจฟ เจเจน เจ เจชเจกเฉเจ เจเจฆเฉเจ เจฌเจฃเจพเจเจ เจเจฟเจ เจธเฉเฅค
- me: เจเจธ เจ เฉฑเจชเจกเฉเจ เจจเฉเฉฐ เจชเฉเจฐเจพเจชเจค เจเจฐเจจ เจตเจพเจฒเฉ เจเจฟเจกเจพเจฐเฉ เจฌเจพเจฐเฉ เจเจพเจฃเจเจพเจฐเฉเฅค
- เจนเฉเจฐ: เจเจธเฉ เจเฉเจฎ เจตเจฟเฉฑเจ เจญเจพเจ เจฒเฉเจฃ เจตเจพเจฒเฉ เจนเฉเจฐ เจเจฟเจกเจพเจฐเฉเจเจ เจฌเจพเจฐเฉ เจเจพเจฃเจเจพเจฐเฉ เจฆเฉ เจเฉฑเจ เจฒเฉเฉเฅค
- เจเฉเจฒเฉ: เจเฉเจฎ เจตเจฟเฉฑเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒเจพเจ เจฌเจพเจฐเฉ เจเจพเจฃเจเจพเจฐเฉ เจฆเฉ เจฒเฉเฉเฅค
- เจฒเฉเจกเจฐเจฌเฉเจฐเจก: เจฎเฉเจเฉเจฆเจพ เจฒเฉเจกเจฐเจฌเฉเจฐเจก เจกเฉเจเจพเฅค เจ เจธเฉเจ เจเจธ เจชเฉเจธเจ เจตเจฟเฉฑเจ เจเจนเจจเจพเจ เจจเฉเฉฐ เจงเจฟเจเจจ เจตเจฟเฉฑเจ เจจเจนเฉเจ เจฐเฉฑเจเจพเจเจเฉเฅค
7.1 เจเจฒเจพเจเฉฐเจ เจฆเฉ เจญเฉเจฒเฉ เจนเจพเจฒเจค
เจจเจฟเจฐเจชเฉฑเจ เจ
เจฎเจฒ getCurrentState()
เจธเจฟเจฐเจซ เจธเจญ เจคเฉเจ เจนเจพเจฒ เจนเฉ เจตเจฟเฉฑเจ เจชเฉเจฐเจพเจชเจค เจนเฉเจ เจเฉเจฎ เจ
เจชเจกเฉเจ เจคเฉเจ เจธเจฟเฉฑเจงเจพ เจกเฉเจเจพ เจตเจพเจชเจธ เจเจฐ เจธเจเจฆเจพ เจนเฉเฅค
naive-state.js
let lastGameUpdate = null;
// Handle a newly received game update.
export function processGameUpdate(update) {
lastGameUpdate = update;
}
export function getCurrentState() {
return lastGameUpdate;
}
เจธเฉเฉฐเจฆเจฐ เจ เจคเฉ เจธเจชเจธเจผเจ! เจชเจฐ เจเฉ เจธเจฟเจฐเจซ เจเจน เจธเจงเจพเจฐเจจ เจนเฉเฉฐเจฆเจพ. เจเจธ เจฒเจพเจเฉ เจเจฐเจจ เจฆเฉ เจเจพเจฐเจจเจพเจ เจตเจฟเฉฑเจเฉเจ เจเฉฑเจ เจธเจฎเฉฑเจธเจฟเจ เจนเฉ: เจเจน เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจซเจฐเฉเจฎ เจฐเฉเจ เจจเฉเฉฐ เจธเจฐเจตเจฐ เจเจฒเจพเจ เจธเจชเฉเจก เจคเฉฑเจ เจธเฉเจฎเจฟเจค เจเจฐเจฆเจพ เจนเฉ.
เจซเจฐเฉเจฎ เจฆเฉ เจฆเจฐ: เจซเจฐเฉเจฎเจพเจ เจฆเฉ เจเจฟเจฃเจคเฉ (เจเจฟเจตเฉเจ เจเจฟ เจเจพเจฒเจพเจ
render()
) เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ, เจเจพเจ FPSเฅค เจเฉเจกเจพเจ เจเจฎ เจคเฉเจฐ 'เจคเฉ เจเฉฑเจเฉ-เจเฉฑเจ 60 FPS เจชเฉเจฐเจพเจชเจค เจเจฐเจจ เจฆเฉ เจเฉเจธเจผเจฟเจธเจผ เจเจฐเจฆเฉเจเจ เจนเจจเฅค
เจเจฟเจ เจฐเฉเจ: เจเจน เจฌเจพเจฐเฉฐเจฌเจพเจฐเจคเจพ เจเจฟเจธ เจจเจพเจฒ เจธเจฐเจตเจฐ เจเจฒเจพเจเฉฐเจเจธ เจจเฉเฉฐ เจเฉเจฎ เจ เฉฑเจชเจกเฉเจ เจญเฉเจเจฆเจพ เจนเฉเฅค เจเจน เจ เจเจธเจฐ เจซเจฐเฉเจฎ เจฐเฉเจ เจคเฉเจ เจเฉฑเจ เจนเฉเฉฐเจฆเจพ เจนเฉ. เจธเจพเจกเฉ เจเฉเจฎ เจตเจฟเฉฑเจ, เจธเจฐเจตเจฐ 30 เจเจฟเฉฑเจ เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ 'เจคเฉ เจเฉฑเจฒเจฆเจพ เจนเฉเฅค
เจเฉเจเจฐ เจ
เจธเฉเจ เจนเฉเจฃเฉ เจนเฉ เจจเจตเฉเจจเจคเจฎ เจเฉเจฎ เจ
เจชเจกเฉเจ เจชเฉเจธเจผ เจเจฐเจฆเฉ เจนเจพเจ, เจคเจพเจ FPS เจเจผเจฐเฉเจฐเฉ เจคเฉเจฐ 'เจคเฉ เจเจฆเฉ เจตเฉ 30 เจคเฉเจ เจตเฉฑเจง เจจเจนเฉเจ เจนเฉ เจธเจเฉเจเจพ เจเจฟเจเจเจเจฟ เจธเจพเจจเฉเฉฐ เจธเจฐเจตเจฐ เจคเฉเจ เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ 30 เจคเฉเจ เจตเฉฑเจง เจ
เฉฑเจชเจกเฉเจ เจชเฉเจฐเจพเจชเจค เจจเจนเฉเจ เจนเฉเฉฐเจฆเฉ เจนเจจ. เจญเจพเจตเฉเจ เจ
เจธเฉเจ เจฌเฉเจฒเจพเจเจเจฆเฉ เจนเจพเจ render()
60 เจตเจพเจฐ เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ, เจซเจฟเจฐ เจเจนเจจเจพเจ เจตเจฟเฉฑเจเฉเจ เจ
เฉฑเจงเฉเจเจ เจเจพเจฒเจพเจ เจธเจฟเจฐเจซเจผ เจเจธเฉ เจเฉเจเจผ เจจเฉเฉฐ เจฆเฉเจฌเจพเจฐเจพ เจเจฟเฉฑเจเจฃเจเฉเจเจ, เจเจผเจฐเฉเจฐเฉ เจคเฉเจฐ 'เจคเฉ เจเฉเจ เจจเจนเฉเจ เจเจฐเจจเจพเฅค เจเฉฑเจ เจญเฉเจฒเฉเจชเจฃ เจจเฉเฉฐ เจฒเจพเจเฉ เจเจฐเจจ เจฆเฉ เจจเจพเจฒ เจเฉฑเจ เจนเฉเจฐ เจธเจฎเฉฑเจธเจฟเจ เจเจน เจนเฉ เจเจฟ เจเจน เจฆเฉเจฐเฉ เจฆเฉ เจ
เจงเฉเจจ. เจเจฆเจฐเจธเจผ เจเฉฐเจเจฐเจจเฉเจ เจธเจชเฉเจก 'เจคเฉ, เจเจฒเจพเจเฉฐเจ เจจเฉเฉฐ เจนเจฐ 33 ms (30 เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ) เจตเจฟเฉฑเจ เจเฉฑเจ เจเฉเจฎ เจ
เจชเจกเฉเจ เจชเฉเจฐเจพเจชเจค เจนเฉเจตเฉเจเจพ:
เจฌเจฆเจเจฟเจธเจฎเจคเฉ เจจเจพเจฒ, เจเฉเจ เจตเฉ เจธเฉฐเจชเฉเจฐเจจ เจจเจนเฉเจ เจนเฉ. เจเฉฑเจ เจนเฉเจฐ เจฏเจฅเจพเจฐเจฅเจตเจพเจฆเฉ เจคเจธเจตเฉเจฐ เจนเฉเจตเฉเจเฉ:
เจเจฆเฉเจ เจฒเฉเจเฉเจเจธเฉ เจฆเฉ เจเฉฑเจฒ เจเจเจเจฆเฉ เจนเฉ เจคเจพเจ เจเฉฑเจ เจญเฉเจฒเจพ เจ
เจฎเจฒ เจธเจญ เจคเฉเจ เจฎเจพเฉเจพ เจนเฉเฉฐเจฆเจพ เจนเฉเฅค เจเฉเจเจฐ เจเฉเจ เจเฉเจฎ เจ
เฉฑเจชเจกเฉเจ 50ms เจฆเฉเจฐเฉ เจจเจพเจฒ เจชเฉเจฐเจพเจชเจค เจนเฉเฉฐเจฆเจพ เจนเฉ, เจคเจพเจ เจเจพเจนเจ เจนเฉเจฒเฉ เจนเฉ เจเจฟเจ เจนเฉ เจเฉฑเจ เจตเจพเจงเฉ 50ms เจฆเฉเจเจฐเจพ เจเจฟเจเจเจเจฟ เจเจน เจ
เจเฉ เจตเฉ เจชเจฟเจเจฒเฉ เจ
เจชเจกเฉเจ เจคเฉเจ เจเฉเจฎ เจธเจเฉเจ เจจเฉเฉฐ เจชเฉเจธเจผ เจเจฐ เจฐเจฟเจนเจพ เจนเฉเฅค เจคเฉเจธเฉเจ เจเจฒเจชเจจเจพ เจเจฐ เจธเจเจฆเฉ เจนเฉ เจเจฟ เจเจน เจเจฟเจกเจพเจฐเฉ เจฒเจ เจเจฟเฉฐเจจเจพ เจ
เจธเฉเจตเจฟเจงเจพเจเจจเจ เจนเฉ: เจฎเจจเจฎเจพเจจเฉ เจฎเฉฐเจฆเฉ เจฆเฉ เจเจพเจฐเจจ, เจเฉเจก เจเจเจเฉเจฆเจพเจฐ เจ
เจคเฉ เจ
เจธเจฅเจฟเจฐ เจเจพเจชเจฆเฉ เจนเฉเฅค
7.2 เจธเฉเจงเจฐเฉ เจเจฒเจพเจเฉฐเจ เจธเจเฉเจ
เจ เจธเฉเจ เจญเฉเจฒเฉเจชเจฃ เจจเฉเฉฐ เจฒเจพเจเฉ เจเจฐเจจ เจฒเจ เจเฉเจ เจธเฉเจงเจพเจฐ เจเจฐเจพเจเจเฉเฅค เจชเจนเจฟเจฒเจพเจ, เจ เจธเฉเจ เจตเจฐเจคเจฆเฉ เจนเจพเจ เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจฆเฉเจฐเฉ 100 ms เจฆเฉเจเจฐเจพ เจเจธเจฆเจพ เจฎเจคเจฒเจฌ เจนเฉ เจเจฟ เจเจฒเจพเจเฉฐเจ เจฆเฉ "เจฎเฉเจเฉเจฆเจพ" เจธเจฅเจฟเจคเฉ เจนเจฎเฉเจธเจผเจพเจ เจธเจฐเจตเจฐ 'เจคเฉ เจเฉเจฎ เจธเจเฉเจ เจคเฉเจ 100ms เจชเจฟเฉฑเจเฉ เจนเฉเจตเฉเจเฉเฅค เจเจฆเจพเจนเจฐเจจ เจฒเจ, เจเฉเจเจฐ เจธเจฐเจตเจฐ เจฆเจพ เจธเจฎเจพเจ เจนเฉ 150, เจซเจฟเจฐ เจเจฒเจพเจเฉฐเจ เจเจธ เจธเจฅเจฟเจคเฉ เจจเฉเฉฐ เจฐเฉเจเจกเจฐ เจเจฐเฉเจเจพ เจเจฟเจธ เจตเจฟเฉฑเจ เจธเจฐเจตเจฐ เจเจธ เจธเจฎเฉเจ เจธเฉ 50:
เจเจน เจธเจพเจจเฉเฉฐ เจเฉเจฎ เจ
เฉฑเจชเจกเฉเจ เจฆเฉ เจ
เจฃเจชเจเจพเจคเฉ เจธเจฎเฉเจ เจคเฉเจ เจฌเจเจฃ เจฒเจ 100ms เจฌเจซเจฐ เจฆเจฟเฉฐเจฆเจพ เจนเฉ:
เจเจธ เจฆเฉ เจเฉเจฎเจค เจธเจฅเจพเจ เจนเฉเจตเฉเจเฉ
เจ เจธเฉเจ เจเจ เจนเฉเจฐ เจคเจเจจเฉเจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐ เจธเจเจฆเฉ เจนเจพเจ เจเจฟเจธ เจจเฉเฉฐ เจเจฟเจนเจพ เจเจพเจเจฆเจพ เจนเฉ
"เจเจพเจนเจ-เจชเจพเจธเฉ เจฆเฉ เจญเจตเจฟเฉฑเจเจฌเจพเจฃเฉ" , เจเฉ เจธเจฎเจเฉ เจเจ เจฒเฉเจเฉเจเจธเฉ เจจเฉเฉฐ เจเจเจพเจเจฃ เจฆเจพ เจตเจงเฉเจ เจเฉฐเจฎ เจเจฐเจฆเจพ เจนเฉ, เจชเจฐ เจเจธ เจชเฉเจธเจ เจตเจฟเฉฑเจ เจเจฐเจเจพ เจจเจนเฉเจ เจเฉเจคเฉ เจเจพเจตเฉเจเฉเฅค
เจเฉฑเจ เจนเฉเจฐ เจธเฉเจงเจพเจฐ เจเฉ เจ
เจธเฉเจ เจตเจฐเจคเจฆเฉ เจนเจพเจ เจเจน เจนเฉ เจฐเฉเจเจฟเจ เจเฉฐเจเจฐเจชเฉเจฒเฉเจธเจผเจจ. เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจฒเฉเจ เจฆเฉ เจเจพเจฐเจจ, เจ
เจธเฉเจ เจเจฎ เจคเฉเจฐ 'เจคเฉ เจเจฒเจพเจเฉฐเจ เจตเจฟเฉฑเจ เจฎเฉเจเฉเจฆเจพ เจธเจฎเฉเจ เจคเฉเจ เจเฉฑเจเฉ-เจเฉฑเจ เจเฉฑเจ เจ
เฉฑเจชเจกเฉเจ เจ
เฉฑเจเฉ เจนเฉเฉฐเจฆเฉ เจนเจพเจเฅค เจเจฆเฉเจ เจฌเฉเจฒเจพเจเจ เจเจฟเจ 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);
// Keep only one game update before the current server time
const base = getBaseUpdate();
if (base > 0) {
gameUpdates.splice(0, base);
}
}
function currentServerTime() {
return firstServerTimestamp + (Date.now() - gameStart) - RENDER_DELAY;
}
// Returns the index of the base update, the first game update before
// current server time, or -1 if N/A.
function getBaseUpdate() {
const serverTime = currentServerTime();
for (let i = gameUpdates.length - 1; i >= 0; i--) {
if (gameUpdates[i].t <= serverTime) {
return i;
}
}
return -1;
}
เจชเจนเจฟเจฒเฉ เจเฉฑเจฒ เจเจน เจนเฉ เจเจฟ เจคเฉเจนเจพเจจเฉเฉฐ เจเจน เจเจฐเจจ เจฆเฉ เจฒเฉเฉ เจนเฉ เจเจฟ เจเจน เจเฉ เจเจฐเจฆเจพ เจนเฉ currentServerTime()
. เจเจฟเจตเฉเจ เจเจฟ เจ
เจธเฉเจ เจชเจนเจฟเจฒเจพเจ เจฆเฉเจเจฟเจ เจธเฉ, เจนเจฐเฉเจ เจเฉเจฎ เจ
เจชเจกเฉเจ เจตเจฟเฉฑเจ เจเฉฑเจ เจธเจฐเจตเจฐ เจเจพเจเจฎเจธเจเฉเจเจช เจธเจผเจพเจฎเจฒ เจนเฉเฉฐเจฆเจพ เจนเฉเฅค เจ
เจธเฉเจ เจธเจฐเจตเจฐ เจฆเฉ เจชเจฟเฉฑเจเฉ เจเจฟเฉฑเจคเจฐ เจจเฉเฉฐ 100ms เจฐเฉเจเจกเจฐ เจเจฐเจจ เจฒเจ เจฐเฉเจเจกเจฐ เจฒเฉเจเฉเจเจธเฉ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจจเจพ เจเจพเจนเฉเฉฐเจฆเฉ เจนเจพเจ, เจชเจฐ เจธเจพเจจเฉเฉฐ เจธเจฐเจตเจฐ 'เจคเฉ เจฎเฉเจเฉเจฆเจพ เจธเจฎเจพเจ เจเจฆเฉ เจจเจนเฉเจ เจชเจคเจพ เจนเฉเจตเฉเจเจพ, เจเจฟเจเจเจเจฟ เจ
เจธเฉเจ เจจเจนเฉเจ เจเจพเจฃ เจธเจเจฆเฉ เจเจฟ เจเจฟเจธเฉ เจตเฉ เจ
เฉฑเจชเจกเฉเจ เจจเฉเฉฐ เจธเจพเจกเฉ เจคเฉฑเจ เจชเจนเฉเฉฐเจเจฃ เจตเจฟเฉฑเจ เจเจฟเฉฐเจจเจพ เจธเจฎเจพเจ เจฒเฉฑเจเจพเฅค เจเฉฐเจเจฐเจจเฉเจ เจ
เจชเฉเจฐเจคเฉฑเจ เจนเฉ เจ
เจคเฉ เจเจธเจฆเฉ เจเจคเฉ เจฌเจนเฉเจค เจฌเจฆเจฒ เจธเจเจฆเฉ เจนเฉ!
เจเจธ เจธเจฎเฉฑเจธเจฟเจ เจจเฉเฉฐ เจนเฉฑเจฒ เจเจฐเจจ เจฒเจ, เจ
เจธเฉเจ เจเฉฑเจ เจตเจพเจเจฌ เจ
เจจเฉเจฎเจพเจจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐ เจธเจเจฆเฉ เจนเจพเจ: เจ
เจธเฉเจ เจเจ เจฆเจฟเจเจพเจเจเจฆเฉ เจนเจพเจ เจเจฟ เจชเจนเจฟเจฒเจพ เจ
เจชเจกเฉเจ เจคเฉเจฐเฉฐเจค เจ เจเจฟเจ. เจเฉ เจเจน เจธเฉฑเจ เจธเฉ, เจคเจพเจ เจธเจพเจจเฉเฉฐ เจเจธ เจเจพเจธ เจชเจฒ 'เจคเฉ เจธเจฐเจตเจฐ เจฆเจพ เจธเจฎเจพเจ เจชเจคเจพ เจนเฉเจตเฉเจเจพ! เจ
เจธเฉเจ เจธเจฐเจตเจฐ เจเจพเจเจฎเจธเจเฉเจเจช เจจเฉเฉฐ เจธเจเฉเจฐ เจเจฐเจฆเฉ เจนเจพเจ 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();
// If base is the most recent update we have, use its state.
// Else, interpolate between its state and the state of (base + 1).
if (base < 0) {
return gameUpdates[gameUpdates.length - 1];
} else if (base === gameUpdates.length - 1) {
return gameUpdates[base];
} else {
const baseUpdate = gameUpdates[base];
const next = gameUpdates[base + 1];
const r = (serverTime - baseUpdate.t) / (next.t - baseUpdate.t);
return {
me: interpolateObject(baseUpdate.me, next.me, r),
others: interpolateObjectArray(baseUpdate.others, next.others, r),
bullets: interpolateObjectArray(baseUpdate.bullets, next.bullets, r),
};
}
}
เจ เจธเฉเจ เจคเจฟเฉฐเจจ เจเฉเจธเจพเจ เจจเฉเฉฐ เจธเฉฐเจญเจพเจฒเจฆเฉ เจนเจพเจ:
base < 0
เจฎเจคเจฒเจฌ เจเจฟ เจฎเฉเจเฉเจฆเจพ เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจธเจฎเฉเจ เจคเฉฑเจ เจเฉเจ เจ เฉฑเจชเจกเฉเจ เจจเจนเฉเจ เจนเจจ (เจเฉฑเจชเจฐ เจฒเจพเจเฉเจเจฐเจจ เจฆเฉเจเฉgetBaseUpdate()
). เจเจน เจฐเฉเจเจกเจฐเจฟเฉฐเจ เจฒเฉเจ เจฆเฉ เจเจพเจฐเจจ เจเฉเจฎ เจฆเฉ เจธเจผเฉเจฐเฉ เจตเจฟเฉฑเจ เจนเฉ เจนเฉ เจธเจเจฆเจพ เจนเฉเฅค เจเจธ เจธเจฅเจฟเจคเฉ เจตเจฟเฉฑเจ, เจ เจธเฉเจ เจชเฉเจฐเจพเจชเจค เจเฉเจคเฉ เจธเจญ เจคเฉเจ เจคเจพเจเจผเจพ เจ เจชเจกเฉเจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจฆเฉ เจนเจพเจเฅคbase
เจธเจพเจกเฉ เจเฉเจฒ เจธเจญ เจคเฉเจ เจคเจพเจเจผเจพ เจ เจชเจกเฉเจ เจนเฉเฅค เจเจน เจจเฉเฉฑเจเจตเจฐเจ เจฒเฉเจเฉเจเจธเฉ เจเจพเจ เจเจฐเจพเจฌ เจเฉฐเจเจฐเจจเฉเฉฑเจ เจเจจเฉเจเจธเจผเจจ เจเจพเจฐเจจ เจนเฉ เจธเจเจฆเจพ เจนเฉเฅค เจเจธ เจฎเจพเจฎเจฒเฉ เจตเจฟเฉฑเจ เจตเฉ เจ เจธเฉเจ เจธเจพเจกเฉ เจเฉเจฒ เจจเจตเฉเจจเจคเจฎ เจ เจชเจกเฉเจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจฆเฉ เจนเจพเจเฅค- เจธเจพเจกเฉ เจเฉเจฒ เจฎเฉเจเฉเจฆเจพ เจฐเฉเจเจกเจฐ เจธเจฎเฉเจ เจคเฉเจ เจชเจนเจฟเจฒเจพเจ เจ เจคเฉ เจฌเจพเจ เจฆ เจตเจฟเฉฑเจ เจเฉฑเจ เจ เฉฑเจชเจกเฉเจ เจนเฉ, เจเจธ เจฒเจ เจ เจธเฉเจ เจเจฐ เจธเจเจฆเฉ เจนเจพเจ เจเฉฐเจเจฐเจชเฉเจฒเฉเจ!
เจเจน เจธเจญ เจเฉเจ เจฌเจพเจเฉ เจนเฉ state.js
เจฒเฉเจจเฉเจ
เจฐ เจเฉฐเจเจฐเจชเฉเจฒเฉเจธเจผเจจ เจฆเจพ เจเฉฑเจ เจฒเจพเจเฉเจเจฐเจจ เจนเฉ เจเฉ เจธเจงเจพเจฐเจจ (เจชเจฐ เจฌเฉเจฐเจฟเฉฐเจ) เจเจฃเจฟเจค เจนเฉเฅค เจเฉ เจคเฉเจธเฉเจ เจเฉเจฆ เจเจธ เจฆเฉ เจชเฉเจเฉเจฒ เจเจฐเจจเจพ เจเจพเจนเฉเฉฐเจฆเฉ เจนเฉ, เจคเจพเจ เจเฉเจฒเฉเจนเฉ state.js
'เจคเฉ
เจญเจพเจ 2. เจฌเฉเจเจเจเจก เจธเจฐเจตเจฐ
เจเจธ เจนเจฟเฉฑเจธเฉ เจตเจฟเฉฑเจ เจ
เจธเฉเจ 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');
// Setup an Express server
const app = express();
app.use(express.static('public'));
if (process.env.NODE_ENV === 'development') {
// Setup Webpack for development
const compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler));
} else {
// Static serve the dist/ folder in production
app.use(express.static('dist'));
}
// Listen on port
const port = process.env.PORT || 3000;
const server = app.listen(port);
console.log(`Server listening on port ${port}`);
เจฏเจพเจฆ เจฐเฉฑเจเฉ เจเจฟ เจชเจนเจฟเจฒเฉ เจญเจพเจ เจตเจฟเฉฑเจ เจ เจธเฉเจ เจตเฉเจฌเจชเฉเจ เจฌเจพเจฐเฉ เจเจฐเจเจพ เจเฉเจคเฉ เจธเฉ? เจเจน เจเจน เจฅเจพเจ เจนเฉ เจเจฟเฉฑเจฅเฉ เจ เจธเฉเจ เจธเจพเจกเฉเจเจ เจตเฉเจฌเจชเฉเจ เจธเฉฐเจฐเจเจจเจพเจตเจพเจ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจพเจเจเฉเฅค เจ เจธเฉเจ เจเจนเจจเจพเจ เจจเฉเฉฐ เจฆเฉ เจคเจฐเฉเจเจฟเจเจ เจจเจพเจฒ เจฒเจพเจเฉ เจเจฐเจพเจเจเฉ:
- เจตเจฐเจคเจฃ เจฒเจ
webpack-dev-midleware เจธเจพเจกเฉ เจตเจฟเจเจพเจธ เจชเฉเจเฉเจเจพเจ เจจเฉเฉฐ เจเจเฉเจฎเฉเจเจฟเจเจฒเฉ เจฆเฉเจฌเจพเจฐเจพ เจฌเจฃเจพเจเจฃ เจฒเจ, เจเจพเจ - เจเฉฑเจ เจซเฉเจฒเจกเจฐ เจจเฉเฉฐ เจธเจฅเจฟเจฐ เจฐเฉเจช เจตเจฟเฉฑเจ เจเฉเจฐเจพเจเจธเจซเจฐ เจเจฐเฉ
dist/
, เจเจฟเจธ เจตเจฟเฉฑเจ เจตเฉเจฌเจชเฉเจ เจชเฉเจฐเฉเจกเจเจธเจผเจจ เจฌเจฟเจฒเจก เจคเฉเจ เจฌเจพเจ เจฆ เจธเจพเจกเฉเจเจ เจซเจพเจเจฒเจพเจ เจจเฉเฉฐ เจฒเจฟเจเฉเจเจพเฅค
เจเฉฑเจ เจนเฉเจฐ เจฎเจนเฉฑเจคเจตเจชเฉเจฐเจจ เจเฉฐเจฎ server.js
เจธเจฐเจตเจฐ เจจเฉเฉฐ เจธเจฅเจพเจชเจค เจเจฐเจจเจพ เจธเจผเจพเจฎเจฒ เจนเฉ
server.js, เจญเจพเจ 2
const socketio = require('socket.io');
const Constants = require('../shared/constants');
// Setup Express
// ...
const server = app.listen(port);
console.log(`Server listening on port ${port}`);
// Setup socket.io
const io = socketio(server);
// Listen for socket.io connections
io.on('connection', socket => {
console.log('Player connected!', socket.id);
socket.on(Constants.MSG_TYPES.JOIN_GAME, joinGame);
socket.on(Constants.MSG_TYPES.INPUT, handleInput);
socket.on('disconnect', onDisconnect);
});
เจธเจฐเจตเจฐ เจจเจพเจฒ เจธเจซเจฒเจคเจพเจชเฉเจฐเจตเจ เจเฉฑเจ socket.io เจเจจเฉเจเจธเจผเจจ เจธเจฅเจพเจชเจค เจเจฐเจจ เจคเฉเจ เจฌเจพเจ
เจฆ, เจ
เจธเฉเจ เจจเจตเฉเจ เจธเจพเจเจ เจฒเจ เจเจตเฉเจเจ เจนเฉเจเจกเจฒเจฐ เจจเฉเฉฐ เจธเฉฐเจฐเจเจฟเจค เจเจฐเจฆเฉ เจนเจพเจเฅค เจเจตเฉเจเจ เจนเฉเจเจกเจฒเจฐ เจเฉฑเจ เจธเจฟเฉฐเจเจฒเจเจจ เจเจฌเจเฉเจเจ เจจเฉเฉฐ เจธเฉเจเจช เจเฉ เจเจพเจนเจเจพเจ เจคเฉเจ เจชเฉเจฐเจพเจชเจค เจธเฉเจจเฉเจนเจฟเจเจ เจฆเฉ เจชเฉเจฐเจเจฟเจฐเจฟเจ เจเจฐเจฆเฉ เจนเจจ game
:
server.js, เจญเจพเจ 3
const Game = require('./game');
// ...
// Setup the Game
const game = new Game();
function joinGame(username) {
game.addPlayer(this, username);
}
function handleInput(dir) {
game.handleInput(this, dir);
}
function onDisconnect() {
game.removePlayer(this);
}
เจ
เจธเฉเจ เจเฉฑเจ .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;
// Generate a position to start this player at.
const x = Constants.MAP_SIZE * (0.25 + Math.random() * 0.5);
const y = Constants.MAP_SIZE * (0.25 + Math.random() * 0.5);
this.players[socket.id] = new Player(socket.id, username, x, y);
}
removePlayer(socket) {
delete this.sockets[socket.id];
delete this.players[socket.id];
}
handleInput(socket, dir) {
if (this.players[socket.id]) {
this.players[socket.id].setDirection(dir);
}
}
// ...
}
เจเจธ เจเฉเจฎ เจตเจฟเฉฑเจ เจ
เจธเฉเจ เจซเฉเจฒเจก เจฆเฉเจเจฐเจพ เจเจฟเจกเจพเจฐเฉเจเจ เจฆเฉ เจชเจเจพเจฃ เจเจฐเจพเจเจเฉ id
เจเจนเจจเจพเจ เจฆเฉ เจธเจพเจเจ socket.io (เจเฉ เจคเฉเจธเฉเจ เจเจฒเจเจฃ เจตเจฟเฉฑเจ เจนเฉ, เจคเจพเจ เจตเจพเจชเจธ เจเจพเจ server.js
). Socket.io เจเฉเจฆ เจนเจฐเฉเจ เจธเจพเจเจ เจจเฉเฉฐ เจเฉฑเจ เจตเจฟเจฒเฉฑเจเจฃ เจจเจฟเจฐเจงเจพเจฐเจค เจเจฐเจฆเจพ เจนเฉ id
, เจเจธ เจฒเจ เจธเจพเจจเฉเฉฐ เจเจธ เจฌเจพเจฐเฉ เจเจฟเฉฐเจคเจพ เจเจฐเจจ เจฆเฉ เจฒเฉเฉ เจจเจนเฉเจ เจนเฉเฅค เจฎเฉเจ เจเจธเจจเฉเฉฐ เจฌเฉเจฒเจพเจตเจพเจเจเจพ เจชเจฒเฉเจ
เจฐ เจเจ.เจกเฉ.
เจเจธ เจจเฉเฉฐ เจงเจฟเจเจจ เจตเจฟเฉฑเจ เจฐเฉฑเจเจฆเฉ เจนเฉเจ, เจเจ เจเจฒเจพเจธ เจตเจฟเฉฑเจ เจเฉฐเจธเจเฉเจเจธ เจตเฉเจฐเฉเจเจฌเจฒ เจฆเฉ เจเจพเจเจ เจเจฐเฉเจ Game
:
sockets
เจเฉฑเจ เจตเจธเจคเฉ เจนเฉ เจเฉ เจชเจฒเฉเจ เจฐ ID เจจเฉเฉฐ เจธเจพเจเจ เจจเจพเจฒ เจเฉเฉเจฆเฉ เจนเฉ เจเฉ เจชเจฒเฉเจ เจฐ เจจเจพเจฒ เจเฉเฉเจฟเจ เจนเฉเจเจ เจนเฉเฅค เจเจน เจธเจพเจจเฉเฉฐ เจธเจฎเฉเจ เจฆเฉ เจจเจพเจฒ เจเจนเจจเจพเจ เจฆเฉ เจชเจฒเฉเจ เจฐ เจเจเจกเฉ เจฆเฉเจเจฐเจพ เจธเจพเจเจเจพเจ เจคเฉฑเจ เจชเจนเฉเฉฐเจ เจเจฐเจจ เจฆเฉ เจเจเจฟเจ เจฆเจฟเฉฐเจฆเจพ เจนเฉเฅค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() {
// Calculate time elapsed
const now = Date.now();
const dt = (now - this.lastUpdateTime) / 1000;
this.lastUpdateTime = now;
// Update each bullet
const bulletsToRemove = [];
this.bullets.forEach(bullet => {
if (bullet.update(dt)) {
// Destroy this bullet
bulletsToRemove.push(bullet);
}
});
this.bullets = this.bullets.filter(
bullet => !bulletsToRemove.includes(bullet),
);
// Update each player
Object.keys(this.sockets).forEach(playerID => {
const player = this.players[playerID];
const newBullet = player.update(dt);
if (newBullet) {
this.bullets.push(newBullet);
}
});
// Apply collisions, give players score for hitting bullets
const destroyedBullets = applyCollisions(
Object.values(this.players),
this.bullets,
);
destroyedBullets.forEach(b => {
if (this.players[b.parentID]) {
this.players[b.parentID].onDealtDamage();
}
});
this.bullets = this.bullets.filter(
bullet => !destroyedBullets.includes(bullet),
);
// Check if any players are dead
Object.keys(this.sockets).forEach(playerID => {
const socket = this.sockets[playerID];
const player = this.players[playerID];
if (player.hp <= 0) {
socket.emit(Constants.MSG_TYPES.GAME_OVER);
this.removePlayer(socket);
}
});
// Send a game update to each player every other time
if (this.shouldSendUpdate) {
const leaderboard = this.getLeaderboard();
Object.keys(this.sockets).forEach(playerID => {
const socket = this.sockets[playerID];
const player = this.players[playerID];
socket.emit(
Constants.MSG_TYPES.GAME_UPDATE,
this.createUpdate(player, leaderboard),
);
});
this.shouldSendUpdate = false;
} else {
this.shouldSendUpdate = true;
}
}
// ...
}
.เฉฐเจ update()
เจธเจผเจพเจเจฆ เจธเจฐเจตเจฐ-เจธเจพเจเจก เจคเจฐเจ เจฆเจพ เจธเจญ เจคเฉเจ เจฎเจนเฉฑเจคเจตเจชเฉเจฐเจจ เจนเจฟเฉฑเจธเจพ เจฐเฉฑเจเจฆเจพ เจนเฉเฅค เจเจฒเฉ เจเจน เจธเจญ เจเฉเจ เจเฉเจฐเจฎ เจ
เจจเฉเจธเจพเจฐ เจธเฉเจเฉเจฌเฉฑเจง เจเจฐเฉเจ:
- เจเจฃเจจเจพ เจเจฐเจฆเจพ เจนเฉ เจเจฟ เจเจน เจเจฟเฉฐเจจเจพ เจธเจฎเจพเจ เจนเฉ
dt
เจเจน เจชเจฟเจเจฒเฉ เจธเจฎเฉเจ เจคเฉเจ เจนเฉupdate()
. - เจนเจฐเฉเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเฉเฉฐ เจคเจพเจเจผเจพ เจเจฐเจฆเจพ เจนเฉ เจ
เจคเฉ เจเฉ เจฒเฉเฉ เจนเฉเจตเฉ เจคเจพเจ เจเจนเจจเจพเจ เจจเฉเฉฐ เจจเจธเจผเจ เจเจฐเจฆเจพ เจนเฉเฅค เจ
เจธเฉเจ เจฌเจพเจ
เจฆ เจตเจฟเฉฑเจ เจเจธ เจเจพเจฐเจเจธเจผเฉเจฒเจคเจพ เจจเฉเฉฐ เจฒเจพเจเฉ เจเจฐเจจเจพ เจฆเฉเจเจพเจเจเฉเฅค เจซเจฟเจฒเจนเจพเจฒ เจธเจพเจกเฉ เจฒเจ เจเจน เจเจพเจฃเจจเจพ เจนเฉ เจเจพเจซเฉ เจนเฉ
bullet.update()
เจตเจพเจชเจธเฉtrue
, เจเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเฉเฉฐ เจจเจธเจผเจ เจเฉเจคเจพ เจเจพเจฃเจพ เจเจพเจนเฉเจฆเจพ เจนเฉ (เจเจน เจ เจเจพเฉเฉ เจคเฉเจ เจฌเจพเจนเจฐ เจเจฒเจพ เจเจฟเจ) - เจนเจฐเฉเจ เจเจฟเจกเจพเจฐเฉ เจจเฉเฉฐ เจ
เฉฑเจชเจกเฉเจ เจเจฐเจฆเจพ เจนเฉ เจ
เจคเฉ เจฒเฉเฉ เจชเฉเจฃ 'เจคเฉ เจเฉฑเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจฌเจฃเจพเจเจเจฆเจพ เจนเฉเฅค เจ
เจธเฉเจ เจเจธ เจฒเจพเจเฉเจเจฐเจจ เจจเฉเฉฐ เจฌเจพเจ
เจฆ เจตเจฟเฉฑเจ เจตเฉ เจฆเฉเจเจพเจเจเฉ -
player.update()
เจเฉฑเจ เจตเจธเจคเฉ เจจเฉเฉฐ เจตเจพเจชเจธ เจเจฐ เจธเจเจฆเจพ เจนเฉBullet
. - เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒเจพเจ เจ
เจคเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจตเจฟเจเจเจพเจฐ เจเจเจฐเจพเจ
เจฆเฉ เจเจพเจเจ เจเจฐเจฆเจพ เจนเฉ
applyCollisions()
, เจเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจนเจฟเฉฑเจ เจเจฐเจจ เจตเจพเจฒเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒเจพเจ เจฆเฉ เจเฉฑเจ เจฒเฉเฉ เจตเจพเจชเจธ เจเจฐเจฆเจพ เจนเฉเฅค เจตเจพเจชเจธ เจเฉเจคเฉ เจนเจฐเฉเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจฒเจ, เจ เจธเฉเจ เจเจธ เจเจฟเจกเจพเจฐเฉ เจฆเฉ เจธเจเฉเจฐ เจจเฉเฉฐ เจตเจงเจพเจเจเจฆเฉ เจนเจพเจ เจเจฟเจธ เจจเฉ เจเจธเจจเฉเฉฐ เจซเจพเจเจฐ เจเฉเจคเจพ (เจตเจฐเจคเจฆเฉ เจนเฉเจplayer.onDealtDamage()
), เจ เจคเฉ เจซเจฟเจฐ เจเจฐเฉ เจคเฉเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเฉเฉฐ เจนเจเจพเจbullets
. - เจธเจพเจฐเฉ เจฎเจพเจฐเฉ เจเจ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจธเฉเจเจฟเจค เจ เจคเฉ เจจเจธเจผเจ เจเจฐเจฆเจพ เจนเฉเฅค
- เจธเจพเจฐเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจเฉเจฎ เจ
เฉฑเจชเจกเฉเจ เจญเฉเจเจฆเจพ เจนเฉ เจนเจฐ เจธเจเจฟเฉฐเจ เจเจ เจตเจพเจฐ เจเจฆเฉเจ เจฌเฉเจฒเจพเจเจ เจเจพเจเจฆเจพ เจนเฉ
update()
. เจเฉฑเจชเจฐ เจเจผเจฟเจเจฐ เจเฉเจคเจพ เจธเจนเจพเจเจ เจตเฉเจฐเฉเจเจฌเจฒ เจเจธ เจจเฉเฉฐ เจเจฐเฉเจ เจเจฐเจจ เจตเจฟเฉฑเจ เจธเจพเจกเฉ เจฎเจฆเจฆ เจเจฐเจฆเจพ เจนเฉshouldSendUpdate
. เจเจฟเจเจเจเจฟupdate()
60 เจตเจพเจฐ/เจธเจเจฟเฉฐเจ เจจเฉเฉฐ เจฌเฉเจฒเจพเจเจ เจเจพเจเจฆเจพ เจนเฉ, เจ เจธเฉเจ เจเฉเจฎ เจ เฉฑเจชเจกเฉเจ 30 เจตเจพเจฐ/เจธเฉเจเจฟเฉฐเจก เจญเฉเจเจฆเฉ เจนเจพเจเฅค เจเจธ เจคเจฐเฉเจนเจพเจ, เจเฉเฉ เจฆเฉ เจฌเจพเจฐเฉฐเจฌเจพเจฐเจคเจพ เจธเจฐเจตเจฐ 30 เจเฉเฉ เจเฉฑเจเจฐ/s เจนเฉ (เจ เจธเฉเจ เจชเจนเจฟเจฒเฉ เจญเจพเจ เจตเจฟเฉฑเจ เจเฉเฉ เจฆเฉ เจฌเจพเจฐเฉฐเจฌเจพเจฐเจคเจพ เจฌเจพเจฐเฉ เจเฉฑเจฒ เจเฉเจคเฉ เจนเฉ)เฅค
เจธเจฟเจฐเจซเจผ เจเฉเจฎ เจ เฉฑเจชเจกเฉเจ เจเจฟเจเจ เจญเฉเจเฉ เจธเจฎเฉเจ เจฆเฉเจเจฐเจพ ? เจเฉเจจเจฒ เจจเฉเฉฐ เจฌเจเจพเจเจฃ เจฒเจเฅค 30 เจเฉเจฎ เจ เฉฑเจชเจกเฉเจ เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ เจฌเจนเฉเจค เจนเฉ!
เจซเจฟเจฐ เจเจฟเจเจ เจจเจพ เจเจพเจฒ เจเจฐเฉ?
update()
30 เจตเจพเจฐ เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ? เจเฉเจฎ เจธเจฟเจฎเฉเจฒเฉเจธเจผเจจ เจจเฉเฉฐ เจฌเจฟเจนเจคเจฐ เจฌเจฃเจพเจเจฃ เจฒเจเฅค เจเจฟเฉฐเจจเฉ เจตเจพเจฐ เจเจธ เจจเฉเฉฐ เจเจฟเจนเจพ เจเจพเจเจฆเจพ เจนเฉupdate()
, เจเฉเจฎ เจธเจฟเจฎเฉเจฒเฉเจธเจผเจจ เจตเจงเฉเจฐเฉ เจธเจเฉเจ เจนเฉเจตเฉเจเฉเฅค เจชเจฐ เจเฉเจฃเฉเจคเฉเจเจ เจฆเฉ เจเจฟเจฃเจคเฉ เจฆเฉเจเจฐเจพ เจฌเจนเฉเจค เจเจผเจฟเจเจฆเจพ เจฆเฉเจฐ เจจเจพ เจนเฉเจตเฉupdate()
, เจเจฟเจเจเจเจฟ เจเจน เจเฉฑเจ เจเจฃเจจเจพเจคเจฎเจ เจคเฉเจฐ 'เจคเฉ เจฎเจนเจฟเฉฐเจเจพ เจเฉฐเจฎ เจนเฉ - 60 เจชเฉเจฐเจคเฉ เจธเจเจฟเฉฐเจ เจเจพเจซเจผเฉ เจนเฉเฅค
เจฌเจพเจเฉ เจเจฒเจพเจธ Game
เจตเจฟเฉฑเจ เจตเจฐเจคเฉ เจเจ เจธเจนเจพเจเจ เจคเจฐเฉเจเจฟเจเจ เจฆเฉ เจธเจผเจพเจฎเจฒ เจนเจจ update()
:
game.js, เจญเจพเจ 3
class Game {
// ...
getLeaderboard() {
return Object.values(this.players)
.sort((p1, p2) => p2.score - p1.score)
.slice(0, 5)
.map(p => ({ username: p.username, score: Math.round(p.score) }));
}
createUpdate(player, leaderboard) {
const nearbyPlayers = Object.values(this.players).filter(
p => p !== player && p.distanceTo(player) <= Constants.MAP_SIZE / 2,
);
const nearbyBullets = this.bullets.filter(
b => b.distanceTo(player) <= Constants.MAP_SIZE / 2,
);
return {
t: Date.now(),
me: player.serializeForUpdate(),
others: nearbyPlayers.map(p => p.serializeForUpdate()),
bullets: nearbyBullets.map(b => b.serializeForUpdate()),
leaderboard,
};
}
}
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;
}
// Returns true if the bullet should be destroyed
update(dt) {
super.update(dt);
return this.x < 0 || this.x > Constants.MAP_SIZE || this.y < 0 || this.y > Constants.MAP_SIZE;
}
}
ะ ะตะฐะปะธะทะฐัะธั 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;
}
// Returns a newly created bullet, or null.
update(dt) {
super.update(dt);
// Update score
this.score += dt * Constants.SCORE_PER_SECOND;
// Make sure the player stays in bounds
this.x = Math.max(0, Math.min(Constants.MAP_SIZE, this.x));
this.y = Math.max(0, Math.min(Constants.MAP_SIZE, this.y));
// Fire a bullet, if needed
this.fireCooldown -= dt;
if (this.fireCooldown <= 0) {
this.fireCooldown += Constants.PLAYER_FIRE_COOLDOWN;
return new Bullet(this.id, this.x, this.y, this.direction);
}
return null;
}
takeBulletDamage() {
this.hp -= Constants.BULLET_DAMAGE;
}
onDealtDamage() {
this.score += Constants.SCORE_BULLET_HIT;
}
serializeForUpdate() {
return {
...(super.serializeForUpdate()),
direction: this.direction,
hp: this.hp,
};
}
}
เจเจฟเจกเจพเจฐเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒเจพเจ เจจเจพเจฒเฉเจ เจตเจงเฉเจฐเฉ เจเฉเฉฐเจเจฒเจฆเจพเจฐ เจนเฉเฉฐเจฆเฉ เจนเจจ, เจเจธเจฒเจ เจเจธ เจเจฒเจพเจธ เจจเฉเฉฐ เจเฉเจ เจนเฉเจฐ เจเฉเจคเจฐเจพเจ เจจเฉเฉฐ เจธเจเฉเจฐ เจเจฐเจจเจพ เจเจพเจนเฉเจฆเจพ เจนเฉเฅค เจเจธเจฆเจพ เจคเจฐเฉเจเจพ update()
เจตเจงเฉเจฐเฉ เจเฉฐเจฎ เจเจฐเจฆเจพ เจนเฉ, เจเจพเจธ เจคเฉเจฐ 'เจคเฉ เจจเจตเฉเจ เจฌเจฃเจพเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเฉเฉฐ เจตเจพเจชเจธ เจเจฐเจจเจพ เจเฉเจเจฐ เจเฉเจ เจฌเจเจฟเจ เจจเจนเฉเจ เจนเฉ fireCooldown
(เจฏเจพเจฆ เจนเฉ เจเจฟ เจ
เจธเฉเจ เจชเจฟเจเจฒเฉ เจญเจพเจ เจตเจฟเฉฑเจ เจเจธ เจฌเจพเจฐเฉ เจเฉฑเจฒ เจเฉเจคเฉ เจธเฉ?) เจเจน เจตเจฟเจงเฉ เจจเฉเฉฐ เจตเฉ เจตเจงเจพเจเจเจฆเจพ เจนเฉ serializeForUpdate()
, เจเจฟเจเจเจเจฟ เจธเจพเจจเฉเฉฐ เจเฉเจฎ เจ
เฉฑเจชเจกเฉเจ เจตเจฟเฉฑเจ เจชเจฒเฉเจ
เจฐ เจฒเจ เจตเจพเจงเฉ เจเฉเจคเจฐ เจธเจผเจพเจฎเจฒ เจเจฐเจจ เจฆเฉ เจฒเฉเฉ เจนเฉเฅค
เจฌเฉเจธ เจเจฒเจพเจธ เจฆเฉ เจเจชเจฒเจฌเจงเจคเจพ Object
- เจเฉเจก เจฆเฉเจนเจฐเจพเจเจฃ เจคเฉเจ เจฌเจเจฃ เจฒเจ เจเฉฑเจ เจฎเจนเฉฑเจคเจตเจชเฉเจฐเจจ เจเจฆเจฎ. เจเจฆเจพเจนเจฐเจจ เจฒเจ, เจเจฒเจพเจธ เจคเฉเจ เจฌเจฟเจจเจพเจ Object
เจนเจฐเฉเจ เจเฉเจฎ เจเจฌเจเฉเจเจ เจจเฉเฉฐ เจเฉฑเจเฉ เจเจฟเจนเจพ เจฒเจพเจเฉ เจเจฐเจจเจพ เจเจพเจนเฉเจฆเจพ เจนเฉ distanceTo()
, เจ
เจคเฉ เจเจนเจจเจพเจ เจธเจพเจฐเฉ เจฒเจพเจเฉเจเจฐเจจเจพเจ เจจเฉเฉฐ เจเจ เจซเจพเจเจฒเจพเจ เจตเจฟเฉฑเจ เจเจพเจชเฉ-เจชเฉเจธเจ เจเจฐเจจเจพ เจเฉฑเจ เจกเจฐเจพเจเจฃเจพ เจธเฉเจชเจจเจพ เจนเฉเจตเฉเจเจพเฅค เจเจน เจตเฉฑเจกเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจ เจฒเจ เจเจพเจธ เจคเฉเจฐ 'เจคเฉ เจฎเจนเฉฑเจคเจตเจชเฉเจฐเจจ เจฌเจฃ เจเจพเจเจฆเจพ เจนเฉ, เจเจฆเฉเจ เจตเจฟเจธเจคเจพเจฐ เจฆเฉ เจธเฉฐเจเจฟเจ Object
เจเจฒเจพเจธเจพเจ เจตเจง เจฐเจนเฉเจเจ เจนเจจเฅค
4. เจเฉฑเจเจฐ เจเฉเจ
เจธเจพเจกเฉ เจฒเจ เจธเจฟเจฐเจซ เจเจเฉ เจเฉเจเจผ เจฌเจเฉ เจนเฉ เจเจฆเฉเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจฎเจพเจฐเจฆเฉ เจนเจจ เจคเจพเจ เจชเจเจพเจฃเฉ! เจตเจฟเจงเฉ เจคเฉเจ เจเจธ เจเฉเจก เจฆเฉ เจธเจจเจฟเฉฑเจชเจ เจจเฉเฉฐ เจฏเจพเจฆ เจฐเฉฑเจเฉ update()
เจเจฒเจพเจธ เจตเจฟเฉฑเจ Game
:
game.js
const applyCollisions = require('./collisions');
class Game {
// ...
update() {
// ...
// Apply collisions, give players score for hitting bullets
const destroyedBullets = applyCollisions(
Object.values(this.players),
this.bullets,
);
destroyedBullets.forEach(b => {
if (this.players[b.parentID]) {
this.players[b.parentID].onDealtDamage();
}
});
this.bullets = this.bullets.filter(
bullet => !destroyedBullets.includes(bullet),
);
// ...
}
}
เจธเจพเจจเฉเฉฐ เจตเจฟเจงเฉ เจจเฉเฉฐ เจฒเจพเจเฉ เจเจฐเจจ เจฆเฉ เจฒเฉเฉ เจนเฉ applyCollisions()
, เจเฉ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจนเจฟเฉฑเจ เจเจฐเจจ เจตเจพเจฒเฉ เจธเจพเจฐเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจตเจพเจชเจธ เจเจฐเจฆเจพ เจนเฉเฅค เจเฉเจธเจผเจเจฟเจธเจฎเจคเฉ เจจเจพเจฒ, เจเจน เจเจฐเจจเจพ เจเฉฐเจจเจพ เจฎเฉเจธเจผเจเจฒ เจจเจนเฉเจ เจนเฉ เจเจฟเจเจเจเจฟ
- เจธเจพเจฐเฉเจเจ เจเจเจฐเจพเจเจฃ เจตเจพเจฒเฉเจเจ เจตเจธเจคเฉเจเจ เจเฉฑเจเจฐ เจนเจจ, เจ เจคเฉ เจเจน เจเฉฑเจเจฐ เจเฉเจ เจจเฉเฉฐ เจฒเจพเจเฉ เจเจฐเจจ เจฒเจ เจธเจญ เจคเฉเจ เจธเจฐเจฒ เจเจเจพเจฐ เจนเฉเฅค
- เจธเจพเจกเฉ เจเฉเจฒ เจชเจนเจฟเจฒเจพเจ เจนเฉ เจเฉฑเจ เจคเจฐเฉเจเจพ เจนเฉ
distanceTo()
, เจเจฟเจธ เจจเฉเฉฐ เจ เจธเฉเจ เจชเจฟเจเจฒเฉ เจญเจพเจ เจตเจฟเฉฑเจ เจเจฒเจพเจธ เจตเจฟเฉฑเจ เจฒเจพเจเฉ เจเฉเจคเจพ เจธเฉObject
.
เจเฉฑเจเจฐ เจฆเจพ เจชเจคเจพ เจฒเจเจพเจเจฃ เจฆเจพ เจธเจพเจกเจพ เจ เจฎเจฒ เจเจธ เจคเจฐเฉเจนเจพเจ เจฆเจฟเจเจฆเจพ เจนเฉ:
collisions.js
const Constants = require('../shared/constants');
// Returns an array of bullets to be destroyed.
function applyCollisions(players, bullets) {
const destroyedBullets = [];
for (let i = 0; i < bullets.length; i++) {
// Look for a player (who didn't create the bullet) to collide each bullet with.
// As soon as we find one, break out of the loop to prevent double counting a bullet.
for (let j = 0; j < players.length; j++) {
const bullet = bullets[i];
const player = players[j];
if (
bullet.parentID !== player.id &&
player.distanceTo(bullet) <= Constants.PLAYER_RADIUS + Constants.BULLET_RADIUS
) {
destroyedBullets.push(bullet);
player.takeBulletDamage();
break;
}
}
}
return destroyedBullets;
}
เจเจน เจธเจงเจพเจฐเจจ เจเฉฑเจเจฐ เจเฉเจ เจเจธ เจคเฉฑเจฅ 'เจคเฉ เจ เจงเจพเจฐเจค เจนเฉ เจเจฟ เจฆเฉ เจเฉฑเจเจฐ เจเจเจฐเจพเจเจเจฆเฉ เจนเจจ เจเฉเจเจฐ เจเจนเจจเจพเจ เจฆเฉ เจเฉเจเจฆเจฐเจพเจ เจตเจฟเจเจเจพเจฐ เจฆเฉเจฐเฉ เจเจนเจจเจพเจ เจฆเฉ เจฐเฉเจกเฉเจเจ เจฆเฉ เจเฉเฉ เจคเฉเจ เจเฉฑเจ เจนเฉ. เจเฉฑเจฅเฉ เจเฉฑเจ เจ เจเจฟเจนเจพ เจฎเจพเจฎเจฒเจพ เจนเฉ เจเจฟเฉฑเจฅเฉ เจฆเฉ เจเฉฑเจเจฐเจพเจ เจฆเฉ เจเฉเจเจฆเจฐเจพเจ เจตเจฟเจเจเจพเจฐ เจฆเฉเจฐเฉ เจเจนเจจเจพเจ เจฆเฉ เจฐเฉเจกเฉเจเจ เจฆเฉ เจเฉเฉ เจฆเฉ เจฌเจฟเจฒเจเฉเจฒ เจฌเจฐเจพเจฌเจฐ เจนเฉ:
เจเฉฑเจฅเฉ เจคเฉเจนเจพเจจเฉเฉฐ เจเฉเจ เจนเฉเจฐ เจชเจนเจฟเจฒเฉเจเจ เจตเฉฑเจฒ เจงเจฟเจเจจ เจฆเฉเจฃ เจฆเฉ เจฒเฉเฉ เจนเฉ:
- เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเฉเฉฐ เจเจธ เจเจฟเจกเจพเจฐเฉ เจจเฉเฉฐ เจจเจนเฉเจ เจฎเจพเจฐเจจเจพ เจเจพเจนเฉเจฆเจพ เจเจฟเจธเจจเฉ เจเจธเจจเฉเฉฐ เจฌเจฃเจพเจเจ เจนเฉเฅค เจเจน เจคเฉเจฒเจจเจพ เจเจฐเจเฉ เจชเฉเจฐเจพเจชเจค เจเฉเจคเจพ เจเจพ เจธเจเจฆเจพ เจนเฉ
bullet.parentID
ัplayer.id
. - เจเจเฉ เจธเจฎเฉเจ เจเจ เจเจฟเจกเจพเจฐเฉเจเจ เจจเฉเฉฐ เจฎเจพเจฐเจจ เจฆเฉ เจ
เจคเจฟเจ
เฉฐเจค เจเฉเจธ เจตเจฟเฉฑเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเฉเฉฐ เจธเจฟเจฐเจซ เจเฉฑเจ เจตเจพเจฐ เจฎเจพเจฐเจจเจพ เจเจพเจนเฉเจฆเจพ เจนเฉเฅค เจ
เจธเฉเจ เจเจชเจฐเฉเจเจฐ เจฆเฉ เจตเจฐเจคเฉเจ เจเจฐเจเฉ เจเจธ เจธเจฎเฉฑเจธเจฟเจ เจจเฉเฉฐ เจนเฉฑเจฒ เจเจฐเจพเจเจเฉ
break
: เจเฉฑเจ เจตเจพเจฐ เจเจฆเฉเจ เจเฉฑเจ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ เจจเจพเจฒ เจเจเจฐเจพเจเจฃ เจตเจพเจฒเจพ เจเจฟเจกเจพเจฐเฉ เจฎเจฟเจฒ เจเจพเจเจฆเจพ เจนเฉ, เจคเจพเจ เจ เจธเฉเจ เจเฉเจ เจเจฐเจจเจพ เจฌเฉฐเจฆ เจเจฐ เจฆเจฟเฉฐเจฆเฉ เจนเจพเจ เจ เจคเฉ เจ เจเจฒเฉ เจชเฉเจฐเฉเจเฉเจเจเจพเจเจฒ 'เจคเฉ เจเจฒเฉ เจเจพเจเจฆเฉ เจนเจพเจเฅค
เจ เฉฐเจค
เจเจน เจธเจญ เจนเฉ! เจ เจธเฉเจ .io เจตเฉเฉฑเจฌ เจเฉเจฎ เจฌเจฃเจพเจเจฃ เจฒเจ เจคเฉเจนเจพเจจเฉเฉฐ เจเฉ เจตเฉ เจเจพเจฃเจจ เจฆเฉ เจฒเฉเฉ เจนเฉ, เจเจธ เจจเฉเฉฐ เจเจตเจฐ เจเฉเจคเจพ เจนเฉเฅค เจ เฉฑเจเฉ เจเฉ เจนเฉ? เจเจชเจฃเฉ เจเฉเจฆ เจฆเฉ .io เจเฉเจฎ เจฌเจฃเจพเจ!
เจธเจพเจฐเจพ เจเจฆเจพเจนเจฐเจจ เจเฉเจก เจเจชเจจ เจธเฉเจฐเจธ เจนเฉ เจ
เจคเฉ เจเจธ 'เจคเฉ เจชเฉเจธเจ เจเฉเจคเจพ เจเจฟเจ เจนเฉ
เจธเจฐเฉเจค: www.habr.com