表示ってどうやって作ってんの?

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

神は言われた.「光Array」.
すると,
まばゆく輝く配列「index out of range」

…とか何とか言う啓示を受けた気がしないでもないので,プログラミングの話をしよう.そうしよう.
例によって,まともにゲームプログラミングをしたことのない者の妄言というかそんな.

---

RPG でも SLG でも何でもいいけど,「AがBを攻撃する」という処理があるとしよう.
この処理だけを考えれば,

何か攻撃手段に応じたダメージ計算をして,必要なら追加でBが状態異常になるとかいう処理をしたり,BのHPが0になったらどうのこうの…

っていうのをやることになるのだろうけど,この処理って,単に処理(計算)するだけなら一瞬で終わるよね.
で,ふつーの(仕事とかの?)処理ってのは,まぁ一瞬で終わるならそれに越したことは無いわけで,「OK,できた」ってなるんだけども,これがゲームだと話が違ってくる:

何か攻撃のエフェクトを表示して,次にダメージの表示があって,Bが消える演出が…

とか何とかいうことになって,これは「一瞬」で済ませるわけにはいかない.面倒な限りだ.
つまり,処理内容的には一瞬で済むような話なんだけども,その様子を時間をかけて,言わば「スロー再生」して見せなければならなくて,且つ「それが終わるまでは処理を次に進めない」っていう制御が必要になるわけだ.
こういうのって,どうやってるんだろう?(何かしらのかっこいい実装方法的な意味で) っていう話.
最後に編集したユーザー usao on 2022年8月29日(月) 18:29 [ 編集 1 回目 ]

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

Re: 表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

とりあえずこんな形に組み替えれば,表示物単体と表示物のシーケンスとの区別が無くなったから,好きな単位で待つ形に使えば良い,と.

ところで,処理(計算)側が「表示器」の Finished() にダイレクトにアクセスできるのだとしたら,「Observer がどうの」いう通知機構の部分は別に要らないんだよなぁ.
両者がそれなりに離れたところにあって互いに直接触れられない,っていうような分離した形で実装することにならないと恩恵は 薄いor無い っていうことになりそうだな. 

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

Re: 表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

どうでもいいけど,シーケンスの AddDispItem() のコメントには "would" を使ってみましたぞ!
(よくわかってないのにw)

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

Re: 表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

そんなこんなで,「表示器」側と「ゲーム自体の進行処理(計算)」側のそれぞれに Update() というメソッドがある状態だから,例えば通常時には両者を平等に呼ぶ:

CODE:

表示器.Update();  //アニメーションとかそういうのを進める
ゲーム進行処理.Update();  //こいつが仕事するのは表示側の進行と歩調を合わせなくてよい状態のときのみ
みたいなことになっている個所があるのだとして,ここのところがある条件下においては不平等になる:

CODE:

表示器.Update();
if( 何かの条件 )表示器.Update();  //もう1回やるぜ!
ゲーム進行処理.Update();
とかすれば「2倍速表示モード」みたいな話になる感だな.

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

Re: 表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

いやこれ,「シーケンス」の動作がシーケンシャルになってねぇやんっていう,しょーもないバグに一同驚愕!
パラレルすぎてワラタw

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

Re: 表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

というわけで,つまらないバグ修正.
パラレルなやつもそれはそれで必要なので適当な名前にして残し,シーケンスの側はqueueの先頭だけを扱うやつとして追加.

CODE:

//Sequence of IDispItem.
class DispItemSeq : public IDispItem
{
public:
	DispItemSeq(){}
	DispItemSeq( const DispItemSeq & ) = delete;
	DispItemSeq &operator=( const DispItemSeq & ) = delete;
	virtual ~DispItemSeq(){}

public:
	//Add to the tail of sequence.
	//When the added item's Finished() returns true, the item would be automatically popped from this sequence.
	void PushDispItem( std::shared_ptr<IDispItem> spItem ){	m_Items.push( spItem );	}

public:	//IDispItem implementation
	virtual bool Finished() const override {	return m_Items.empty();	}

	virtual bool Update() override
	{
		//Handling the fact that item's Finish() may return true at the first call.
		while( !m_Items.empty()  &&  m_Items.front()->Finished() ){	m_Items.pop();	}

		bool NeedToRedraw = false;
		if( !m_Items.empty() )
		{
			NeedToRedraw = m_Items.front()->Update();
			if( m_Items.front()->Finished() ){	m_Items.pop();	}
		}
		return NeedToRedraw;
	}

	virtual void Paint( HDC hdc, int W, int H ) const override
	{
		if( !m_Items.empty() ){	m_Items.front()->Paint( hdc,W,H );	}
	}
protected:
	std::queue< std::shared_ptr<IDispItem> > m_Items;
};
「 IDispItem::Finish() が初回コールでいきなり true を返してくる可能性!」とか思って Update() の最初に備えを入れてみたけど,Paint() 側はそこらへんどうなん?っていう.
(そういう項目が先頭にある状態で Update() 呼ばずに Paint() 呼ばれた場合…うーん,シラネw)

アバター
usao
記事: 1892
登録日時: 12年前
連絡を取る:

Re: 表示ってどうやって作ってんの?

投稿記事 by usao » 3年前

表示物側の Update() っていうメソッド名がどうにも好きじゃない.
(処理側のメソッドと名称が被ってる点も嫌)

…なんだけど,他の良い単語があるのか?っていうのがわからん.