Coffescript回调&功能 [英] Coffescript Callbacks & Functions

查看:224
本文介绍了Coffescript回调&功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个功能,我试图使用两个大的函数组成的较小的和一个while循环。一个是当玩家转身时,一个是当对手的回合,一个是循环,当玩家赢了。当我在浏览器中运行它,按钮不做任何事情。什么是错?

  $ attackButtonClick =(opponent) - > 
如果playersTurn而不是player.Win
player.attack(opponent)
如果opponent.currentHealth< = 0
player.Win = true;
allOff()
postBattle(opponent)
else
playersTurn = false;
opponentTurn(opponent)

$ defendButtonClick =(opponent) - >
if playersTurn and not player.Win
player.defend()
appendToBattleOutputBox< p>你的防御已经翻了一番。< / p>
if opponent.currentHealth< = 0
player.Win = true;
allOff()
return postBattle(opponent)
else
playersTurn = false;
opponentTurn(opponent)

$ useItemButtonClick =(opponent) - >
如果playersTurn而不是player.Win
如果$ useItemSelection.html()。length> 15
itemBeingUsed = $(select [name ='useItemSelection'] option:selected)。text()
switch itemBeingUsed
当法术书
player.Items .bookOfSpells.use()
如果player.Items.bookOfSpells.effect是burn或player.Items.bookOfSpells.effect是poison
appendToBattleOutputBox< p& Items.bookOfSpells.effect} ed#{opponent.Name}。< / p>
如果player.Items.bookOfSpells.effect是burn
opponent.Burned = true;
else
opponent.Poisoned = true;
else
appendToBattleOutputBox< p>您已冻结#{opponent.Name}。< / p>
opponent.Frozen = true;
player.Items.bookOfSpells.used = true;
当Shield Charm
if(player.Items.shieldCharm.used is false)
player.Items.shieldCharm.use()
appendToBattleOutputBox< p&阻止下一次攻击你的盾牌魅力。< / p>
player.Items.shieldCharm.used = true;
当正常药水时
player.Items.normalPotion.use()
如果opponent.currentHealth< = 0
player.Win = true;
allOff()
postBattle(opponent)
else
playersTurn = false;
opponentTurn(opponent)
else
noUsableItemP = $(< p id ='noUsableItemP'>您没有可用的项目,请选择其他命令< / p>)
$ battleCommandPromptDiv.empty()
$ battleCommandPromptDiv.append(noUsableItemP)

battle =(opponent) - >
console.log(p)
appendToBattleOutputBox< p>你做第一个动作!< / p>
battleInProgress = yes;
playersTurn = true;
playerTurn =(opponent) - >
$ attackButton.click - > $ attackButtonClick(opponent)

$ defendButton.click - > $ defendButtonClick(opponent)

$ useItemButton.click - > $ useItemButtonClick(opponent)

status.Poison(opponent,opponent)if opponent.Poisoned
status.Burn(opponent,opponent)if opponent.Burned
status 。如果对手冻结(对手,对手)。冻结
opponent.undefend()if opponent.defenseDoubled or opponent.defenseTripled
refresh(opponent)

opponentTurn = ) - >
如果不是playersTurn而不是player.Win
如果rndmNumber(10)> 5
thisTurnAttack = opponent.attack(opponent.Attack,opponent.Luck)
player.currentHealth - = thisTurnAttack
refresh(opponent)
如果thisTurnAttack为0,则appendToBattleOutputBox< p class ='right'>您已阻止攻击。< / p> else appendToBattleOutputBox< p class ='right'>#{thisTurnAttack}损害。< / p>
else
opponent.defend()
appendToBattleOutputBox< p class ='right'>#{opponent.Name}已经使他的防守加倍了一回合。< / p&
player.undefend()if player.defenseDoubled or player.defenseTripled
player.Poisoned = true if(opponent.Type isSnakeand rndmNumber(10)> 7)
player。 Burned = true if(opponent.Name isSalamanderand rndmNumber(10)> 3)或opponent.Name是Fire Dragon
player.Frozen = true if(opponent.Name是Penguinand rndmNumber (10)> 5)或(opponent.Name是Wolf和rndmNumber(10)> 6)或(opponent.Name是Polar Bear和rndmNumber(10)> 4)
状态。 Poison(player)if player.Poisoned
status.Burn(player)if player.Burned
status.Freeze(player)if player.Frozen
if player.currentHealth < = 0 then postBattle(opponent)else playerTurn(opponent)
playersTurn = true;

playerTurn(opponent)

while(player.Win is true)
player.Win is false;
postBattle(opponent)

