三角形弾幕を発射させたい!

まえがき

ここ最近、弾幕風でちょっとした弾幕を作っているのですが、己のネタが尽きてしまい何を作ろうかと考えていた時に袿姫の方形弾幕がふと思い浮かび「そういえばあれはどうやって実装しているのだろう?」と疑問を抱き、自分なりに考えたのですが全く思いつかず、仕方なく色々と調べてみることに。

 

すると答えは意外と単純で、、

qiita.com

 

ふむふむ、なるほど。要は単位時間あたりの速度を三角関数を使って求めることであのような方形弾幕が出来上がるのか...

 

じゃあ、三角形もいけるんじゃね?

 

いいネタが見つかった(グヘヘw)、そう思い実装しようと思ったのがきっかけです。

 

計算方法

方形弾幕に倣って、求めたい値は「正三角形の重心から辺まで伸びた線の長さ」です。(数学的な用語が分からないので変な言い回しですいません...)

この線の長さが弾速度となります。

とてもありがたいことに、その部分はcosの変形で求めることが出来ます。

なぜなら、その部分は直角三角形だからです。

 

cosの式は「cosΘ = b / a」で求まります。(以下の画像を参照)

今回求めたい部分は「a」の部分なので、変形して 「a = b / cosΘ

更に単位時間にするために「b」は1とすると、「a = 1 / cosΘ」となり、これで欲しい式が出来上がりました。

 

いざ実装

今回は東方弾幕風ph3を使用して実装します。もちろんv0.12mでも実装可能ですが、一部関数に互換性が無いため、その部分は各個人で調整してください。

 

// x : 発射x座標
// y : 発射y座標
// bulletNum : 一辺の弾数(1 ~ 120)
// offsetAngle : 傾き
// bulletType : 弾画像
// delay : 発射遅延
task EquiTriangleShot(let x, let y, let bulletNum, let offsetAngle, let bulletType, let delay)
{
	let speed = 0;	// 弾速度
	let angle = 0;	// 弾角度
	let offset = 0;	// オフセット
	
	bulletNum = Clamp(bulletNum, 1 , 120);	// 一辺で発射できる範囲は1 ~ 120
	let oneShotRate = 120 / bulletNum;	// 発射間隔

	// 3辺で構成されているので3回
	loop(3)
	{
		angle = 0;
		
		// 一辺にbulletNumの数だけ発射
		while(angle < 120)
		{
			speed = 1 / cos(angle - 60);
			CreateShotA1(x, y, speed, angle + offset + offsetAngle, bulletType,  delay);
			angle += oneShotRate;
		}
		
		// 三等分にすると二等辺三角形になりその頂角は120となる
		offset += 120; 
	}
}

 

Clampは無かったため作りました。

function Clamp(let num, let min, let max)
{
	if(num < min)
	{
		return min;
	}
	else if(num >= max)
	{
		return max;
	}
	
	return num;
}

 

とりあえずこれで実装完了です。

頂点に近いほど隙間が大きくなっていますが、これは仕方ないですね。

 

 

 

 

オマケ