はかせのラボ

私の頭の中を書いていく雑記ブログです

DirectX オプションユニット作成 ~長押しで挙動を変える~

あいさつ

どうも、はかせです。
今回はちょっと前に作った長押し判定を使って
オプションユニットと自機の挙動を変えてみました。

前回の長押し判定の問題点

以前作った長押し判定は
長押しフラグが立っていなければ立てる
②長押しフラグが立っている状態で打とうとすると長押し

こんな感じで作っていました。

(詳細はこちら)

ただこれだと問題がありました。
長押し時私がイメージしている怒首領蜂では
オプションユニットは前方に集約しレーザーを打っていました。

それで長押し判定フラグが立っているとき前方に移動させようとしました。
そうすると私の判定の作り上
長押しの1フレーム前から前方に移動してしまいました。
これでは困ります。

解決方法

問題なのは最初に長押し判定フラグを立ててしまうことです。
なので最初から立てず長押しだとちゃんと判断してから
フラグを立てるようにしました。

長押しの判定は押されている間カウントアップし、
一定値以上になったら長押しと判定します。

bool Player::IsMyLongPush()
{
	//既に長押し判定済みなら判定しない
	if (mIsLongPush) return true;
	//押し始めのフレームか
	if (mDXInput->GetKeyDown(DIK_Z))
	{
		//カウントリセット
		mPushFrame = 0;
		return false;
	}
	else
	{
		//カウントアップ
		mPushFrame++;
		//長押し判定フレーム数より長い間押してたら
		if(mPushFrame > mJudgeLongPushFrame)
		{
			//カウントリセット
			mPushFrame = 0;
			return true;
		}
	}
	//押されていない
	return false;
}

このメソッドをショットボタンの(私の場合はZキー)
入力があった際に呼びます。

//ショットボタンが押されているか
if (mDXInput->GetInputState(DIK_Z))
{
	//発射判定
	mIsShot = CanShot();
	//長押し判定
	mIsLongPush = IsMyLongPush();
}

理由は単純でショットボタンが押されていない時には
ショットボタンの長押しという状態には絶対ならないからです。
(不必要な判定は減らしていきたい)

これで長押しの1フレーム前に長押し時の行動をしてしまう問題は解決されました。

長押し時の処理

長押し判定が直ったので長押し時の処理を作っていきます。

怒首領蜂では長押しするとオプションユニットが前方に集まり
レーザーを打ちます。
そしてレーザーを打っている間は自機の移動速度が遅くなります。

今回は
・オプションユニットが前方に集まる
・自機の移動速度が遅くなる

この2つを実装していきます。
(レーザーは衝突の判定や弾の処理が変わるので今回は一旦置いておきます)

オプションユニットが前方に集まる

前回まででプレイヤーと一定距離を置いて追従する処理は出来ています。
あとはプレイヤーのボタン長押しを検知して離れる距離や方向を変更するだけです。

今回はプレイヤー側に長押しされているかの変数を外部に公開させています。
なのでその変数をif文の条件にして変更します。

/*
mYOffset,mXOffsetは生成時に設定しています
*/
//長押しされているか
if(mPlayerCom->IsLongPush())
{
	//されていたら前方に
	mTransform->Position.y += mYOffset;
}
else
{
	//されていなければ横に
	mTransform->Position.x += mXOffset;
}

あとは前回と変わらないので割愛します。

自機の移動速度が遅くなる

これもやはり簡単です。
私のプログラムはコンポーネント指向で作っています。
ということで移動には移動用のコンポーネントがあります。

class Mover :public Component
{
public:
	Mover() {};
	~Mover() {};
	virtual void Initialize(DXGameObject* gameObject) override;
	virtual void Update() override;
	void SetSpeed(float speed) { mMoveSpeed = speed; }
private:
	DXInput* mDXInput;
	//移動速度
	float mMoveSpeed = 0.02f;
};

void Mover::Initialize(DXGameObject * gameObject)
{
	mDXInput = gameObject->GetDXInput();
	mGameObject = gameObject;
}

void Mover::Update()
{
	auto transform = mGameObject->GetTransform();
	if (mDXInput->GetInputState(DIK_LEFTARROW)) transform->Position.x -= mMoveSpeed;
	if (mDXInput->GetInputState(DIK_RIGHTARROW)) transform->Position.x += mMoveSpeed;
	if (mDXInput->GetInputState(DIK_UPARROW)) transform->Position.y += mMoveSpeed;
	if (mDXInput->GetInputState(DIK_DOWNARROW)) transform->Position.y -= mMoveSpeed;
}

単純に入力を受けてコンポーネントがついているオブジェクトの
transform情報を更新しているだけです。

この中でmMoveSpeedっていうのが移動速度です。
この変数の中身を増減させれば自機の移動速度を変えることが出来ます。

//ショットボタンが押されているか
if (mDXInput->GetInputState(DIK_Z))
{
	//発射判定
	mIsShot = CanShot();
	//長押し判定
	mIsLongPush = IsMyLongPush();
	if(mIsLongPush)
	{
		mMover->SetSpeed(0.01f);
	}
	else
	{
		mMover->SetSpeed(0.02f);
	}
}

(値が直打ちなのは調整中なのでご勘弁をm(__)m)

実行結果

オプションユニットが白いはんぺんから
赤いはんぺんに変わっています。

長押ししていたらオプションユニットが前方に移動し
自機の移動が遅くなっています。
youtu.be

あとがき

今回は長押しで挙動を変えるでした。

記事の文量からわかるかもしれませんが、
オプションユニットや自機の移動速度よりも
長押し判定の作り直しが大変でした。

作り直しても作り直しても1フレーム早いか
そもそも判定されないかみたいな状態が続いてました。

結局ごり押しで作ると後で泣きを見るってことですね。
ただ後々のこと考えて作りこんでしまうと時間と手間がかかりすぎる・・・・

この辺は残りの時間と要求クオリティとの相談で
良い落としどころを探すしかないんでしょうね。

それでは今回はこの辺でノシ

今回作ったものはgithubに上げました。
github.com