忽略分号后的true和false。我知道他们不应该在那里。






UPDATE



现在我的问题是,当我尝试调用 opponentTurn 它没有定义。我试着找一种方法来在Coffeescript中提升一个函数,但是没有找到任何东西。有没有办法提升函数或只是另一种方式来订购代码?

  $ attackButtonClick =(opponent) - > 
console.log(playersTurn)
如果playersTurn而不是player.Win
player.attack(对手)
如果opponent.currentHealth< = 0
player.Win = true;
allOff()
postBattle(opponent)
else
playersTurn = false;
opponentTurn(opponent)

$ defendButtonClick =(opponent) - >
if playersTurn and not player.Win
player.defend()
appendToBattleOutputBox< p>你的防御已经翻了一番。< / p>
if opponent.currentHealth< = 0
player.Win = true;
allOff()
return postBattle(opponent)
else
playersTurn = false;
opponentTurn(opponent)

$ useItemButtonClick =(opponent) - >
如果playersTurn而不是player.Win
如果$ useItemSelection.html()。length> 15
itemBeingUsed = $(select [name ='useItemSelection'] option:selected)。text()
switch itemBeingUsed
当Book of Spells时
player.Items .bookOfSpells.use()
如果player.Items.bookOfSpells.effect是burn或player.Items.bookOfSpells.effect是poison
appendToBattleOutputBox< p>你有#{player。 Items.bookOfSpells.effect} ed#{opponent.Name}。< / p>
如果player.Items.bookOfSpells.effect是burn
opponent.Burned = true;
else
opponent.Poisoned = true;
else
appendToBattleOutputBox< p>您已冻结#{opponent.Name}。< / p>
opponent.Frozen = true;
player.Items.bookOfSpells.used = true;
当Shield Charm
if(player.Items.shieldCharm.used is false)
player.Items.shieldCharm.use()
appendToBattleOutputBox< p&阻止下一次攻击你的盾牌魅力。< / p>
player.Items.shieldCharm.used = true;
当正常药水时
player.Items.normalPotion.use()
如果opponent.currentHealth< = 0
player.Win = true;
allOff()
postBattle(opponent)
else
playersTurn = false;
opponentTurn(opponent)
else
noUsableItemP = $(< p id ='noUsableItemP'>您没有可用的项目,请选择其他命令< / p>)
$ battleCommandPromptDiv.empty()
$ battleCommandPromptDiv.append(noUsableItemP)

battle =(opponent) - >
appendToBattleOutputBox< p>您进行第一步!< / p>
battleInProgress = yes;
playerTurn =(opponent) - >
$ attackButton.click - > $ attackButtonClick(opponent)

$ defendButton.click - > $ defendButtonClick(opponent)

$ useItemButton.click - > $ useItemButtonClick(opponent)

status.Poison(opponent,opponent)if opponent.Poisoned
status.Burn(opponent,opponent)if opponent.Burned
status 。如果对手冻结(对手,对手)。冻结
opponent.undefend()if opponent.defenseDoubled or opponent.defenseTripled
refresh(opponent)

opponentTurn = ) - >
如果不是playersTurn而不是player.Win
如果rndmNumber(10)> 5
thisTurnAttack = opponent.attack(opponent.Attack,opponent.Luck)
player.currentHealth - = thisTurnAttack
refresh(opponent)
如果thisTurnAttack为0,那么appendToBattleOutputBox< p class ='right'>您已阻止攻击。< / p> else appendToBattleOutputBox< p class ='right'>#{thisTurnAttack}损害。< / p>
else
opponent.defend()
appendToBattleOutputBox< p class ='right'>#{opponent.Name}已经使他的防守加倍了一回合。< / p&
player.undefend()if player.defenseDoubled or player.defenseTripled
player.Poisoned = true if(opponent.Type isSnakeand rndmNumber(10)> 7)
player。 Burned = true if(opponent.Name isSalamanderand rndmNumber(10)> 3)或opponent.Name是Fire Dragon
player.Frozen = true if(opponent.Name是Penguinand rndmNumber (10)> 5)或(opponent.Name是Wolf和rndmNumber(10)> 6)或(opponent.Name是Polar Bear和rndmNumber(10)> 4)
状态。 Poison(player)if player.Poisoned
status.Burn(player)if player.Burned
status.Freeze(player)if player.Frozen
if player.currentHealth < = 0 then postBattle(opponent)else playerTurn(opponent)
playersTurn = true;

playerTurn(opponent)

while(player.Win is true)
player.Win is false;
postBattle(opponent)

