Created
August 4, 2019 22:18
-
-
Save timetocode/5c069d0865f5fda6598ade1e77d2944e to your computer and use it in GitHub Desktop.
nengi bot example using multiple cpus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const glue = require('./glue') | |
const nengi = glue.nengi.default | |
const nengiConfig = glue.nengiConfig.default | |
const PlayerInput = glue.PlayerInput.default | |
// bots need to all share the same protocols | |
const protocolMap = new nengi.ProtocolMap(nengiConfig, nengi.metaConfig) | |
//var address = 'ws://localhost:8001' | |
const address = null // put some url here | |
let numberOfBots = 10 // just a default, actual amount set by parent process | |
const bots = new Map() | |
// process communication | |
process.on('message', msg => { | |
if (msg.address) { | |
address = msg.address | |
} | |
if (msg.count) { | |
numberOfBots = msg.count | |
} | |
if (msg.start) { | |
for (let i = 0; i < numberOfBots; i++) { | |
setTimeout(() => { | |
connectNewBot(i) | |
}, i * 250) | |
} | |
} | |
if (msg.stop) { | |
bots.forEach(bot => { | |
if (bot.websocket) { | |
bot.websocket.terminate() | |
} | |
}) | |
} | |
}) | |
process.on('SIGINT', function () { | |
console.log("childBot caught interrupt signal, cleaning up websockets") | |
bots.forEach(bot => { | |
if (bot.websocket) { | |
bot.websocket.terminate() | |
} | |
}) | |
process.exit() | |
}) | |
// creating a bot | |
function connectNewBot(id) { | |
const bot = new nengi.Bot(nengiConfig, protocolMap) | |
bot.id = id | |
// may not need this depending on the game | |
bot.controls = { | |
w: false, | |
a: false, | |
s: false, | |
d: false, | |
space: false, | |
sprint: false, | |
primary: false, | |
secondary: false, | |
reload: false, | |
rotationX: Math.random() * Math.PI * 2, | |
rotationY: Math.random() * Math.PI * 2, | |
rotationZ: Math.random() * Math.PI * 2, | |
delta: 1 / 60 | |
} | |
bot.onConnect(response => { | |
console.log('Bot attempted connection, response:', response) | |
bot.tick = 0 | |
}) | |
bot.onClose(() => { | |
bots.delete(bot.id) | |
}) | |
bots.set(bot.id, bot) | |
bot.connect(address, {}) | |
} | |
function randomBool() { | |
return Math.random() > 0.5 | |
} | |
const loop = () => { | |
bots.forEach(function botLoop(bot) { | |
if (bot.websocket) { | |
// releases memory!! also returns snapshots, if you want the bots to intelligently play the game | |
bot.readNetwork() | |
// randomly hitting keys and changing controls - will vary for your game | |
if (Math.random() > 0.95) { | |
bot.controls = { | |
w: randomBool(), | |
a: randomBool(), | |
s: randomBool(), | |
d: randomBool(), | |
space: false, //randomBool(), | |
sprint: false, | |
primary: false, //randomBool(), | |
secondary: false, | |
reload: false, | |
rotationX: Math.random() * Math.PI * 2, | |
rotationY: Math.random() * Math.PI * 2, | |
rotationZ: Math.random() * Math.PI * 2, | |
delta: 1 / 60 | |
} | |
} | |
// actually creating and sending the input to the server | |
const input = new PlayerInput( | |
bot.controls.w, | |
bot.controls.a, | |
bot.controls.s, | |
bot.controls.d, | |
bot.controls.space, | |
bot.controls.sprint, | |
bot.controls.primary, | |
bot.controls.secondary, | |
bot.controls.reload, | |
bot.controls.rotationX, | |
bot.controls.rotationY, | |
bot.controls.rotationZ, | |
bot.controls.delta | |
) | |
if (Math.random() > 0.7) { | |
// another type of command periodically?? up to you | |
// bot.addCommand(new FireCommand(500, 500, Math.random())) | |
} | |
bot.addCommand(input) | |
bot.update() | |
bot.tick++ | |
} | |
}) | |
} | |
setTimeout(() => { | |
setInterval(loop, 16) // simulated client tick rate | |
}, 100) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require = require('esm')(module/*, options*/) | |
module.exports.nengi = require('nengi') | |
module.exports.nengiConfig = require('../common/nengiConfig') | |
/* from here on your needs will vary per game, use your games commands */ | |
module.exports.PlayerInput = require('../common/command/PlayerInput') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { fork } = require('child_process') | |
/* | |
// example of creating ONE child | |
const forked = fork('./game/bot/childBot.js') | |
forked.on('message', (msg) => { | |
console.log('Message from child', msg) | |
}) | |
forked.send({ | |
address: 'wss://asia-pacific-3.example.io/1', | |
count: 10, | |
start: true | |
}) | |
*/ | |
// sending 10 players each to servers wss://asia-pacific-3.example.io/1 thru wss://asia-pacific-3.example.io/10 | |
for (var i = 1; i <= 24; i++) { | |
const forked = fork('./game/bot/childBot.js') | |
forked.send({ | |
address: `wss://asia-pacific-3.example.io/${i}`, | |
count: 10, | |
start: true | |
}) | |
} | |
process.on('SIGINT', function () { | |
console.log("multiBot caught interrupt signal") | |
process.exit() | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment