質問

I started making a game using Java. I am currently working on a basic enemy that will fire in range and when it fires I want it to wait for x seconds and fire 3 bullets at a rate of y.

So I decided to use a Timer to create this delay:

public class DelayFire
{
    Toolkit toolkit;

    Timer timer;
    //The enemy firing
    Enemy com;

    public DelayFire(double seconds, Enemy e, boolean un)
    {
        toolkit = Toolkit.getDefaultToolkit();
        timer = new Timer();
        com = e;
        timer.schedule(new FireTask(un), (int) seconds * 1000);
    }

    class FireTask extends TimerTask
    {
        public boolean unfire = false;

        public FireTask (boolean x)
        {
            this.unfire = x;
        }

        public void run()
        {
            if(com.health>0)
            {
                com.charging = false;
                com.fire();
                if(unfire==true)
                {
                    com.fire = false;
                    com.canFire = true;
                }
                this.cancel();
            }
        }
    }
}

Then which I call in Enemy class it 3 times each with a different delay:

void spray()
{
    new DelayFire(2.0,this,false);
    new DelayFire(2.5,this,false);
    new DelayFire(3.0,this,true);
}

This void is called when ever the player is in firing range (This is also in the Enemy class):

if(canFire==true && fire==false)
{
    spray();
    canFire = false;
    fire = true;
}

Yet after all this work it will only create two bullets once I'm within range. Until I leave and re-enter the enemy's sight again.

Note: I only put the parts of my code where I would expect some mistake is made. Let me know if you need to see more code.

役に立ちましたか?

解決

Are you absolutely sure only two bullets are fired? You can try inserting System.out.println("Hello, Bullet World!") in the run() method of FireTask. You might be surprised to find that the line will print three times.

What you're experiencing is the associativity of casts. Consider this part of your code:

(int) seconds * 1000

Since seconds is a double, and you want an int (or perhaps a long), it's natural that you'll want to cast it. However, the cast does not cast the entire expression seconds * 1000 to an int - just seconds. Next, consider your instantiations of your DelayFire class:

new DelayFire(2.0,this,false);
new DelayFire(2.5,this,false);
new DelayFire(3.0,this,true);

Here, you use the double values 2.0, 2.5, and 3.0. However, the 2.5 is casted to an int before the multiplication, causing it to become a flat 2. As a result, your program will schedule two bullets to be fired after 2 seconds, and one bullet to be fired after 3 seconds.

To get around this problem, stick some parentheses around the entire expression with the multiplication in it:

(int) (seconds * 1000)

This should result in the correct behavior. There may be other bugs in your code, though. But try that first.

Edit: As a side note, the conditions in your if-statements are overcomplicated. You are basically turning a boolean-valued expression into another boolean-valued expression by writing if (unfire == true). Since unfire is a boolean expression, there is no need for the == operator. You can simply write if (unfire). And instead of checking if the value is false, use the unary !-operator to negate the expression, if (!unfire).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top