如何聆听另一个物体的事件发射?

埃米尔

我正在尝试使用事件侦听器和排放来复制后院捕捞游戏。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');

如果我想扩展游戏范围以包括第三人怎么办(在这种情况下,投掷的目标只能是两个可能的接收者之一)

一只狼

我不完全了解您的游戏如何运作,因此我使用不同的游戏逻辑对游戏进行了编码。但是您可以轻松地根据需要进行调整。

游戏的工作原理如下:

每个玩家交替投掷两个骰子。第一个玩家1比玩家2掷骰子,依此类推。每个玩家可以随机抓取其他玩家的骰子。抓到的骰子被加到分数中,得分最高的玩家将赢得比赛。

现在到代码。起初,我没有看到您正在做一个nodeJs应用程序。但是我的前端应用程序应该可以通过一些调整在节点上运行。

我已将SignalsJS用于事件。您可以在此处找到示例

以下引用来自这里

信号类似于事件发射器/调度程序或发布/订阅系统,主要区别在于每种事件类型都有其自己的控制器,并且不依赖于字符串来广播/订阅事件

将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>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何聆听另一个物体的事件发射?

来自分类Dev

如何在另一个模块中使用事件发射器?

来自分类Dev

我如何让一个物理物体抵消另一个物理物体的碰撞。

来自分类Dev

如何判断一个物体是否在另一个物体的距离之内?

来自分类Dev

如何在另一个物体周围移动某个物体?

来自分类Dev

SpriteKit-计算一个物体击中另一个物体的次数

来自分类Dev

如何从另一个控件调用另一个控件的LostFocus事件

来自分类Dev

跟随另一个正在旋转的物体

来自分类Dev

如何将不可包裹的物体从一个活动传递到另一个活动?

来自分类Dev

如何将物体从一个碎片传递到另一个碎片?

来自分类Dev

另一个事件的stopPropagation()

来自分类Dev

Fancybox与另一个事件

来自分类Dev

绕着另一个物体旋转的物体不断加速

来自分类Dev

动态缩放堆叠在另一个物体上的物体

来自分类Dev

不能从一个孩子发射到另一个

来自分类Dev

传送后将一个物体移动到另一个物体上的同一点

来自分类Dev

如何使一个事件在另一个类中触发

来自分类Dev

检查一个物理物体是否在不等待didBeginContact的情况下接触另一个物体

来自分类Dev

只要对象在Phaser 3中与另一个物体发生碰撞,如何播放动画?

来自分类Dev

jQuery事件被另一个事件取代

来自分类Dev

点击事件触发另一个按钮事件

来自分类Dev

使事件取决于另一个事件的完成

来自分类Dev

如何从Timer.Elapsed事件中触发另一个事件?

来自分类Dev

ReactJS:如何从另一个事件触发表单提交事件

来自分类Dev

如何根据另一个事件的时间戳顺序找到最近的事件

来自分类Dev

如何从Timer.Elapsed事件中触发另一个事件?

来自分类Dev

jQuery如何在单击另一个事件时禁用滚动事件

来自分类Dev

如何从另一个单击事件函数内的单击事件调用函数?

来自分类Dev

如何为从另一个类引发的事件创建事件侦听器

Related 相关文章

  1. 1

    如何聆听另一个物体的事件发射?

  2. 2

    如何在另一个模块中使用事件发射器?

  3. 3

    我如何让一个物理物体抵消另一个物理物体的碰撞。

  4. 4

    如何判断一个物体是否在另一个物体的距离之内?

  5. 5

    如何在另一个物体周围移动某个物体?

  6. 6

    SpriteKit-计算一个物体击中另一个物体的次数

  7. 7

    如何从另一个控件调用另一个控件的LostFocus事件

  8. 8

    跟随另一个正在旋转的物体

  9. 9

    如何将不可包裹的物体从一个活动传递到另一个活动?

  10. 10

    如何将物体从一个碎片传递到另一个碎片?

  11. 11

    另一个事件的stopPropagation()

  12. 12

    Fancybox与另一个事件

  13. 13

    绕着另一个物体旋转的物体不断加速

  14. 14

    动态缩放堆叠在另一个物体上的物体

  15. 15

    不能从一个孩子发射到另一个

  16. 16

    传送后将一个物体移动到另一个物体上的同一点

  17. 17

    如何使一个事件在另一个类中触发

  18. 18

    检查一个物理物体是否在不等待didBeginContact的情况下接触另一个物体

  19. 19

    只要对象在Phaser 3中与另一个物体发生碰撞,如何播放动画?

  20. 20

    jQuery事件被另一个事件取代

  21. 21

    点击事件触发另一个按钮事件

  22. 22

    使事件取决于另一个事件的完成

  23. 23

    如何从Timer.Elapsed事件中触发另一个事件?

  24. 24

    ReactJS:如何从另一个事件触发表单提交事件

  25. 25

    如何根据另一个事件的时间戳顺序找到最近的事件

  26. 26

    如何从Timer.Elapsed事件中触发另一个事件?

  27. 27

    jQuery如何在单击另一个事件时禁用滚动事件

  28. 28

    如何从另一个单击事件函数内的单击事件调用函数?

  29. 29

    如何为从另一个类引发的事件创建事件侦听器

热门标签

归档