我正在尝试使用事件监听器和排放复制一个后院的捕获游戏。人A'投掷'并且 - 十分之九的人 - B'捕获'然后又回来了。两个人都不能抓住自己的投掷。我该怎么做呢?下面的示例/伪代码。
var events = require('events'),
EventEmitter = require('events').EventEmitter;
var a = new EventEmitter(),
b = new EventEmitter();
a.on('start', function() {
this.emit('throw', b);
})
a.on('catch', function() {
console.log('a caught b\'s throw');
this.emit('throw', b);
});
b.on('catch', function() {
console.log('b caught a\'s throw');
this.emit('throw', a);
});
a.emit('start');
如果我想扩展游戏以包括第三人(在这种情况下投掷的目标只能是两个可能的接收者之一),该怎么办?
答案 0 :(得分:0)
我不确切知道你的游戏是如何运作的,所以我用不同的游戏逻辑编写了一个游戏。但您可以轻松地根据自己的需要进行调整。
游戏的工作原理如下:
每个玩家以交替的方式投掷两个骰子。第一个玩家1投掷骰子而不是玩家2,依此类推。 每个玩家可以随机捕捉其他玩家的骰子。捕获的骰子总和得分,得分最高的玩家赢得比赛。
现在到代码。起初,我没有看到你正在做一个nodeJs应用程序。但是我的前端应用程序应该可以在节点上运行并进行一些调整。
我已经使用SignalsJS进行活动。您可以找到示例here。
以下引用来自here:
信号类似于事件发射器/调度器或发布/订阅系统,主要区别在于每个事件类型都有自己的控制器,并且不依赖于字符串来广播/订阅事件
将signalJS视为发布者和订阅者系统是最好的理解它正在做什么。
订阅者/侦听者正在侦听来自发布者的事件。一旦发布者调度某些内容,就会调用订阅者的回调。
要管理事件,您需要在评论中提出某种中介,这样您就可以处理所有事情。在我的演示中,对象DiceGame
充当调解器,因为它将玩家和抛出的骰子保存在数组中。
请在jsFiddle找到以下游戏的演示。
(如果有什么需要改进的地方,请在评论中告诉我。)
//store local reference for brevity
var Signal = signals.Signal;
/*
// simple signals demo code here as an example
//custom object that dispatch signals
var dice = {
threw: new Signal(), //past tense is the recommended signal naming convention
carched: new Signal()
};
function onThrew(param1, param2) {
console.log(param1 + param2);
}
dice.threw.add(onThrew); //add listener
dice.threw.dispatch('user1', ' - dice no. = 6'); //dispatch signal passing custom parameters
dice.threw.remove(onThrew); //remove a single listener
*/
var DiceGame = function(settings) {
this.settings = $.extend(DiceGame.defaultSettings, settings);
var activePlayer = {};
this.addPlayer = function() {
var index = this.players.push({
name: 'player' + (this.players.length + 1),
//custom object that dispatch signals
dice: {
threw: new Signal(), //past tense is the recommended signal naming convention
catched: new Signal()
},
score: 0,
dicesThrown: 0
});
activePlayer = this.players[index-1];
activePlayer.index = index-1;
this.setActivePlayer(activePlayer);
// add display listener
activePlayer.dice.threw.add(this.onDiceThrew, this);
activePlayer.dice.catched.add(this.onDiceCatched, this);
//console.log(this.players, index, this.$activePlayerInfo, activePlayer);
};
this.getActivePlayer = function() {
return activePlayer;
};
this.setActivePlayer = function(player, index){
if ( typeof index != 'undefined' ) {
console.log(index, this.players[index]);
activePlayer = this.players[index];
}
else {
activePlayer = player;
}
this.updatePlayerInfo(activePlayer.name);
this.$activePlayerScore.html(activePlayer.score);
};
this.initGame = function() {
this.$activePlayerInfo = $(this.settings.elActivePlayer);
this.$activePlayerScore = $(this.settings.elActivePlayerScore);
this.$gameInfo = $(this.settings.elGameInfo);
this.$playField = $(this.settings.elPlayField);
// add click handlers (bind to DiceGame obj. with this)
$('#newGame').click(this.reset.bind(this));
$('#addPlayer').click(this.addPlayer.bind(this));
$('#changePlayer').click(this.nextPlayer.bind(this));
$('#throw').click(this.throwDice.bind(this));
$('#catch').click(this.catchDice.bind(this));
// add two players
_.each(new Array(this.settings.defaultPlayerCount), function(){
this.addPlayer();
}, this);
this.setActivePlayer(null, 0); // can change current player by index
}
this.initGame();
};
DiceGame.defaultSettings = {
elActivePlayer: '#activePlayer',
elActivePlayerScore: '#activePlayerScore',
elGameInfo: '#gameInfo',
elPlayField: '#playField',
defaultPlayerCount: 2,
maxThrownCount: 2
};
DiceGame.prototype = {
players: [],
diceList: [],
updatePlayerInfo: function(text) {
this.$activePlayerInfo.html(text);
},
reset: function() {
this.diceList = [];
$.each(this.players, function(index, item) {
console.log(item);
item.score = 0;
item.dicesThrown = 0;
});
this.setActivePlayer(null, 0); // can change current player by index
this.refreshPlayField();
//this.showGameInfo('');
this.hideGameInfo();
},
nextPlayer: function() {
var index = this.getActivePlayer().index;
index++;
if (index >= this.players.length ) {
//'roll over' required!
index = 0;
}
//var playerCopy = this.players.slice(0);
this.setActivePlayer(this.players[index]); // next player
},
onDiceThrew: function(diceNo) {
console.log('threw dice', diceNo);
var newDice = {player: this.getActivePlayer(),
diceValue: diceNo};
if ( newDice.player.dicesThrown < this.settings.maxThrownCount ) {
this.diceList.push(newDice);
this.$playField.append($('<p/>').text(newDice.player.name + ' - threw dice: ' +newDice.diceValue));
//console.log('threw', this.diceList);
newDice.player.dicesThrown++;
}
else {
//alert(newDice.player.dicesThrown+ ' dices thrown. None left.');
//show message that all dices are thrown
this.showGameInfo(newDice.player.dicesThrown+ ' dices thrown. None left.');
return;
}
console.log(newDice);
this.nextPlayer(); // change to next player
},
checkGameOver: function() {
// all thrown and nothing to catch --> game is over
var winner = _.max(this.players, function(player) {
console.log(player);
return player.score;
});
console.log("winner", winner, this.players);
var otherPlayers = _.omit(this.players, function(value) {
console.log('value', value, value===winner);
return value === winner;});
var scoresStr = '';
_.each(otherPlayers, function(player) {
scoresStr += player.name + ': ' + player.score + '<br/>';
});
// check if we have a draw.
//this.players[0].score = 5; // needed for testing
//this.players[1].score = 5;
var draw = _.every(this.players, function(player) {
return player.score === winner.score;
});
console.log(draw);
if (draw) {
this.showGameInfo('Game over!<br/>Draw with score ' +
winner.score, true);
}
else
{
// call showGameInfo with true --> keeps message displayed
this.showGameInfo('Game over!<br/>' + winner.name +
' wins the game with score ' + winner.score
+ '!<br/>Other scores:<br/>' + scoresStr, true);
}
},
onDiceCatched: function() {
// catch one dice of other player
var player = this.getActivePlayer();
var diceList = this.diceList.slice(0); // copy dice list
var allowedDice = _.filter(diceList, function(dice) {
return dice.player.name !== player.name;
});
var catched = allowedDice[Math.floor(Math.random()*allowedDice.length)];
// console.log('catched dice = ', catched);
// add score to active player
if ( catched ) {
player.score += catched.diceValue;
this.$activePlayerScore.html(player.score);
// update play field
var newDiceList = this.removeItem(diceList, catched);
this.diceList = newDiceList.slice(0); // copy new list to the dice list
this.refreshPlayField();
var allDone = _.every(this.players.dicesThrown, function(element) {
return element == this.settings.maxThrownCount;
});
if ( this.diceList.length == 0 && allDone ){
this.checkGameOver();
}
}
else {
// nothing catched
// check if game is over? if yes, who is the winner?
if ( player.dicesThrown >= this.settings.maxThrownCount )
{
this.checkGameOver();
return;
}
}
this.nextPlayer(); // change to next player
},
removeItem: function(array, id) {
// remove dice from list
return _.reject(array, function(item) {
//console.log(item, id, item===id);
return item === id; // or some complex logic
});
},
refreshPlayField: function() {
var $field = this.$playField,
$row = $('<p/>');
$field.empty();
$.each(this.diceList, function(index, item) {
console.log(index, item);
$row.text(item.player.name + ' - threw dice: ' +item.diceValue)
$field.append($row.clone());
});
},
showGameInfo: function(message, keep) {
var $info = this.$gameInfo;
$info.html(message);
// show info with jQuery animation
$info
.stop()
.animate({opacity:1}, 'fast');
if ( !keep ) { // don't auto hidde --> required for game over
$info
.delay(2000) // display time of message
.animate({opacity:0},'fast');
}
},
hideGameInfo: function() {
// required to hide gameover message
this.$gameInfo.stop()
.animate({opacity:0}, 'fast'); // also stop every animation if any is active
},
throwDice: function() {
var player = this.getActivePlayer();
player.dice.threw.dispatch(Math.floor(Math.random()*6+1));
},
catchDice: function() {
console.log('catch dice method');
var player = this.getActivePlayer();
player.dice.catched.dispatch();
}
}
$(function() {
// start game after DOM ready
var game = new DiceGame();
});
.playerInfo {
position: absolute;
top: 0px;
right: 10px;
border: 1px solid black;
width: 200px;
}
#gameInfo {
opacity: 0;
margin: 0 auto;
color: red;
text-align: center;
width: 300px;
height: 100px;
/* center div horizontally and vertically */
position:absolute;
left:50%;
top:50%;
margin:-50px 0 0 -150px;
border: 0px solid black;
background-color: #FAFFBF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore.js"></script>
<script src="https://cdn.rawgit.com/millermedeiros/js-signals/master/dist/signals.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="newGame">New Game</button>
<button id="addPlayer">New Player</button>
<!-- <button id="changePlayer">Change player</button> -->
<button id="throw">Throw dice</button>
<button id="catch">Catch dice</button>
<div class="playerInfo">
Active player: <span id="activePlayer"></span><br/>
Score: <span id="activePlayerScore"></span>
</div>
<div id="gameInfo"></div>
<div id="playField"></div>