忽略分号后的true和false。我知道他们不应该在那里。

解决方案

没有简单的方法来解释这个。你从根本上误解了Javascript(和扩展Coffeescript)的工作原理。



Javascript是一种异步语言,不会阻止io。当你做这样的事情

  while(playerTurn is true and player.Win is false)
$ attackButton.click - >
player.attack(opponent)
...

一个循环,它注册一个click事件的回调,然后再次运行该循环。这是发生,几百,可能几千次,因为你的while循环的性质。这是为什么你的浏览器崩溃了。



一个检查这种事情的好方法是使用console.log调试语句,这样你就可以



您需要重构游戏的逻辑,这样才能看到您的代码的不同部分通过查看控制台中打印输出的数量输入多久。而不是在while循环并等待阻塞条件发生;你有一组函数在事件发生时互相调用。



我会建议的是这样的:

  attack =  - > 
#条件转到这里
如果playerTurn而不是player.Win
player.attack(对手)
如果opponent.currentHealth< = 0
player.Win = true
allOff()
回调函数中不需要返回语句
postBattle(opponent)
else
playerTurn = false;

#不在while循环中
$ attackButton.click攻击

你可以使用这个模型为你的游戏中的任何事件,例如按钮点击或更改的条件等。



> Coffeescript不支持函数提升,所以你在这里只有两个选项。尝试解开代码,以便可以按照不需要使用尚未定义的函数的方式编写代码,,因为我更喜欢使用 Livescript



Livescript与Coffeescript有很多兼容性,它带来了很多有用的功能到具有类似语法的表。其中一个特点是功能提升。您的悬挂函数将声明如下:

  function opponentTurn(opponent)
...
#而不是
opponentTurn =(opponent) - >
...

这将分别编译到

  function opponentTurn(opponent){
...
}

var opponentTurn;
opponentTurn = function(opponent){
...
};

我不能推荐Livescript作为Coffeescript的替代品。



http://livescript.net/ blog / ten-reasons-to-switch-from-coffeescript.html


I have this function and I am trying to use two large functions made up of smaller ones and one while loops. One for when it's the players turn, one when it's the opponent's turn, and a while loop when the player has won. When I run it in the browser, the buttons do not do anything. What is wrong?

$attackButtonClick = (opponent) ->
    if playersTurn and not player.Win
        player.attack(opponent)
        if opponent.currentHealth <= 0
            player.Win = true;
            allOff()
            postBattle(opponent)
        else 
            playersTurn = false;
            opponentTurn(opponent)

$defendButtonClick = (opponent) ->
    if playersTurn and not player.Win
        player.defend()
        appendToBattleOutputBox "<p>Your defense has been doubled for one turn.</p>"
        if opponent.currentHealth <= 0
            player.Win = true;
            allOff()
            return postBattle(opponent)
        else 
            playersTurn = false;
            opponentTurn(opponent)

$useItemButtonClick = (opponent) ->
    if playersTurn and not player.Win
        if $useItemSelection.html().length > 15
            itemBeingUsed = $("select[name='useItemSelection'] option:selected").text()
            switch itemBeingUsed
                when "Book of Spells"
                    player.Items.bookOfSpells.use()
                    if player.Items.bookOfSpells.effect is "burn" or player.Items.bookOfSpells.effect is "poison"
                        appendToBattleOutputBox "<p>You have #{player.Items.bookOfSpells.effect}ed #{opponent.Name}.</p>"
                        if player.Items.bookOfSpells.effect is "burn"
                            opponent.Burned = true;
                        else
                            opponent.Poisoned = true;
                    else
                        appendToBattleOutputBox "<p>You have frozen #{opponent.Name}.</p>"
                        opponent.Frozen = true;
                    player.Items.bookOfSpells.used = true;
                when "Shield Charm"
                    if (player.Items.shieldCharm.used is false)
                        player.Items.shieldCharm.use()
                        appendToBattleOutputBox "<p>You will block the next attack with you shield charm.</p>"
                        player.Items.shieldCharm.used = true;
                when "Normal Potion"
                    player.Items.normalPotion.use()
            if opponent.currentHealth <= 0
                player.Win = true;
                allOff()
                postBattle(opponent)
            else 
                playersTurn = false;
                opponentTurn(opponent)
        else 
            noUsableItemP = $("<p id='noUsableItemP'>You have no usable items. Select another command.</p>")
            $battleCommandPromptDiv.empty()
            $battleCommandPromptDiv.append(noUsableItemP)

