アマゾンバナーリンク

初心者弾幕講座その4 特殊な弾幕

みなさんこんにちは!ジェイです。前回までは割とオーソドックスな弾幕だったので今回はちょっと変わった弾幕を紹介します。

ストップ&スタート

角度は前回紹介したbase_angle + add_angle * (i – way/2)をベースにして、0.5=180度を基準にして0.1=36度ずつずらして、10発、弾を発射してます。発射して、20カウント後にスピードを0にして弾を止め、40カウント後にスピードを5.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)
        {
            //b_angle + d_angle * (i - way/2)
            if (Cnt%40 == 0)
                for(int i = 0; i < 10; ++i)
                    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 4.0,
                        angle:0.5 + 0.1 * (i-10/2), graph_type: 9, color: 0));
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }
        for(int i = 0; i < BC.Bullet.Count; ++i)
        {
            double cnt = BC.Bullet[i].Cnt;
            if (cnt == 20)
                BC.Bullet[i].Speed = 0.0;
            if (cnt == 40)
                BC.Bullet[i].Speed = 5.0;
        }
        // 基底クラスのMove関数を呼び出す
        return base.Move();
    }
}

ストップ&スタート 実行結果

跳ね返り弾幕

壁についたら反対側に跳ね返る弾幕です。これを作るコツは左右の壁に弾が接触したら、180度から今進んでる角度を引けば反対の角度を求められ、上下の壁は360度から今進んでる角度を引けば、反対の角度を求めることができます。

// 横に跳ね返す
BC.Bullet[i].Angle = 0.5 – BC.Bullet[i].Angle; // 0.5=180度
// 上下に跳ね返す
BC.Bullet[i].Angle = 1.0 – BC.Bullet[i].Angle; // 1.0=360度

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)
        {
            //b_angle + d_angle * (i - way/2)
            if (Cnt%30 == 0)
                for(int i = 0; i < 20; ++i)
                    BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 4.0,
                        angle: 0.05 * (i-20/2), graph_type: 4, color: 0));
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }
        for(int i = 0; i < BC.Bullet.Count; ++i)
        {
            double bx = BC.Bullet[i].X;
            double by = BC.Bullet[i].Y;
            //左右の壁
            if (bx < 10 + 21 || bx > FMX - 11 + 42)
                BC.Bullet[i].Angle = 0.5 - BC.Bullet[i].Angle;
            // 上の壁と下の壁
            if (by < 1 || by > FMY - 6 + 20)
                BC.Bullet[i].Angle = 1.0 - BC.Bullet[i].Angle;
        }

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

跳ね返り弾幕 実行結果

軌道変化ショット

この弾幕はあらかじめStateを決めておいて2種類の角度を後から操作できるようにしてます。Stateが0の時は、0.5 / 10 / 100ずつマイナスに。Stateが1の時は 0.5 / 10 / 100ずつプラスに角度を調整してます。


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)
        {
            //b_angle + d_angle * (i - way/2)
            if (Cnt%40 == 0)
                for(int j = 0; j < 2; ++j)
                    for(int i = 0; i < 16; ++i)
                        BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 1.0,
                            angle: (1.0/16) * (i-16/2), graph_type: 8, color: j,state:j));
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }
        for(int i = 0; i < BC.Bullet.Count; ++i)
        {
            int state = BC.Bullet[i].State;
            switch (state)
            {
                case 0:
                    BC.Bullet[i].Angle -= 0.5 / 10 / 100;
                    break;
                case 1:
                    BC.Bullet[i].Angle += 0.5 / 10 / 100;
                    break;
                default:
                    break;
            }
        }

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

軌道変化ショット 実行結果

ワープショット

弾が横の枠を超えたら逆の位置から出現して現れるショットです。
一度ワープしたショットはStateを1にして2回ワープしないように判定しています。

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 % 5 == 0) 
            {  // 右下
               BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 1.5,
                          angle: 0.125, graph_type: 5, color: 2));
               // 左下
               BC.Bullet.Add(new CBullet(x: X, y: Y, speed: 1.5,
                           angle: 0.375, graph_type: 5, color: 1));
             }
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }
        for(int i = 0; i < BC.Bullet.Count; ++i)
        {
            if (BC.Bullet[i].State == 0)
            {
                double bx = BC.Bullet[i].X;

                if (bx < 10 + 21)
                {
                    BC.Bullet[i].X = FMX - 10 + 42;
                    BC.Bullet[i].State = 1;
                }
                if (FMX - 10 + 41 < bx)
                {
                    BC.Bullet[i].X = 10 + 20;
                    BC.Bullet[i].State = 1;
                }
            }
        }

        return base.Move();
    }
}

ワープショット 実行結果

3Dショット


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 % 30 == 0)
            {
                for (int i = -7; i < 7; i++)
                {
                    double x = X - Math.Cos(BC.GetPlayerAnglePI2(X,Y) + PI / 2) * 10 * i;
                    double y = Y - Math.Sin(BC.GetPlayerAnglePI2(X,Y) + PI / 2) * 10 * i;
                    BC.Bullet.Add(new CBullet(x: x, y: y, speed: 1.5,
                        angle: BC.GetPlayerAnglePI2(X, Y) + PI/45 * i, graph_type: 7, color: 0, pi2or1:1.0));
                }
            }
            //b_angle + d_angle * (i - way/2)
        }
        if (Cnt > 300 + 240)
        {
            Y -= 2.0;
        }

        return base.Move();
    }
}

3Dショット 実行結果

いかがだったでしょうか?今回は特殊な弾幕を紹介しました。次回は実践的でかっこいい弾幕を紹介します。