Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm creating a bullet shooter much in the style of Touhou. Right now I want to have a very simple circular shot being fired from the enemy.

See this picture:

As you can see, the spacing is very uneven, which isn't very good if you want to survive.

The code I'm using is this:

private function shoot() : void
{
    const BULLETS_PER_WAVE : int = 72;
    var interval : Number = BULLETS_PER_WAVE / 360;

    for (var i : int = 0; i < BULLETS_PER_WAVE; ++i)
    {
        var xSpeed : Number = GameConstants.BULLET_NORMAL_SPEED_X * Math.sin(i * interval);
        var ySpeed : Number = GameConstants.BULLET_NORMAL_SPEED_Y * Math.cos(i * interval);

        BulletFactory.createNormalBullet(bulletColor_, alice_.center, xSpeed, ySpeed);
    }

    canShoot_ = false;
    cooldownTimer_.start();
}

I imagine my mistake is in the sin, cos functions, but I'm not entirely sure what's wrong.

share|improve this question
    
How did a typing error get into your code snippet? Didn't you copy paste from your editor after confirming that the code compiles? –  eBusiness Nov 13 '11 at 18:34
2  
This is not a math answer but BulletML will help you define and store barrage of bullets in XML: asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html –  BrandFeelsGood Nov 14 '11 at 4:06
    
@eBusiness: What typing error? The code compiles just fine. –  IAE Nov 14 '11 at 6:22
    
@SoulBeaver Without the end bracket on line 6, no it doesn't, so of course it is there in your code, but why didn't it make it to the question? –  eBusiness Nov 14 '11 at 6:30
    
@eBusiness: I have absolutely no idea what happened there. I might have made a mistake while indenting and formatting the code to look right on GameDev, but I have no other explanation xD Fixed now, thanks. –  IAE Nov 14 '11 at 13:11
show 2 more comments

5 Answers 5

up vote 13 down vote accepted

Golden rule when working with any kind of angle: Make sure you are using the correct unit. In this case, you should be using radians, not degrees.

Math.sin(i * interval * Math.PI / 180);
Math.cos(i * interval * Math.PI / 180);

If you want to fire bullets directly between boss and player, use atan2, FYI.

share|improve this answer
    
Why are Radians better than degrees? –  ashes999 Nov 14 '11 at 0:48
    
Because you're dividing by 360. You're essentially spinning around the circle hundreds of times, that's why it's not even. –  UltimateBrent Nov 14 '11 at 4:57
1  
Radians are necessary for trig function calls in AS3. But as for why they're better mathematically (and hence why many languages opt for them), that's because radians relate directly the value of pi, which is a universal mathematical constant. Whereas degrees are a man-made construct, so an extra level of indirection is involved in processing (which is the * or / Math.PI/180 you see out in the open there -- if it's not included in the base trig functions, you have to do it yourself to convert to and from degrees). –  Nick Wiggill Nov 14 '11 at 12:00
1  
Sine and Cosine are calculated as series of fractions, in their simplest form these series take radians as input. Only by introducing a constant based on π can these series be used with degrees. I'd advice that you skip degrees altogether for internal representation, radians may take a little getting used to, but in the long run it is easier to not have to convert all the time. –  eBusiness Nov 14 '11 at 15:32
    
Fun radians trivia: If you have a circle with a one meter radius, and you walk along an n radian arc of that circle, you would have travelled a distance of precisely n meters, and the sector of the circle defined by that walk has an area of precisely **n**/2 square meters. Radians are awesome. –  Trevor Powell Nov 16 '11 at 1:04
show 1 more comment

You are doing the division the wrong way round, and you are using degrees rather than radians, like the maths functions do. By chance this results in a pattern that look a bit like the desired. Just fix your calculation of the interval variable.

var interval : Number = 2 * Math.PI / BULLETS_PER_WAVE;

Edit: For those not familiar with the concept this code produce the desired angle between bullets in radians, thus enabling leaving the calculation of xSpeed and ySpeed as it is with no further constants applied.

share|improve this answer
    
+1 True. He should compute period = 2 * pi of sin/cos functions and then interval = period / BULLETS_PER_WAVE. –  user712092 Nov 16 '11 at 1:02
add comment

I think you should do 360 / BULLETS_PER_WAVE instead which gives in your case 360 / 72 = 5 degrees between each bullet. Also are you sure that the Math.sin and Math.cos functions wants their input in degrees and not radians?

share|improve this answer
add comment

While you have been answered, here is a funnier answer : learn from nature.

Use the golden ratio instead.

const GOLDEN_RATIO : Number = 1.618033989;
var interval : Number = 2 * Math.PI * GOLDEN_RATIO;

See : http://www.mathsisfun.com/numbers/nature-golden-ratio-fibonacci.html

share|improve this answer
1  
+1 cool, I like this idea. Thanks. –  user712092 Nov 16 '11 at 0:59
    
Now, if you put a small delay between each shot it's going to be a really beautiful pattern. –  eBusiness Nov 16 '11 at 7:20
    
@Klems: Awesome! I'm totally using this for my next pattern :3 –  IAE Nov 16 '11 at 16:28
    
You're welcome :) I fucked the formulae but you get the point. You may want to compute it instead of using a floating point number. The exact ratio is (1 + sqrt(5)) / 2 –  Klems Nov 16 '11 at 17:43
add comment

Apart from possible degree/radian issue, I reckon the main problem is that you're using integer values for the calculations. You haven't shown GameConstants.BULLET_NORMAL_SPEED_X or its Y counterpart but make sure they are represented as floating point numbers, not integers. Alternatively, cast them into floating point values during the multiplication for the speed calculation.

share|improve this answer
    
The values are autocast. I'm not familiar enough with Actionscript to call every single case, but in this case I'm pretty sure that is not the problem. –  eBusiness Nov 13 '11 at 13:48
    
I don't think they're being cast properly. Look at the 2 circles closest to the character, above and to the right of it. Those 2, and every single circle in both of those rays, have identical Y values to the one in the other ray, which is not what you'd expect if the Y increments were a floating point value. –  Kylotan Nov 13 '11 at 17:12
    
You are right, there is some problem with values getting rounded, but I don't think it is visible in the posted code snippet, anything that could go bad there would result in a 0 and thus produce nothing that looks remotely like a circle. It must be a problem further down the chain, probably some variable that should have been number is instead declared int. –  eBusiness Nov 13 '11 at 18:30
    
+1: I forgot to specify the type of BULLET_X so AS defaulted it to an int. Oops. –  IAE Nov 14 '11 at 6:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.