battle = (opponent) ->
    console.log(p)
    appendToBattleOutputBox "<p>You make the first move!</p>"
    battleInProgress = yes;
    playersTurn = true;
    playerTurn = (opponent) ->
        $attackButton.click -> $attackButtonClick(opponent)

        $defendButton.click -> $defendButtonClick(opponent)

        $useItemButton.click -> $useItemButtonClick(opponent)

        status.Poison("opponent", opponent) if opponent.Poisoned
        status.Burn("opponent", opponent) if opponent.Burned
        status.Freeze("opponent", opponent) if opponent.Frozen
        opponent.undefend() if opponent.defenseDoubled or opponent.defenseTripled
        refresh(opponent)

    opponentTurn = (opponent) ->
        if not playersTurn and not player.Win
            if rndmNumber(10) > 5
                thisTurnAttack = opponent.attack(opponent.Attack, opponent.Luck)
                player.currentHealth -= thisTurnAttack
                refresh(opponent)
                if thisTurnAttack is 0 then appendToBattleOutputBox "<p class='right'>You have blocked the attack.</p>" else appendToBattleOutputBox "<p class='right'>#{thisTurnAttack} damage has been inflicted upon you.</p>"
            else 
                opponent.defend()
                appendToBattleOutputBox "<p class='right'>#{opponent.Name} has doubled his defense for one turn.</p>"
            player.undefend() if player.defenseDoubled or player.defenseTripled
            player.Poisoned = true if (opponent.Type is "Snake" and rndmNumber(10) > 7)
            player.Burned = true if (opponent.Name is "Salamander" and rndmNumber(10) > 3) or opponent.Name is "Fire Dragon"
            player.Frozen = true if (opponent.Name is "Penguin" and rndmNumber(10) > 5) or (opponent.Name is "Wolf" and rndmNumber(10) > 6) or (opponent.Name is "Polar Bear" and rndmNumber(10) > 4)
            status.Poison("player") if player.Poisoned
            status.Burn("player") if player.Burned
            status.Freeze("player") if player.Frozen
            if player.currentHealth <= 0 then postBattle(opponent) else playerTurn(opponent)
            playersTurn = true;

    playerTurn(opponent)

    while (player.Win is true)
        player.Win is false;
        postBattle(opponent)

P.S. disregard the semicolons after true and false. I know they aren't supposed to be there.


UPDATE

Now my problem is that when I try calling opponentTurn it is not defined. I have tried looking up a way to hoist a function in Coffeescript, but have found nothing. Is there a way to hoist the function or just another way to order the code?

$attackButtonClick = (opponent) ->
    console.log(playersTurn)
    if playersTurn and not player.Win
        player.attack(opponent)
        if opponent.currentHealth <= 0
            player.Win = true;
            allOff()
            postBattle(opponent)
        else 
            playersTurn = false;
            opponentTurn(opponent)

$defendButtonClick = (opponent) ->
    if playersTurn and not player.Win
        player.defend()
        appendToBattleOutputBox "<p>Your defense has been doubled for one turn.</p>"
        if opponent.currentHealth <= 0
            player.Win = true;
            allOff()
            return postBattle(opponent)
        else 
            playersTurn = false;
            opponentTurn(opponent)

$useItemButtonClick = (opponent) ->
    if playersTurn and not player.Win
        if $useItemSelection.html().length > 15
            itemBeingUsed = $("select[name='useItemSelection'] option:selected").text()
            switch itemBeingUsed
                when "Book of Spells"
                    player.Items.bookOfSpells.use()
                    if player.Items.bookOfSpells.effect is "burn" or player.Items.bookOfSpells.effect is "poison"
                        appendToBattleOutputBox "<p>You have #{player.Items.bookOfSpells.effect}ed #{opponent.Name}.</p>"
                        if player.Items.bookOfSpells.effect is "burn"
                            opponent.Burned = true;
                        else
                            opponent.Poisoned = true;
                    else
                        appendToBattleOutputBox "<p>You have frozen #{opponent.Name}.</p>"
                        opponent.Frozen = true;
                    player.Items.bookOfSpells.used = true;
                when "Shield Charm"
                    if (player.Items.shieldCharm.used is false)
                        player.Items.shieldCharm.use()
                        appendToBattleOutputBox "<p>You will block the next attack with you shield charm.</p>"
                        player.Items.shieldCharm.used = true;
                when "Normal Potion"
                    player.Items.normalPotion.use()
            if opponent.currentHealth <= 0
                player.Win = true;
                allOff()
                postBattle(opponent)
            else 
                playersTurn = false;
                opponentTurn(opponent)
        else 
            noUsableItemP = $("<p id='noUsableItemP'>You have no usable items. Select another command.</p>")
            $battleCommandPromptDiv.empty()
            $battleCommandPromptDiv.append(noUsableItemP)

