A propagação circular de balas não é uniforme

7

Estou criando um atirador de balas muito ao estilo de Touhou. No momento, quero ter um tiro circular muito simples sendo disparado do inimigo.

No entanto, o espaçamento é muito desigual, o que não é muito bom se você quiser sobreviver.

O código que estou usando é o seguinte:

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();
}

Imagino que meu erro esteja nas funções sin& cos, mas não tenho certeza do que está errado.

IAE
fonte
Como um erro de digitação entrou no seu snippet de código? Você não copiou a pasta do seu editor depois de confirmar que o código é compilado?
Aaaaaaaaaaaa
2
Esta não é uma resposta matemática, mas BulletML irá ajudá-lo a definir e armazenar rajada de balas em XML: asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html
BrandFeelsGood
@eBusiness: Que erro de digitação? O código compila perfeitamente.
IAE
@SoulBeaver Sem o suporte final na linha 6, não existe, então é claro que existe no seu código, mas por que não chegou à pergunta?
aaaaaaaaaaaa 14/11
@eBusiness: Não faço a menor idéia do que aconteceu lá. Eu posso ter cometido um erro ao recuar e formatar o código para ficar bem no GameDev, mas não tenho outra explicação xD Fixed now, thanks.
IAE

Respostas:

13

Regra de ouro ao trabalhar com qualquer tipo de ângulo: verifique se você está usando a unidade correta. Nesse caso, você deve usar radianos, não graus.

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

Se você quiser disparar balas diretamente entre o chefe e o jogador, use atan2FYI.

Engenheiro
fonte
Por que os radianos são melhores que os graus?
ashes999
Porque você está dividindo por 360. Você está basicamente girando em torno do círculo centenas de vezes, é por isso que nem é igual.
UltimateBrent
11
Os radianos são necessários para chamadas de função trigonométrica no AS3. Mas, por que eles são melhores matematicamente (e, portanto, por que muitas línguas optam por eles), isso ocorre porque os radianos relacionam diretamente o valor de pi, que é uma constante matemática universal. Considerando graus são uma construção feita pelo homem, assim que um nível extra de engano está envolvido no processamento (que é o *ou / Math.PI/180você vê a céu aberto lá - se não está incluída nas funções de base trig, você tem que fazê-lo sozinho para converter de e para graus).
Engenheiro
11
Seno e cosseno são calculados como séries de frações; em sua forma mais simples, essas séries recebem radianos como entrada. Somente introduzindo uma constante com base em π essas séries podem ser usadas com graus. Eu aconselho que você pule completamente os graus para representação interna, os radianos podem demorar um pouco para se acostumar, mas a longo prazo, é mais fácil não ter que converter o tempo todo.
Aaaaaaaaaaaa
Curiosidades divertidas sobre radianos: se você tem um círculo com um raio de um metro e caminha ao longo de um arco n radiano desse círculo, percorreu uma distância de precisamente n metros, e o setor do círculo definido por esse passeio tem uma área de precisamente ** n ** / 2 metros quadrados. Radianos são incríveis.
Trevor Powell
7

Você está fazendo a divisão da maneira errada e está usando graus em vez de radianos, como fazem as funções matemáticas. Por acaso, isso resulta em um padrão que se parece um pouco com o desejado. Apenas corrija seu cálculo da variável de intervalo.

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

Edit: Para aqueles que não estão familiarizados com o conceito, esse código produz o ângulo desejado entre os marcadores em radianos, permitindo assim deixar o cálculo de xSpeede ySpeedcomo ele é, sem outras constantes aplicadas.

aaaaaaaaaaaa
fonte
+1 Verdadeiro. Ele deve calcular as period = 2 * pifunções sin / cos e então interval = period / BULLETS_PER_WAVE.
user712092
5

Eu acho que você deve fazer 360 / BULLETS_PER_WAVE em vez disso, que dá no seu caso 360/72 = 5 graus entre cada marcador. Você também tem certeza de que as funções Math.sin e Math.cos desejam sua entrada em graus e não em radianos?

Durza007
fonte
4

Enquanto você foi respondido, aqui está uma resposta mais engraçada: aprenda com a natureza.

Use a proporção áurea.

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

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

Klems
fonte
Agora, se você colocar um pequeno atraso entre cada foto, será um padrão realmente bonito.
Aaaaaaaaaaaa
@ Klems: impressionante! Estou usando isso totalmente para o meu próximo padrão: 3
IAE 16/11
3

Além do possível problema de grau / radiano, acho que o principal problema é que você está usando valores inteiros para os cálculos. Você não mostrou GameConstants.BULLET_NORMAL_SPEED_Xou sua contraparte Y, mas verifique se eles são representados como números de ponto flutuante, não inteiros. Como alternativa, converta-os em valores de ponto flutuante durante a multiplicação para o cálculo da velocidade.

Kylotan
fonte
Os valores são de autocast. Não estou familiarizado o suficiente com o Actionscript para chamar todos os casos, mas nesse caso, tenho certeza de que esse não é o problema.
Aaaaaaaaaaaa
Eu não acho que eles estão sendo escalados corretamente. Olhe para os 2 círculos mais próximos do personagem, acima e à direita dele. Esses 2 e todos os círculos de ambos os raios têm valores Y idênticos aos do outro raio, o que não seria o que você esperaria se os incrementos de Y fossem um valor de ponto flutuante.
Kylotan
Você está certo, há algum problema com os valores sendo arredondados, mas não acho que seja visível no snippet de código publicado, qualquer coisa que pudesse dar errado resultaria em um 0 e, portanto, não produziria nada que parecesse remotamente um círculo. Deve ser um problema mais abaixo na cadeia, provavelmente alguma variável que deveria ter sido numberdeclarada int.
Aaaaaaaaaaaa
+1: esqueci de especificar o tipo de BULLET_X, de modo que o padrão foi int. Opa
IAE