actionscript-3flashactionscriptactionscript-2

Flash actionscript: moneycounter code not behaving correctly


I am trying to set up a virtual bus fare vending machine in Adobe Flash (Animate) animation.

The premise is that you must enter exact fare into the slot because drivers don't carry change. Exact fare is $2. The machine accepts denominations of 5 cents, 10 cents, 25 cents, $1, $5, $10 and $20. If anything over $2 is entered, a message pops up saying the "Exact fare only please. Drivers cannot provide change." So in this case, only the 5 cent, 10 cent, 25 cent and $1 denominations will work, but they must be entered to add up to exactly $2.

The code below works correctly for the 25 cent and $1 denominations alone and in combination, but works erratically when 5 cent and 10 cent are used alone or included in combination with the 25 cent and $1. For example, if you try reach $2 by only using the dimes, the total reaches $1.90 but does not payout the fare when you enter the final 10 cents. Instead the pop up "Exact fare only please" message is triggered. If you then add a nickel, the total reaches $1.95 but again will not payout the fare when you enter the final nickel. Instead the pop up "Exact fare only please." message is triggered again.

Entering $1 and then another $1 works perfectly. Entering 8 quarters works as well as does entering $1 and 4 quarters. Can't figure out what the problem is. Would appreciate any help. Thanks!

Code is below:

var Cash = 00.00
var payola = Money.text = "02.00";
Money.text = "$" + Cash.toFixed(2);
popup.visible = false;


nickel_btn.addEventListener(MouseEvent.CLICK, add5cents);

function add5cents(event:MouseEvent):void
{
    nickelcoin_mc.gotoAndPlay ("nickel_pay"); 
    Cash+=00.05;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        nickelcoin_mc.gotoAndPlay ("nickel_nopay");
        Cash-=00.05;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}

dime_btn.addEventListener(MouseEvent.CLICK, add10cents);

function add10cents(event:MouseEvent):void
{
    dimecoin_mc.gotoAndPlay ("dime_pay"); 
    Cash+=00.10;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        dimecoin_mc.gotoAndPlay ("dime_nopay");
        Cash-=00.10;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}

quarter_btn.addEventListener(MouseEvent.CLICK, add25cents);

function add25cents(event:MouseEvent):void
{
    quartercoin_mc.gotoAndPlay ("quarter_pay"); 
    Cash+=00.25;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        quartercoin_mc.gotoAndPlay ("quarter_nopay");
        Cash-=00.25;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}

one_btn.addEventListener(MouseEvent.CLICK, add$1);

function add$1(event:MouseEvent):void
{
    onebill_mc.gotoAndPlay ("one_pay"); 
    Cash+=01.00;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        onebill_mc.gotoAndPlay ("one_nopay");
        Cash-=01.00;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}

five_btn.addEventListener(MouseEvent.CLICK, add$5);

function add$5(event:MouseEvent):void
{
    fivebill_mc.gotoAndPlay ("five_pay"); 
    Cash+=05.00;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        fivebill_mc.gotoAndPlay ("five_nopay");
        Cash-=05.00;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}

ten_btn.addEventListener(MouseEvent.CLICK, add$10);

function add$10(event:MouseEvent):void
{
    tenbill_mc.gotoAndPlay ("ten_pay"); 
    Cash+=10.00;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        tenbill_mc.gotoAndPlay ("ten_nopay"); 
        Cash-=10.00;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}

twenty_btn.addEventListener(MouseEvent.CLICK, add$20);

function add$20(event:MouseEvent):void
{
    twentybill_mc.gotoAndPlay ("twenty_pay"); 
    Cash+=20.00;
    Money.text = "$" + Cash.toFixed(2);
    if(Cash == payola){
      setTimeout(delay, 500);
      function delay(){
        gotoAndStop(46);
        }
    }
    if(Cash > payola){
        twentybill_mc.gotoAndPlay ("twenty_nopay");
        Cash-=20.00;
        Money.text = "$" + Cash.toFixed(2);
        popup.visible = true;
    }
    else {
        popup.visible = false;
    }
}


stop();

Solution

  • This could be a problem caused by floating point numbers. Try putting this in your code and check the console output:

    // Expect result to be 0.1
    trace(0.3-0.2);
    

    0.09999999999999998

    // Adding lots of 5 cent coins. Expect result to be 0.5
    trace(0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05);
    

    0.49999999999999994

    Your == comparison is failing sometimes because adding floating point numbers together can result in unexpected values. This answer explains the problem well: https://stackoverflow.com/a/3730040/11678918

    For your case, try changing your Cash variable into an int, and store the cents instead of the dollars:

    var Cash:int = 0;
    var payola:int = 200; // 2 dollars
    
    // Add 5 cents
    Cash += 5;
    
    // Adding 1 dollar
    Cash += 100;
    
    // Printing out the amount in dollars and cents
    Money.text = "$" + (Cash / 100).toFixed(2);
    
    // Our exact check is safe now that we avoid floats.
    if(Cash == payola) { ... }