battle = (opponent) ->
    appendToBattleOutputBox "<p>You make the first move!</p>"
    battleInProgress = yes;
    playerTurn = (opponent) ->
        $attackButton.click -> $attackButtonClick(opponent)

        $defendButton.click -> $defendButtonClick(opponent)

        $useItemButton.click -> $useItemButtonClick(opponent)

        status.Poison("opponent", opponent) if opponent.Poisoned
        status.Burn("opponent", opponent) if opponent.Burned
        status.Freeze("opponent", opponent) if opponent.Frozen
        opponent.undefend() if opponent.defenseDoubled or opponent.defenseTripled
        refresh(opponent)

    opponentTurn = (opponent) ->
        if not playersTurn and not player.Win
            if rndmNumber(10) > 5
                thisTurnAttack = opponent.attack(opponent.Attack, opponent.Luck)
                player.currentHealth -= thisTurnAttack
                refresh(opponent)
                if thisTurnAttack is 0 then appendToBattleOutputBox "<p class='right'>You have blocked the attack.</p>" else appendToBattleOutputBox "<p class='right'>#{thisTurnAttack} damage has been inflicted upon you.</p>"
            else 
                opponent.defend()
                appendToBattleOutputBox "<p class='right'>#{opponent.Name} has doubled his defense for one turn.</p>"
            player.undefend() if player.defenseDoubled or player.defenseTripled
            player.Poisoned = true if (opponent.Type is "Snake" and rndmNumber(10) > 7)
            player.Burned = true if (opponent.Name is "Salamander" and rndmNumber(10) > 3) or opponent.Name is "Fire Dragon"
            player.Frozen = true if (opponent.Name is "Penguin" and rndmNumber(10) > 5) or (opponent.Name is "Wolf" and rndmNumber(10) > 6) or (opponent.Name is "Polar Bear" and rndmNumber(10) > 4)
            status.Poison("player") if player.Poisoned
            status.Burn("player") if player.Burned
            status.Freeze("player") if player.Frozen
            if player.currentHealth <= 0 then postBattle(opponent) else playerTurn(opponent)
            playersTurn = true;

    playerTurn(opponent)

    while (player.Win is true)
        player.Win is false;
        postBattle(opponent)

P.S. disregard the semicolons after true and false. I know they aren't supposed to be there.

解决方案

There's no easy way to explain this. You've fundamentally misunderstood how Javascript (and by extension Coffeescript) works.

Javascript is an asynchronous language which doesn't block on io. When you do things like this

while (playerTurn is true and player.Win is false)
    $attackButton.click ->
        player.attack(opponent)
        ...

You're entering a loop which registers a callback for a click event and then runs the loop again. This is happening, hundreds, probably thousands of times because of the nature of your while loop. That's why your browser has crashed.

A good way to check this kind of thing out is to use debugging statements with console.log, this way you'll be able to see how often different sections of your code are being entered by looking at the number of printed outputs in your console.

You need to restructure the logic of your game, so that rather than doing while loops and waiting for blocking conditions to happen; you have a set of functions that call each other when events take place.

What I would suggest is something like this:

attack = ->
  # conditions go here instead
  if playerTurn and not player.Win
    player.attack(opponent)
    if opponent.currentHealth <= 0
      player.Win = true
      allOff()
      # return statements aren't needed inside callback functions
      postBattle(opponent)
    else 
      playerTurn = false;

# not inside a while loop
$attackButton.click attack

You can use this model for any 'event' in your game e.g. a button click or a changed condition etc.


UPDATE

Coffeescript doesn't support function hoisting, so you've only really got two options here. Try to untangle your code so that you can write it out in fashion that doesn't require using functions that haven't yet been defined, or as I prefer to do, use Livescript.

Livescript has a lot of compatibility with Coffeescript and it brings a lot of useful features to the table with a similar syntax. One of the features is function hoisting. Your hoisted function would be declared like this:

function opponentTurn (opponent)
  ...
# rather than
opponentTurn = (opponent) ->
  ... 

Which will respectively compile to

function opponentTurn(opponent){
  ...
}

var opponentTurn;
opponentTurn = function(opponent){
  ...
};

I couldn't recommend Livescript enough as an alternative to Coffeescript.

http://livescript.net/blog/ten-reasons-to-switch-from-coffeescript.html

这篇关于Coffescript回调&amp;功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