123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- #!/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')
- , nssocket;
- try {
- nssocket = require('nssocket');
- } catch (e) {
- ;
- }
- var server
- , socket;
- /**
- * Screen Layout
- */
- var screen = blessed.screen();
- var table = blessed.box({
- left: 0,
- top: 0,
- width: screen.width,
- height: screen.height
- });
- var ball = blessed.box({
- width: 1,
- height: 1,
- bg: 'white',
- top: 0,
- left: 0
- });
- var lpaddle = blessed.box({
- width: 1,
- height: 3,
- bg: 'yellow',
- top: 0,
- left: 0
- });
- var rpaddle = blessed.box({
- width: 1,
- height: 3,
- bg: 'yellow',
- top: 0,
- right: 0
- });
- var score = blessed.box({
- top: 0,
- left: 4,
- height: 3,
- width: 'shrink',
- border: {
- type: 'line'
- },
- //align: 'center',
- style: {
- bold: true
- },
- tags: true
- });
- score.lwins = 0;
- score.rwins = 0;
- var net = blessed.box({
- width: 1,
- height: '100%',
- bg: 'yellow',
- top: 0,
- left: 'center'
- });
- var message = blessed.box({
- width: '50%',
- height: 3,
- border: {
- type: 'line'
- },
- top: 'center',
- left: 'center'
- });
- var text = blessed.box({
- top: 'center',
- left: 1,
- right: 1,
- height: 1,
- align: 'center',
- 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;
- if ((score.lwins + score.rwins) % 2 !== 0) {
- ball.direction = 'left';
- ball.rleft = table.width - 1;
- }
- lpaddle.rtop = 0;
- rpaddle.rtop = 0;
- score.setContent('{green-fg}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.rtop = 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();
|