アマゾンバナーリンク

初心者弾幕講座その3 速度も変更する弾幕

前回は角度を変えて狙い撃ち弾、誘導弾などを作りました。今回は速度も変える弾幕を作ります。

変速ショット

Speedに代入する時にカウンタ(Cnt)を使用する
speed: 0.1 + 0.2 * (Cnt / 15) Cntの値が大きいほどスピードが上がるので、後に発射した弾の方が速くなる。この場合、速度は0.1を基準速度として、15カウンタ増える度に、0.2ずつ弾の速度が増える。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static BulletCourse.CBulletCourse;
using DxLibDLL;

namespace BulletCourse
{
    public abstract class CEnemy : CMover
    {
        protected int Muki = 1;
        protected int ImageCnt = 0;
        public CEnemy(double x, double y) :base(x,y,1)
        {
            X = x;
            Y = y;
        }
        public virtual bool Move()
        {
            if (X < 10 + 20 || // 左座標の上限
                X > FMX - 10 + 42 || // 右座標の上限
                Y < 0 || // 上座標の上限
                Y > FMY - 5 + 20) // 下座標の上限
            {
                return false;
            }
            // 画像用カウンタ
            ImageCnt = Muki * 3 + (Cnt % 18) / 6;
            ++Cnt;
            return Life > 0;
        }
        public void Draw()
        {
            // 敵を描画
            DX.DrawRotaGraphF((float)X, (float)Y, 1.0f, 0.0f, BC.ImageEnemy[ImageCnt], 1);
        }
    }
    public class CEnemy0 : CEnemy
    {
        public CEnemy0(double x, double y)
            : base(x,y)
        {

        }
        public override bool Move()
        {
            if (Cnt < 60)
            {
                Y += 2.0;
            }
            else if (Cnt < 300)
            {
                // 5フレームに一度弾を発射する
                if (Cnt % 5 == 0)
                    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 0.1 + 0.2 * (Cnt / 15),
                                    angle: BC.GetPlayerAngle1(X, Y), graph_type: 1, color: 0));
            }
            if (Cnt > 300 + 240)
            {
                //BulletDischarge = false;
                Y -= 2.0;
            }

            // 基底クラスのMove関数を呼び出す
            return base.Move();
        }
    }
}

変速ショット 実行結果

全方位ショット

全方位ショットはfor分を使い角度を均等に分散させて発射させます。ここでは20方向に打たせているので、角度は360度=1.0で一発分の角度差は1.0/20になります。それにiを掛ければ等間隔で全方位に弾を打たせることができます。発射部分以外のソースコードは時間差ショットと同じなので省略

// 16フレームに一度弾を発射する
if (Cnt % 16 == 0)
   for(int i = 0; i < 20; ++i)
      BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 2.0,
         angle: i*1.0/20, graph_type: 7, color: 0));

全方位ショット実行結果

渦巻ショット

渦巻ショットを打つ基本の型としては、base_angle + add_angle * (i – way/2)という式です。
この場合は、wayが3で、 base_angleが(1.0 / 3 / 8 * Cnt)で add_angleが(1.0 / 3 * (i – 3 / 2))となります。1.0が360度なので、もしラジアンであればPI2を代入することで同じ結果が得られます。

for (int i = 0; i < 3; ++i)
    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 4.0,
        angle: (1.0 / 3 / 8 * Cnt) + (1.0 / 3 * (i - 3 / 2)), graph_type: 9, color: 1));

渦巻ショット 実行結果

ばらまきショット

  • 3.0を基準として、-1.5~1.5の間の乱数を発生させ速度に渡す
  • プレイヤーの角度を基準として、-0.1~0.1の間で乱数を発生させ角度に渡す
  • 0~1の数をcolorに渡す

CUtility.Rang(0.1)の0.1は360度=1.0なので、36度の間で弾を発射するように設定してます。
この値を小さくするとばらまく範囲が狭くなり、大きくするとばらまく範囲が広くなります。

if(Cnt%2 == 0)
    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 3.0 + CUtility.Rang(1.5),
        BC.GetPlayerAngle1(X,Y)+ CUtility.Rang(0.1), graph_type: 6, color: DX.GetRand(1)));

CUtility.Rang関数

// 渡された-ang~angまでのランダムな角度を返す
public static double Rang(double angle)
{
    return (double)(-angle + angle * 2 * DX.GetRand(10000) / 10000.0);
}

減速ショット

public class CEnemy0 : CEnemy
{
    public CEnemy0(double x, double y)
        : base(x,y)
    {

    }
    public override bool Move()
    {
        if (Cnt < 60)
        {
            Y += 2.0;
        }
        else if (Cnt < 300)
        {     
            if(Cnt%20 == 0)
                for(int i = 0; i < 20; ++i)
                    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 5.0,
                        angle:0.05*(i-20/2), graph_type: 9, color: 0));
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }
        for(int i = 0; i < BC.Bullet.Count; ++i)
        {
            double spd = BC.Bullet[i].Speed;
            if (spd >= 1.5)
                BC.Bullet[i].Speed -= 3.5 / 50;
        }
        // 基底クラスのMove関数を呼び出す
        return base.Move();
    }
}

減速ショット 実行結果

減速しすぎるショット

減速ショットを減速しすぎて、逆方向に移動してしまうショットです。

public class CEnemy0 : CEnemy
{
    public CEnemy0(double x, double y)
        : base(x,y)
    {

    }
    public override bool Move()
    {
        if (Cnt < 60)
        {
            Y += 2.0;
        }
        else if (Cnt < 300)
        {     
            if(Cnt%20 == 0)
                for(int i = 0; i < 11; ++i)
                    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 5.0,
                        angle:BC.GetPlayerAngle1(X,Y)+0.05*(i-11/2), graph_type: 9, color: 1));
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }
        for(int i = 0; i < BC.Bullet.Count; ++i)
        {
            double spd = BC.Bullet[i].Speed;
            if (spd > -4.0)
                BC.Bullet[i].Speed -= 8.0 / 100;
        }
        // 基底クラスのMove関数を呼び出す
        return base.Move();
    }
}

減速しすぎるショット 実行結果

今回は以上です。次回以降は少しトリッキーな弾幕も紹介します。