add example online game created with blessed.
This commit is contained in:
parent
54bde3badd
commit
831425d5af
|
@ -0,0 +1,439 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* ping
|
||||
* https://github.com/chjj/blessed
|
||||
* Copyright (c) 2013, Christopher Jeffrey (MIT License)
|
||||
* Online (ping)pong in your terminal.
|
||||
*/
|
||||
|
||||
// Example Usage:
|
||||
// Server: $ ./example/ping 3000
|
||||
// Client: $ ./example/ping 127.0.0.1 3000
|
||||
// Demo: $ ./example/ping
|
||||
|
||||
process.title = 'ping';
|
||||
|
||||
if (/^(-h|--help|-\?)$/.test(process.argv[2])) {
|
||||
console.log('node-ping');
|
||||
console.log('Example Usage:');
|
||||
console.log('Server: $ node-ping 3000');
|
||||
console.log('Client: $ node-ping 127.0.0.1 3000');
|
||||
console.log('Demo: $ node-ping');
|
||||
return process.exit(0);
|
||||
}
|
||||
|
||||
var blessed = require('blessed')
|
||||
, program = blessed()
|
||||
, nssocket;
|
||||
|
||||
try {
|
||||
nssocket = require('nssocket');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
|
||||
var server
|
||||
, socket;
|
||||
|
||||
/**
|
||||
* Screen Layout
|
||||
*/
|
||||
|
||||
var screen = new blessed.Screen({
|
||||
program: program
|
||||
});
|
||||
|
||||
var table = new blessed.Box({
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: screen.width,
|
||||
height: screen.height
|
||||
});
|
||||
|
||||
var ball = new blessed.Box({
|
||||
width: 1,
|
||||
height: 1,
|
||||
bg: 'white',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
|
||||
var lpaddle = new blessed.Box({
|
||||
width: 1,
|
||||
height: 3,
|
||||
bg: 'yellow',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
|
||||
var rpaddle = new blessed.Box({
|
||||
width: 1,
|
||||
height: 3,
|
||||
bg: 'yellow',
|
||||
top: 0,
|
||||
right: 0
|
||||
});
|
||||
|
||||
var score = new blessed.Box({
|
||||
top: 0,
|
||||
left: 4,
|
||||
height: 3,
|
||||
width: 20,
|
||||
bold: true
|
||||
});
|
||||
|
||||
score.lwins = 0;
|
||||
score.rwins = 0;
|
||||
|
||||
var net = new blessed.Box({
|
||||
width: 1,
|
||||
height: '100%',
|
||||
bg: 'yellow',
|
||||
top: 0,
|
||||
left: 'center'
|
||||
});
|
||||
|
||||
var message = new blessed.Box({
|
||||
width: '50%',
|
||||
height: 3,
|
||||
border: {
|
||||
type: 'ascii'
|
||||
},
|
||||
top: 'center',
|
||||
left: 'center'
|
||||
});
|
||||
|
||||
var text = new blessed.Box({
|
||||
top: 'center',
|
||||
left: 1,
|
||||
right: 1,
|
||||
height: 1,
|
||||
content: 'Waiting for players to connect...'
|
||||
});
|
||||
|
||||
message.append(text);
|
||||
|
||||
screen.append(table);
|
||||
|
||||
table.append(score);
|
||||
table.append(lpaddle);
|
||||
table.append(rpaddle);
|
||||
table.append(net);
|
||||
table.append(ball);
|
||||
table.append(message);
|
||||
|
||||
screen.on('resize', function() {
|
||||
table.width = screen.width;
|
||||
table.height = screen.height;
|
||||
[ball, lpaddle, rpaddle].forEach(function(el) {
|
||||
if (el.rbottom < 0) el.rtop = table.height - 1 - el.height;
|
||||
if (el.rright < 0) el.rleft = table.width - 1;
|
||||
});
|
||||
screen.render();
|
||||
sync();
|
||||
});
|
||||
|
||||
/**
|
||||
* Options
|
||||
*/
|
||||
|
||||
ball.speed = 2;
|
||||
ball.unpredictable = true;
|
||||
lpaddle.speed = 2;
|
||||
rpaddle.speed = 2;
|
||||
|
||||
/**
|
||||
* Game
|
||||
*/
|
||||
|
||||
function sync() {
|
||||
if (!socket) return;
|
||||
socket.send(['update'], {
|
||||
table: { width: table.width, height: table.height },
|
||||
lpaddle: { rleft: lpaddle.rleft, rtop: lpaddle.rtop, speed: lpaddle.speed },
|
||||
rpaddle: { rleft: rpaddle.rleft, rtop: rpaddle.rtop, speed: rpaddle.speed },
|
||||
score: { lwins: score.lwins, rwins: score.rwins }
|
||||
});
|
||||
}
|
||||
|
||||
function reset() {
|
||||
text.setContent('Waiting for players to connect...');
|
||||
message.hide();
|
||||
ball.moving = true;
|
||||
ball.direction = 'right';
|
||||
ball.angle = 'down';
|
||||
ball.rtop = 1;
|
||||
ball.rleft = 1;
|
||||
lpaddle.rtop = 0;
|
||||
rpaddle.rtop = 0;
|
||||
|
||||
score.setContent('Score: ' + score.lwins + ' | ' + score.rwins);
|
||||
|
||||
rpaddle.movable = true;
|
||||
|
||||
screen.render();
|
||||
if (server && socket) {
|
||||
socket.send(['reset']);
|
||||
}
|
||||
}
|
||||
|
||||
function rand(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
function startGame() {
|
||||
reset();
|
||||
|
||||
if (startGame._bound) return;
|
||||
startGame._bound = true;
|
||||
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (!ball.moving) return;
|
||||
if (key.name === 'up' || key.name === 'k') {
|
||||
if (socket) socket.send(['up']);
|
||||
if (lpaddle.rtop > 0) lpaddle.rtop -= lpaddle.speed;
|
||||
if (!socket) if (rpaddle.rtop > 0) rpaddle.rtop -= rpaddle.speed;
|
||||
if (lpaddle.rtop < 0) lpaddle.rtop = 0;
|
||||
if (rpaddle.rtop < 0) rpaddle.rtop = 0;
|
||||
screen.render();
|
||||
} else if (key.name === 'down' || key.name === 'j') {
|
||||
if (socket) socket.send(['down']);
|
||||
if (lpaddle.rbottom > 0) lpaddle.rtop += lpaddle.speed;
|
||||
if (!socket) if (rpaddle.rbottom > 0) rpaddle.rtop += rpaddle.speed;
|
||||
if (lpaddle.rbottom < 0) lpaddle.rtop = table.height - lpaddle.height - 1;
|
||||
if (rpaddle.rbottom < 0) rpaddle.rbottom = table.height - rpaddle.height - 1;
|
||||
screen.render();
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(function() {
|
||||
if (!ball.moving) return;
|
||||
if (ball.direction === 'right') {
|
||||
if (ball.rright > 1) {
|
||||
ball.rleft += ball.speed;
|
||||
} else {
|
||||
if (ball.rtop >= rpaddle.rtop && ball.rtop <= rpaddle.rtop + rpaddle.height) {
|
||||
ball.direction = 'left';
|
||||
ball.rleft -= ball.speed;
|
||||
|
||||
ball.rleft -= rand(0, 3);
|
||||
if (ball.angle === 'down') ball.rtop += rand(0, 3);
|
||||
else if (ball.angle === 'up') ball.rtop -= rand(0, 3);
|
||||
} else {
|
||||
// Right loses
|
||||
score.lwins++;
|
||||
ball.rleft = table.width - 1;
|
||||
if (socket) socket.send(['lose']);
|
||||
ball.moving = false;
|
||||
text.setContent('Right player loses!');
|
||||
message.show();
|
||||
setTimeout(reset, 3000);
|
||||
screen.render();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ball.rright < 1) ball.rleft = table.width - 2;
|
||||
} else if (ball.direction === 'left') {
|
||||
if (ball.rleft > 1) {
|
||||
ball.rleft -= ball.speed;
|
||||
} else {
|
||||
if (ball.rtop >= lpaddle.rtop && ball.rtop <= lpaddle.rtop + lpaddle.height) {
|
||||
ball.direction = 'right';
|
||||
ball.rleft += ball.speed;
|
||||
|
||||
ball.rleft += rand(0, 3);
|
||||
if (ball.angle === 'down') ball.rtop += rand(0, 3);
|
||||
else if (ball.angle === 'up') ball.rtop -= rand(0, 3);
|
||||
} else {
|
||||
// Left loses
|
||||
score.rwins++;
|
||||
ball.rleft = 0;
|
||||
if (socket) socket.send(['win']);
|
||||
ball.moving = false;
|
||||
text.setContent('Left player loses!');
|
||||
message.show();
|
||||
setTimeout(reset, 3000);
|
||||
screen.render();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ball.rleft < 1) ball.rleft = 1;
|
||||
}
|
||||
if (ball.angle === 'down') {
|
||||
if (ball.rbottom > 0) {
|
||||
ball.rtop++;
|
||||
if (ball.unpredictable) ball.rtop += rand(0, 3);
|
||||
} else {
|
||||
ball.angle = 'up';
|
||||
ball.rtop--;
|
||||
}
|
||||
} else if (ball.angle === 'up') {
|
||||
if (ball.rtop > 0) {
|
||||
ball.rtop--;
|
||||
if (ball.unpredictable) ball.rtop -= rand(0, 3);
|
||||
} else {
|
||||
ball.angle = 'down';
|
||||
ball.rtop++;
|
||||
}
|
||||
}
|
||||
if (ball.rtop < 0) ball.rtop = 0;
|
||||
if (ball.rbottom < 0) ball.rtop = table.height - 1;
|
||||
if (socket) socket.send(['ball'], { rleft: ball.rleft, rtop: ball.rtop });
|
||||
screen.render();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function startServer() {
|
||||
server = nssocket.createServer({}, function(socket_) {
|
||||
socket = socket_;
|
||||
|
||||
sync();
|
||||
|
||||
socket.data(['up'], function() {
|
||||
if (!ball.moving) return;
|
||||
if (rpaddle.rtop > 0) rpaddle.rtop -= rpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['down'], function() {
|
||||
if (!ball.moving) return;
|
||||
if (rpaddle.rtop < table.height - 1) rpaddle.rtop += rpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.on('error', function() {
|
||||
socket = null;
|
||||
reset();
|
||||
ball.moving = false;
|
||||
message.show();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
startGame();
|
||||
});
|
||||
|
||||
server.listen(+process.argv[2]);
|
||||
}
|
||||
|
||||
function startClient() {
|
||||
var socket = new nssocket.NsSocket({
|
||||
reconnect: true,
|
||||
maxRetries: Infinity,
|
||||
retryInterval: 5000
|
||||
});
|
||||
|
||||
socket.connect(+process.argv[3], process.argv[2]);
|
||||
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (!rpaddle.movable) return;
|
||||
if (key.name === 'up' || key.name === 'k') {
|
||||
socket.send(['up']);
|
||||
if (rpaddle.rtop > 0) rpaddle.rtop -= rpaddle.speed;
|
||||
if (rpaddle.rtop < 0) rpaddle.rtop = 0;
|
||||
screen.render();
|
||||
} else if (key.name === 'down' || key.name === 'j') {
|
||||
socket.send(['down']);
|
||||
if (rpaddle.rbottom > 0) rpaddle.rtop += rpaddle.speed;
|
||||
if (rpaddle.rbottom < 0) rpaddle.rtop = table.height - rpaddle.height - 1;
|
||||
screen.render();
|
||||
}
|
||||
});
|
||||
|
||||
socket.data(['up'], function() {
|
||||
if (lpaddle.rtop > 0) lpaddle.rtop -= lpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['down'], function() {
|
||||
if (lpaddle.rtop < table.height - 1) lpaddle.rtop += lpaddle.speed;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['ball'], function(data) {
|
||||
ball.rleft = data.rleft;
|
||||
ball.rtop = data.rtop;
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['update'], function(data) {
|
||||
if (data.lpaddle) {
|
||||
lpaddle.rleft = data.lpaddle.rleft;
|
||||
lpaddle.rtop = data.lpaddle.rtop;
|
||||
lpaddle.speed = data.lpaddle.speed;
|
||||
}
|
||||
|
||||
if (data.rpaddle) {
|
||||
rpaddle.rleft = data.rpaddle.rleft;
|
||||
rpaddle.rtop = data.rpaddle.rtop;
|
||||
rpaddle.speed = data.rpaddle.speed;
|
||||
}
|
||||
|
||||
if (data.ball) {
|
||||
ball.moving = data.ball.moving;
|
||||
ball.rleft = data.ball.rleft;
|
||||
ball.rtop = data.ball.rtop;
|
||||
}
|
||||
|
||||
if (data.table) {
|
||||
table.height = data.table.height;
|
||||
table.width = data.table.width;
|
||||
}
|
||||
|
||||
if (data.score) {
|
||||
score.lwins = data.score.lwins;
|
||||
score.rwins = data.score.rwins;
|
||||
}
|
||||
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['win'], function() {
|
||||
rpaddle.movable = false;
|
||||
score.rwins++;
|
||||
text.setContent('Left player loses!');
|
||||
message.show();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['lose'], function() {
|
||||
rpaddle.movable = false;
|
||||
score.lwins++;
|
||||
text.setContent('Right player loses!');
|
||||
message.show();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
socket.data(['reset'], reset);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main
|
||||
*/
|
||||
|
||||
function main() {
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (key.name === 'q' || key.name === 'escape') {
|
||||
return process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
// Demo Mode / Single Player
|
||||
if (!nssocket || !process.argv[2]) return startGame();
|
||||
|
||||
// Server Mode
|
||||
if (!process.argv[3]) return startServer();
|
||||
|
||||
// Client Mode
|
||||
if (process.argv[2] && process.argv[3]) return startClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*/
|
||||
|
||||
main();
|
Loading…
Reference in New Issue