เบเปเบญเบเบญเบญเบเบกเบฒเปเบกเบทเปเบญเบเบต 2015
เปเบโเบเปโเบฅเบฐโเบเบตโเบเบตเปโเบเปเบฒเบโเบเปเปโเปเบเบตเบโเปเบเปโเบเบดเบโเบเบญเบโเปเบเบกโเปเบซเบผเบปเปเบฒโเบเบตเปโเบกเบฒโเบเปเบญเบโ, เบเบงเบโเปเบเบปเบฒโเปเบเบปเปเบฒโเปเบกเปเบโเบเบฃเบตโ, เปเบเบกโเบซเบผเบฒเบโเปเบงเบฑเบโเบเบตเปโเบเปเบฒเบโเบเบตเปโเบเบฐโเบซเบผเบดเปเบ (เบเปเปโเบเปเบญเบโเบเบฒเบโเบเบฑเบโเบเบตโ)โ. เบเบปเบเบเบฐเบเบดเปเบฅเปเบง เบเบงเบเปเบเบปเบฒเบเบตเบเบนเปเบซเบผเบดเปเบเบเปเบฒเบเบเปเบฒเบเบซเบผเบฒเบเบเบปเบเบขเบนเปเปเบเบชเบฐเบซเบเบฒเบกเบเบดเบฅเบฒเบเบฝเบง. เปเบเบก .io เบเบตเปเบกเบตเบเบทเปเบชเบฝเบเบญเบทเปเบเป:
เปเบเบเบปเบเบเบฝเบเบเบตเป, เบเบงเบเปเบฎเบปเบฒเบเบฐเบเบดเบเบฒเบฅเบฐเบเบฒเบงเบดเบเบตเบเบฒเบ เบชเปเบฒเบเปเบเบก .io เบเบฑเปเบเปเบเปเปเบฅเบตเปเบกเบเบปเปเบ. เปเบเบทเปเบญเปเบฎเบฑเบเบชเบดเปเบเบเบตเป, เบเบฝเบเปเบเปเบเบงเบฒเบกเบฎเบนเปเบเบญเบ Javascript เบเบฐเบเบฝเบเบเป: เบเปเบฒเบเบเปเบฒเปเบเบฑเบเบเปเบญเบเปเบเบปเปเบฒเปเบเบชเบดเปเบเบเปเบฒเบเปเปเบเบฑเปเบ syntax this
ะธ
เบเบปเบงเบขเปเบฒเบเบเบญเบเปเบเบก .io
เบชเปเบฒเบฅเบฑเบเบเบฒเบเบเปเบงเบเปเบซเบผเบทเบญเบเบฒเบเบเบถเบเบญเบปเบเบฎเบปเบกเบเบงเบเปเบฎเบปเบฒเบเบฐเบญเปเบฒเบเปเบเบดเบ
เปเบเบกเปเบกเปเบเบเปเบญเบเบเปเบฒเบเบเปเบฒเบเบเบฒเบ: เบเปเบฒเบเบเบงเบเบเบธเบกเปเบฎเบทเบญเปเบเบเบฒเบกเบซเบฅเบดเปเบเบเบดเบฅเบฒเบเบฑเบเบเบนเปเบเบญเบทเปเบเป. เปเบฎเบทเบญเบเบญเบเปเบเบปเปเบฒเบเบฐเบเบดเบเบฅเบนเบเบเบทเบเบญเบฑเบเบเบฐเปเบเบกเบฑเบ เปเบฅเบฐเปเบเบปเปเบฒเบเบฐเบเบฒเบเบฒเบกเบเบตเปเบเบทเปเบญเบเบซเบผเบดเปเบเบญเบทเปเบเปเบเบเบฐเบเบฐเบเบตเปเบซเบผเบตเบเบฅเปเบฝเบเบฅเบนเบเบเบทเบเบเบญเบเปเบเบปเบฒเปเบเบปเปเบฒ.
1. เบเบฒเบเบฅเบงเบกเปเบเบเบซเบเปเป/เปเบเบเบชเปเบฒเบเปเบเบเบเบฒเบ
เบเปเบฒเบเบฐเปเบเบปเปเบฒเปเบเบฐเบเปเบฒเปเบซเป
เบเบฒเบงเปเบซเบฅเบเบฅเบฐเบซเบฑเบเปเบซเบผเปเบ เปเบเบกเบเบปเบงเบขเปเบฒเบเบเบฑเปเบเบเบฑเปเบเบเปเบฒเบเบชเบฒเบกเบฒเบเบเบฐเบเบดเบเบฑเบเบเบฒเบกเบเปเบฒเบเบฐเปเบเบปเปเบฒ.
เบเบปเบงเบขเปเบฒเบเปเบเปเบเบฑเปเบเบเปเปเปเบเบเบตเป:
เบชเบฐเปเบเบ เปเบกเปเบเบเบญเบเปเบงเบฑเบเบเบตเปเบเบดเบเบปเบกเบเบตเปเบชเบธเบเบชเปเบฒเบฅเบฑเบ Node.js เบเบตเปเบเบฑเบเบเบฒเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเปเบงเบฑเบเบเบญเบเปเบเบก.socket.io โ เบซเปเบญเบเบชเบฐเปเบธเบ websocket เบชเปเบฒเบฅเบฑเบเบเบฒเบเปเบฅเบเบเปเบฝเบเบเปเปเบกเบนเบเบฅเบฐเบซเบงเปเบฒเบ browser เปเบฅเบฐ server.Webpack - เบเบนเปเบเบฑเบเบเบฒเบเปเบกเบเบนเบ. เบเปเบฒเบเบชเบฒเบกเบฒเบเบญเปเบฒเบเบงเปเบฒเปเบเบฑเบเบซเบเบฑเบเบเปเบญเบเปเบเป Webpackเบเบตเปเบเบตเป .
เบเบตเปเปเบกเปเบเบชเบดเปเบเบเบตเปเปเบเบเบชเปเบฒเบเปเบเปเบฅเบเบฐเบเปเบฅเบตเบเบญเบเปเบเบเบเบฒเบเปเบเบดเปเบเบเบทเบงเปเบฒ:
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). Webpack เบเบฐเปเบฅเบตเปเบกเบเบฒเบเบเปเบญเบเบเบตเป เปเบฅเบฐเบเบญเบเบซเบฒเปเบเบฅเปเบเบตเปเบเบณเปเบเบปเปเบฒเบญเบทเปเบเบเปเบณเป.- เบเบปเบเบเบฐเบฅเบดเบ JS เบเบญเบ Webpack build เบเบญเบเบเบงเบเปเบฎเบปเบฒเบเบฐเบเบฑเปเบเบขเบนเปเปเบเปเบเปเบฅเบเบฐเบเปเบฅเบต
dist/
. เบเปเบญเบเบเบฐเปเบเบซเบฒเปเบเบฅเปเบเบตเปเบเบญเบเบเบงเบเปเบฎเบปเบฒ เบเบธเบ JS. - เบเบงเบเปเบฎเบปเบฒเปเบเป
Babel , เปเบฅเบฐเปเบเบเบชเบฐเปเบเบฒเบฐเบเบฒเบเบเบฑเปเบเบเปเบฒ@babel/preset-env เปเบเบทเปเบญเบเบญเบเบฅเบฐเบซเบฑเบ JS เบเบญเบเบเบงเบเปเบฎเบปเบฒเบชเปเบฒเบฅเบฑเบเบเบปเบงเบเปเบญเบเปเบงเบฑเบเบเบตเปเปเบเบปเปเบฒเบเบงเปเบฒ. - เบเบงเบเปเบฎเบปเบฒเปเบเป plugin เปเบเบทเปเบญเบชเบฐเบเบฑเบ CSS เบเบฑเบเบซเบกเบปเบเบเบตเปเบญเปเบฒเบเบญเบดเบเปเบเบเปเบเบฅเป JS เปเบฅเบฐเบฅเบงเบกเบเบงเบเบกเบฑเบเปเบเบปเปเบฒเปเบเปเบเบเปเบญเบเบเบฝเบง. เบเปเบฒเบเบฐเปเบเบปเปเบฒเบเบฐเปเบเบซเบฒเบกเบฑเบเบเบญเบเบเบงเบเปเบฎเบปเบฒ เบเบธเบ CSS.
เบเปเบฒเบเบญเบฒเบเบเบฐเปเบเปเบชเบฑเบเปเบเบเปเบซเบฑเบเบเบทเปเปเบเบฅเปเปเบเบฑเบเปเบเบฑเบเบเบตเปเปเบเบเบเบฐเบซเบผเบฒเบ '[name].[contenthash].ext'
. เบเบงเบเปเบเบปเบฒเปเบเบปเปเบฒเบเบฐเบเบญเบเบเปเบงเบ [name]
เบเบฐเบเบทเบเปเบเบเบเบตเปเบเปเบงเบเบเบทเปเบเบญเบเบเบธเบเบเปเบญเบเบเปเปเบกเบนเบ (เปเบเบเปเบฅเบฐเบเบตเบเบญเบเบเบงเบเปเบฎเบปเบฒเบกเบฑเบเปเบกเปเบ game
), เบ [contenthash]
เบเบฐเบเบทเบเปเบเบเบเบตเปเบเปเบงเบ hash เบเบญเบเปเบเบทเปเบญเปเบเปเบเบฅเป. เบเบงเบเปเบฎเบปเบฒเปเบฎเบฑเบเบชเบดเปเบเบเบตเปเปเบเบทเปเบญ 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
, เปเบเบทเปเบญเปเบเบตเปเบกเบเบฐเบชเบดเบเบเบดเบเบฒเบเบเบฐเบซเบเบฒเบเบเบธเบเปเบเปเบงเบฅเบฒเบเบตเป deploying เบเบฑเบเบเบฒเบเบเบฐเบฅเบดเบ.
เบเบฒเบเบเบฑเปเบเบเปเบฒเบเปเบญเบเบเบดเปเบ
เบเปเบฒเบเบฐเปเบเบปเปเบฒเปเบเบฐเบเปเบฒเปเบซเปเบเบดเบเบเบฑเปเบเปเบเบเบเบฒเบเบขเบนเปเปเบเปเบเบทเปเบญเบเบเปเบญเบเบเบดเปเบเบเบญเบเบเปเบฒเบเปเบเบทเปเบญเปเบซเปเบเปเบฒเบเบชเบฒเบกเบฒเบเบเบฐเบเบดเบเบฑเบเบเบฒเบกเบเบฑเปเบเบเบญเบเบเบตเปเบฅเบฐเบเบธเปเบงเปเปเบเบเปเปเบเบงเบฒเบกเบเบตเป. เบเบฒเบเบเบดเบเบเบฑเปเบเปเบกเปเบเบเปเบฒเบเบเบฒเบ: เบเปเบฒเบญเบดเบ, เบฅเบฐเบเบปเบเบเปเบญเบเบกเบต
$ 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 (<canvas>
), เปเบเบดเปเบเบเบงเบเปเบฎเบปเบฒเบเบฐเปเบเปเปเบเบทเปเบญเบชเบฐเปเบเบเปเบเบก.<link>
เปเบเบทเปเบญเปเบเบตเปเบกเบเบธเบ CSS เบเบญเบเบเบงเบเปเบฎเบปเบฒ.<script>
เปเบเบทเปเบญเปเบเบตเปเบกเบเบธเบ Javascript เบเบญเบเบเบงเบเปเบฎเบปเบฒ.- เปเบกเบเบนเบซเบผเบฑเบเบเบตเปเบกเบตเบเบทเปเบเบนเปเปเบเป
<input>
เปเบฅเบฐเบเบธเปเบก โPLAYโ (<button>
).
เปเบกเบทเปเบญเบซเบเปเบฒเบเปเบฒเบญเบดเบเปเบซเบผเบ, เบเบปเบงเบเปเบญเบเปเบงเบฑเบเบเบฐเปเบฅเบตเปเบกเบเบฐเบเบดเบเบฑเบเบฅเบฐเบซเบฑเบ Javascript, เปเบฅเบตเปเบกเบเบปเปเบเบเปเบงเบเปเบเบฅเป 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 (เบเบฑเปเบเบเบฑเปเบ Webpack เบฎเบนเปเบงเปเบฒเบเบฐเบฅเบงเบกเบเบงเบเบกเบฑเบเบขเบนเปเปเบเบเบธเบ 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. เบเบฒเบเบชเบฐเปเบเบเบฅเบนเบเบเปเบฒ
เบกเบฑเบเปเบเบดเบเปเบงเบฅเบฒเบเบตเปเบเบฐเบชเบฐเปเบเบเบฎเบนเบเบเบฒเบเปเบเบซเบเปเบฒเบเป!
...เปเบเปโเบเปเบญเบโเบเบตเปโเบเบงเบโเปเบฎเบปเบฒโเบเบฐโเบชเบฒโเบกเบฒเบโเปเบฎเบฑเบโเปเบเป, เบเบงเบโเปเบฎเบปเบฒโเบเปเบฒโเปเบเบฑเบโเบเปเบญเบโเปเบเปโเบเบฒเบงโเบโเปโเปเบซเบฅเบโเบฎเบนเบโเบเบฒเบโเบเบฑเบโเบซเบกเบปเบ (เปเบซเบผเปเบโเบเปเปโเบกเบนเบโ) เบเบตเปโเบเปเบฒโเปเบเบฑเบโเบชเปเบฒโเบฅเบฑเบโเบเบฒเบโเบเบตเปโ. เบกเบฒเบเบฝเบเบเบปเบงเบเบฑเบเบเบฒเบเบเบฑเบเบเบฐเบเบฒเบเบญเบ:
เบเบฑเบเบชเบดเบ.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: เบเปเปเบกเบนเบเบเปเบฝเบงเบเบฑเบเบเบนเปเบเปเบเปเบฎเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเบเบตเป.
- เบเบปเบเบญเบทเปเบ: array เบเบญเบเบเปเปเบกเบนเบเบเปเบฝเบงเบเบฑเบเบเบนเปเบเบญเบทเปเบเปเบเบตเปเปเบเบปเปเบฒเบฎเปเบงเบกเปเบเปเบเบกเบเบฝเบงเบเบฑเบ.
- เบฅเบนเบเบเบทเบ: array เบเบญเบเบเปเปเบกเบนเบเบเปเบฝเบงเบเบฑเบ projectiles เปเบเปเบเบก.
- เบเบฐเบเบฒเบ เบเบณ: เบเปเปเบกเบนเบเบเบฐเบเบฒเบเบเบฑเบเบญเบฑเบเบเบฑเบเบเบฑเบเบเบธเบเบฑเบ. เบเบงเบเปเบฎเบปเบฒเบเบฐเบเปเปเปเบญเบปเบฒเบเบงเบเบกเบฑเบเปเบเบปเปเบฒเปเบเปเบเบเบฑเบเบเบตเปเบเบเปเปเบเบงเบฒเบกเบเบตเป.
7.1 เบชเบฐเบเบฒเบเบฐ naive เบเบญเบเบฅเบนเบเบเปเบฒ
เบเบฒเบเบเบฐเบเบดเบเบฑเบ Naive getCurrentState()
เบชเบฒเบกเบฒเบเบชเบปเปเบเบเบทเบเบเปเปเบกเบนเบเปเบเบเบเบปเบเบเบฒเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบกเบเบตเปเปเบเปเบฎเบฑเบเบซเบผเปเบฒเบชเบธเบ.
naive-state.js
let lastGameUpdate = null;
// Handle a newly received game update.
export function processGameUpdate(update) {
lastGameUpdate = update;
}
export function getCurrentState() {
return lastGameUpdate;
}
เบเบฒเบกเปเบฅเบฐเบเบฑเบเปเบเบ! เปเบเปเบเปเบฒเบซเบฒเบเบงเปเบฒเบเบฝเบเปเบเปเบกเบฑเบเปเบกเปเบเบเปเบฒเบเบเบฒเบเบเบตเป. เบซเบเบถเปเบเปเบเปเบซเบเบเบปเบเบเบฒเบเบเบฐเบเบดเบเบฑเบเบเบตเปเปเบกเปเบเบเบฑเบเบซเบฒ: เบกเบฑเบเบเปเบฒเบเบฑเบเบญเบฑเบเบเบฒเปเบเบฃเบกเบเบฒเบเบชเบฐเปเบเบเปเบเบดเบเบเบงเบฒเบกเปเบงเปเบกเบเปเบเบตเบเปเบงเบต.
เบญเบฑเบเบเบฒเปเบเบฃเบก: เบเปเบฒเบเบงเบเบเบญเบเบเบญเบ (i. e. เปเบ
render()
) เบเปเปเบงเบดเบเบฒเบเบต, เบซเบผเบท FPS. เปเบเบกเบเบปเบเบเบฐเบเบดเปเบฅเปเบงเบเบฐเบเบฒเบเบฒเบกเบเบฑเบเบฅเบธเบขเปเบฒเบเบซเบเปเบญเบ 60 FPS.
เบญเบฑเบโเบเบฒโเบเบฒเบโเบซเบกเบฒเบโเบเบดเบโ: เบเบงเบฒเบกเบเบตเปเบเบตเปเปเบเบตเบเปเบงเบตเบชเบปเปเบเบญเบฑเบเปเบเบเปเบเบกเปเบซเปเบเบฑเบเบฅเบนเบเบเปเบฒ. เบกเบฑเบเบกเบฑเบเบเบฐเบเปเปเบฒเบเบงเปเบฒเบญเบฑเบเบเบฒเบเบญเบ. เปเบเปเบเบกเบเบญเบเบเบงเบเปเบฎเบปเบฒ, เปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเปเบฅเปเบเบขเบนเปเบเบตเป 30 เบซเบกเบฒเบเบเบดเบเบเปเปเบงเบดเบเบฒเบเบต.
เบเปเบฒเบเบงเบเปเบฎเบปเบฒเบเบฝเบเปเบเปเปเบฎเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบกเบซเบฅเปเบฒเบชเบธเบ, FPS เบเบตเปเบชเปเบฒเบเบฑเบเบเบฐเบเปเปเบชเบฒเบกเบฒเบเปเบเบตเบ 30 เปเบเบฒเบฐเบงเปเบฒ เบเบงเบเปเบฎเบปเบฒเบเปเปเปเบเบตเบเปเบเปเบฎเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเบซเบผเบฒเบเบเบงเปเบฒ 30 เปเบเบทเปเบญเบเปเปเบงเบดเบเบฒเบเบตเบเบฒเบเปเบเบตเบเปเบงเบต. เปเบเบดเบเปเบกเปเบเบงเปเบฒเบเบงเบเปเบฎเบปเบฒเปเบเบซเบฒ render()
60 เปเบเบทเปเบญเบเปเปเบงเบดเบเบฒเบเบต, เบซเบผเบฑเบเบเบฒเบเบเบฑเปเบเปเบเบดเปเบเบซเบเบถเปเบเบเบญเบเบเบฒเบเปเบเปเบซเบผเบปเปเบฒเบเบตเปเบเบฝเบเปเบเปเบเบฐเปเบฎเบฑเบเบเปเปเบฒเบชเบดเปเบเบเบฝเบงเบเบฑเบ, เบเบตเปเบชเปเบฒเบเบฑเบเบเปเปเปเบฎเบฑเบเบซเบเบฑเบเปเบฅเบตเบ. เบเบฑเบเบซเบฒเบญเบตเบเบเบฐเบเบฒเบเบซเบเบถเปเบเบเบตเปเบกเบตเบเบฒเบเบเบฐเบเบดเบเบฑเบ naive เปเบกเปเบเบงเปเบฒเบกเบฑเบ เบเบถเปเบเบเบฑเบเบเบงเบฒเบกเบฅเปเบฒเบเปเบฒ. เปเบเบเบงเบฒเบกเปเบงเบญเบดเบเปเบเบตเปเบเบฑเบเบเบตเปเปเบซเบกเบฒเบฐเบชเบปเบก, เบฅเบนเบเบเปเบฒเบเบฐเปเบเปเบฎเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบกเปเบเปเบเบญเบเบเบธเบเป 33 ms (30 เบเปเปเบงเบดเบเบฒเบเบต):
เปเบเปเบซเบเปเบฒเปเบชเบเบเบฒเบ, เบเปเปเบกเบตเบซเบเบฑเบเบเบตเปเบชเบปเบกเบเบนเบเปเบเบ. เบฎเบนเบโเบเบฒเบโเบเบตเปโเปเบเบฑเบโเบเบดเบโเบซเบผเบฒเบโเบเบงเปเบฒโเบเบฐโเปเบเบฑเบโ:
เบเบฒเบเบเบฐเบเบดเบเบฑเบเบเบตเปเปเบฎเปเบเบฝเบเบชเบฒเปเบกเปเบเบเปเบญเบเบเปเบฒเบเปเบเบฑเบเบเปเบฅเบฐเบเบตเบเบตเปเบฎเปเบฒเบเปเบฎเบเบเบตเปเบชเบธเบเปเบเปเบงเบฅเบฒเบเบตเปเบกเบฑเบเบกเบฒเบเบฑเบ latency. เบเปเบฒเปเบเปเบฎเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบกเบเปเบงเบเบเบงเบฒเบกเบฅเปเบฒเบเปเบฒ 50ms, เบซเบผเบฑเบเบเบฒเบเบเบฑเปเบ เบฅเบนเบเบเปเบฒเบเปเบฒเบฅเบปเบ เปเบเบ 50ms เบเบดเปเบชเบเปเบเบทเปเบญเบเบเบฒเบเบงเปเบฒเบกเบฑเบเบเบฑเบเบชเบฐเปเบเบเบชเบฐเบเบฒเบเบฐเปเบเบกเบเบฒเบเบเบฒเบเบเบฑเบเบเบธเบเบเบตเปเบเปเบฒเบเบกเบฒ. เบเปเบฒเบเบชเบฒเบกเบฒเบเบเบดเบเบเบฐเบเบฒเบเบฒเบเบงเปเบฒเบเบตเปเบเปเปเบชเบฐเบเบงเบเบชเปเบฒเบฅเบฑเบเบเบนเปเบซเบผเบดเปเบ: เปเบเบทเปเบญเบเบเบฒเบเบเบฒเบเบเปเบฒเบฅเบปเบเปเบเบเบเบปเบเปเบญเบ, เปเบเบกเบเบฐเปเบเบดเปเบเบเบทเบงเปเบฒ jerky เปเบฅเบฐเบเปเปเบซเบกเบฑเปเบเบเบปเบ.
7.2 เบเบฑเบเบเบธเบเบชเบฐเบเบฒเบเบฐเบฅเบนเบเบเปเบฒ
เบเบงเบโเปเบฎเบปเบฒโเบเบฐโเปเบฎเบฑเบโเปเบซเปโเบเบฒเบโเบเบฑเบโเบเบธเบโเบเบฒเบโเบขเปเบฒเบโเปเบโเบเบฒเบโเบเบฐโเบเบดโเบเบฑเบ naive. เบเปเบญเบเบญเบทเปเบ เปเบปเบ, เบเบงเบเปเบฎเบปเบฒเปเบเป เบเบงเบฒเบกเบฅเปเบฒเบเปเบฒเบเบญเบเบเบฒเบเบชเบฐเปเบเบเบเบปเบ เปเบเบ 100 ms. เบเบตเปเบซเบกเบฒเบเบเบงเบฒเบกเบงเปเบฒเบชเบฐเบเบฒเบเบฐ "เบเบฐเบเบธเบเบฑเบ" เบเบญเบเบฅเบนเบเบเปเบฒเบเบฐเบขเบนเป 100ms เบซเบฅเบฑเบเบชเบฐเบเบฒเบเบฐเปเบเบกเบขเบนเปเปเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบ. เบเบปเบงเบขเปเบฒเบ, เบเปเบฒเปเบงเบฅเบฒเบเบญเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเปเบกเปเบ 150, เบซเบผเบฑเบเบเบฒเบเบเบฑเปเบเบฅเบนเบเบเปเบฒเบเบฐเบชเบฐเปเบเบเบชเบฐเบเบฒเบเบฐเบเบตเปเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเบขเบนเปเปเบเปเบงเบฅเบฒเบเบฑเปเบ 50:
เบเบตเปเปเบฎเบฑเบเปเบซเปเบเบงเบเปเบฎเบปเบฒเบกเบต buffer 100ms เปเบเบทเปเบญเบเบงเบฒเบกเบขเบนเปเบฅเบญเบเบเบญเบเปเบงเบฅเบฒเบเบตเปเบเปเปเบชเบฒเบกเบฒเบเบเบฒเบเปเบเบปเบฒเปเบเปเบเบญเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบก:
เบฅเบฒเบเบฒเบชเปเบฒเบฅเบฑเบเบเบฒเบเบเบตเปเบเบฐเบเบฒเบงเบญเบ
เบเบงเบเปเบฎเบปเบฒเบชเบฒเบกเบฒเบเบเปเบฒเปเบเปเปเบเบฑเบเบเบดเบเบญเบทเปเบเบเบตเปเปเบญเบตเปเบเบงเปเบฒ
"เบเบฒเบโเบเบฒเบโเบเบฐโเปเบโเบเปเบฒเบโเบฅเบนเบโเบเปเบฒโ" , เปเบเบดเปเบเปเบฎเบฑเบเบงเบฝเบเปเบเปเบเบตเปเบเบเบฒเบเบซเบผเบธเบเบเปเบญเบเบเบงเบฒเบกเบฅเปเบฒเบเปเบฒเบเบตเปเบฎเบฑเบเบฎเบนเปเปเบเป, เปเบเปเบเบฐเบเปเปเบเบทเบเบเปเบฒเบงเปเบเบดเบเปเบเปเบเบชเบเบตเป.
เบเบฒเบเบเบฑเบเบเบธเบเบญเบตเบเบญเบฑเบเบซเบเบถเปเบเบเบตเปเบเบงเบเปเบฎเบปเบฒเปเบเปเปเบกเปเบ interpolation เปเบชเบฑเปเบ. เปเบเบทเปเบญเบเบเบฒเบเบเบงเบฒเบกเบเบฑเบเบเปเบฒเบเบญเบเบเบฒเบเบชเบฐเปเบเบเบเบปเบ, เบเบงเบเปเบฎเบปเบฒเบกเบฑเบเบเบฐเบกเบตเบขเปเบฒเบเบซเบเปเบญเบเบซเบเบถเปเบเบเบฒเบเบเบฑเบเบเบธเบเบเปเบญเบเปเบงเบฅเบฒเบเบฐเบเบธเบเบฑเบเบขเบนเปเปเบเบฅเบนเบเบเปเบฒ. เปเบกเบทเปเบญเบเบทเบเปเบญเบตเปเบ 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()
. เบเบฑเปเบเบเบตเปเบเบงเบเปเบฎเบปเบฒเปเบเปเปเบซเบฑเบเบเปเบญเบเบซเบเปเบฒเบเบฑเปเบ, เบเบธเบเปเบเบฒเบเบเบฑเบเบเบธเบเปเบเบกเบเบฐเบเบญเบเบกเบตเปเบงเบฅเบฒเบเบญเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบ. เบเบงเบเปเบฎเบปเบฒเบเปเบญเบเบเบฒเบเปเบเป render latency เปเบเบทเปเบญ render เบฎเบนเบเบเบฒเบ 100ms เบซเบฅเบฑเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบ, เปเบเป เบเบงเบเปเบฎเบปเบฒเบเบฐเบเปเปเบฎเบนเปเปเบงเบฅเบฒเบเบฐเบเบธเบเบฑเบเบขเบนเปเปเบเปเบเบตเบเปเบงเบต, เปเบเบฒเบฐเบงเปเบฒเบเบงเบเปเบฎเบปเบฒเบเปเปเบชเบฒเบกเบฒเบเบฎเบนเปเบงเปเบฒเบกเบฑเบเปเบเปเปเบงเบฅเบฒเบเบปเบเบเบฒเบเปเบเบชเปเบฒเบฅเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเปเบเบตเปเบเบฐเบกเบฒเบฎเบญเบเบเบงเบเปเบฎเบปเบฒ. เบญเบดเบเปเบเบตเปเบเบฑเบเปเบกเปเบเบเปเปเบชเบฒเบกเบฒเบเบเบฒเบเปเบเบปเบฒเปเบเปเปเบฅเบฐเบเบงเบฒเบกเปเบงเบเบญเบเบกเบฑเบเบชเบฒเบกเบฒเบเปเบเบเบเปเบฒเบเบเบฑเบเบขเปเบฒเบเบซเบผเบงเบเบซเบผเบฒเบ!
เปเบเบทเปเบญเปเบซเปเปเบเปเบฎเบฑเบเบเบฐเบกเบฒเบเบเบฑเบเบซเบฒเบเบตเป, เบเบงเบเปเบฎเบปเบฒเบชเบฒเบกเบฒเบเบเปเบฒเปเบเปเบเบฐเบกเบฒเบเบเบตเปเบชเบปเบกเปเบซเบเบชเบปเบกเบเบปเบ: เบเบงเบเปเบฎเบปเบฒ เปเบซเปเบชเบปเบกเบกเบธเบเบงเปเบฒเบเบฒเบเบเบฑเบเบเบธเบเบเบฑเปเบเบเปเบฒเบญเบดเบเบกเบฒเบฎเบญเบเบเบฑเบเบเบต. เบเปเบฒเบเบตเปเปเบกเปเบเบเบงเบฒเบกเบเบดเบ, เบเบงเบเปเบฎเบปเบฒเบเบฐเบฎเบนเปเปเบงเบฅเบฒเปเบเบตเบเปเบงเบตเปเบเบเปเบงเบเปเบงเบฅเบฒเบเบฑเปเบ! เบเบงเบเปเบฎเบปเบฒเปเบเบฑเบเบฎเบฑเบเบชเบฒเปเบงเบฅเบฒเบเบญเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเบขเบนเปเปเบ firstServerTimestamp
เปเบฅเบฐเบเปเบงเบเบเบฐเบขเบฑเบเบเบญเบเบเบงเบเปเบฎเบปเบฒ เบเปเบญเบเบเบดเปเบ (เบฅเบนเบโเบเปเบฒโ) timestamp เปเบโเบเบฑเบโเบเบธโเบเบฑเบโเบเบฝเบงโเบเบฑเบโเปเบโ gameStart
.
เปเบญเป, เบฅเปเบเปเบฒเบเบฒเบเบต. เบเปเปเบเบงเบเบกเบตเปเบงเบฅเบฒเบขเบนเปเปเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบ = เปเบงเบฅเบฒเบขเบนเปเปเบเบฅเบนเบเบเปเบฒเบเป? เปเบเบฑเบเบซเบเบฑเบเบเบงเบเปเบฎเบปเบฒเบเบถเปเบเบกเบตเบเบงเบฒเบกเปเบเบเบเปเบฒเบเบเบฑเบเบฅเบฐเบซเบงเปเบฒเบ "เปเบงเบฅเบฒเปเบเบตเบเปเบงเบต" เปเบฅเบฐ "เปเบงเบฅเบฒเบฅเบนเบเบเปเบฒ"? เบเบตเปเปเบกเปเบเบเปเบฒเบเบฒเบกเบเบตเปเบเบดเปเบเปเบซเบเป! เบกเบฑเบ turns เปเบซเป เปเบซเบฑเบ เบงเปเบฒ เปเบซเบผเบปเปเบฒ เบเบตเป เบเปเป เปเบกเปเบ เบชเบดเปเบ เบเบฝเบง เบเบฑเบ . Date.now()
เบเบฐเบชเบปเปเบเบเบทเบเบเบฒเบเบชเบฐเปเบเบกเปเบงเบฅเบฒเบเบตเปเปเบเบเบเปเบฒเบเบเบฑเบเบขเบนเปเปเบเบฅเบนเบเบเปเบฒเปเบฅเบฐเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเปเบฅเบฐเบเบตเปเปเบกเปเบเบเบถเปเบเบเบฑเบเบเบฑเบเปเบเบเปเบญเบเบเบดเปเบเบเบญเบเปเบเบทเปเบญเบเบเบฑเบเปเบซเบผเบปเปเบฒเบเบตเป. เบขเปเบฒเบชเบปเบกเบกเบธเบเบงเปเบฒเบชเบฐเปเบเบกเปเบงเบฅเบฒเบเบฐเบเบทเบเบฑเบเปเบเบเบธเบเปเบเบทเปเบญเบ.
เปเบเบเบฑเบเบเบธเบเบฑเบเบเบงเบเปเบฎเบปเบฒเปเบเบปเปเบฒเปเบเบชเบดเปเบเบเบตเปเบกเบฑเบเปเบฎเบฑเบ currentServerTime()
: เบกเบฑเบเบเบฑเบเบเบทเบเบกเบฒ เปเบงเบฅเบฒเปเบเบตเบเปเบงเบตเบเบญเบเปเบงเบฅเบฒเบเบฒเบเบชเบฐเปเบเบเบเบปเบเบเบฐเบเบธเบเบฑเบ. เปเบเบเปเบฒเบชเบฑเบเบเปเบฒเบเปเบญเบทเปเบเป, เบเบตเปเปเบกเปเบเปเบงเบฅเบฒเบเบญเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเปเบเบเบฐเบเบธเบเบฑเบ (firstServerTimestamp <+ (Date.now() - gameStart)
) เบฅเบปเบโเบเบฒเบโเบฅเปเบฒโเบเปเบฒโเบเบฒเบโเบชเบฐโเปเบเบ (RENDER_DELAY
).
เบเบญเบเบเบตเปเปเบซเปเปเบเบดเปเบเบงเบดเบเบตเบเบตเปเบเบงเบเปเบฎเบปเบฒเบเบฑเบเบเบฒเบเบเบฑเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบก. เปเบกเบทเปเบญเปเบเปเบฎเบฑเบเบเบฒเบเบเบฑเบเบเบธเบเบเบฒเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบ, เบกเบฑเบเบเบทเบเปเบญเบตเปเบเบงเปเบฒ processGameUpdate()
, เปเบฅเบฐเบเบงเบเปเบฎเบปเบฒเบเบฑเบเบเบถเบเบเบฒเบเบเบฑเบเบเบธเบเปเบซเบกเปเปเบชเป array 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
เปเบกเปเบเบเบฒเบเบเบฑเบเบเบธเบเบซเบผเปเบฒเบชเบธเบเบเบตเปเบเบงเบเปเบฎเบปเบฒเบกเบต. เบญเบฑเบเบเบตเปเบญเบฒเบเบเบฐเปเบเบตเบเบเบถเปเบเปเบเบทเปเบญเบเบเบฒเบเบเบฒเบเบเบญเบเบชเบฐเปเบญเบเบเบญเบเปเบเบทเบญเบเปเบฒเบ เบซเบผเบทเบเบฒเบเปเบเบทเปเบญเบกเบเปเปเบญเบดเบเปเบเบตเปเบเบฑเบเบเปเปเบเบต. เปเบเบเปเบฅเบฐเบเบตเบเบตเปเปเบเบฑเปเบเบเบฝเบงเบเบฑเบเบเบงเบเปเบฎเบปเบฒเปเบเปเบเบฒเบเบเบฑเบเบเบธเบเบซเบฅเปเบฒเบชเบธเบเบเบตเปเบเบงเบเปเบฎเบปเบฒเบกเบต.- เบเบงเบโเปเบฎเบปเบฒโเบกเบตโเบเบฒเบโเบเบฑเบโเบเบธเบโเบเบฑเบโเบเปเบญเบโเปเบฅเบฐโเบซเบผเบฑเบโเบเบฒเบโเบเบตเปโเปเบเปโเปเบงโเบฅเบฒ render เปเบโเบเบฐโเบเบธโเบเบฑเบโ, เบเบฑเปเบโเบเบฑเปเบโเบเบงเบโเปเบฎเบปเบฒโเบชเบฒโเบกเบฒเบโเปเบฎเบฑเบโเปเบเปโ interpolate!
เบเบฑเบเบซเบกเบปเบเบเบตเปเปเบซเบฅเบทเบญเบขเบนเปเปเบ state.js
เปเบกเปเบเบเบฒเบเบเบฑเบเบเบฑเปเบเบเบฐเบเบดเบเบฑเบเบเบฒเบเปเบเบทเปเบญเบกเบชเบฒเบเปเบชเบฑเปเบเบเบทเปเบเบตเปเบเปเบฒเบเบเบฒเบ (เปเบเปเปเปเบฒเปเบเบทเปเบญ) เบเบฐเบเบดเบเบชเบฒเบ. เบเปเบฒเบเปเบฒเบเบเปเบญเบเบเบฒเบเบชเปเบฒเบซเบผเบงเบเบกเบฑเบเปเบญเบ, เบซเบผเบฑเบเบเบฒเบเบเบฑเปเบเปเบเบตเบ state.js
เบชเบธเบ
เบชเปเบงเบเบเบต 2. เปเบเบตเบเปเบงเบต Backend
เปเบเบชเปเบงเบเบเบตเปเบเบงเบเปเบฎเบปเบฒเบเบฐเปเบเบดเปเบ backend 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? เบเบตเปเปเบกเปเบเบเปเบญเบเบเบตเปเบเบงเบเปเบฎเบปเบฒเบเบฐเปเบเปเบเบฒเบเบเบฑเปเบเบเปเบฒ Webpack เบเบญเบเบเบงเบเปเบฎเบปเบฒ. เบเบงเบเปเบฎเบปเบฒเบเบฐเบเปเบฒเปเบเปเบเบงเบเบกเบฑเบเปเบเบชเบญเบเบงเบดเบเบต:
- เปเบเป
webpack-dev-middleware เบญเบฑเบเบเบฐเปเบเบกเบฑเบเบชเปเบฒเบเบเบธเบเบเบฒเบเบเบฑเบเบเบฐเบเบฒเบเบญเบเบเบงเบเปเบฎเบปเบฒ, เบซเบผเบท - เปเบญเบเบเปเบฒเบเปเบเบเปเบเบตเปเบเบเบเบปเบเบเบตเป
dist/
, เบเบตเป Webpack เบเบฐเบเบฝเบเปเบเบฅเปเบเบญเบเบเบงเบเปเบฎเบปเบฒเบซเบผเบฑเบเบเบฒเบเบเบฒเบเบเปเปเบชเปเบฒเบเบเบฒเบเบเบฐเบฅเบดเบ.
เบงเบฝเบเบเบฒเบเบเบตเปเบชเปเบฒเบเบฑเบเบญเบตเบเบญเบฑเบเบซเบเบถเปเบ 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 เบเบปเบงเบเบญเบเบกเบฑเบเปเบญเบเบเปเบฒเบเบปเบเปเบเปเบฅเบฐ socket เปเบเบฑเบเปเบญเบเบฐเบฅเบฑเบ id
, เบเบฑเปเบเบเบฑเปเบเบเบงเบเปเบฎเบปเบฒเบเปเปเบเปเบฒเปเบเบฑเบเบเปเบญเบเบเบฑเบเบงเบปเบเบเปเบฝเบงเบเบฑเบเบกเบฑเบ. เบเปเบญเบเบเบฐเปเบเบซเบฒเบฅเบฒเบง ID เบเบนเปเบซเบผเบดเปเบ.
เบเปเบงเบเบงเปเบฒเบขเบนเปเปเบเปเบ, เปเบซเปเบเบงเบเปเบเบดเปเบเบเบปเบงเปเบเบเบปเบงเบขเปเบฒเบเปเบเบเบฑเปเบเบฎเบฝเบ Game
:
sockets
เปเบกเปเบเบงเบฑเบเบเบธเบเบตเปเบเบนเบ ID เบเบนเปเบเบเบฑเบ socket เบเบตเปเบเปเบฝเบงเบเปเบญเบเบเบฑเบเบเบนเปเบเปเบเป. เบกเบฑเบเบญเบฐเบเบธเบเบฒเบเปเบซเปเบเบงเบเปเบฎเบปเบฒเปเบเบปเปเบฒเปเบเบดเบเปเบเบปเปเบฒเบฎเบฑเบเปเบเบ ID เบเบนเปเบเบเบญเบเปเบเบปเบฒเปเบเบปเปเบฒเปเบเปเบฅเบเบฐเปเบงเบฅเบฒ.players
เปเบเบฑเบเบงเบฑเบเบเบธเบเบตเปเบเบนเบ ID เบเบนเปเบเบเบฑเบเบฅเบฐเบซเบฑเบ> เบงเบฑเบเบเบธเบเบนเปเบ
bullets
เปเบเบฑเบ array เบเบญเบเบงเบฑเบเบเบธ 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()
. - เบเบฑเบเบเบธเบเปเบเปเบฅเบฐ projectile เปเบฅเบฐเบเปเบฒเบฅเบฒเบเบเบงเบเบกเบฑเบเบเปเบฒเบเปเบฒเปเบเบฑเบ. เบเบงเบเปเบฎเบปเบฒเบเบฐเปเบซเบฑเบเบเบฒเบเบเบฐเบเบดเบเบฑเบเบซเบเปเบฒเบเบตเปเบเบตเปเบเปเปเบกเบฒ. เบชเปเบฒเบฅเบฑเบเปเบเบเบฑเบเบเบธเบเบฑเบเบกเบฑเบเบเบฝเบเบเปเบชเปเบฒเบฅเบฑเบเบเบงเบเปเบฎเบปเบฒเบเบตเปเบเบฐเบฎเบนเปเบงเปเบฒ
bullet.update()
เบเบฑเบเบเบทเบtrue
, เบเปเบฒ projectile เบเปเบญเบเปเบเปเบฎเบฑเบเบเบฒเบเบเปเบฒเบฅเบฒเบ (เบฅเบฒเบงเบญเบญเบเปเบเบเบญเบเบชเบฐเปเบฒเบกเบเบดเบฅเบฒ). - เบเบฑเบเบเบธเบเบเบนเปเบเปเบเปเบฅเบฐเบเบปเบเปเบฅเบฐเบชเปเบฒเบ projectile เบเปเบฒเบเปเบฒเปเบเบฑเบ. เบเบงเบเปเบฎเบปเบฒเบเบฑเบเบเบฐเปเบซเบฑเบเบเบฒเบเบเบฐเบเบดเบเบฑเบเบเบตเปเบเปเปเบกเบฒ -
player.update()
เบชเบฒเบกเบฒเบเบชเบปเปเบเบเบทเบเบงเบฑเบเบเบธBullet
. - เบเบงเบโเบชเบญเบโเบเบฒเบโเบเบฐโเบเบฐโเบเบฑเบโเบฅเบฐโเบซเบงเปเบฒเบ projectiles เปเบฅเบฐโเบเบนเปเบโเบเบฒเบโเบเปเบฒโเปเบเปโ
applyCollisions()
, เปเบเบดเปเบเบชเบปเปเบเบเบทเบ array เบเบญเบ projectiles เบเบตเปเบเบตเบเบนเปเบ. เบชเปเบฒเบฅเบฑเบเปเบเปเบฅเบฐ projectile เบเบฑเบเบเบทเบ, เบเบงเบเปเบฎเบปเบฒเปเบเบตเปเบกเบเบฐเปเบเบเบเบญเบเบเบนเปเบเบเบนเปเบเบตเปเบเบดเบเบกเบฑเบ (เบเบฒเบเบเปเบฒเปเบเปplayer.onDealtDamage()
), เปเบฅเบฐเบซเบผเบฑเบเบเบฒเบเบเบฑเปเบเปเบญเบปเบฒ projectile เบญเบญเบเบเบฒเบ array เปเบเปbullets
. - เปเบเปเบโเบเบฒเบโเปเบฅเบฐโเบเปเบฒโเบฅเบฒเบโเบเบนเปเบโเบเบฒเบโเบเบฑเบโเบซเบกเบปเบโ.
- เบชเบปเปเบเบญเบฑเบเปเบเบเปเบเบกเปเบซเปเบเบฑเบเบเบนเปเบซเบผเบดเปเบเบเบฑเบเปเบปเบ เบเบธเบเปเบงเบดเบเบฒเบเบต เปเบงเบฅเบฒเปเบญเบตเปเบ
update()
. เบเบปเบงเปเบเปเบชเบตเบกเบเบตเปเปเบเปเบเปเบฒเบงเบกเบฒเบเปเบฒเบเปเบเบดเบเบเปเบงเบเปเบซเปเบเบงเบเปเบฎเบปเบฒเบเบดเบเบเบฒเบกเบชเบดเปเบเบเบตเปshouldSendUpdate
. เปเบเบฑเบupdate()
เปเบญเบตเปเบเบงเปเบฒ 60 เปเบเบทเปเบญ/เบงเบดเบเบฒเบเบต, เบเบงเบเปเบฎเบปเบฒเบชเบปเปเบเบเบฒเบเบญเบฑเบเปเบเบเปเบเบก 30 เปเบเบทเปเบญ/เบงเบดเบเบฒเบเบต. เบเบฑเปเบเบเบฑเปเบ, เบเบงเบฒเบกเบเบตเปเปเบกเบ เปเบเบตเบเปเบงเบตเปเบกเปเบ 30 เบฎเบญเบเบงเบฝเบเปเบกเบ/เบงเบดเบเบฒเบเบต (เบเบงเบเปเบฎเบปเบฒเปเบเปเปเบงเบปเปเบฒเปเบเบดเบเบเบงเบฒเบกเบเบตเปเปเบกเบเปเบเบเบฒเบเบเบณเบญเบดเบ).
เปเบเบฑเบเบซเบเบฑเบเบเปเบญเบเบชเบปเปเบเบญเบฑเบเปเบเบเปเบเบกเปเบเบปเปเบฒเบเบฑเปเบ เบเปเบฒเบเปเบงเบฅเบฒ ? เปเบเบทเปเบญเบเบฑเบเบเบถเบเบเปเบญเบ. 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
. เปเบซเปเบชเบฑเบเปเบเบเบงเปเบฒเบกเบฑเบเบเบฝเบเปเบเปเบชเบปเปเบเบเปเปเบกเบนเบเปเบเบซเบฒเบเบนเปเบเปเบเปเบฅเบฐเบเบปเบเบเปเบฝเบงเบเบฑเบ เปเบเปเบเบตเปเบชเบธเบ เบเบนเปเบเปเบฅเบฐ projectiles - เบเปเปเบเปเบฒเปเบเบฑเบเบเปเบญเบเบชเบปเปเบเบเปเปเบกเบนเบเบเปเบฝเบงเบเบฑเบเบงเบฑเบเบเบธเปเบเบกเบเบตเปเบเบฑเปเบเบขเบนเปเปเบเบเบฒเบเบเบนเปเบเปเบเป!
3. เบงเบฑเบเบเบธเปเบเบกเบขเบนเปเปเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบ
เปเบโเปเบเบกโเบเบญเบโเบเบงเบโเปเบฎเบปเบฒโ, projectiles เปเบฅเบฐโเบเบนเปเบโเปเบกเปเบโเบเบปเบงโเบเบดเบโเปเบฅเปเบงโเบเปเบฒเบโเบเบทโเบเบฑเบโเบซเบผเบฒเบโ: เบเบงเบโเปเบเบปเบฒโเปเบเบปเปเบฒโเปเบกเปเบโเบเปเปโเบกเบตโเบเบปเบงโเบเบปเบโเบเบญเบโเปเบเบกโเปเบเบทเปเบญเบโเบเปเบฒเบโเบฎเบญเบโ. เปเบเบทเปเบญเปเบเปเบเบฐเปเบซเบเบเบเบฒเบเบเบงเบฒเบกเบเปเบฒเบเบเบทเบเบฑเบเบเบตเปเบฅเบฐเบซเบงเปเบฒเบเปเบเบทเปเบญเบเบซเบผเบดเปเบ เปเบฅเบฐเบฅเบนเบเบเบทเบ, เปเบซเปเปเบฅเบตเปเบกเบเบปเปเบเบเปเบงเบเบเบฒเบเบเบฐเบเบดเบเบฑเบเบเบฑเปเบเบเบทเปเบเบเบฒเบ 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
, เบเบฑเปเบเบเบฑเปเบเบเปเบฒเบเบชเบฒเบกเบฒเบเบเบดเบเบเบฒเบกเบเบนเปเบเบเบนเปเบเบตเปเบชเปเบฒเบ projectile เบเบตเป. - เบเบฒเบเปเบเบตเปเบกเบกเบนเบเบเปเบฒเบเบฑเบเบเบทเบเปเบเบซเบฒ
update()
, เปเบเบดเปเบเปเบเบปเปเบฒเบเบฑเบtrue
, เบเปเบฒ projectile เปเบกเปเบเบขเบนเปเบเบญเบเบชเบฐเบซเบเบฒเบกเบเบดเบฅเบฒ (เบเบทเปเบเบงเบเปเบฎเบปเบฒเปเบเปเปเบงเบปเปเบฒเบเปเบฝเบงเบเบฑเบเปเบฅเบทเปเบญเบเบเบตเปเปเบเบเบฒเบเบชเบธเบเบเปเบฒเบ?).
เบเปเปเบซเปเบเปเบฒเบงเปเบเบชเบนเป 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,
};
}
}
เบเบนเปเบเปเบกเปเบเบชเบฐเบฅเบฑเบเบชเบฑเบเบเปเบญเบเบซเบผเบฒเบเบเปเบงเบฒ projectiles, เบชเบฐเบเบฑเปเบเบซเปเบญเบเบฎเบฝเบเบเบตเปเบเบงเบเบเบฐเปเบเบฑเบเบฎเบฑเบเบชเบฒเบเปเบญเบเบเปเปเบกเบนเบเบเปเบฒเบเบงเบเบซเบเบถเปเบ. เบงเบดเบเบตเบเบฒเบเบเบญเบเบฅเบฒเบง update()
เปเบฎเบฑเบเบงเบฝเบเบซเบผเบฒเบเบเบถเปเบ, เปเบเบเบชเบฐเปเบเบฒเบฐเบเบฒเบเบชเบปเปเบเบเบทเบ projectile เบเบตเปเบชเปเบฒเบเบเบถเปเบเปเบซเบกเปเบเปเบฒเบเปเปเบกเบตเบญเบฑเบเปเบเปเบซเบผเบทเบญเปเบงเป 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()
, เปเบเบดเปเบเบชเบปเปเบเบเบทเบ projectiles เบเบฑเบเบซเบกเบปเบเบเบตเปเบเบตเบเบนเปเบ. เปเบเบเบเบต, เบเบตเปเบเปเปเปเบกเปเบเบเบฒเบเบเบฒเบเบเบตเปเบเบฐเปเบฎเบฑเบเปเบเบฒเบฐเบงเปเบฒ
- เบงเบฑเบเบเบธเบเบตเปเบเบณเบเบฑเบเบเบฑเบเปเบปเบเปเบกเปเบเบฎเบนเบเบงเบปเบเบกเบปเบ, เปเบฅเบฐเบเบตเปเปเบกเปเบเบฎเบนเบเบฎเปเบฒเบเบเบตเปเบเปเบฒเบเบเบฒเบเบเบตเปเบชเบธเบเปเบเบทเปเบญเบเบฐเบเบดเบเบฑเบเบเบฒเบเบเบงเบเบซเบฒเบเบฒเบเบเบฐเบเบฐเบเบฑเบ.
- เบเบงเบเปเบฎเบปเบฒเบกเบตเบงเบดเบเบตเบเบฒเบเปเบฅเปเบง
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;
}
เบเบฒเบเบเบญเบเบเบปเปเบเบซเบฒ collision เบเปเบฒเบเบเบฒเบเบเบตเปเปเบกเปเบเบญเบตเบเปเบชเปเบเบงเบฒเบกเบเบดเบเบเบตเปเบงเปเบฒ เบงเบปเบเบกเบปเบเบชเบญเบเบญเบฑเบเบเบฑเบเบเบฑเบเบเปเบฒเปเบฅเบเบฐเบซเปเบฒเบเบฅเบฐเบซเบงเปเบฒเบเบเบธเบเบชเบนเบเบเบฒเบเบเบญเบเบเบงเบเบกเบฑเบเปเปเบญเบเบเบงเปเบฒเบเบปเบเบฅเบงเบกเบเบญเบ radii. เบเบตเปเปเบกเปเบเบเปเบฅเบฐเบเบตเบเบตเปเปเบฅเบเบฐเบซเปเบฒเบเบฅเบฐเบซเบงเปเบฒเบเบชเบนเบเบเบฒเบเบเบญเบเบชเบญเบเบงเบปเบเปเบกเปเบเปเบเบปเปเบฒเบเบฑเบเบเบปเบเบฅเบงเบกเบเบญเบ radii:
เปเบเบเบตเปเบเบตเปเบเปเบฒเบเบเปเบญเบเปเบญเบปเบฒเปเบเปเบชเปเบชเบญเบเบเปเบฒเบเปเบเบตเปเบกเปเบเบตเบก:
- projectile เบเบฐเบเปเบญเบเบเปเปเบกเบปเบเบเบตเบเบนเปเบเบเบนเปเบเบตเปเบชเปเบฒเบเบกเบฑเบ. เบเบตเปเบชเบฒเบกเบฒเบเบเบฑเบเบฅเบธเปเบเปเปเบเบเบเบฒเบเบเบฝเบเบเบฝเบ
bullet.parentID
ัplayer.id
. - เบฅเบนเบเบชเบญเบเปเบเบเบงเบเบเบตเบเบฝเบเบเบฑเปเบเบเบฝเบงเปเบเบเปเบฅเบฐเบเบตเบเบตเปเบฎเปเบฒเบเปเบฎเบเบเบญเบเบเบฒเบเบเบตเบเบนเปเบซเบผเบดเปเบเบซเบผเบฒเบเบเบปเบเปเบเปเบงเบฅเบฒเบเบฝเบงเบเบฑเบ. เบเบงเบเปเบฎเบปเบฒเบเบฐเปเบเปเปเบเบเบฑเบเบซเบฒเบเบตเปเปเบเบเปเบเปเบเบปเบงเบเบฐเบเบดเบเบฑเบเบเบฒเบ
break
: เปเบกเบทเปเบญเบเบปเบเบเบนเปเบซเบผเบดเปเบเบเบตเปเบเบฐเบเบฐเบเบฑเบเบเบฑเบเบฅเบนเบเบชเบญเบเปเบ, เบเบงเบเปเบฎเบปเบฒเบขเบธเบเบเบฒเบเบเบญเบเบซเบฒ เปเบฅเบฐเบเปเบฒเบงเปเบเบชเบนเปเบฅเบนเบเบชเบญเบเปเบเบเปเปเปเบ.
เบเบตเปเบชเบธเบ
เบซเบกเบปเบโเปเบเบปเปเบฒโเบเบตเป! เบเบงเบเปเบฎเบปเบฒเปเบเปเบเบงเบกเปเบญเบปเบฒเบเบธเบเบขเปเบฒเบเบเบตเปเปเบเบปเปเบฒเบเปเบญเบเบเบฒเบเบฎเบนเปเปเบเบทเปเบญเบชเปเบฒเบเปเบเบกเปเบงเบฑเบ .io. เบเปเปเปเบเปเบกเปเบเบซเบเบฑเบ? เบชเปเบฒเบเปเบเบก .io เบเบญเบเบเปเบฒเบเปเบญเบ!
เบฅเบฐเบซเบฑเบเบเบปเบงเบขเปเบฒเบเบเบฑเบเปเบปเบเปเบกเปเบเปเบซเบผเปเบเปเบเบตเบ เปเบฅเบฐ เบเบฐเบเบฒเบเปเบ
เปเบซเบผเปเบเบเปเปเบกเบนเบ: www.habr.com