キャラ同士の重なりについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
土門

キャラ同士の重なりについて

#1

投稿記事 by 土門 » 7年前

どうしても自分では解決出来ず、
相談させて下さい。

21. キャラを一区間歩かせる。
http://dixq.net/g/23.html
を利用し、16マス区切りで移動させています。

そして、現在画面には
プレイヤーと敵多数をインスタンス化させ、
配置しております。
敵同士は互いに障害物として重ならないように設定しており、
そのプログラムは、敵同士を取り出しては、

コード:

if(ishitcheck((*it),(*it2)))  //座標から重なっているかどうか調べる関数
{
	(*it)->setwalking_flg(false); //すぐ移動フラグを消し、stopさせる
	(*it)->setposX((*it)->getQposX());	//その前の座標位置を使い、元の位置に戻す
	(*it)->setposY((*it)->getQposY());	//その前の座標位置を使い、元の位置に戻す
}
です。
これで、敵同士は重ならなくなりました。
確認のためにも、敵を自分が操作できるようにしています。
しかしここで問題が起きました。
敵三体を並べて移動させて、端っこのキャラが壁に到達して止まるとします。
ABC
壁| ←●●●(A,B,Cの敵三体)
理想ではAは壁にぶつかっているので進めない。
      BはそのAにぶつかって進めない。
CはそのBにぶつかって進めない。
となり、三体ともが並んだまま進めなくなるはずですが、
一番壁から遠いキャラは二体目と重なってしまうのです。
注意(移動ボタンを押しっぱなし状態です)
結果↓
AB
壁|●●(BにCが重なってしまうため、見えているのは敵二体)

しかもどうやら、上下左右関係無く三体並んでしまった状態で
端のキャラが壁で止まると、三体目が二体目にめり込んで重なってしまいます。

次に、ボタンを押しっぱなしでは無く、1マスずつ区切りながら押すと、
この場合は三体目が二体目に1ドットめり込み、
元の場所に押し出されて、重なることはありません(1ドットめり込む様が丸見えなのはおかしいが)。

この状況を打破するためにはなんの情報が必要なのでしょう?
なぜこのような状況になるのか気付けません、、、。

土門

Re: キャラ同士の重なりについて

#2

投稿記事 by 土門 » 7年前

ちなみに、これらの敵は全員同時に動かしています。

土門

Re: キャラ同士の重なりについて

#3

投稿記事 by 土門 » 7年前

皆様、わかりにくい質問で
申し訳ないです。

>>副管理人さん
もう一度自分で考えてみます。
今回のこのトピックは削除お願いします。
(それでもまた質問させて頂くにしても、もっと整理して質問したいと思いますので
今回は削除お願い致します、お手間取らせて申し訳ありません)

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#4

投稿記事 by ISLe » 7年前

敵の衝突判定について
こちらのスレが参考になりませんか?

マップのキャラの位置(あるいは移動先の位置)のタイルの進入禁止フラグを操作します。


タイル単位ではなく、ピクセル単位でキャラを動かすのであれば、めり込んでいたら離れる、という処理を行うほうが良いと思います。

前のスレは投稿する前に解決してしまったので今更ですが、移動する前に移動先をチェックするとか、移動して当たっていたら単純に移動する前に戻すとかだと、コードは単純になりますが、応用範囲を狭くするのであまりお勧めしません。

土門

Re: キャラ同士の重なりについて

#5

投稿記事 by 土門 » 7年前

すみません、

コード:

int IsAbleToGo(int x,int y,int muki){//進めるかを判定する
        if(muki==0)//上向きなら
                if(hantei[y/32-1][x/32]!=0)//進めるか判定
                        return 1;//エラー
        if(muki==1)//左向きなら
                if(hantei[y/32][x/32-1]!=0)
                        return 1;
        if(muki==2)//下向きなら
                if(hantei[y/32+1][x/32]!=0)
                        return 1;
        if(muki==3)//右向きなら
                if(hantei[y/32][x/32+1]!=0)
                        return 1;
        return 0;//正常
}
これの意味は分かるんですが、
今回の相手は制止したオブジェクトでは無く
常に移動しているオブジェクトなんです。
その場合hantei[y/32][x/32]といった表記では
その相手の位置を割り出せませんよね??固定されていないので。
で、なので毎度、現在地を二次元配列に記憶しておく関数を作ることになる。

でも、そこを自分は相手の座標を抽出し、
自分が移動しようとする先に、その敵がいるかどうか判定したいのです。

理由としては、自分はゲーム中のインスタンス化されたオブジェクトすべてが
格納されたlistを作っており、そのlistの中の情報で判定させてやりたいのです。

例えば、プレイヤーが移動する時に、移動先に敵がいるかどうかを調べる際に、
自分のクラス内にてすべての敵が入ったオブジェクトlistの中を確認しながら
自分の移動先の座標とその敵の座標とを関数で比較して行き先が空いてるかどうか
判断したいのです。
で、上記のソースを改造しました。
(オブジェクトはすべて16マス区切りで移動しているとします)
プレイヤーのクラス内にて、

コード:

list<sChara*>::iterator it;
for(it = ObjectMgr::getInstance()->objectlist.begin(); it !=ObjectMgr::getInstance()->objectlist.end(); ++it)//オブジェクトlistを端から最後まで回す
{
    if(IsAbleToGo(this->posX,this->posY,this->muki,(*it)->getposX(), (*it)->getposY())==false)
    {
      this->walking_flg=false; } //歩かないフラグを立てる。
}
改造したIsAbleToGo関数は
引数でそれぞれ、プレイヤーの現在値のX座標、Y座標、進行方向、敵の現在値のX座標、Y座標を受け取り、
中でプレイヤーの現在値の数値を増減させ、移動先の座標を取得し、そこに敵がいるかどうかを調べて真偽を返す、という感じです。

コード:

bool sChara::IsAbleToGo(int x1,int y1,int muki,int x2,int y2){//進めるかを判定する
        if(muki==0)//上向きなら
		{
			if(x1==x2 && y1-16==y2)//進めるか判定
			{	return false;}
		}
        if(muki==1)//左向きなら
		{
			if(x1-16==x2 && y1==y2)
			{	return false;}
		}
        if(muki==2)//下向きなら
		{
			if(x1==x2 && y1+16==y2)
			{	return false;}
		}
        if(muki==3)//右向きなら
		{
			if(x1+16==x2 && y1==y2)
			{	return false;}
		}
		return true;//正常
}
しかし、うまくいきません。
プレイヤーが動いている敵をすり抜けてしまいます。
なにがいけないのでしょうか?


本当は、動くオブジェクトにめり込んだら離れるという処理で進めていたのですが
それだとこのトピの最初に話したような状況に陥り、それをどうしても打開できなかったので、
もう、めり込む前に判定させ、移動出来ないようにすることにしました、、、、。
こっちはこっちで実現出来てませんが、、、、、。
相手の座標だけを使って、自分の移動先にいるかどうかを判断させるには
自分が改造したIsAbleToGo関数ではまだ不可能ですか?

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#6

投稿記事 by ISLe » 7年前

リンク先のスレにわたしが投稿したコードを動かしてみましたか?
大量のキャラが同時にわらわら動くプログラムですが。

マップの進入禁止フラグを追加して操作しているのはIsAbleToGo関数を流用するためであって、本質はそこではないです。
土門さんがスルーした、『現在地を二次元配列に記憶しておく関数』で求めているインデックスが必要な情報です。
つまりはタイル単位の座標です。

いちいち相手の座標を引っ張ってこなくて済むのでネストするループもなくなりコードがシンプルになるのですが、マップを書き換えたくないのであれば、『現在地を二次元配列に記憶しておく関数』で求めているインデックスを毎回求めて比較すれば良いだけです。
「毎回求める」という言葉だけだとコストは同じように聞こえますが、自分の中で自分のタイル座標を求めるだけで良いのと、自分の中で自分以外の相手の数だけ相手のタイル座標を繰り返し求めるのとどっちが開発および実行の効率が良いと思います?

ところで、土門さんがやりたいのは…
ひとつのマスにはひとつのキャラしか入れないようにする
のか
ピクセル単位で重なる寸前までは同じマスに複数のキャラが入れるようにする
のかどちらですか?

前者であれば、自分も相手も向きを考慮する必要がないし、後者であれば自分も相手も向きを考慮する必要があります。
前者であれば、自分も相手も向きを考慮する必要がありますし、後者であれば自分も相手も向きを考慮する必要がありません。
土門さんが提示したコードは、自分の向きは考慮するが相手の向きは考慮していないので、どちらでもありません。

リンク先のスレのコードは前者です。

後者であれば、めり込んでいたら離れる処理が必要です。
『めり込んだら』離れるではないですよ。
『めり込んでいたら』離れるです。
違いが分かりますか?

(編集)
向きを考慮する部分が逆になっていたのを修正しました。
最後に編集したユーザー ISLe on 2013年6月11日(火) 18:36 [ 編集 1 回目 ]

土門

Re: キャラ同士の重なりについて

#7

投稿記事 by 土門 » 7年前

ISLeさん、返答をお待ちしておりました。

まず、私のやりたいことは
「ひとつのマスにはひとつのキャラしか入れないようにする」
です。

>『現在地を二次元配列に記憶しておく関数』
>hantei配列のキャラが居る位置の上位バイトにデータを書き込んで障害物と同じように判定する

なんとなく理解してきました。
オブジェクトたちの位置の情報を格納する為の二次元配列を生成するんですね?
で、その二次元配列に自分たちの存在を、例えば”1”として格納しておく。
1として格納された時点で、もうタイルの座標で確認、判断すればいいので
障害物と同じように容易に壁扱いが出来る、と。そういうことですよね?

とても理想的に聞こえました。
ただ、自分の場合、重なることが出来ない壁扱いのキャラと、
重なって処理させたいキャラとが存在しています。
その区別をする場合はどうすればいいでしょうか?
二次元配列に格納する存在フラグに種類をつけたとしても
ちょっとここがややこしいのですが、
自分のやりたいことは、A、B、C、のキャラがいたとして、
AはBと重なることが出来ないが、AはCと重なることが出来、重なるとある処理を施す。
BもAとは重なることは出来ないが、BはCと重なることが出来、重なるとある処理を施す。
CはAと重なることが出来ないし、CはBとも重なることが出来ない。
です。
一見矛盾が見られると思いますが、
ポイントがありまして、
実は、AからCにぶつかった場合は重なることが出来るが、
CからAにぶつかった場合は重なることが出来ない。
のです。
この仕様であったとしても、
『現在地を二次元配列に記憶しておく』方法はうまく使えますか?
この場合、自分の向きを考慮するといいのでしょうか。


>『めり込んだら』離れるではないですよ。
>『めり込んでいたら』離れるです。
>違いが分かりますか?

後者はDRAWさせる段階を考慮した言い回し?
ということくらいしか思いつきません。。。
どういった違いがありますか?

あと、自分は上記の目的を成すために
オブジェクト同士を直接接触判定させていたのですが
このトピの最初に書いた通り、なんだか不具合が起きてしまい
改善させられましたが、結局はそれを打開することが出来ませんでした。
今は、列を成し、ある条件が発動?すると
そのキャラがプルプルと震えてしまいます(重なろうとしている?)。

あのー、ISLeさん、よろしかったらプロジェクトごとお渡ししますので
原因を突き止めて頂けないですか?
プログラムはそこだけを取り出した感じの簡潔にしたものにしてます。
自分ではこの処理でバッチリのつもりですが、、、、
なぜ特定の場合だけプルプルが発動するのか、、、わかりません。
この不具合が解決したら、自分はこれでいければなあ、とも思っていました。。
原因を探るのが難航するようでしたらどうぞ、スルーしてください。

それこそ、
「現在地を二次元配列に記憶しておく」で再チャレンジしたいと思いますので
また相談させてください。

※アップしたプロジェクトはISLeさん以外の方も確認してくださって構いません。
 原因がわかる方、ご指摘お願い出来ればと思います。

http://ux.getuploader.com/zipcodezipcod ... /DxLib.zip
パス無しです

nil
記事: 428
登録日時: 8年前

Re: キャラ同士の重なりについて

#8

投稿記事 by nil » 7年前

ビット操作によるフラグ管理はどうでしょう?
それぞれのキャラクタに

カテゴリーを表すビット値と
どのカテゴリーと衝突できないか(衝突できるか)を表すビット値
をunsigned型などで与え、

前者をマップの要素にコピーします。
衝突しようと動いた(動こうとした)キャラはマップからビット値を取得し、
ビット操作で接触可能か調べればいいのです。

例(unsigned shortでデータを与えた場合),
Player( 0x0001, 0x0003 ) -- 0x0001カテゴリーで0x0001および0x0002とは接触できない
Event( 0x0002, 0x0000 ) -- 0x0002カテゴリーで何とでも接触できる

Eventはマップに0x0000という情報を与え、
Playerはマップから情報を取得、 0x0001 & 0x0000 == 0なので接触できる->移動

逆に
Playerはマップに0x0002という情報を与え、
Eventはマップから情報を取得, 0x0003 & 0x0002 != 0なので移動できない->そのまま

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#9

投稿記事 by usao » 7年前

横から口を出すべきではないのかもしれませんが,
解析を他者に投げる前に
まずは自分のプログラムで起きていることを自分で解析してみるべきなんじゃないでしょうか?
(特定の条件で現象が起こることがわかっているのなら,
その時のコードの流れとか変数の値の変化を追って原因や何が起こっているかを調べる.
自分が想定したのとは違う判定結果や変数値変化が起こっているはず.)
「そういった努力は既にやったうえでなおかつわからないから言っているんだよ!」というのであれば,それはそれで
少なくとも解析を頼む相手に,そのとき得た情報も伝えた方がスムーズにいくんじゃないでしょうか.

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#10

投稿記事 by ISLe » 7年前

土門 さんが書きました:この仕様であったとしても、
『現在地を二次元配列に記憶しておく』方法はうまく使えますか?
この場合、自分の向きを考慮するといいのでしょうか。
「ひとつのマスにはひとつのキャラしか入れないようにする」のであれば常に向きを考慮する必要があります。
#前の投稿は逆に書いていました。修正しました。
土門 さんが書きました:自分のやりたいことは、A、B、C、のキャラがいたとして、
AはBと重なることが出来ないが、AはCと重なることが出来、重なるとある処理を施す。
BもAとは重なることは出来ないが、BはCと重なることが出来、重なるとある処理を施す。
CはAと重なることが出来ないし、CはBとも重なることが出来ない。
です。
Cが進入禁止フラグを立てないようにするだけで良いのでは。

Cが複数存在して互いに重なることはできないという条件が加わるならば、例えばA,Bは第16ビットでCは第17ビットを使うようにします。
#リンク先のスレのコードでは第16ビットだけをキャラが操作するフラグにしています。
そして、A,Bは第16ビットだけをチェックし、Cは第16ビットと第17ビットの両方をチェックすることで条件を満たせます。
#もちろん元からある障害物判定も行う必要があります。
土門 さんが書きました:>『めり込んだら』離れるではないですよ。
>『めり込んでいたら』離れるです。
>違いが分かりますか?

後者はDRAWさせる段階を考慮した言い回し?
ということくらいしか思いつきません。。。
どういった違いがありますか?
『めり込んでいたら』というのは前提なしです。
つまり自分が動かない場合にも対処する必要があります。
動いて迫って来る壁に押されてさがるような処理のことです。
今回は必要ないので考えなくても良いです。
土門 さんが書きました:あのー、ISLeさん、よろしかったらプロジェクトごとお渡ししますので
原因を突き止めて頂けないですか?
先の投稿にも書きましたが、土門さんのコードは、自分の向きは考慮するが相手の向きは考慮していない、というものです。
設計レベルの問題なので、小手先の対応はより大きな問題を引き起こすことになります。
まずは土門さん自身で設計を煮詰めることが必要です。

土門

Re: キャラ同士の重なりについて

#11

投稿記事 by 土門 » 7年前

usaoさん
>そういった努力は既にやったうえでなおかつわからないから言っているんだよ!

すみません、こちらとしては、その状況でした。
どういう状況でどうなるのも一応トピ内にも書いていましたので
割愛してしまいました。
頼むにも情報が足りないといえば足りないとも思います。
他の相談者のようにソースをここに張り付けて、
それを修正改善して頂いてるうらやましい状況を期待したい気持ちもありますが
伝えるにはすでにド素人には理解しがたい複雑さはすでにあると思ってますので
張り付けて長々と説明させて頂いたところで、じゃあそれに答えられる方が
そんなにいるのかと思えば、いないだろうなと推測もあり、
ならば、どうしたこうした語るより、プロジェクトを丸ごと渡して
動きを拝見して頂いた方がきっとわかってくれるだろうと思った次第です。
それがナンセンスな選択で「いやいや、ソースを全部張り付けて意見を問え」というなら
申し訳ありませんでした。

あと、まったくの丸投げかどうかはソースを見て頂ければ
自分なりにめちゃくちゃ努力してるのが見て取れるとも思います。
自分のやってることはそこらへんに転がってるレベルのソースでは無いと思います。
少なくとも自分でネットを調べた限りでは、objectlistから二つのイテレータを利用して
IDから目的のオブジェクトを抽出し、比較判断させる、なんて講座
見かけたことないですし。。
でも手抜きと思われたなら申し訳ありませんでした。

ということで、
ISLeさんのくださったいくつかのヒントを元に、自分で頑張ります。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: キャラ同士の重なりについて

#12

投稿記事 by h2so5 » 7年前

土門 さんが書きました: あと、まったくの丸投げかどうかはソースを見て頂ければ
自分なりにめちゃくちゃ努力してるのが見て取れるとも思います。
自分のやってることはそこらへんに転がってるレベルのソースでは無いと思います。
少なくとも自分でネットを調べた限りでは、objectlistから二つのイテレータを利用して
IDから目的のオブジェクトを抽出し、比較判断させる、なんて講座
見かけたことないですし。。
でも手抜きと思われたなら申し訳ありませんでした。
「zip上げるからデバッグしてください」という態度を丸投げと言っているのであって、ソースコードの中身は関係ないとおもいます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#13

投稿記事 by softya(ソフト屋) » 7年前

自分でデバッグ出来ないのは、デバッグ技術が未熟か、そもその自分で組んだものをちゃんとイメージ出来ていない事になります。
デバッグや問題点を解析するテクニックや問題点を解析するためだけのプログラムも場合によっては書かなくてはいけません。
長いコードを解析するのは骨の折れることなので、だんだんと誰も答えてくれないことになりますから、今のうちになんとかする技術を身につけることは大事です。

丸投げと見做されない質問をする一つの方法は、問題点を取り出した問題点だけのプログラム用意して、それを診てもらうことです(それを作っている時に問題点の解決方法が自分で分かることもあります)。
つまり、コードを単純化して再現やら調べるのが容易な状況に持っていく事をしていないのなら、回答者に負担を丸投げしていると思われる可能性があるわけです。複雑なのだと回答者が調べるために状況を単純化して調べる必要が出てくる可能性も多いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

土門

Re: キャラ同士の重なりについて

#14

投稿記事 by 土門 » 7年前

softya(ソフト屋)さん
言い訳と取られても仕方ありませんが、
>プログラムはそこだけを取り出した感じの簡潔にしたものにしてます
と書いた通り、すでに中身は問題がありそうな部分だけにそぎ落としております。
シーンマネージャーも骨組みだけにして、ステージしかありません。
自分のそのままをお渡ししているのではないんです。
まあ自分なりになんですが、
原因を探るために関係しそうなところまでをまとめた感じにしました。

とにかく、問題のあるソースをアップして確認してもらうというのも
この掲示板ではよく見た光景でしたので、今回真似をさせて頂いたつもりです。
ちゃんとソースもそれ用に編集して。
でも、ここまで皆さんから責められるとは思いませんでした。
失礼致しました。もう二度と自分はこちらでアップすることは無いです。
勉強になりました。

トントン
記事: 100
登録日時: 9年前

Re: キャラ同士の重なりについて

#15

投稿記事 by トントン » 7年前

土門 さんが書きました:softya(ソフト屋)さん
言い訳と取られても仕方ありませんが、
>プログラムはそこだけを取り出した感じの簡潔にしたものにしてます
と書いた通り、すでに中身は問題がありそうな部分だけにそぎ落としております。
シーンマネージャーも骨組みだけにして、ステージしかありません。
自分のそのままをお渡ししているのではないんです。
まあ自分なりになんですが、
原因を探るために関係しそうなところまでをまとめた感じにしました。

とにかく、問題のあるソースをアップして確認してもらうというのも
この掲示板ではよく見た光景でしたので、今回真似をさせて頂いたつもりです。
ちゃんとソースもそれ用に編集して。
でも、ここまで皆さんから責められるとは思いませんでした。
失礼致しました。もう二度と自分はこちらでアップすることは無いです。
勉強になりました。
ソースは404だったので見てませんが。

もしも感情的になっているのであれば
感情的になるべきではありません。
レスをもう一度読み直してみましょう。

>もう二度と自分はこちらでアップすることは無いです。
ソースを見てもらうのは成長するチャンスです。
チャンスは多い方がいいと思います。

土門

Re: キャラ同士の重なりについて

#16

投稿記事 by 土門 » 7年前

トントンさん

レスに感謝します。
感情的になっていたかもしれません
そんな私にわざわざ優しいお声をかけてくださり、
ありがとうございます。

>ソースを見てもらうのは成長するチャンスです。
>チャンスは多い方がいいと思います。

その通りですね。
見て下さる方は見て下さるでしょうし。

先週の金曜日から毎日何時間も悩み、改善するも完全に打開は出来ません。
その理由にやはり原因がわからないからでしょう。
ちなみにネットで調べても、
プログラマの知人に尋ねても解決出来ませんでした。
そんな藁をもすがるおもいでこちらに相談したつもりが
丸投げするな、まだ自分で調べられるでしょ的な指摘を受けたので
こちらのことも知らないでよくそんなことを、とついムカッとしてしまいました。
でも皆さんはそんなのしったこっちゃ無いし、わかるわけもないですよね。
こちらが反省すべきでした。
こちらでアップして、何人かの方がダウンロードしてくださったみたいですが
反応が無いのは、きっと複雑で調査する気が失せたか、やはり原因がわからないのでしょう。
自分の組み立て方としては、効率はよくなくとも「有り」ではあると思いますんで
原因が無いとは信じていますが、自分の実力ではここまでのようです。

トントンさん、ぜひ見てやってくださいませんか?
キャラが何人か並んで、壁で止まると何人かがプルプルと震えてしまいます。
悩ませるのは、必ずこの状況なら発現する、といった状況が無いことです。
ちなみにコメントアウトも皆さんにわかりやすいようにと加えたものです。
http://ux.getuploader.com/zipcodezipcod ... /DxLib.zip

自分のソースのなにが悪いのか、原因がわかればありがたいのですが、、、
自分や知人もお手上げ状態なので、、、

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#17

投稿記事 by ISLe » 7年前

少なくともわたしは最初の質問の段階で原因は想像できましたし、途中提示されたプレイヤークラスの当たり判定コードで想像どおりだと確信しました。

コメントしたとおり、設計レベルの問題なのですが、どうしてほしいのですか?
設計の見直しから方針の決定、リファクタリング、コード修正、一連の作業をタダでやってくれという依頼ですか?
コードを削ぎ落したところで問題は変わらないです。

土門さんはずいぶん逆方向に突っ走ってしまっているのですよ。
スタートの仕方が分からないとか、走り方が分からないといった質問とはまるで違います。
それが分からないことも問題を大きくしている一因だと思いますけど。

とりあえず言えることは、相手も向きを考慮して、タイル座標で比較してください。

いちおうダウンロードしました。
無駄にサイズが大きいですね。
期待はしないでください。

トントン
記事: 100
登録日時: 9年前

Re: キャラ同士の重なりについて

#18

投稿記事 by トントン » 7年前

プロジェクトを見ました。

アドバイスとして
1.ソフト屋さんのレスを読んでみましょう。
2.クラス分けがされているみたいですが、アタリをつけて何処の箇所を見てほしいのかを書きましょう。
3.他の方のアドバイスも検討はしてみましょう。

ちなみに、さっと見てわかればいいですけど
正直、平日は見る時間(暇)があまりとれません。
見るとすれば休日、あるいは気分で追いきらないかもしれません。

>反応が無いのは、きっと複雑で調査する気が失せたか、やはり原因がわからないのでしょう。
まぁ、その通りでしょう。
他の人の書いたソースを解析するというのは時間がかかることです。

最終的には土門さん自身が解決することだと思っています。
休日中であれば、ヒントまでは提供できるかもしれません。

もしくは、他の方が土門さんが求める答えまで導いてくれるかもしれませんが。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#19

投稿記事 by softya(ソフト屋) » 7年前

ざっと見ましたが、これを直すよりはISLeさんの言われるように根本の設計から考えた方が良いと言うのが結論です。
全部が移動した後に当たり判定しているので処理順番次第で今回のような振動が発生します。
このプログラム構造だと振動他の問題を避けるのは困難だと思われます。

【追記】
正確に書くと出来ないわけではないですが、コードの複雑さが増すのでバグの発生確率増加やコードのメンテナンス性がいちじるしく低下する可能性が高いと思われます。つまり苦しくなるので今のうちに変更するに限るです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#20

投稿記事 by ISLe » 7年前

めり込んだり震えるのは、タイル単位で判定していないことに加えてまとめて移動してからまとめて当たり判定をしているのが原因です。
土門 さんが書きました:ちなみに、これらの敵は全員同時に動かしています。
この考え方が間違いのもとです。
ゲームプログラムで同時に動くものはありません。

例えば振動は以下のように発生します。

壁[1][3][2]
[]内の順番にリストに入っているとします。

左キーを押すと、[1][2][3]は左に1単位移動します。ただしまだ画面は更新されません。

そして当たり判定で以下の現象が発生します。
[1]は壁に当たって元の位置に戻ります。
[2]は[3]が左に動いたままなのでそのままです。
[3]は[1]が元の位置に戻っているので自分も元の位置に戻ります。
結果、[2]だけが1単位左に移動した状態で画面に表示されます。

左キーを押したまま次のフレームになると、再び[1][2][3]は左に1単位移動します。ただしまだ画面は更新されません。

そして当たり判定で以下の現象が発生します。
[1]は壁に当たって元の位置に戻ります。
[2]は既に[3]にめり込んでいるので元の位置に戻ります。ただし元の位置はマス単位で記録されているので実際には2フレーム前の位置です。
[3]は[1]が元の位置に戻っているので自分も元の位置に戻ります。
結果、[1][2][3]は壁に当たって動かない場合の正しい位置に表示されます。

上記を繰り返すことにより[2]は振動します。


softyaさんが既に指摘されてますね。
当たり判定でキャラの種類や移動フラグをチェックしていたりするのも何のために必要なのか分かりません。
設計レベルから見なおして整理すれば少なくともコード量はいまの5分の1以下になるはずです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#21

投稿記事 by ISLe » 7年前

余談ですが、「藁をもすがる」じゃなくて「藁にもすがる」ですが、使い方を考えたほうが良いと思いますよ。

土門

Re: キャラ同士の重なりについて

#22

投稿記事 by 土門 » 7年前

>設計の見直しから方針の決定、リファクタリング、
>コード修正、一連の作業をタダでやってくれという依頼ですか?

そんなこと頼んでませんし、頼むつもりもないですよ。
こちらはとにかく原因が知りたいのでソースを見てもらいたかったということです。
もちろん、それがびびたるミスで、修正してもらえたりしたら嬉しいなくらいは
思ったりもしますけど(そういう回答も他のトピで何度も拝見したので)、
だからといって直してくれと頼むのは違いでしょ。

「なんでこうなるのか教えてくれませんか?」
これがすべてですよ。

でもそれこそあなたが原因を明確に説明してくださったので助かりました。
感謝いたします、どうもありがとうございました。
原因がハッキリと理解出来ました。

>Cが複数存在して互いに重なることはできないという条件が加わるならば、

そうですよ、加わるんです。
そのうえで、言わせて頂きますと、

>例えばA,Bは第16ビットでCは第17ビットを使うようにします。
>A,Bは第16ビットだけをチェックし、Cは第16ビットと第17ビットの両方を
>チェックすることで条件を満たせます。

ここは今の自分の知識ではなにを言ってるのかわかりませんでした。
ビット操作によるフラグ管理、なんでしょうか。
触ったことないんで、それをするくらいなら、少し手間が増えても
例えば、フラグを二つ用意したのでも、代用できないですかね。
それならば、そうした方が単純でこちらは助かりますが。

>相手も向きを考慮して

ここが一番疑問でして、自分の移動先を確認するのに
相手の向きを考慮する必要性を教えて下さいませんか?


softya(ソフト屋) さん

>全部が移動した後に当たり判定しているので
>処理順番次第で今回のような振動が発生します。

今は制作途中ということでキャラ同士の当たり判定などを試すために
キャラ全員がこちらのひとつの操作で一度に(厳密には順繰りなのはわかってます)
動くようにしてますが、
実際のゲームでは、各キャラ少しラグが出るようにするつもりです。
将棋?みたいなノリです。主人公が一マス動いたら、次に敵が一マス動く、
敵は沢山いますが、それも少しラグが出来てちょっとバラバラっと動く感じです。
ああ、わかりやすく言うなら、ボコスカウォーズのノリです。
あのノリを再現したいのだと思ってくださって構いません。
(あれは確か、敵から重なっては来ませんし、主人公らの行動の後に敵が行動しますよね?
重なると戦闘が始まりますし。)

それでも自分のこのプログラム構造はナンセンスなんでしょうか?
、、、いや、ナンセンスなんですよね?

ISLeさんに言われた通り、相手も向きを考慮して、タイル座標で比較の方向で
考え直したいと思います。

taketoshi
記事: 221
登録日時: 9年前
住所: 日本国

Re: キャラ同士の重なりについて

#23

投稿記事 by taketoshi » 7年前

ソースをDLしようとしたのですが404だったのでソースは読めておりませぬ。
ただ、私が過去に実装したのと似たようなことで悩んでいるのかなと思ったので投稿します。

SRPGを作っているのですがキャラ同士の重なりについて考えた時がありました。実装内容は。
味方ユニットは味方とNPCを通過でき、敵ユニットは通過できない。
敵ユニットは敵ユニットは通過でき、味方ユニットとNPCは通過できない。
NPCは味方ユニットは通過でき、敵ユニットは通過できない。

実装方法はマップの大きさと同じで、どのキャラがマップ上にいるかを保存しておく二次元配列を用意し
キャラクタが動くたびそこに所属をフラグを書き込み、もともといた場所の所属をクリアしていきました。

何もいないなら0を代入し、味方ユニットがいるなら1を代入、敵がいるならば2を代入、NPCならば3を代入します。
そして、それぞれのキャラクタに自分は何処に所属しているかの定数を持たせておきました。
あとはキャラクタが移動する前に移動先のマス目に対応した二次元配列表をチェックして移動可能か判定します。

私の場合はSRPGのユニットの移動に実装したので、
大多数のキャラクターを動かしていたわけではないのですが組み方次第で対応できそうな気がします。

涼雅さんが仰られているビット操作によるフラグ管理の簡単バージョンでしょうか?
参考になれば嬉しいです。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#24

投稿記事 by usao » 7年前

無駄に刺激してしまったようで申し訳ないですが,失礼ついでに
「あくまでも個人的に感じたこと」を申し上げれば,

ISLe さん(NO.20)が指定されていることが問題としている現象そのものであるとするならば,
現象はたかだか2フレーム間の情報から観測できる&対象オブジェクトも非常に少数であり,
デバッガで追うなり,問題箇所の動作ログを吐くなり,あるいはprintfデバックなりでもすれば
”(実情を知らない外野から見れば)容易にわかりそうな類のもの”だと感じます.

#一応断っておきますが,
 コードは先の投稿前にダウンロードして該当箇所と思われる場所を眺めてはみました.
 動作解析をするつもりで見たわけではないので,本当にざっくりと,ですけど,
 特段テクニカルというか複雑/難解 なコードになっているようにも見受けられませんでしたので
 デバッグ(というか時系列で何が起こっているかを知ること)はかなり容易なものと推測しました.


別に煽っているとかそういう意図はありません.
ただ,ある程度の規模のソフトを作られるのであれば
「画面上表示の見た目」とか,「コードを目で追って」とかで理由がわからない場合,こういった
実際の動作状況を追う泥臭い動作確認方法を取るしかない…んじゃないですか?っていうか,
うまく言えませんけど,そういう方法を取らずに進めるのだとあとあと(すぐにでも)また同様に困ることになるんじゃないか,と.
……完全に余計なおせっかいだったかもしれませんね.


[追記]
余計かもしれませんが 加えて申し上げておくと

>丸投げするな、まだ自分で調べられるでしょ的な指摘を受けたので
私の文面が良くなかったのか
この時点ですこしばかり意味合いが曲解されてしまっているのではないかなぁ,と.
私は 「丸投げ」 という厳しい具合のいい方はしていないつもり.これでも.
最後に編集したユーザー usao on 2013年6月12日(水) 13:25 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#25

投稿記事 by softya(ソフト屋) » 7年前

そうですね。
私のしたい事は、こういう風にプログラムで躓かないようにアドバイスをしたいのです。
つまり、何が何でもバグの解析がしたいわけでもなく、元のソースコードを残して苦しむよりは必要なら手間をかけて大改造をすることを提案すべきと思っています。
デバッグ方法が分かっていないなら、そちらに優先して誘導します。

なので、デバッグ方法を覚えてくださいとか、デバッグ方法を工夫してくださいとか、自分で訳のわからないことになるなら設計から見なおすべきです。というコメントに成るわけです。

【補足】
デバッグの工夫について。
今回の場合、まず振動しやすいようにキャラを並べて発生させた上で、Sleep(100);とかをメインループに入れると起きている状況がわかりやすくなります。これが工夫その1。
あと当たり判定が関係しているのは、土門さん自身も仰っているので当たり判定部分で既に提案されているログファイルを書きだすようにすることでバグの分析が可能になります。これが工夫その2。
どのキャラとどのキャラが当たって、座標をどのタイミングで戻したかをファイルに書き出してみましょう。どのキャラの分かりやすく成るようにキャラに採番して画像の上に番号を表示するのも良いでしょう。タイミングが分かるように移動を開始してからのフレーム数もログファイルに書きだすと良さそうです。
ログファイルに分析出来るだけのデータを載せるのは色々と考えなきゃいけませんが良い勉強に成るでしょう。

プログラムを組む上で、デバッグ技術は実はとんでもなく重要です。
これの習得を怠ったために完成しないプログラムがたくさんあります。最終的に自分で自分の作ったバグにさじを投げてしまうのです。
リファクタリングと共に中級者と言うかある程度のプログラムを組めるように成るためには習得すべき必須技術なのです。
私は土門さんは、既にデバッグ技術抜きに先に進めない段階に差し掛かっていると判断しました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#26

投稿記事 by ISLe » 7年前

土門 さんが書きました:>例えばA,Bは第16ビットでCは第17ビットを使うようにします。
>A,Bは第16ビットだけをチェックし、Cは第16ビットと第17ビットの両方を
>チェックすることで条件を満たせます。

ここは今の自分の知識ではなにを言ってるのかわかりませんでした。
ビット操作によるフラグ管理、なんでしょうか。
触ったことないんで、それをするくらいなら、少し手間が増えても
例えば、フラグを二つ用意したのでも、代用できないですかね。
それならば、そうした方が単純でこちらは助かりますが。
でしたら参考スレのリンクを張った時点で『現在地を二次元配列に記憶しておく関数』が何をやっているのか分からないと書いていただければ良かったのではないでしょうか。
土門さんがスルーしたからわたしもスルーした、それだけのことですが。

それと、知りたいことはスレを読み直したら書いてあると思いますけど。

(追記)
土門さんのいまの状況はいわゆるデスマーチパターンです。
喜んでデスマーチに送り出して欲しいというなら放っておきます。
関われば損をするだけなのが明らかですから。

トントン
記事: 100
登録日時: 9年前

Re: キャラ同士の重なりについて

#27

投稿記事 by トントン » 7年前

原因も、デバッグ方法も
ISLeさん、softyaさんが書いてくれてるのでコードについては何も言うことがありません。
まぁ、思った以上に整っていたので追いやすかったです、ハイ。

さて、恐らく土門さんが思っている以上に周りは冷静で、
思っている以上にすごい方達ばかりです。
そんな人たちにアドバイスをもらって羨ましい限りです。

>それでも自分のこのプログラム構造はナンセンスなんでしょうか?
>、、、いや、ナンセンスなんですよね?
自分の考えを貫きたいと思っているのであればそれはそれでありなのですが、
せっかくアドバイスをもらっているんです。
まず、それを試してみて、その後見比べて、自分が良いと思う方を選んでも(取り入れて言っても)良いでしょう。

僕からは以上になります。
頑張ってください。

土門

Re: キャラ同士の重なりについて

#28

投稿記事 by 土門 » 7年前

一晩経って、昨日よりも冷静になれました。
昨日までは、トントンさんのご指摘通り、自分の考えを貫きたい気持ちもあり、
どこかでなるべく別のやり方は避けようとしていました。
ですが、やはり皆さんのいうように、自分のやりたいことを成すには
今のやり方ではダメだと思い、移動前にタイル座標を使って
移動先を調べてから移動する、といったものに今日から修正してっています。

softya(ソフト屋)さん
デバッグについてですが、ご指摘通り自分はまだまだ未熟で
(visualstudioのデバッグ機能もままなりません)
変数の中身を確認したり、プログラムの流れを追うくらいのことしか
したことありません。
今後はデバッグ方法の幅も広げていきたいと思い知らされました。
貴重なアドバイスをありがとうございます。
勉強していきたいと思います。

usaoさん
usaoさんには別のトピでもお世話になっており、
冷静に考えれば今回のusaoさんの言葉にはなんの悪気も無かったとわかるはずなのに
こちらが感情的な態度をとってしまいました、すみません。
プログラムに数日頭を抱えていたこともあって冷静さを欠いていたと思います。
自分は一年前までプログラムのプの字も知らなかった素人でして
今回ほど苦しんだことは無かったので、とてもストレスを感じておりました。
言い訳にもなりませんが、ガキでした。どうぞお許し下さい。

taketoshi さん
回答を下さりありがとうございます。
とてもわかりやすく、非常に参考になっています。
トピがこんな状態だったにも関わらず、
アドバイスしてくれてありがとうございます。

ISLeさん
>参考スレのリンクを張った時点で『現在地を二次元配列に記憶しておく関数』が
>何をやっているのか分からないと書いていただければ

そうですね、なんかその時はもう頭がいっぱいいっぱいで
今から別のことをやるなんて余裕が無かったので。。。
でも、ISLeさんの回答が最初から適格だったのだと今なら理解出来てます。
ほんと申し訳ありません。ISLeさんのおかげで自分が今のプログラムを
どうすべきかわかりました。
こんな生意気なド素人に付き合って最後までレスを下さり、恐縮です。
こんなド素人ですから今後もまたなにか障害にぶつかると思いますが
またアドバイスなり頂けると嬉しいです。

皆様へ
今回は皆様にご迷惑をおかけして申し訳ありませんでした。
それでも見捨てず、レスをくださったことに心から感謝致します。

プログラムの方ですが、
各キャラの現在地を表す二次元配列を作り、
(各キャラが移動するたびに二次元配列のフラグも移動させる)
各キャラが移動する前に移動先が空き状態かどうかを調べ、
進行可能か不可能かを判断するようにしようと思います。
まず、それを確実にした後に、移動先にいるキャラフラグに
重なることが出来る、出来ない等の種類を作ろうと思います。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#29

投稿記事 by ISLe » 7年前

土門 さんが書きました:実際のゲームでは、各キャラ少しラグが出るようにするつもりです。
将棋?みたいなノリです。主人公が一マス動いたら、次に敵が一マス動く、
敵は沢山いますが、それも少しラグが出来てちょっとバラバラっと動く感じです。
ああ、わかりやすく言うなら、ボコスカウォーズのノリです。
あのノリを再現したいのだと思ってくださって構いません。
(あれは確か、敵から重なっては来ませんし、主人公らの行動の後に敵が行動しますよね?
重なると戦闘が始まりますし。)
ボコスカウォーズはキャラが重なることはありません。
まず戦闘フェーズがあり、進行方向のマスに敵キャラがいたらダメージ計算、ライフが0になったキャラは消滅します。
次に移動フェーズで、単純に進行方向のマスが空いていれば移動します。

キャラの移動にタイムラグを設けるということなので、キャラの移動は『アニメーション演出』として実装されることを提案します。

内部処理はすべてタイル単位を中心に行い、ピクセル単位の移動は、アニメーション演出として見せるだけのものにします。
複雑な当たり判定がすべて不要になります。

既にそのように取り組んでおられるのかもしれませんが。


いま言っても混乱するだけかもしれませんが、タイル単位で処理しても、キャラ処理順によって動けるはずのマスに動かないという不具合が起こり得ます。
それを防ぐには、キャラがひとりでも動いたら、まだ動いていないキャラをすべてチェックし直す必要があります。
内部処理をタイル単位にしておくとこれらの実装を単純なループで構成できます。

土門

Re: キャラ同士の重なりについて

#30

投稿記事 by 土門 » 7年前

ISLeさん
No: 28で話したように、修正している途中なんですが、
まったく思うように判定してくれません。
各キャラの居場所を表す二次元配列を作り、
そこに各キャラの座標を元に、要素の中でフラグを立てれば済むだけの話なのに
なぜこうも思うようになってくれないのでしょうか、、。

コード:

//16×16のマス区切り。
//OBNowPointクラス(シングルトン)にて二次元配列OBnowpointを作っています

<プレイヤーclass>
initializeにて、
OBNowPoint::getInstance()->OBnowpoint[this->posX/16][this->posY/16]=1;//二次元配列に現在値格納

Updateにて
  //座標が16で割り切れたら入力可能
    if((int)posX%16==0 && (int)posY%16==0){
		walking_flg=true;
		//現在位置から新たに2次元配列に存在を表す"1"を格納(”1”はプレイヤー軍、敵classでは”2”を格納
		OBNowPoint::getInstance()->OBnowpoint[this->posX/16][this->posY/16]=1;
		//移動後、旧座標をもとに2次元配列の旧フラグを空き(0)に。
		OBNowPoint::getInstance()->OBnowpoint[this->QposX/16][this->QposY/16]=0;
		this->QposX = this->posX;//現在座標を旧座標に格納し、旧座標を更新
		this->QposY = this->posY;

		if	( key & PAD_INPUT_UP){  //上ボタンが押されたら
			muki=0;}
		else if( key & PAD_INPUT_LEFT){//左ボタンが押されたら
			muki=1;}         //左向きフラグを立てる
		else if( key & PAD_INPUT_DOWN){//下ボタンが押されたら
			muki=2;}         //下向きフラグを立てる
		else if( key & PAD_INPUT_RIGHT){  //右ボタンが押されたら
			muki=3;}         //右向きフラグを立てる
		else {this->walking_flg=false;}
       if(this->walking_flg==true){    //もし歩くなら
         if(IsPLAYERAbleToGo(this->posX,this->posY,this->muki)==1)//行き先が歩けないなら
		  {
			this->walking_flg=false;}         //歩かないフラグを立てる。
        }
   }
		if(this->walking_flg==true){        //歩くフラグが立っていたら
			if     (muki==0)        //上向きならy座標を減らす
					posY--;
			else if(muki==1)        //左向きならx座標を減らす
					posX--;
			else if(muki==2)        //下向きならy座標を増やす
					posY++;
			else if(muki==3)        //右向きならx座標を増やす
					posX++;
		}

//進めるかを判定するIsPLAYERAbleToGoの中身です
IsPLAYERAbleToGo(int x,int y,int muki){
	if(muki==0){//上向きなら
		if(OBNowPoint::getInstance()->OBnowpoint[this->posY/16-1][this->posX/16]==2)//"2"は敵軍を表す
			return 1;
	}
	if(muki==1){//左向きなら
		if(OBNowPoint::getInstance()->OBnowpoint[this->posY/16][this->posX/16-1]==2)
			return 1;
	}
      if(muki==2){//下向きなら
		if(OBNowPoint::getInstance()->OBnowpoint[this->posY/16+1][this->posX/16]==2)
            return 1;
	}
      if(muki==3){//右向きなら
		if(OBNowPoint::getInstance()->OBnowpoint[this->posY/16][this->posX/16+1]==2)
			return 1;
	}
      return 0;//正常
}
各キャラのclass内で判定させるので
各キャラの現在位置を表す二次元配列はシングルトンで作りました。

上記で動かしても、すべてのキャラがすり抜けるばかりです。
考え方がまだおかしいでしょうか?

>ボコスカウォーズはキャラが重なることはありません。

一見、敵と重なってすぐ戦闘フェーズが始まってるように見えますが、
あれは違うのですね。

>キャラの移動にタイムラグを設けるということなので、
>キャラの移動は『アニメーション演出』として実装されることを提案します。
>内部処理はすべてタイル単位を中心に行い、
>ピクセル単位の移動は、アニメーション演出として見せるだけのものにします。

ということは、キャラの移動量自体を16ずつにしてしまい、
そのマスとマスの移動部分はDrawにて表示してやるってことですか?

>複雑な当たり判定がすべて不要になります。

どうやらボコスカウォーズのアルゴリズム自体、自分が考えているものと違う、
つまり、自分が今やってることは少しズレているということでしょうか。
もちろん、自分がしたいことはボコスカウォーズみたいなものですが
今作ってて、思ったより大変で参っています。
ISLeさんのこの言葉は、要は、
ボコスカウォーズみたいなものならもっと単純に出来るよってことですよね?

>それを防ぐには、キャラがひとりでも動いたら、
>まだ動いていないキャラをすべてチェックし直す必要があります。
>内部処理をタイル単位にしておくとこれらの実装を単純なループで構成できます。

なぜ動いてないキャラだけをcheckしなおすべきなのか、
思いつきません。。ISLeさんのリンクしてくれたトピを参考にしつつ修正していますが、
それらを考慮したものにするなら、リンク先のトピは忘れた方がいいですか?

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#31

投稿記事 by usao » 7年前

多分,やりたいことは以下のようなことなんだと思いますが,

コード:

(1)キャラクタがN人いて,それぞれの現在位置の箇所にフラグが立ってる2次元配列がある,
 例えば,キャラクタのいる箇所を1で,他を0で埋めているような.

for( All Caractors )
{
    (2)各キャラクタの移動処理
    (2.1)いまから移動可能か?(posX%16==0とかいう判定.移動アニメーション中でないことを判定していると思われ.)可能なら(2.2)へ.
    (2.2)移動しようとする方向の決定.例えばプレイヤ操作対象ならキー入力で判定.移動したいのなら(2.3)へ.
    (2.3)移動したい先が開いているか調べる.フラグ配列の「移動先となる箇所」を調べる.値が0ならこのキャラクタは移動できる
    (2.4)移動することにする.その旨をフラグ配列へ反映.
           フラグ配列[現在位置]=0 にして,フラグ配列[移動先位置]=1 にする.
    (2.5)(16フレーム間の)移動アニメーション処理の開始のための処理.
}
>Updateにて
の処理順がこのようなことを実現する流れになっていますか?


#本当にどうでもいい話だけど,私だったら OBNowPoint::getInstance() をUpdateの中から直接呼ぶのではなく,Updateの引数でフラグ配列を指定するかも.

土門

Re: キャラ同士の重なりについて

#32

投稿記事 by 土門 » 7年前

usaoさん
ありがとうございます!言う通りに組み直した結果、上手く機能出来ました!
めちゃくちゃだったものがまともに動いています。
自分のミスでYとXを書き間違えてた部分もあったんですが、
なにより、usaoさんの言う「順番」がとても重要だったようです。
自分の頭の中でも順番を意識して組み立てていたUpdeta内だったのですが、
実際は思ったようになりませんでした。
ありがとうございます。

しかし、まさにまともに動くようになった今、ISLeさんのレスにある
>タイル単位で処理しても、キャラ処理順によって動けるはずのマスに動かないという不具合が起こり得ます。
が起きています。
そして、押しっぱなしでグリグリ動かしていると相手キャラをすり抜けて重なってしまう輩も出ています
まあこれは今の操作自体が想定外だから仕方ないかもしれません。
本当は1マスごとに移動を停止させたいので。

なので、ISLeさんの言う
>それを防ぐには、キャラがひとりでも動いたら、まだ動いていないキャラをすべてチェックし直す必要があります。
>内部処理をタイル単位にしておくとこれらの実装を単純なループで構成できます。
を実装したいのですが、ちょっと自分にはピンと来ない、理解出来ずにいますので
組み立て方のヒントというか、usaoさんの書いてくれた流れ図的な解説をお願い出来ませんか?
解決が近いような気がします、どうかお願いいたします。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#33

投稿記事 by usao » 7年前

>自分の頭の中でも順番を意識して組み立てていたUpdeta内だったのですが、
>実際は思ったようになりませんでした。
簡単な処理,というか,「自分にとって自明な処理内容」であれば
(1)処理手順を考える→(2)コード書く
という手順で十分ですが,そうではない場合であれば
(1)処理手順を考える→(2)私が示したような,日本語な状態での疑似コードを書いてみる→(3)コード化する
という手順を踏むことを個人的にお勧めします.
(よく「フローチャートを書きなさい」とか言いますが,それを フローチャートという図 ではなくて コードっぽい形 で書く,ということ)

利点は
(a)プログラムっぽく書くので,この時点でコード状態のイメージが明確になる.
(b)この時点でダメそうかいけそうか,何が起こりそうか,を追うことができる
(c)コーディング作業を途中で中断することがあったりした際に,再開時にやるべきことがすぐわかる(実装することメモ として機能)
(d)消さずにコメントアウトすれば,そのまま処理内容の意味を説明する注釈として残る.(もちろん,その後,実装内容に変更あったら消す)
…といった感じでしょうか.
特にプログラムに不慣れなうちは(a),(b)が役立ちます.


さて,本題ですが,
>すり抜けて重なってしまう
こっちはよくわかりませんが,
>キャラ処理順によって動けるはずのマスに動かない
とは,例えば,AとBが並んでいて,共に左に行きたいような場合,
処理順が A→B だと両者共に移動するけど
処理順が B→A だった場合には Aだけが移動し,Bが動かないので,結果として,AとBの間に1マス空きができてしまう
といったような現象でしょうか? であれば,
>キャラがひとりでも動いたら、まだ動いていないキャラをすべてチェックし直す
をもっとも簡単に実現する方法は,(効率とかは別として)

コード:


while( 1 )
{
    だれか一人でも動けたよフラグ = false;

    //全キャラ分移動処理ループ
    for( All Caractors )
    {
        (2.4)で,さらに,だれか一人でも動けたよフラグ = true; とする.
    }

    //終了判定
    if( だれか一人でも動けたよフラグ == false )break;
}
みたいな感じでいいんじゃないでしょうか.

もちろん,これでもうまくいかないケースは想定できます.例えば,
”AとB が隣接していて,Aは右(Bの位置)に,Bは左(Aの位置)に 動きたい” とかいう場合.
まぁ,この状況だと「動かなくて正解」ってことにしてしまってもよいかもしれませんが,
”4人が輪になっていて…”みたいな(ループ構造的な)状態だったら膠着させたくない!動け!とかいうことだと,何かしら工夫しないとだめそうです.

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#34

投稿記事 by ISLe » 7年前

usao さんが書きました:もちろん,これでもうまくいかないケースは想定できます.例えば,
”AとB が隣接していて,Aは右(Bの位置)に,Bは左(Aの位置)に 動きたい” とかいう場合.
まぁ,この状況だと「動かなくて正解」ってことにしてしまってもよいかもしれませんが,
”4人が輪になっていて…”みたいな(ループ構造的な)状態だったら膠着させたくない!動け!とかいうことだと,何かしら工夫しないとだめそうです.
輪が回転するようにしたいということだとループしていることを判定する必要がありますね。
処理自体はそんなに難しくはないと思いますが。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#35

投稿記事 by usao » 7年前

おおっと,これだと
>まだ動いていないキャラをすべてチェックし直す
の「まだ動いていないキャラを」の判定がないので,別の問題が出てしまうかもしれませんね.

コード:

//キャラクタ数分の,「私はこのフレームでの判定は無事に終えました」チェックフラグを用意.
bool 判定終えたフラグ[ キャラクタ数 ];  //※↓のwhileループに入る前に,すべてfalseに初期化しておく.

while( 1 )
{
    bool  だれか一人でも動けたよフラグ = false;
 
    //全キャラ分移動処理ループ
    for( All Charactors )
    {
        if( 判定終えたフラグ[ このキャラクタ ] == true )  //俺は移動するぜ!という判定を終えたやつは飛ばす
        {    continue;    }

        (2)...
        (2.4)で,さらに,
            ・だれか一人でも動けたよフラグ = true; とする.
            ・判定終えたフラグ[ このキャラクタ ] = true; とする.
    }
 
    //終了判定
    if( だれか一人でも動けたよフラグ == false )break;
}
でどうかな?

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#36

投稿記事 by ISLe » 7年前

土門 さんが書きました:>キャラの移動にタイムラグを設けるということなので、
>キャラの移動は『アニメーション演出』として実装されることを提案します。
>内部処理はすべてタイル単位を中心に行い、
>ピクセル単位の移動は、アニメーション演出として見せるだけのものにします。

ということは、キャラの移動量自体を16ずつにしてしまい、
そのマスとマスの移動部分はDrawにて表示してやるってことですか?
キャラの移動量1を1マスにするのです。
座標が16で割り切れるとき~とか、いちいち座標を16で割ったりという手間がすべて不要になります。

内部でタイル単位の移動処理が完了したら、移動アニメーション再生フェーズに移ります。
移動したキャラ個々に対して、移動前のマスから移動後のマスまで移動するアニメーションを再生します。
単にアニメーションを再生するだけのフェーズですから、例えば戦闘により相手が消滅したマスに移動するなら戦闘アニメーションに続けて移動アニメーションを再生すれば良いし、直線移動だけではなくキャラごとに異なるアニメーションにすることもできますし、個々のアニメーションの再生時間や再生タイミングも自由で、単純に必要な分のアニメーションを再生するだけです。
すべてのアニメーションの再生が終わったら、ユーザーの入力を待つフェーズに戻ります。


1ピクセルずつ移動しながら、マス判定とユーザー入力判定を並行してやろうとすれば複雑で分かりにくいのは当たり前です。

・ユーザー入力
・マス移動(マス単位)
・移動アニメーション(ピクセル単位)
と完璧に処理を分けてしまったほうが分かりやすくなります。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#37

投稿記事 by usao » 7年前

>1ピクセルずつ移動しながら、マス判定とユーザー入力判定を並行してやろうとすれば複雑で分かりにくいのは当たり前です。
おっしゃる内容については全く同意ですが,
この点に関しては「参考にされたページで取られている方法のひどさ」をそのまま引きずっている結果と思われるので
(まぁ,その方法をそのまま流用するという判断を下したのは利用者側なのだ,という話はあるかもしれませんけど)
現段階で この点を問い詰めるのはどうかなー…とか思ったり.

>21. キャラを一区間歩かせる。
>http://dixq.net/g/23.html
>を利用し、16マス区切りで移動させています。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#38

投稿記事 by ISLe » 7年前

わたしは当初からマップのタイル単位で処理する方向へ誘導するつもりでコメントしているのですが。

%16とか/16とか書かれたあたりのコードをごっそり削るには適したタイミングかなと思ったんですけどね。

いまさら感があるということは個人的感覚ではデスマーチ確定ということなので、あとは、まあ、頑張ってください。
前に書いたとおり、突き進みたいというのをわたしは無理に止めようとは思いません。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#39

投稿記事 by usao » 7年前

うーん,なんというか
”一度に改善してくステップの細かさの単位”がどのくらいの刻み幅が良さそうか?
という点での考えの違いなのかな,という気もしますけど,
方針が食い違っているのであれば,先に対応されていた方の方針をないがしろにする気はありませんので
その場合は消えるべきは私かと.

peot

Re: キャラ同士の重なりについて

#40

投稿記事 by peot » 7年前

以前こちらにあげたRPGモドキからテストプログラムをつくってみました。
参考になりますでしょうか。

pass[ kasanari ]
http://www1.axfc.net/uploader/so/2933825

タイル単位での当たり判定をしていますが、配列で管理するのではなく
キャラごとに直接X,Yの値をもっています。けど、考え方は一緒だと思います。

アニメに関しては本来フレームカウントでやってましたが、座標(というか移動量)
からでもできるようにしてみました。
ですが、本当ならアニメと移動は別のものとして変数をつくって処理したほうが
いいような気がします。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#41

投稿記事 by ISLe » 7年前

選択するのは土門さんですし、usaoさんはusaoさんのやり方で続けていただいてかまわないと思います。
わたしは投稿したいと思えば投稿するだけですから。

当初はもっとゆるやかに誘導する予定でした。
土門さんのプロジェクトを見た時点で、参考にするべきは、落ち物パズルのブロックの落下処理だというのがはっきりしました。
だからといっていきなり大きく舵を切っては混乱すると思ったのですが、直後に大きく舵を切らざるを得なくなったのです。

一気に切ってしまわないと中途半端で解決してしまいそうだと思ったのでとりあえず理想形を提示しておくべきかと思ったわけです。
最後に編集したユーザー ISLe on 2013年6月13日(木) 18:52 [ 編集 1 回目 ]

土門

Re: キャラ同士の重なりについて

#42

投稿記事 by 土門 » 7年前

usaoさん
すみません、No: 35 の疑似コードでわからない部分がいくつかあります。
補足というか解説をお願い出来ませんでしょうか?
●「だれか一人でも動けたよフラグ」の存在の意味
コードを見たところ、このフラグがtureになった後に与える影響がわかりません。
●判定終えたフラグ[ このキャラクタ ] が trueになった後、それをfalseに戻すタイミング。
whileループに入る前に,すべてfalseに初期化しておく、とありますが、これは一番最初だけでなく、
このループに入る前に毎回、すべてをfalseに戻しておく、ということでしょうか?

自分は、移動処理を各キャラの中でさせています。
usaoさんの疑似コードはひとつのループで全員の移動処理をさせていることが仮定ですよね?
なので、usaoさんの教えてくれた構造と少し違うのでNo: 31も少し調節しつつ、実装しました。
が、今回の形を、自分の構造に実装するのが難しく?ちょっと頭を悩ませています。
キャラクラスの基底クラスにstaticで「誰か一人でも動けたよフラグ」を作り、
それを各キャラの中でtrue,falseを代入しながらまわす。
また、判定終えたフラグ[ このキャラクタ ] については配列では無く、
それぞれのキャラに「判定を終えたフラグ」を作る。
としています。しかし、それぞれをどこに入れたらいいのかが、難しいです。
各キャラのUpdateの中で移動処理をまわしているので、疑似コードの要領では
break;で終えることもが出来ませんし、continueで抜けることも出来ないようです。
とりあえず、判定終えたフラグがtrueの時は、移動処理をしない、ということで
移動処理自体をif(判定終えたフラグ==false)で囲んでやりました。同じ流れになりますよね?
ただ、「だれか一人でも動けたよフラグ」をどう組み込めばいいのかが、思いつきません。
その理由が、trueにした後の影響をどう与えるのかが推測出来てないからです。

あと、話は変わりますが、
>「参考にされたページで取られている方法のひどさ」をそのまま引きずっている結果
とありますが、
>21. キャラを一区間歩かせる。
>http://dixq.net/g/23.html
のことですよね?
このページの内容は、参考にすべきでは無いほどの講座だったのですか?
つまり、ナンセンスなプログラムだと。初心者なのでその辺のことはわからなかったのですが、
本来、21. キャラを一区間歩かせる。でも言っている「FCドラクエのマス移動方法」をやるとしても、あの講座内容はナンセンスで
、ISLeさんの言うところの
「キャラの移動量1を1マスにする」方法をやるべきだということでしょうか?
確かに、マス移動云々のゲームを作るならば、
ISLeさんの言う方法の方がシンプルでわかりやすく、合理的な気がします。。。。

[記事訂正] 21:01 ご本人から誤解と言うことで削除の依頼がありましたが訂正線とさせていただきました。 by softya(ソフト屋)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#43

投稿記事 by softya(ソフト屋) » 7年前

ISLeさんの言っているのは、「キャラを一区間歩かせる」は使うけど区間移動中は他のキャラは動かないようにする(当たり判定が発生しない)と言うシンプルなものにするという意味だと思いますが。

【追記】
>つまり、ナンセンスなプログラムだと。初心者なのでその辺のことはわからなかったのですが、
>本来、21. キャラを一区間歩かせる。でも言っている「FCドラクエのマス移動方法」をやるとしても、あの講座内容はナンセンスで、ISLeさんの言うところの
>「キャラの移動量1を1マスにする」方法をやるべきだということでしょうか?

言葉遣いには注意してくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

土門

Re: キャラ同士の重なりについて

#44

投稿記事 by 土門 » 7年前

>言葉遣いには注意してくださいね。[/quote]

大変申し訳ありませんでした
自分はその講座のプログラムの良し悪しを判断出来るレベルにはありませんので
usaoさんの言葉?を素直に受け取って、聞きかえしただけなのです。
というか、皆さんに迷惑かけならが、usaoさんにはひどい方法を引きずっていると言われるし、
ISLeさんにデスマーチ確定まで言われ、ただ聞き返したら、副管理人さんに誤解されて怒られるし、
自分のプログラムは解決しないし、、、もう最悪の気持ちです。

自分はいったいどうすればいいんですか?
わかりやすくいうと、ボコスカウォーズが
作りたいんです。わかりやくす、それを再現とまで言います。

皆さんの意見をもとに、進行先を調べて移動する方法に変えています。
移動方法をこんど1マスごとにしたほうがいいならそうします。
そっちのほうが自分も良い気がしますし。

>ISLeさんの言っているのは、「キャラを一区間歩かせる」は使うけど
>区間移動中は他のキャラは動かないようにする(当たり判定が発生しない)と言うシンプルなもの

一歩を1マスとしたゲームにするならば、
あの講座のプログラムでいうif(posX%16==0 &&posY%16~とか要らなくなります?
少しプログラムは変わって来ると思うんです。
そういう意味でも、usaoさんもそのページを参考にしたままじゃよくないと
言われたのかなと思ったんですよ、、、。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#45

投稿記事 by softya(ソフト屋) » 7年前

ISLeさんのやりたい事のイメージがよく分からないのなら何処から分からないのかISLeさんに質問してください。横から口を出すとどんどん誤解されそうな気がして来ました。
とりあえず「ナンセンスなプログラム」と書かれると他の人が誤解します。それを訂正したかっただけです。

あとISLeさんのやり方と、usaoさんのやり方は全く違うので、どちらかを選ぶのは土門さんです。両方共採用はできないと思ってください。
両方を一度に採用しようとすると混乱するのは当たり前です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

土門

Re: キャラ同士の重なりについて

#46

投稿記事 by 土門 » 7年前

peotさん
ありがとうございます。早速ダウンロードして確認しました。
しかしソリューションを開いた後、ビルド出来ません。
GameFrame.hがincludeが出来ない状態になっています。
バージョン?違いのせいでしょうか?
自分は2010のvisualstudioなんですが
ビルドするためにはなにかしないとダメなんでしょうか?
一応プロパティから、インクルードディレクトリとライブラリディレクトリで
「プロジェクトに追加すべきファイル」に設定はしました。

peot

Re: キャラ同士の重なりについて

#47

投稿記事 by peot » 7年前

一度、incファイルの中身をsrcファイルのなかに移してからビルドしてみてもらえますか?
それでもダメなら、もう一度あげなおします。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#48

投稿記事 by usao » 7年前

>●「だれか一人でも動けたよフラグ」の存在の意味
>コードを見たところ、このフラグがtureになった後に与える影響がわかりません。
while(1){...}を抜ける条件に使用しています.
このwhileループの各回において,いずれかのキャラが”「俺は移動するぜ」という判定をした”場合,
そのキャラの座標移動によって空いた箇所に丁度入りたい別のキャラが存在するかもしれないので,
その場合はwhileループを抜けません.

>●判定終えたフラグ[ このキャラクタ ] が trueになった後、それをfalseに戻すタイミング。
”ループに入ろうとする際に毎回”で合っています.

>usaoさんの疑似コードはひとつのループで全員の移動処理をさせていることが仮定ですよね?
おそらくあなたのコードでもループしているものと思いますが,違いますか?
仮に N個のキャラクタ群が 配列Character_Instances[N] で保持されているとしたら

コード:

for( int i=0; i<N; i++ )  //全キャラクタ分ループ
{
    Character_Instances[i].Update();
}
のような形をとると思います.(配列だろうがリストだろうが)
クラスに分かれていて,コードの位置が見た目離れていても,処理の流れという意味ではほぼ変わらないハズです.
continueとかbreakとかフラグの位置とか,については,
同じ流れになるように然るべき箇所にあればよいと思います.
例えば,キャラクタクラスのUpdate()メソッドが,「移動することにした」のかどうかを戻り値で返すようにしたとすれば,
全キャラクタ分ループさせている箇所 に情報を伝えられるので staticな変数を作らなくてもよいハズですよね.
(   誰か一人でも動けたよフラグ |= Character_Instances.Update();   とかすれば同じことができる.)


>「参考にされたページで取られている方法のひどさ」
私も言い方が大変悪かったです.該ページを乏しめす意図があるわけではないです.
このページが説明したいのは単に”一定間隔でループする値を取得する方法”程度の事柄であって
そのことをとても簡単に説明するためにpixel座標に基づいた方法 が書いてある ものだと思います.
なんというか,全くうまく説明できないのですが,
本番でこれ([Pixel]に支配された処理)をそのまま用いてゲームのロジック部分の制御を行うのだとしたら 方法としてひどい と思います.
(本来の講座の趣旨でもないはず)
”「ロジックでの演算結果を→表示する」のであって,「表示側(表示方法)の都合によって→ロジックが制御される」ではない” というか.
(参考ページでは たまたま 「表示単位[Pixel]の値を ロジック上の座標値の値 と一致するようにして描画している」のであって
 「ロジック上のキャラクタの位置を表すデータ」の単位としては[pixel]は不適切.
 今回の例で言えば,ロジック単位が[マス]になったのであれば,キャラクタ座標を表す変数の単位も[マス]であってしかるべき.
 描画するために,いつかは[マス]座標から表示単位たる[pixel]に翻訳せねばならないが,それば描画を司る箇所の役目.)

ISLeさんもこのことをおっしゃっているのだと思うので 同意 と書きました.
ただ,私は,このことにはとりあえず目をつむって,まずは当たり判定と移動がまずは動く形にもっていこう としているのに対して,
ISLeさんはこっち側を先に(同時に?)修正しようとしているのではないかな,と.(全然ちがってたりして…)

[追記]
なので,私自身は
>ISLeさんのやり方と、usaoさんのやり方は全く違う
とは思ってないんですよね.

土門

Re: キャラ同士の重なりについて

#49

投稿記事 by 土門 » 7年前

softya(ソフト屋)さん
その通りですね、申し訳ありません。
たまにこの掲示板で自分の書き込みを編集しているのを見ますが
あれはユーザー登録した人だけが出来るのでしょうか?
もしそうでしたら自分は編集できない立場ですので
誤解を生む文面の削除お願い出来ませんか?二重線でも構いませんので。
でも面倒でしたらそのままでも、、その辺は副管理人さんの意向で構いません。

>あとISLeさんのやり方と、usaoさんのやり方は
>全く違うので、どちらかを選ぶのは土門さんです

当初の自分のやり方もそうですが、
usaoさんのやり方(というか、私のまずいプログラムに合わせてくださったやり方ですね)
もまだ最後まで出来ていません。試行錯誤している状態です。
No: 35を自分がうまく実装出来るかわかりません。
でもきっとISLeさんのやり方でも、No: 35の考え方は必要となるのでしょうし
理解しといた方がいいと思うんです。

ISLeさん
>1ピクセルずつ移動しながら、マス判定とユーザー入力判定を
>並行してやろうとすれば複雑で分かりにくいのは当たり前です。

そうですよね。根本が間違っていたようです。

>・ユーザー入力
>・マス移動(マス単位)
>・移動アニメーション(ピクセル単位)
>と完璧に処理を分けてしまったほうが分かりやすくなります。

今回の自分の目的のゲームは、
これが理想形だと自分でもわかるので、今更と言わず、
ISLeさんのやり方というのを突き詰められたらなと思いました。
ただ、そうするにしてもNo.35は活かせられるはずですよね?
そこは当たり判定云々の部分じゃなく、移動先を調べる云々の話ですし。

とりあえず、このトピのISLeさんの言葉を読み直し
マス移動をマス単位にして、移動先を調べてから移動する方式にして、
アニメーションでその間を補うやり方に修正していってみようと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#50

投稿記事 by softya(ソフト屋) » 7年前

余計な口出しかもしれないですが、ISLeさんの方法ならNo.35は不要な処理のはずです。
※ 私が「ISLeさんのやり方と、usaoさんのやり方は全く違う」と判断した理由は、そういう所です。

>たまにこの掲示板で自分の書き込みを編集しているのを見ますが
>あれはユーザー登録した人だけが出来るのでしょうか?

出来ますが、前後の人と話が繋がらなくなるなど問題が多いので無闇な編集はフォーラムルール上で禁止しております。

>もしそうでしたら自分は編集できない立場ですので
>誤解を生む文面の削除お願い出来ませんか?二重線でも構いませんので。
>でも面倒でしたらそのままでも、、その辺は副管理人さんの意向で構いません。

今回も話が繋がらなくなるので、文は残したいと思います。
ただ、訂正線は引いておきましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

土門

Re: キャラ同士の重なりについて

#51

投稿記事 by 土門 » 7年前

peotさん
うまくいきました。ソースを研究させて頂きます。
ありがとうございます。

usaoさん

はい、確かにキャラはすべてObjectMgrクラスのlistに格納入れてます。
それをステージ.cppのUpdateにて
ObjectMgr::getInstance()->Update();といった形でおいてます。

そのObjectMgrのUpdateは
list<sChara*>::iterator it; //イテレータ宣言
it = objectlist.begin();//itの指すところを先頭にする
while( it != objectlist.end()){
(*it)->Update();
it++;}
と書いてます。
そして、それぞれのコンテナの「キャラ」のUpdetaにて
移動先を調べたりの細かな移動処理を書いているのです。
その場合、continueとかbreakはどこに置けばいいのか、、、、
キャラのUpdate内ですよね?
「だれか一人でも動けたよフラグ」は、キャラのUpdeta内じゃないですよね?
ということは、ステージのUpdate内か、ObjectMgrのUpdate内か、、
頭がこんがらがってしまって。。頭痛がしてます、はい。

土門

Re: キャラ同士の重なりについて

#52

投稿記事 by 土門 » 7年前

>余計な口出しかもしれないですが、ISLeさんの方法ならNo.35は不要な処理のはずです

え、そうなんですか??
No35は存在するキャラたちが行先のマスを調べて移動する場合の話ですのに、
No35は不要になるんですか??ということは現時点のもので
移動については完成してしまう感じなんでしょうか。
マス目移動じゃなく、ピクセル移動だから
「行けるはずのマスにいけない場合」や、「重なる場合」が出てしまうのでしょうか。
それとも行先を見る判断に別のなにかを加えなければならないとか。
ああ、頭がこんがらがってきました、、、頭痛がしてきました。
でもボコスカウォーズみたいな初期のゲームの移動を再現するだけなのに
ここまで複雑で苦しんでいるのは、ISLeさんの言う通り
「1ピクセルずつ移動しながら、マス判定とユーザー入力判定を並行してやろうと」しているせいですよね。
ちゃんとISLeさんのいうように直していきたいと思います。
ここまで、苦しむとは思いませんでした。本当に。

usaoさん
usaoさんも同意ということですし、自分もISLeさんのいう一番合理的なプログラムに
直してみたいと思います。色々アドバイス頂いたのにすみません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#53

投稿記事 by softya(ソフト屋) » 7年前

ISLeさんの書いてきたことを、まとめ直して仕様とし書きだしてみて合っているかご本人に確認してもらったらどうでしょうか?
まとめる作業の時に、頭も整理できると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#54

投稿記事 by usao » 7年前

>色々アドバイス頂いたのにすみません。
あやまることは何もありません.
というか,私はNo.30付近の話を見て,方針がNo.31のような事柄なのだと思い,以降を書いていたわけですが,
>全く違う
のであれば,私はいったい何をやっていたんだ?というか
行われている話とは違う事柄を書いていらぬ混乱を招いただけであり,謝るべきはむしろこちらです.
本来伝えたかったことは私が最初に書いたような事柄であったはずなのに
内容方面に立ち入ってしまったのは完全に失敗でした.

方針が固まったのであれば,その方向で頑張ってください.
その際,No.31~の内容は全く役に立たないかもしれませんが,
少なくとも私が最初に書いた内容については,土門さんの今後に少しでも役立てば幸いです.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラ同士の重なりについて

#55

投稿記事 by softya(ソフト屋) » 7年前

usao さんが書きました:>色々アドバイス頂いたのにすみません。
あやまることは何もありません.
というか,私はNo.30付近の話を見て,方針がNo.31のような事柄なのだと思い,以降を書いていたわけですが,
>全く違う
のであれば,私はいったい何をやっていたんだ?というか
行われている話とは違う事柄を書いていらぬ混乱を招いただけであり,謝るべきはむしろこちらです.
本来伝えたかったことは私が最初に書いたような事柄であったはずなのに
内容方面に立ち入ってしまったのは完全に失敗でした.

方針が固まったのであれば,その方向で頑張ってください.
その際,No.31~の内容は全く役に立たないかもしれませんが,
少なくとも私が最初に書いた内容については,土門さんの今後に少しでも役立てば幸いです.
すいません。私も話の流れを誤解していた様です。
NO.35に関しては、それに似た何かは実装しないとマズイです。
ただ、あまりにNO.35は何か気持は分かるのですが分かりづらくないか?と言う疑問が新たに生まれました。
【補足】ちょっと検討してみます。

あんまり変わりませんでしたね(汗)。

コード:

bool 移動確定したフラグ; 各オブジェクトが持つ。

void hantei()
{
	//	初期化
	for( All Charactors )
	{
		//ここで、各キャラ移動確定したフラグをリセットするメソッドを呼び出す。
		
	}
	//	全部の移動判定が確定するまで
	while( 1 ) {
		//	全キャラの移動処理
		if( !AllCharsMove() ) {
			break;	//	全部の移動判定が確定なので抜ける。
		}
	}
	
	
}

bool AllCharsMove()
{
    //全キャラ分移動処理ループ
    for( All Charactors )
    {
		if( 移動確定したフラグはON? ) { //メソッドで判定
			continue;	//このキャラは動くことは確定。
		}
		
	 	(2)各キャラクタの移動処理
		(2.1)いまから移動可能か?
		(2.2)移動しようとする方向の決定.例えばプレイヤ操作対象ならキー入力で判定.移動したいのなら(2.3)へ.
		(2.3)移動したい先が開いているか調べる.フラグ配列の「移動先となる箇所」を調べる.値が0ならこのキャラクタは移動できる
		(2.4)移動することにする.その旨をフラグ配列へ反映.
			フラグ配列[現在位置]=0 にして,フラグ配列[移動先位置]=1 にする.
	 		移動確定したフラグをセットするメソッドを呼び出す。
	 		return true;	//1つ動いたので再度全キャラの判定が必要
	}
	
	//	全部の移動判定が確定
	return false;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#56

投稿記事 by ISLe » 7年前

ISLe さんが書きました:いま言っても混乱するだけかもしれませんが、タイル単位で処理しても、キャラ処理順によって動けるはずのマスに動かないという不具合が起こり得ます。
それを防ぐには、キャラがひとりでも動いたら、まだ動いていないキャラをすべてチェックし直す必要があります。
内部処理をタイル単位にしておくとこれらの実装を単純なループで構成できます。
わたしが言い出しっぺです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#57

投稿記事 by ISLe » 7年前

誰か移動したら、移動した後のマスが空くので、まだ移動していないキャラの中の誰かがそこに移動できるようになるかもしれません。
まだ移動していないキャラの中の誰かがそこに移動することで、また移動した後のマスが空くので、まだ移動していないキャラの中の誰かがそこに移動できるようになるかもしれません。

と誰も移動しなくなるまで繰り返すために必要な『誰か移動したフラグ』です。

館のコードは順番に読み進めて分かりやすいように、プログラミングの学習のために書かれているものだと思います。
館に限らず初心者向けのコードというのはどこでも応用しにくく書かれているものです。
応用しやすいコードというのは使用目的が明確では無くなる分初心者には理解し難くなります。
応用しやすいコードほど初心者には分かりにくくなってしまうというわけです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#58

投稿記事 by ISLe » 7年前

最終的な理想形は、処理を
  • ユーザー入力
  • マス移動(マス単位)
  • 移動アニメーション(ピクセル単位)
というフェーズに分離することです。

わたしが思い描いていたロードマップは、
  1. 内部の当たり判定をマス単位に変更
  2. 当たり判定に食い込んでいるピクセル単位の処理を除去
    ※見た目はいったんマス単位の移動になる
  3. 移動できるはずのマスに移動できないパターンの解消
  4. アニメーションフェーズを追加
以上で完成、というものです。
できるだけ早い段階でピクセル単位の呪縛を解けば開発効率も上がると考えます。

現状は、
  1. 内部の当たり判定をマス単位に変更
  2. ピクセル単位とのズレに起因するバグを排除
  3. 移動できるはずのマスに移動できないパターンの解消
  4. 当たり判定に食い込んでいるピクセル単位の処理を除去
    ※見た目はいったんマス単位の移動になる
  5. アニメーションフェーズを追加
という感じになっています。
3.はピクセル単位→マス単位を気にしながらコーディングしています。
2.が解消されないことで3.に影響を与えていると思われます。
そして2.でイジったコードは4.ですべて削除されるでしょうし作業対象も増えます。

土門

Re: キャラ同士の重なりについて

#59

投稿記事 by 土門 » 7年前

ISLeさん
ご教示をありがとうございます。
副管理人さんのアドバイスもありますし、
No: 58を含め、このトピのISLeさんのレスをすべてプリントアウトして、
明日は一日中、何度も読み返して理解に努めたいと思います。
今回の件で、久しぶりに挫折しそうになりましたが、
自分を奮い立たせております。

で、改めてレスを確認していて
気になっていることがありますので質問させて下さい。

>リンク先のスレにわたしが投稿したコードを動かしてみましたか?
で、指している”コード”とは、リンク先のトピのNo: 7のISLeさんのレスにある
"相談者様のコードを改造したコード"のことですよね?
そちらのコードは参考になるとのことですが
相談者の不具合コードの修正版?を全力で理解するように
頑張ろうと考えて大丈夫でしょうか?
なぜそんな質問をするかというと、
ISLeさん自身の言葉でもそのコードに対し、
「エラーチェックが甘いです」
「謎の多いコードなので仕様レベルで整理することをお勧めします」
「こちらのコードは正規化しないとバグります」等、
色々書いてあるので、
参考にならない部分、真似てはならない部分があるのでは無いか、
と読むのを躊躇してしまう自分がいまして。

それに、そのトピのNo: 11にてISLeさんが書いてます
>マップは一次元配列のほうが何かと都合が良いので一次元配列

>ビット演算で32ビットある整数値の第16ビットを操作します。
>第16ビットが1の整数値は10進数で65536になります。

というようなものも盛り込まれたソースであったとするならば
今の自分ではまだ理解出来ないとも思っています。

なので、とにかく、今のもてる知識の中でISLeさんの言います、
ユーザー入力、マス移動(マス単位)、移動アニメーション(ピクセル単位)
というフェーズに分離したプログラムに組み立て直すことにしようと
考えています。
…そういう意味ではこちらのトピのこのISLeさんのレス
http://dixq.net/forum/viewtopic.php?t=1 ... 317#p83325
の理解に努めた方がいいのかな、と思ってます。

長々すみません、このトピではもう自分は何度も悩み、やり直し、疲れ切っているので、
もう失敗はしたくないという気持ちが強く、慎重になってしまってます。
でも諦めるわけにはいきません。必ず目的のプログラムを完成させたいです。
とにかく、頑張ります。

アバター
usao
記事: 1596
登録日時: 7年前

Re: キャラ同士の重なりについて

#60

投稿記事 by usao » 7年前

頓珍漢なことだけ書いて逃げた人 みたく見えてしまってもあれなので
私が考えていた(過去形です)こともざっと申し上げておきます.

>そして2.でイジったコードは4.ですべて削除されるでしょうし作業対象も増えます。
作業が増えるのは困りものなのですが,私は,この過程こそが飛ばしてはならないものなのだと考えていました.

>わたしが思い描いていたロードマップは、
> 1. 内部の当たり判定をマス単位に変更
> 2. 当たり判定に食い込んでいるピクセル単位の処理を除去
の2の時点で,それまで存在してたバグや問題点(表面化していたものも潜在的なものも)がなくなってしまいます.
それは「問題の改善」以外の何物でもないのですが,
「バグや問題点の理由(どうしてそうなってしまっていたのか)の理解と,それに対しての2の効能 の理解」といった点が
置き去りになってしまう可能性があることを危惧していました.
(あと,些細なことですが,完全な理想形には程遠い段階でも「とりあえず見た目動いた状態」に行きつくことでモチベーションを保てる,とか.)

でも
>疲れ切っているので
となってしまったのは本末転倒…


とりあえず,本件に関しては,私からは以上とします.
>全く違う
わけではなかったですよね(?)


[以上,とか言っておきながら 最後に追記]
>土門さん
おそらく,ですが,最終的な状態のコードを見ると
「なんだ,そんな簡単なことだったのか」と思われるんじゃないかな,と予想します.
しかし,それを実感するためには
>何度も悩み、やり直し
といったプロセスを経ることが必要なのではないでしょうか.
あまり慎重になることはないと思いますよ.

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#61

投稿記事 by ISLe » 7年前

土門 さんが書きました:>リンク先のスレにわたしが投稿したコードを動かしてみましたか?
で、指している”コード”とは、リンク先のトピのNo: 7のISLeさんのレスにある
"相談者様のコードを改造したコード"のことですよね?
そちらのコードは参考になるとのことですが
相談者の不具合コードの修正版?を全力で理解するように
頑張ろうと考えて大丈夫でしょうか?
必要なことは
>リンク先のスレにわたしが投稿したコードを動かしてみましたか?
の下に書いてあります。

最低限読んで欲しいのは、わたしが追加した関数とそれが使われている箇所です。

分からないことがあれば逐一聞いてください。
土門 さんが書きました:…そういう意味ではこちらのトピのこのISLeさんのレス
http://dixq.net/forum/viewtopic.php?t=1 ... 317#p83325
の理解に努めた方がいいのかな、と思ってます。
そこは既にクリアしたのではないのですか?
そうでないと現時点でまともに動くはずがないのですが。

繰り返し書いてきたことなんですけど、マス単位で処理することと、キャラの向きを考慮すること。

そこまでできて、いったん全部捨てる、その段階まで来てると思ってました。
できていないなら、いままでのやり取りの繰り返しです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#62

投稿記事 by ISLe » 7年前

usao さんが書きました:>そして2.でイジったコードは4.ですべて削除されるでしょうし作業対象も増えます。
作業が増えるのは困りものなのですが,私は,この過程こそが飛ばしてはならないものなのだと考えていました.
内部の当たり判定をマス単位に変更する、の段階だけで過程としては十分だと思いますが。
usao さんが書きました:>わたしが思い描いていたロードマップは、
> 1. 内部の当たり判定をマス単位に変更
> 2. 当たり判定に食い込んでいるピクセル単位の処理を除去
の2の時点で,それまで存在してたバグや問題点(表面化していたものも潜在的なものも)がなくなってしまいます.
それは「問題の改善」以外の何物でもないのですが,
「バグや問題点の理由(どうしてそうなってしまっていたのか)の理解と,それに対しての2の効能 の理解」といった点が
置き去りになってしまう可能性があることを危惧していました.
(あと,些細なことですが,完全な理想形には程遠い段階でも「とりあえず見た目動いた状態」に行きつくことでモチベーションを保てる,とか.)
内部の当たり判定をマス単位に変更するだけで見た目動いた状態に行きつけるはずです。
1.の段階で発生したバグや問題点は1.の段階で解決しなければいけません。
現状は、
  1. 内部の当たり判定をマス単位に変更
  2. ピクセル単位とのズレに起因するバグを排除
  3. 移動できるはずのマスに移動できないパターンの解消
となっている状況で且ついずれもクリアできていません。
クリアできていないのにあちこち手を付けてひたすらバグを量産している状況です。
きちんと理解しないで進めた結果発生したバグに対して場当たり的に対応することが必要なことなのでしょうか。
場当たり的に対応することで問題が広がるだけではないのでしょうか。
わたしにはデスマーチパターンにハマっているとしか見えませんしそう書いてきました。
このまま続けて状況が改善するのでしょうか。

usaoさんがキャラ処理順によって移動できるはずのマスに移動できない現象に対して返信する際、キャラがすり抜けて重なってしまうというバグを放置しましたが、そのあたりに関してどのようにお考えですか?

土門

Re: キャラ同士の重なりについて

#63

投稿記事 by 土門 » 7年前

ISLeさん
すみません、しょーもない質問で恐縮ですが、
キャラの移動をマス単位にしている途中なんですけど、
これは単純に、上を押せば、posY -= タイル縦幅、右を押せば、posX += タイル横幅
みたいなもので大丈夫でしょうか?
あと、移動や当たり判定をマス単位でやれば、
相手の向きを意識する必要もなくなるんですよね?
つまり「向き」の存在意義は今のところ、
移動先を調べる処理をする時だけってことでいいんですよね?

土門

Re: キャラ同士の重なりについて

#64

投稿記事 by 土門 » 7年前

キャラの移動に関する疑似コードです
各キャラの移動処理、こんな感じです、どうでしょうか

コード:

if(歩けるフラグ){
    if(上キー && 入力待ち時間=0){
        muki=上;
             if(移動先調査関数(X,Y,muki)){
                 歩けるフラグ=false;
      }
             if(歩けるフラグ){
                 posY -= マス幅;
                 入力待ち時間 += 1;//待ち時間スタート
             }
   旧座標を利用し、存在場所を表す二次元配列の旧現在値を「0=空き」状態にする
   現座標を利用し、存在場所を表す二次元配列の新現在値に「1=存在」状態にする
   旧座標X,Yに現座標を代入し、旧座標を更新
  }
}
※入力待ち時間変数は>0になる(flgのつもりです)と、待ち時間達成まで+1され続け、達成すると0に初期化されます
これを左押下、下押下、右押下分作ります。
マス移動に関してはどうでしょうか?
ただ、今のところ、これまでの移動先判定のままだと、
キャラ同士がすり抜けてしまいます、、、その関数も直す必要があるのでしょうか?
それともこの移動処理自体、どこか問題がありますか?

土門

Re: キャラ同士の重なりについて

#65

投稿記事 by 土門 » 7年前

訂正
if(歩けるフラグ){
if(上キー && 入力待ち時間=0){←代入になってました

if(歩けるフラグ){
if(上キー && 入力待ち時間==0){←ここは比較が正しいです

土門

Re: キャラ同士の重なりについて

#66

投稿記事 by 土門 » 7年前

上の移動処理は無駄があったのでシンプルにしました。
が、
キャラたちの一歩を16にし、
マス移動させるように出来たのは出来たのですが
移動先に侵入禁止の"1"が格納されてうようが進むようになってしまいました。
つまり、障害物もなにもかもすり抜ける状態です。

見たところ、
ちゃんと移動先の二次元配列に通行禁止の"1"が入っています。

ということは、
walking_flgの設置場所がおかしく、stopが効いていない
か、
移動先であるはずのマスを見ていない
のどちらかであると思われます。

マス移動させるようになった場合、
移動先を調べる関数で注意すべきことはありますか?

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#67

投稿記事 by ISLe » 7年前

えーっとどうしましょうね。

館のコードを最大限活かしたまま内部処理をマス単位に持って行きたかったのですよね。
そこでバグを完全に取ってしまえば、他の部分をマス単位に書き換えるのは単純作業で済むはずだったのです。

振動バグやすり抜けバグを放置したまま進めてしまったためにいわゆる詰み状態なのです。

わたしはデスマーチには関わらないとはっきり書きました。
ですから、わたしがデスマーチパターンだのデスマーチ確定だの書いている時点ではデスマーチではないわけです。
土門さんのプロジェクトの評価ではないのですよ。
このままやり方を変えなければデスマーチ行きだと警告したのにしっかり誘導されてしまいましたね。

現状はわたしの想定外のものがたくさん入ってきていて、それをまともに動くようにするというのは、わたしにとって何のメリットもないのです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#68

投稿記事 by ISLe » 7年前

質問された分については回答しておきます。

各キャラの移動処理をマス単位にするなら、もっとシンプルにできます。

マスの大きさである16という数値を移動処理関連のコードから全て排除してください。
ピクセル単位とマス単位を意識する必要をまず無くしてしまってください。
座標単位は1マスが1です。
描画するときにピクセル座標に変換してください。

参考にした館のコードにないものを追加する必要はありません。

ユーザー入力は、一括で行い、従来のmuki変数に入る値を各キャラの移動処理関数の引数に渡すようにすると良いでしょう。

マスのマーキングは、移動前に現在位置をクリア、移動後に現在位置をセット、としましょう。
旧座標は必要ありません。
アニメーションフェーズ用に必要になると思いますが、移動処理とは切り離して考えます。

マス単位の移動は1フレームですべて完了させます。
移動ラグはアニメーションフェーズで行います。
アニメーションフェーズを実装するまでは、キーを押すとすぐにマスを移動するようになります。
その段階で移動に関する処理のデバッグをします。
アニメーションフェーズを実装してもスキップさせれば良いだけなので並行作業でも良いですが。

マス単位の移動になるとwalking_flagは不要になるので、影響があるのかと問われても回答のしようがありません。


#わたしの理想のロードマップでは、1ピクセル移動がそのまま1マス移動に置き換わって、余分なコードを削るだけで済むはずでした。

土門

Re: キャラ同士の重なりについて

#69

投稿記事 by 土門 » 7年前

なんとなく見えました。
ぜんぜん違う方向に向かってしまった様ですね。
ご要望に添えるよう、もう一度やり直して来ます

土門

Re: キャラ同士の重なりについて

#70

投稿記事 by 土門 » 7年前

ISLeさん
出来ました。完全にマス単位にしました。この考え方は初めてでした、、パズルやテトリスじゃ定石みたいですね。
ただ、ボタン押しっぱなしだと突っ走るので、weightタイムを設定してます。
walking_flg(要は動くflg)はあった方がいいような気がしますし、
このフラグを削除しても同じ状況がなりたつのかまだ自分ではわからないので残してます。

コード:

   if(walking_flg==false){
		if		( key & PAD_INPUT_UP && keyweight==0){  //上ボタンが押されたら
			muki=0;
			this->walking_flg=true;
		}
		else if( key & PAD_INPUT_LEFT&& keyweight==0){	//左ボタンが押されたら
			muki=1;
			this->walking_flg=true;
		}
		else if( key & PAD_INPUT_DOWN&& keyweight==0){//下ボタンが押されたら
			muki=2;
			this->walking_flg=true;
		}
		else if( key & PAD_INPUT_RIGHT&& keyweight==0){  //右ボタンが押されたら
			muki=3;
			this->walking_flg=true;		
		}

		if(this->walking_flg){
			if(IsPLAYERAbleToGo(this->posX,this->posY,this->muki)==1){//移動先になにかいたら
				this->walking_flg=false;}      //歩けないフラグを立てる。
			if(this->walking_flg){
				
				//移動前に現在位置のフラグ削除
				OBNowPoint::getInstance()->OBnowpoint[this->posY][this->posX]=0;
				if     (muki==0){        //上向きならy座標を減らす
						posY-=1;
						this->keyweight +=1;
				}
				else if(muki==1){        //左向きならx座標を減らす
						posX-=1;
						this->keyweight +=1;
				}
				else if(muki==2){        //下向きならy座標を増やす
						posY+=1;
						this->keyweight +=1;
				}
				else if(muki==3){        //右向きならx座標を増やす
						posX+=1;
						this->keyweight +=1;
				}
				//現在位置から新たに2次元配列に存在を表す"1"を代入 ”1”はプレイヤー軍
				OBNowPoint::getInstance()->OBnowpoint[this->posY][this->posX]=1;
			}
		}

		this->walking_flg=false;
		//次回キー入力受付待機時間処理
		if(keyweight >0){
			keyweight +=1;
			if(keyweight >30){
				keyweight = 0;	//初期化
			}
		}
まだ無駄がありますが、とりあえずマス単位で考えるというのは出来たはずですので
報告します。おかげで重なるバグは完全に無くなりました。
ここに、例の「キャラがひとりでも動いたら、まだ動いていないキャラをすべてチェックし直す」を導入するわけですよね?
「内部処理をタイル単位にしておくとこれらの実装を単純なループで構成できます」と言ってましたが
ちょっとどこに設置すればいいのかわかりません。。。場所のヒントをお願い出来ませんか?

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#71

投稿記事 by ISLe » 7年前

土門さんは状態遷移のコードは書いたことがありますか?

前に、マス移動と移動アニメーションの分離とともにユーザー入力も分離すべきと書きました。

現状、キャラのタスクはメインループから直接呼ばれていますよね。
これを、キャラマネージャタスクを作って、キャラマネージャタスクの中にキャラタスクリストを入れるようにしてください。

キャラマネージャタスクの更新メソッドから、キャラの移動メソッドを呼ぶという二段構えにします。
キー入力待ちはマネージャクラスで一括して行うことになります。

とりあえずキャラがひとりでも動いたら~はおいといて、マネージャクラスを挟む形を作ってください。
アニメーションフェーズなど状態遷移の実装もマネージャクラスでまとめて行うことで楽できます。

土門

Re: キャラ同士の重なりについて

#72

投稿記事 by 土門 » 7年前

>状態遷移のコードは書いたことがありますか?

一応sceneで使っております。
要は、タイトル→ステージ→ゲームオーバーと移動させるプログラムですよね?
今のは、どっかのを参考に、ポリモフィズムを利用したものをなんとか使っておりますが
とりあえず、ポリモフィズムを利用しない状態推移自体は
列挙体をつかって組み立てたりしたことはありますが、、。

>現状、キャラのタスクはメインループから直接呼ばれていますよね。
>これを、キャラマネージャタスクを作って、キャラマネージャタスクの中に
>キャラタスクリストを入れるようにしてください。

今のオブジェクトマネージャーclassと、ステージclassの間に、
キャラマネージャタスクclassを作って、間にかまし、
そのキャラマネージャタスクの中で、
オブジェクトマネージャーclassに実行させることのリストを
列挙体で作るイメージですか?
ちょっと初心者には高度なテクニックではないでしょうか?
どこの講座でもまだ見たことない気がしますが。

>キャラマネージャタスクの更新メソッドから、
>キャラの移動メソッドを呼ぶという二段構えにします。
>キー入力待ちはマネージャクラスで一括して行うことになります。
>マネージャクラスを挟む形を作ってください。

この挟むマネージャクラスは、
今回作る「キャラマネージャタスクclass」のことですよね?
(紛らわしくてすみませんが、今キャラ用のオブジェクトマネージャclassが存在しているので、、)

とりあえず、言われてることはわかるのですが
どういう働きをするクラスを実装すればいいのか、イメージが出来ません。
なにを狙っているのか、簡単な流れ図で教えてもらえたり出来ませんでしょうか?
もしくは、参考になるページとか無いでしょうか、んーー、難しいです。

土門

Re: キャラ同士の重なりについて

#73

投稿記事 by 土門 » 7年前

ネットで調べて言われてることがなんとなくわかってきました。
これはゲーム制作においては必ず通るべき道ですね。
というわけでご要望に添えられるものを実装してきます。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#74

投稿記事 by ISLe » 7年前

プロジェクトを見ないで書いてますが、キャラ用のオブジェクトマネージャ(クラス)の位置付けってどういうものでしたっけ。
そのまま流用できるかもしれません。

高度なテクニックではないです。
ただの二重ループです。

既に、メインループ→オブジェクトマネージャクラスの更新メソッド→各キャラの更新メソッド、という呼び出し構成であれば、ユーザー入力部分を各キャラの更新メソッドからオブジェクトマネージャクラスの更新メソッド内に移すだけになります。
やることは無駄に重複しているものを一箇所にまとめることです。

アニメーションフェーズを実装する際に
  1. 入力待ち
  2. 入力があったら移動(これは一瞬)
  3. アニメーション再生中
という状態遷移になります。
アニメーションの内容は各キャラごとに異なるものになります。
アニメーション再生中という状態を一括で扱うには、現状の各キャラに重複した実装では都合が悪いというわけです。


さらに入力関連をコントローラーモジュール化するのが理想ですがとりあえずはおいときましょう。
ちなみにコントローラーモジュール化するとキー入力を記録してリプレイなどの実装が楽にできます。

土門

Re: キャラ同士の重なりについて

#75

投稿記事 by 土門 » 7年前

>プロジェクトを見ないで書いてますが、

自分はメインループで呼んでいないので「?」というのもあったのですが
なるほどです。

>キャラ用のオブジェクトマネージャ(クラス)の位置付けってどういうものでしたっけ。
>そのまま流用できるかもしれません。

キャラ(アイテムもここに入れるつもり)をコンテナとして
すべてのキャラを格納したリストを生成してあるのが
自分のオブジェクトマネージャクラスです。
そして、シングルトンさせてますので
ステージクラスのどこででも呼び出し、
キャラの更新や初期化等させることが出来る状態です。

移動処理については、各キャラクラスの更新処理でさせていますので
ステージクラスでそのキャラリストの更新をさせています。

敵とプレイヤーのクラスは継承クラスで、その上に基底クラスとしてキャラクラスが存在し、
リストに入れてるのはそのキャラ型です。

メインループ上では、メイン更新関数があり、
その中で、シーンクラスの更新関数をおいてます。
シーンがステージになったら、
ステージクラスのコンストラクタ、初期化、
そして更新処理開始となります。
ステージクラスの更新関数の中に、
キャラマネージャクラスの更新関数があり、
そのキャラマネージャの更新関数の中に、
リストにあるすべてのコンテナの更新関数を実行する処理をしてます。

>キャラマネージャタスクの中にキャラタスクリストを入れるようにしてください。
>キャラマネージャタスクの更新メソッドから、
>キャラの移動メソッドを呼ぶという二段構えにします。
>キー入力待ちはマネージャクラスで一括して行うことになります。

すみません、色々調べてみたのですが
やはり今の自分にまだこの文面だけの内容から
今のプログラムを修正する技量が無いようです。
ISLeさんのいうその構造を実現すれば
格段にラクになるのは想像は出来ます。

しかし、類似するゲームプログラムで参考にするサイトが無い以上
(ボスの攻撃を遷移として実装したものとかそういうのは見受けますが)
初心者の完全な独学で組み立てることになりますので
(上記のISLeさんの内容で推測し)
自分だけで組み立てるのは危険だと判断します。

もう少し詳しく解説お願いできないでしょうか?

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#76

投稿記事 by ISLe » 7年前

キャラの移動は1マス単位になり、一瞬で完了するので、もはや更新メソッドで処理するのは適切ではありません。
進行方向のマスを調べて空いていたら移動する、という独立したメソッド(移動メソッドと呼称)を新設してください。
更新メソッドは現時点で空になりますが、アニメーションフェーズの処理を実装することになります。

キャラ専用のマネージャクラスを新設します。
キャラ専マネージャクラスは、個々のキャラクラスに指示を出し、見た目上一斉に動かす役目を持ちます。
ユーザー入力を待ち、ユーザー入力を受けたら各キャラの移動メソッドを呼び出してキャラを移動させ、アニメーションフェーズに以降、アニメーション終了を監視し(予定)、再びユーザー入力を待つ、という処理(状態遷移含む)を、更新メソッド内で繰り返します。
各キャラの更新メソッドも呼び出すようにしておきます。

現時点で必要な作業としては以上というところですが、イメージできますでしょうか。


ネットにある解説、入門書でもそうですが、たいていシステムありきの説明です。
目を引く方向で考えられているので、たいていすぐにボロが出ます。
作成するプログラムは説明しているあいだにボロが出ないような仕様になっています。
ボロが出るころには乗り越えられる力が付いているだろうということでしょうけど。

わたしはブログなどで現場に即したコードを公開することがあるのですが、ボロが出ないうちは違いがないのでよく叩かれます。
しょっちゅう「STL使えよ」って言われますね。

土門

Re: キャラ同士の重なりについて

#77

投稿記事 by 土門 » 7年前

、、、、、単純そうに聴こえるのですが、
イメージが出来ません。

キャラ専用のマネージャクラス
(役割 ユーザー入力を待ち、ユーザー入力を受けたら各キャラの移動メソッドを呼び出して実行)
を新設するということですね?
なんか慣れてないせいか、プレイヤーも仲間も敵も存在するゲームなんですが
それを共通化させた移動?処理で動かすっていうのがイメージしづらいです。

現状は
「移動の入力」「移動可能かどうかの調査」「実際の移動」
を、各キャラのクラス内でしております。

それのどの部分を、キャラ専用マネージャクラスでさせるのでしょうか?
「移動の入力」「移動可能かどうかの調査」ですか?
流れでいうと、新設クラスで、現在のキャラの移動方向入力、
移動可能かどうかの調査、移動可能ならそのキャラの移動メソッドを呼び出して
実行させる。
そんな感じなんでしょうか?
今は、各キャラの更新部分は同じですが、後々いろいろ変わってくるんですが
共通にしてしまって大丈夫なのでしょうか?

確かに移動処理に共通部分はありますが、
やはり、各キャラで細かくはわかれてくるはずですが
(プレイヤーなら移動先がアイテムだと進めて取れる、敵は移動先にアイテムがあると進めないとか)
それらを全部キャラ専用マネージャクラスが担うのでしょうか?

今くみ上げているプログラムのどの部分をまとめて、
その新設するキャラ用マネージャクラスでさせるのかが、まだ見えません。
ずっとプログラムとにらめっこしてるのですが、、、、、、

ちなみに、移動のバグを修正する目的だったので現在は外しておりますが
もともと、全キャラ同士の接触判定を随時調べながら
接触を確認したらその後の処理を各キャラに返す役目を担ったクラスを作っており、
それは正しく動いておりました。
このクラスは接触を察知して、接触後の処理を返すのが目的ですが、
そんな感じとはまた違うんでしょうか?

土門

Re: キャラ同士の重なりについて

#78

投稿記事 by 土門 » 7年前

とりあえず、何度も何度も同じことをお尋ねするのも申し訳無いですし、
トピの方もレス数が異常な数にさしかかりましたしで、
未熟な自分にはまだ早い、説明を受けても理解出来ない馬鹿だ、
ということで、今回のゲームに状態遷移の組み立てを実装のは諦め、
現状の組み方でゲームの制作に戻ろうと思います。
(実装の兆しが見えたら来週中に頑張って実装したいとは思っています)
でも、ISLeさんのおかげで一番問題だったすり抜け、重なりは解決出来ましたし
マス単位で考えるようには出来たので、前よりは複雑にならずに済みそうで、
デスマーチ化は回避されたのではないかなと勝手に思っております。

あと、調べているうちに、
共通した処理関数をひとつのクラスにしてやって
利用するキャラたちで流用しあうというのを覚えましたので
それを実装していこうと思います。
それと今後もC++でゲームを作っていく自分にとって
今回の状態遷移の実装は必ずマスターしないといけない所だと解釈出来ましたので
この先いずれは理解し、実装出来る様にがんばって行く所存です。

ここまで未熟者につき合ってくださり、
本当に感謝しております。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#79

投稿記事 by ISLe » 7年前

土門 さんが書きました:キャラ専用のマネージャクラス
(役割 ユーザー入力を待ち、ユーザー入力を受けたら各キャラの移動メソッドを呼び出して実行)
を新設するということですね?
なんか慣れてないせいか、プレイヤーも仲間も敵も存在するゲームなんですが
それを共通化させた移動?処理で動かすっていうのがイメージしづらいです。
移動処理の中身を共通化するのではないです。
呼び出し方法を共通化しているのです。
いわゆるフレームワークです。
キャラ専用マネージャクラスは移動の指示をするだけで、実際の移動は各キャラの仕事です。

ユーザーが上キーを押したら、キャラ専用マネージャクラスは各キャラに、「みんな上に動けってよ」と指示を出して、各キャラの行動に任せます。
ですから、新たに動けるマスが空いたら、まだ動いていないキャラに再び指示を出してやるのもキャラ専用マネージャクラスの仕事というわけです。
土門 さんが書きました:それのどの部分を、キャラ専用マネージャクラスでさせるのでしょうか?
「移動の入力」「移動可能かどうかの調査」ですか?
キャラクラスに対しては
ISLe さんが書きました:進行方向のマスを調べて空いていたら移動する、という独立したメソッド(移動メソッドと呼称)を新設してください。
と書きました。
ですから、キャラ専用マネージャクラスに移すのはそれ以外の部分です。
土門 さんが書きました:流れでいうと、新設クラスで、現在のキャラの移動方向入力、
移動可能かどうかの調査、移動可能ならそのキャラの移動メソッドを呼び出して
実行させる。
そんな感じなんでしょうか?
違います。
キャラ専用マネージャクラスは、ユーザーの入力を受け、各キャラに指示を出します。
いまのところはそれだけです。
土門 さんが書きました:今は、各キャラの更新部分は同じですが、後々いろいろ変わってくるんですが
共通にしてしまって大丈夫なのでしょうか?
後々各キャラごとにいろいろ異なる実装をするために共通部分を分離しフレームワークを構築しているのです。
ピクセルごとに動かすコードが邪魔になって個別の処理を組み込むのに難儀したのを忘れてしまったのですか?
土門 さんが書きました:確かに移動処理に共通部分はありますが、
やはり、各キャラで細かくはわかれてくるはずですが
(プレイヤーなら移動先がアイテムだと進めて取れる、敵は移動先にアイテムがあると進めないとか)
それらを全部キャラ専用マネージャクラスが担うのでしょうか?
何度も繰り返しますが、キャラ専用マネージャクラスは移動処理を持ちません。
指示を出すだけです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#80

投稿記事 by ISLe » 7年前

土門 さんが書きました:ということで、今回のゲームに状態遷移の組み立てを実装のは諦め、
現状の組み方でゲームの制作に戻ろうと思います。
(実装の兆しが見えたら来週中に頑張って実装したいとは思っています)
でも、ISLeさんのおかげで一番問題だったすり抜け、重なりは解決出来ましたし
マス単位で考えるようには出来たので、前よりは複雑にならずに済みそうで、
デスマーチ化は回避されたのではないかなと勝手に思っております。
新たに空いたマスに移動指示を出す処理はまだできていませんよね。

デスマーチに踏み出そうとしていたのを、デスマーチへ向かう曲がり角の手前まで戻っただけですよ。
ここからデスマーチを避ける方向に進まなければ元の木阿弥なのですが。

土門

Re: キャラ同士の重なりについて

#81

投稿記事 by 土門 » 7年前

ISLeさん
出来ました!!No.79の回答でやっと理解出来ました。
ISLeさんの言う通り、walking_flgも無くしました。
かなりスッキリしたと思います。
この後、キャラに共通する移動メソッドをクラス化してみるつもりです(ですよね?。

ただ、相談があります。
現在、レバーを押すと一マスでは無く、スーッと進んでしまいます。
前回まではweighttimeflgみたいなのを作ってなんとか止めてましたが
ISLeさんなら、どんな風にこれを対処させますか?
教えて頂ければ嬉しいです。

とりあえず、ステージCPPとキャラclassの間に、キャラ専用マネージャclassを挟みました。
バッチリです。
証明のため、確認して頂けたらと思います。
キャラ専用マネージャタスクclassの更新部分です

コード:

void CharaManagerTask::Update(void){
	//ユーザ入力
	int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		if		( key & PAD_INPUT_UP){  //上ボタンが押されたら
			list<sChara*>::iterator it;
			for(it = ObjectMgr::getInstance()->objectlist.begin(); it !=ObjectMgr::getInstance()->objectlist.end(); ++it)
			{
				(*it)->Update(0);}
		}
		else if( key & PAD_INPUT_LEFT){	//左ボタンが押されたら
			list<sChara*>::iterator it;
			for(it = ObjectMgr::getInstance()->objectlist.begin(); it !=ObjectMgr::getInstance()->objectlist.end(); ++it)
			{
				(*it)->Update(1);}
		}
		else if( key & PAD_INPUT_DOWN){//下ボタンが押されたら
			list<sChara*>::iterator it;
			for(it = ObjectMgr::getInstance()->objectlist.begin(); it !=ObjectMgr::getInstance()->objectlist.end(); ++it)
			{
				(*it)->Update(2);}
		}
		else if( key & PAD_INPUT_RIGHT){  //右ボタンが押されたら
			list<sChara*>::iterator it;
			for(it = ObjectMgr::getInstance()->objectlist.begin(); it !=ObjectMgr::getInstance()->objectlist.end(); ++it)
			{
				(*it)->Update(3);}
		}
}
キャラclassの更新部分

コード:

void cPlayer::Update(int mukiadd){//キャラ専用マネージャタスクclassからmukiを受け取る
	this->muki = mukiadd;

	if(IsPLAYERAbleToGo(this->posX,this->posY,this->muki)==0){//移動先になにかいたら				
		//移動前に現在位置のフラグ削除
		OBNowPoint::getInstance()->OBnowpoint[this->posY][this->posX]=0;
		if     (muki==0){        //上向きならy座標を減らす
				posY-=1;
		}
		else if(muki==1){        //左向きならx座標を減らす
				posX-=1;
		}
		else if(muki==2){        //下向きならy座標を増やす
				posY+=1;
		}
		else if(muki==3){        //右向きならx座標を増やす
				posX+=1;
		}
		//現在位置から新たに2次元配列に存在を表す"1"を代入
		OBNowPoint::getInstance()->OBnowpoint[this->posY][this->posX]=1;
	}

	this->muki = 4;
	if(this->life == 0){ this->flg = false;}//オブジェクト消去
}
次はどうすればいいですか?
悩みましたが、楽しかったです。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#82

投稿記事 by ISLe » 7年前

土門 さんが書きました:この後、キャラに共通する移動メソッドをクラス化してみるつもりです(ですよね?。
移動メソッドは更新メソッドとは別の独立したものにしてください。
更新メソッドは、ユーザー入力待機中でも、例えばキャラのその場足踏みアニメを行うなど継続して行う必要のある処理が入ります。
そういう処理が必要なければ更新メソッドでは何もしないようにするべきです。
土門 さんが書きました:ただ、相談があります。
現在、レバーを押すと一マスでは無く、スーッと進んでしまいます。
前回まではweighttimeflgみたいなのを作ってなんとか止めてましたが
ISLeさんなら、どんな風にこれを対処させますか?
教えて頂ければ嬉しいです。
このあとアニメーションフェーズを実装することになります。
キャラ専用マネージャクラスの更新メソッドは、アニメーションフェーズへの状態遷移を処理します。
現時点では適当なフレーム数ウェイトを入れたら、ユーザー入力待ちフェーズに状態遷移して戻るようにしておくと良いでしょう。

キャラクラスも移動処理を更新メソッドから移動メソッドに移せば、一定間隔ごとに一マスずつ移動するようになるはずです。
土門 さんが書きました:キャラ専用マネージャタスクclassの更新部分です
ユーザー入力をいったん記録して、移動メソッドの呼び出しループをひとつにまとめてください。
土門 さんが書きました:次はどうすればいいですか?
悩みましたが、楽しかったです。
キャラの移動メソッドの呼び出しループをひとつにまとめたら、キャラが移動してマスが空いたらまだ移動していないキャラに再び移動指示、の処理を実装してください。
それができたら移動処理はいちおうゴールです。
移動メソッドを呼び出してその中で移動したときは戻り値で判断、既にキャラが移動したかどうかはキャラ自身に覚えておいてもらうようにすると良いと思います。

アニメーションの実装も並行して行うことができます。
とりあえずキャラクラスにはピクセル単位で1マス分、移動前のマスから現在のマスまで移動するアニメを実装するのが良いと思います。
アニメーションを開始するタイミングはとりあえずアニメーションフェーズに入ったら一斉に開始するのでかまわないでしょう。

最終的にはキャラ専用マネージャがアニメーションの開始タイミングをキャラごとに指示する形になるでしょう。
そのあたりに関連する処理はキャラ専用マネージャにまとめたので、試行錯誤もしやすいかと思います。

土門

Re: キャラ同士の重なりについて

#83

投稿記事 by 土門 » 7年前

ISLeさん
お世話になります。
回答ありがとうございます。

>ユーザー入力をいったん記録して、移動メソッドの呼び出しループをひとつにまとめてください。
完了しました。

>現時点では適当なフレーム数ウェイトを入れたら、
>ユーザー入力待ちフェーズに状態遷移して戻るようにしておくと良いでしょう。
完了しました。

>移動メソッドは更新メソッドとは別の独立したものにしてください。
各キャラclassの移動処理は、見ての通り、
まずキャラマネージャタスクclassにてmukiを受け取り、
それを含めたX座標,Y座標,mukiを引数とした移動可能判定関数から始まり、
OKの戻り値を受け取れば、座標を移動させる、といった内容となっております。
この移動をどう更新とは別にしたメソッドにしてやればいいのか、
その区切り具合?がわかりません。
入力フェーズのキャラマネージャタスクから引数として
mukiを受け取るのは正しいですよね?
現在値を格納する話はおいといて、そのmukiを受け取った後の
作業(移動先判定と座標移動)すべてをまとめた関数を作る、ということですか?
だとするとその作った別メソッド内で座標を変えることになりませんか?

>キャラの移動メソッドの呼び出しループをひとつにまとめたら、
>キャラが移動してマスが空いたらまだ移動していないキャラに再び移動指示、の処理を実装してください。
>移動メソッドを呼び出してその中で移動したときは戻り値で判断、
>既にキャラが移動したかどうかはキャラ自身に覚えておいてもらうようにすると良いと思います。

やはりこの処理のイメージが出来ません。
キャラ達に移動が完了したフラグを作って、かつ、戻り値でキャラマネージャタスクに教えるとして、
まだ移動してないキャラの移動を再び実行させる処理が思いつきません。
キャラマネージャタスクは最終的に、「listの中のキャラ全員が移動完了した」ことを認識しているはずですよね?
その方法に戻り値で得たものを使うとしても、list内のキャラ数を知ってないとダメですよね?
size()を使って、全員の数を把握しようとしても、今後listの中にはアイテムや状態が変化する障害物なども
入れてしまうつもりです。ああ、その時はキャラ以外のオブジェクトは移動完了フラグを立ちっぱなしにしてやる感じでしょうか?、、、、、といった感じの面倒なものになりますか?
それともISLeさんはもっと簡単なものを想像してますか?
もう少しやり方の解説をお願い致します。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#84

投稿記事 by ISLe » 7年前

土門 さんが書きました:この移動をどう更新とは別にしたメソッドにしてやればいいのか、
その区切り具合?がわかりません。
難しく考え過ぎだと思います。
現在の更新メソッドの内容をそのまま移動メソッドにするということです。
すべてのタスク共通の更新メソッドは必要です。
土門 さんが書きました:だとするとその作った別メソッド内で座標を変えることになりませんか?
そうなりますね。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#85

投稿記事 by ISLe » 7年前

サンプルコード書いてみました。
カーソル左右キーを押すと赤い四角が一斉に左右に動きます。
全体的としては荒いしコメントもないですが、いま問題になっている点については役に立つかと思います。
89行目をコメントアウトして動作の違いを見てください。

コード:

#include "DxLib.h"
#include <vector>

static const int MAPWIDTH = 7;
static int Map[MAPWIDTH] = { 2,0,0,0,0,0,2 };

struct Task {
	virtual void Update() = 0;
	virtual void Render() = 0;
};

struct Chara : public Task {
	int x0; // 現在位置
	int x1; // 前回位置
	int anim_count;
	int anim_x;
	Chara(int x) : x0(x), x1(x) {
		Map[x0] = 1;
		anim_count = 0;
	}
	bool Move(int muki) {
		if (anim_count == 0) {
			x1 = x0;
			anim_count = 60;
		}
		Map[x0] = 0;
		switch (muki) {
		case 1:
			if (Map[x0-1] == 0) x0--;
			break;
		case 3:
			if (Map[x0+1] == 0) x0++;
			break;
		}
		Map[x0] = 1;
		return isMoved();
	}
	bool isMoved() {
		return x0 != x1;
	}
	bool isAnimate() {
		return anim_count > 0;
	}
	void Update() {
		anim_x = x1*32;
		if (anim_count > 0) {
			if (isMoved()) {
				anim_x = x0*32+(x1*32-x0*32)*anim_count/60;
				anim_count--;
			} else {
				anim_count = 0;
			}
			if (!isAnimate()) {
				x1 = x0;
			}
		}
	}
	void Render() {
		DrawBox(anim_x, 0, anim_x+32, 32, GetColor(255,0,0), TRUE);
	}
};

struct CharaManager : public Task {
	std::vector<Chara> charas;
	enum { MOVE, ANIM };
	int phase;
	CharaManager() {
		changePhase(MOVE);
	}
	void changePhase(int phase) {
		this->phase = phase;
	}
	void move() {
		int muki = -1;
		if (CheckHitKey(KEY_INPUT_LEFT)) {
			muki = 1;
		}
		if (CheckHitKey(KEY_INPUT_RIGHT)) {
			muki = 3;
		}
		if (muki >= 0) {
			bool retry;
			do {
				retry = false;
				std::vector<Chara>::iterator it;
				for (it=charas.begin();it!=charas.end();++it) {
					if (!it->isMoved()) {
						if (it->Move(muki)) {
							retry = true;
						}
					}
				}
			} while (retry);
			changePhase(ANIM);
		}
	}
	void anim() {
		bool finish = true;
		std::vector<Chara>::iterator it;
		for (it=charas.begin();it!=charas.end();++it) {
			if (it->isAnimate()) finish = false;
		}
		if (finish) {
			changePhase(MOVE);
		}
	}
	void Update() {
		switch (phase) {
		case MOVE: move(); break;
		case ANIM: anim(); break;
		}
		std::vector<Chara>::iterator it;
		for (it=charas.begin();it!=charas.end();++it) {
			it->Update();
		}
	}
	void Render() {
		for (int i=0; i<MAPWIDTH; ++i) {
			if (Map[i] == 2) {
				DrawBox(i*32, 0, i*32+32, 32, GetColor(255,255,255), TRUE);
			}
		}
		std::vector<Chara>::iterator it;
		for (it=charas.begin();it!=charas.end();++it) {
			it->Render();
		}
	}
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	ChangeWindowMode(TRUE);
	if (DxLib_Init() != 0) return 0;
	SetDrawScreen(DX_SCREEN_BACK);

	CharaManager charaman;
	charaman.charas.push_back(Chara(1));
	charaman.charas.push_back(Chara(3));
	charaman.charas.push_back(Chara(2));

	while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
		charaman.Update();
		charaman.Render();
	}

	DxLib_End();
	return 0;
}

土門

Re: キャラ同士の重なりについて

#86

投稿記事 by 土門 » 7年前

ISLeさん
ありがとうございます。
こちらはアニメーションフェーズが思ったようにまったくうまくいかず、途方に暮れておりました。
どうあがいても画像のピクセル移動がうまくいきませんでした。
マス通りでは無く、中途半端なところで止まったり、
画像座標は障害物を見てないのでスルりと壁に重なったり、通り抜けたり、、、、
ISLeさんのこのソースを動かしてみました。
おお、現在位置移動フェーズと、画像移動フェーズは別になってますね。
凄いです、まさに実装版ですね
ありがとうございます、自分にとっては複雑なところも見受けますが
研究して理解してみせます

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#87

投稿記事 by ISLe » 7年前

サンプルプログラムでは、キャラはマス移動するとすぐにアニメーションをはじめるようになっていて、アニメーションの終了だけを監視しています。

状態遷移の処理というのは、遷移をコントロールすることです。
キャラごとに移動タイミングをずらしたり、戦闘やアイテムゲットの演出を挟むようにするとなると、キャラ専用マネージャの指示出し処理やキャラ側のフラグ管理などもっと複雑になるでしょう。

移動処理に関してはいちおう目標は達成できたと思います。

演出面に関しては、移動処理と分離しましたので、新たにスレを立てていただいたほうが良いと思います。

土門

Re: キャラ同士の重なりについて

#88

投稿記事 by 土門 » 7年前

ISLeさん
ISLeさんのソースを参考に修正、、、というか
そのまんま取り入れることが出来ました。
大変参考になりました。本当にありがとうございます。
これにて入力フェーズ、移動フェーズ、アニメーションフェーズにわけることも完了しました。
(今回でキャラが重なる、移動がズレる等の不具合は完全に無くなりました)

自分は教えて頂いたソースを分析しながら実装していきましたが、
まだソースすべてをちゃんと理解出来たとは言えません。
それでも次に進みたいと思うのですが、
「いや、演出に移る前に、必ずココで理解しとくべき箇所、繫がりがある」といったことがあるのでしたら
どの部分か聞かせて頂けないでしょうか

ちなみに、次は
>キャラごとに移動タイミングをずらしたり、
>戦闘やアイテムゲットの演出を挟むようにするとなると、
>キャラ専用マネージャの指示出し処理やキャラ側のフラグ管理などもっと複雑になるでしょう。

まさにこれらを実装したいと思っています。
が、当初の自分の組み立てていた構造とは
完全に変わったということで(もちろん、良い意味でです)、
これらの実装を自分でうまく出来るか戸惑いがあります。
というもの、当初は、
当たり判定classを利用して、ピクセル単位で判断し、戦闘については、
プレイヤーが敵と重なった後(とりあえずプレイヤーはマスの区切りまで移動して)
そこからすぐ戦闘が行われ(戦ってる画像を表示)、その結果次第でどちらかの駒が消える
といった処理を施しておりました(ここはまんまボコスカウォーズです)。
しかも、敵からはプレイヤーに重なることが出来ないようにもしてました。
(アイテムについては、プレイヤーがアイテムと重なった後、
 プレイヤー内のパワーアップフラグを立てる、といった感じです。
 そして、そのアイテムはブロックから生まれます。
 ブロックの配置はテキストの読み込みで、ステージCPPのコンストラクタ上で
 プレイヤーや敵と共にオブジェクトlistにインスタンスしては格納するつもりです。)

今回の構造で、これらを実装しようとする場合、
どのような形にすべきでしょうか?
もう完全に当たり判定という概念は捨てて、
移動先に格納された存在フラグの数を増やし、
"1"なら今まで通り侵入禁止、"2"なら移動後戦闘、"3"なら移動後パワーアップ等させる、感じですか?
でも、敵の移動フェーズによる判定の場合は、
アイテムもプレイヤーの存在も、それぞれ侵入禁止フラグと同じに
取らなければなりません。
となれば、各キャラclassのMoveフェーズに詳細を加える感じでいいのでしょうか?

ブロックやアイテムや敵の判定から戦闘など、
それらを加える場合の流れ?みたいなのを聞かせて頂けないでしょうか?
それを参考にし、まずは自分でやってみようと思います。
それでつまずきましたら、トピを立てたいと思いますので
ご助言、ご教示よろしくお願い致します。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#89

投稿記事 by ISLe » 7年前

演出に移る前というわけでなく、ゲームプログラム全般の話になります。
要は状態遷移です。

これから(いままでもですが)いろいろな演出を組み込むにあたり必要な状態遷移の処理というのは…
次の状態に遷移しろと指示があるまでは現在の状態を維持し続ける
という処理です。

待機するオブジェクトは待機中かどうかを判定する処理が必要になるでしょう。
オブジェクトマネージャは、対象オブジェクトの中身を直接見るのは良くないので、監視用のメソッドや指示を出すメソッドを用意することになるでしょう。
とは言え基本的にはこのスレで行った移動処理の実装に近い形になると思います。


マップの進入禁止はあくまでも、進入禁止である、というだけの意味です。
アイテムがあるから、ブロックがあるから、敵キャラがいるから、ではありません。
とにかくそこには進めないから進めないのです。
敵と味方のカテゴリ分けくらいは必要かもしれませんが無闇にフラグの種類を増やす必要はないと思います。

戦闘やパワーアップを移動後に行うのであれば、移動アニメと同じく、移動前に戦闘やパワーアップを行う予定であることを記録しておいて、移動後に実行すれば良いと思います。


わたしがパワーアップアイテムを実装するときは、まずいつでもどこでもパワーアップできるように実装します。
そしてアイテムを取ったらパワーアップするのなら、アイテムを取る瞬間か重なった後かは分かりませんが、適当なタイミングでパワーアップメソッドを呼び出すようにするだけです。
パワーアップだけでなくあらゆることをそういうふうに実装します。
上に書いた進入禁止の話も同じことです。
障害物があろうとなかろうとプログラムのデバッグ実行中に「ちょっとこのマス進入禁止にしてテストしたいな」と思ったらブレークポイントで止めてその場で進入禁止にしたり戻したりできる、そういう作り方をします。

機能を実装するときは一切の前提条件を排して実装する、ということです。
ゲームの仕様とかルールとかの条件というのは機能を利用するときに付けるものですからね。


ですから、今の構造でどのように実装すべきかという問いには、
戦闘もパワーアップも好きなように実装して、適当なタイミングでスタートするように組めば良いのではないか
としか言いようがないのですよね。
そういうことができるプログラム構造にしたつもりです。

土門

Re: キャラ同士の重なりについて

#90

投稿記事 by 土門 » 7年前

ISLeさんの言っていることは頭ではわかります。
無駄が無く、合理的なプログラムの組み方に思えます。
が、情けないですが
自分にはまだそのような方法を描き、そのようなプログラムを組む
実力が備わっておりません。。
多分、フラグを作りまくり、
やりたいことをがむしゃらに加えていくこととなります。
そしてフラグとフレームを利用し、
発動のタイミングも合わせると思います。
汚いプログラムを組んで失敗することも
成長の糧となるとも思いますが、
しかし出来れば、
ISLeさんの考えに添う、いや、無理でもせめて近い方法で
この先の演出を追加していきたいと思っています。。
しかし、まだ思い描けない、、、悔しいです。

>次の状態に遷移しろと指示があるまでは現在の状態を維持し続ける

これは常に意識したいと思います。

>待機するオブジェクトは
>待機中かどうかを判定する処理が必要になるでしょう。

待機中かどうか、、、ですか、、、難しいです、これは。

>敵と味方のカテゴリ分けくらいは必要かもしれませんが
>無闇にフラグの種類を増やす必要はないと思います。

移動先のマスになにがあるかを移動する者が判定してやれば、
一番話が早いという考えなのですがこれはナンセンスでしょうか?
フラグの種類をむやみに増やさずに、移動先のマスにアイテムやブロックがあるというのは
どのように判断させてやればいいのでしょう。。。それもわかりません。

それとも、
>戦闘もパワーアップも好きなように実装して、
好きなようにともありますし、
進入禁止判定メソッドがあくまで進入禁止かどうかを判断するためのメソッドとするならば
オブジェクト同士の判断の処理として、当初のやり方と同じように
オブジェクト同士の接触判定クラスを利用していいのでしょうか??

>タイミングでスタートするように組めば良い

これも意識はしておきます。。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#91

投稿記事 by ISLe » 7年前

いまのところ演出の処理は更新メソッドに詰め込んでいくことになりますから、泥臭くなるのは仕方ないです。
もちろんある程度実装を進めるごとにまとまった部分を関数化するなどのリファクタリングを意識してください。

わたしが書いたサンプルプログラムでは、Chara::anim_countがアニメーションフレーム数とアニメーション再生フラグの両方の機能を担っています。
なのでアニメーションフレーム数を代入した時点で再生が始まってしまい、一時停止することができません。
待機というのは第1フレームで一時停止させることと同じです。
一時停止は真偽値を持つ変数をひとつ用意することで可能になります。

土門 さんが書きました:移動先のマスになにがあるかを移動する者が判定してやれば、
一番話が早いという考えなのですがこれはナンセンスでしょうか?
フラグの種類をむやみに増やさずに、移動先のマスにアイテムやブロックがあるというのは
どのように判断させてやればいいのでしょう。。。それもわかりません。
キャラが他のキャラを直接判定するためには、キャラが他のキャラすべてを知っている必要があります。
最初に土門さんがアップロードしたプロジェクトでは、キャラの組み合わせごとに条件分岐が書いてありましたよね。
あのような形だと新しいキャラの種類を増やすたびにキャラの組み合わせを増やしていくことになります。
2種類なら組み合わせは2
3種類なら組み合わせは5
4種類なら組み合わせは9
アイテムひとつ増やせば組み合わせが一気に増えます。
組み合わせに漏れがないかなど気を使うことになります。
過去に書いたコードがどんどん負担となって覆い被さってきます。

がむしゃらに進むこと自体は悪いことではありませんが、進む方向を誤ると何もかもが無駄になります。
失敗は成長の糧だとしてもただ同じ失敗を繰り返すことにメリットはありません。

組み合わせを1つしか用意しないのがわたしのやり方です。
最初からひとつしかないので過去に書いたコードの影響を受けません。
コードを書くときに考える必要があるのはいまやろうとしていることだけです。
土門 さんが書きました:進入禁止判定メソッドがあくまで進入禁止かどうかを判断するためのメソッドとするならば
オブジェクト同士の判断の処理として、当初のやり方と同じように
オブジェクト同士の接触判定クラスを利用していいのでしょうか??
土門さんが用意した接触判定クラスというのは、比較する対象である自分と相手を直接参照しますよね。

進入禁止はマップ上で進入禁止になっているかどうかを判定しているだけです。
キャラが自分の立っている地面を見るだけです。
誰が進入禁止フラグを立てたのかなんてことは判定時に知る必要がないことです。

ゲームのキャラというのは、概念的には同じ世界で動いているのではなく、個々のキャラはそれぞれの独立した並行世界にいます。
すべての並行世界が同じ形をしているので、重ねてみるとひとつの世界のように見えますが、キャラ同士には接点がないのです。
ですから接点のないもの同士で比較等を行う処理というのは、とても非効率的なことです。

キャラと常に接点があるのは地面、すなわちマップですから、マップを通して他の並行世界と同期を取るのがもっとも効率が良いというわけです。


というわけでクラスにまとめるべきなのは、地面です。
現時点では各キャラに二次元配列を渡して直接フラグを使わせていますが、各キャラが自分の情報を地面に渡して進めるかどうかなどを判断してもらうというのが理想形です。

アイテムの効果などを特殊効果としてまとめて、地面の役割とすることもできます。
特殊効果に抽象化することで、回復アイテムでも回復の泉(地形)でもヒーラー(キャラ)でも同一に扱えます。
特殊効果は回復だけではありません。
罠によるダメージ、地形によるダメージ、戦闘によるダメージ、これらもすべて同一に扱えます。

新たにクラスを作ることにしたらスレがとてつもなく伸びてしまうので中間的な実装に抑えました。
ですから、現時点でも設計としてはあちこちいびつなところがたくさんあります。
いびつなところを直す方向で実装することをお勧めします。

少なくとも並行世界同士に接点を持たせると世界そのものが崩壊しますからそこだけは避けましょう。
複数の並行世界に同時に触れることのできる神の視点を持つオブジェクトを必ず用意してください。

土門

Re: キャラ同士の重なりについて

#92

投稿記事 by 土門 » 7年前

ISLeさん
今回の回答も非常に勉強になりました。
ありがとうございます。

>ゲームのキャラというのは、概念的には同じ世界で動いているのではなく、個々のキャラはそれぞれの独立した並行世界にいます。
>すべての並行世界が同じ形をしているので、重ねてみるとひとつの世界のように見えますが、キャラ同士には接点がないのです。
>ですから接点のないもの同士で比較等を行う処理というのは、とても非効率的なことです。
>キャラと常に接点があるのは地面、すなわちマップですから、マップを通して他の並行世界と同期を取るのがもっとも効率が良いというわけです。

これは非常に目からウロコでした。
今までの自分の考えに新しい風が入ってきた感じなのですが
この概念は、ジャンル問わず、すべてのゲーム制作において
この考え方でいて構わないということなのでしょうか?
例えば横スクロールアクションゲームというもの
(ファミコンでいうところの”忍者くん”や”ロックマン”など)においても
マップを通して同期を取るといった考え方で作るものなのでしょうか?
キャラ同士の接触判定、アイテムとの接触判定等、
今回自分が制作しているゲームとはまったく組み方が変わりそうですし、
その辺気になりました。

>というわけでクラスにまとめるべきなのは、地面です。
>現時点では各キャラに二次元配列を渡して直接フラグを使わせていますが、
>各キャラが自分の情報を地面に渡して進めるかどうかなどを判断してもらうというのが理想形です。

今後すべきことが、なんとなく見えて来ました。
マップ(二次元配列)の1マスに、
いろんな情報を格納出来るようにし、
そして移動するキャラとその地面の情報とを比較して、
取得すべき結果を返すメソッド、を作ってやる。
といった感じでしょうか?
あってますか?

>複数の並行世界に同時に触れることのできる
>神の視点を持つオブジェクトを必ず用意してください。

同時に触れる事の出来る神の視点、、凄いオブジェクトですね、、
そのオブジェクトのスケールのデカさに、
どんなオブジェクトなのかちょっと想像出来ませんが、、。
さっき私が話した”地面の情報とキャラとを比較するソメッド”とかを
オブジェクトにするとかのレベルじゃないですよね?
どのような役目をさせる?クラスを作るのかイメージが出来ませんが、
とりあえずは今回のゲーム制作の話だと
今の段階ではまだ必要がない感じでしょうか、、

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#93

投稿記事 by ISLe » 7年前

土門 さんが書きました:今までの自分の考えに新しい風が入ってきた感じなのですが
この概念は、ジャンル問わず、すべてのゲーム制作において
この考え方でいて構わないということなのでしょうか?
例えば横スクロールアクションゲームというもの
(ファミコンでいうところの”忍者くん”や”ロックマン”など)においても
マップを通して同期を取るといった考え方で作るものなのでしょうか?
ゲームに限らずプログラムの設計においてオブジェクトの相関図はピラミッド型になるのが良い設計だと言われています。
下から上に問い合わせて、上から下に指示を出す、という形です。

アクションゲームの当たり判定となるとピクセル単位で他のキャラと判定を取ることになります。
その場合でも、対象は『キャラ』ではなく、キャラの持つ『判定領域』という形に抽象化します。
各平行世界に、ステージ上のこの部分には何かがあるから触れたら教えて、と下に指示を出して、下のものは触れたら上に問い合わせます。
そこで上のものは何に触れたかをチェックして下のものにリアクションを指示します。
どのキャラにどんなリアクションさせるとか、ついでにエフェクトを発生させるとか、組み合わせは上が決めます。
下のものはそこに何があったのか知らなくとも単に指示されたリアクションを実行します。

相手を知らなくても良いのでギミックが増えてもそのキャラに関する処理は変わりません。
リアクションはキャラの処理なのでパターンが増えたらとうぜん追加しますが、リアクションを起こす要因を気にする必要はありません。

実際にはキャラ=判定領域という実装になることが多いですが、オブジェクト指向で言うところのis aの継承関係と見ることができます。
実際に継承していなくても、実装としては従来とほとんど変わらなかったとしても、そのように考えるだけで効率的に良い方向へ進むはずです。

土門 さんが書きました:マップ(二次元配列)の1マスに、
いろんな情報を格納出来るようにし、
そして移動するキャラとその地面の情報とを比較して、
取得すべき結果を返すメソッド、を作ってやる。
といった感じでしょうか?
あってますか?
地面をクラス化することで、実装を隠蔽化できます。
ですから、下から問い合わせがあった時点で、キャラの位置を確認して回っても下のものには分かりません。
二次元配列を使うかどうかも自由になります。
どんな問い合わせが必要か、そのとき渡すべき情報は何かを考えるのがプログラミングの本質です。

土門 さんが書きました:同時に触れる事の出来る神の視点、、凄いオブジェクトですね、、
そのオブジェクトのスケールのデカさに、
どんなオブジェクトなのかちょっと想像出来ませんが、、。
さっき私が話した”地面の情報とキャラとを比較するソメッド”とかを
オブジェクトにするとかのレベルじゃないですよね?
どのような役目をさせる?クラスを作るのかイメージが出来ませんが、
とりあえずは今回のゲーム制作の話だと
今の段階ではまだ必要がない感じでしょうか、、
神の視点というのはすべてを見通すものではありません。
管理者と言ったほうが良いですかね。
自分の管理下にあるものを見渡し、下からの問い合わせに答えるもののことです。
ここでは神様は分業制ですし神様同士に上下もあります。
地面を管理するのは土地の神様ということになりますかね。

土門

Re: キャラ同士の重なりについて

#94

投稿記事 by 土門 » 7年前

ISLeさん
こんばんは。
あれからも毎日試行錯誤しており、
とりあえず、ISLeさんの助言通りに
ひとマス(地面)をクラスで作り、そのマスが、今どのような状態
(アイテムがあるのか、敵がいるのか、仲間がいるのかといった感じ)
なのかを、常に記録出来るようにしました。
そして、そのマスclassを、マップのサイズの二次元配列の各要素の中に格納した
地面マネージャーclassを作りました。
プレイヤーや敵、アイテムなどが自分の存在するその「マス」に
自分の存在を常に記録しているという感じです。

そして、地面の情報と、キャラクターの情報とを照らし合わせる
ジャッジクラスを作りました。
プレイヤーは、移動が終わる(厳密には移動アニメが終わる)たびに
ジャッジクラスに自分の居場所の情報を渡します。
ジャッジクラスは、受け取ったプレイヤーの座標から
同じ座標(マス)上に別の何かがいるかを地面マネージャクラスから確認し、
リアクションをプレイヤーに指示します。
(プレイヤーは壁と自分の仲間以外のオブジェクトすべてと重なることが出来ますので
重なってからリアクションを仰いでも大丈夫なのです)

(ちなみに「敵」はアイテムやプレイヤーはおろか、自分の仲間など
すべての存在に対して重なることが出来ず、同じマスに入れませんので
移動先になにかが居れば、もうそっちには進めない。
なのでいちいちジャッジクラスを介すこともしておりません。

こんな感じでいけそうなので、組み立ててまいりましたが
現在、情報を渡す?位置で難航しております。
というのも、情報をジャッジクラスに渡したときに、
同じマスに敵がいた場合、とりあえず、プレイヤーと敵をその場に
ストップさせることから始まります(ストップしろとのリアクションの指示を出す。

>わたしが書いたサンプルプログラムでは、
>Chara::anim_countがアニメーションフレーム数とアニメーション再生フラグの両方の機能を担っています。
>なのでアニメーションフレーム数を代入した時点で再生が始まってしまい、
>一時停止することができません。
>待機というのは第1フレームで一時停止させることと同じです。
>一時停止は真偽値を持つ変数をひとつ用意することで可能になります。

ここを何度も読んで、真偽値を持つ変数=stopflgだと思い、
単純にif(stopflg)でどこかを囲んでやり、そのstopflgにtrueを渡せばいい、と
考えたのですがこれがそれらしいところを囲んでも?不具合めいた状況が
起きてしまいます。
プレイヤーclassでstopflgをtrueにしたのに全員が動けなくなったり、、、、、、

現在、プレイヤーclassは主に
Update(主に現在値、画像用座標のリアルタイム更新
Move(向きを受け取り、実際に移動。二次元配列への現在位置の格納
で構成されておりますが
もしかして、stopflgを立てたとしてもプレイヤークラス内で
if(stopflg)~などとどこかを囲み制止させるのは間違ってますか?
キャラマネージャタスクの移動フェーズで、
向きが押されたあと、stopflgが立ってない者だけに反映、みたいな感じですか?
(しかし、行く行く「敵」の移動は入力じゃ無くなります。とすると、
敵の移動は敵クラスの中に書くと思います。となると、移動フェーズ上で制御しても
敵をストップさせることは出来ませんよね??

”重なったらお互いを60フレーム制止させる”
これを実装したいのですが、ISLeさんならどうされますか?
アドバイスを頂きたいのですが、、、、、

土門

Re: キャラ同士の重なりについて

#95

投稿記事 by 土門 » 7年前

ISLeさん
連投になりましたが、先ほどの自分の
>キャラマネージャタスクの移動フェーズで、
>向きが押されたあと、stopflgが立ってない者だけに反映、みたいな感じですか?
をやってみたところ、
かなりスムーズに実装出来ました。

もしかして、敵の移動もキャラマネージャタスク内で
行うことできますか?というか、やる方がいいですよね?
敵はフレームごとに移動を実行、mukiを乱数にしてって感じでしょうか。
それが可能なら、上記の場所は、かなりシックリくる感じなんですが。
しかし、敵のタイプも何種類か作る予定なので、乱数と言わず
プレイヤーの方に向かってくる敵も作ります。
色々なタイプを作るものなら
キャラマネージャタスクのソースの量が膨大になりそうですよね?
それが、各敵クラスに書くならクラスごとに分けられてるので
大した量にならない気もしますし、、、
その辺はどのようにすれば合理的なものになりますか?

現在、プレイヤーのいるマスに敵もいたら
お互いがストップするところまで実装出来ました。
ここで、次に、約60フレーム戦っている画像を表示させて、
ストップ解除間際に勝敗を決める処理をさせ、
敗者の方を削除する感じです。
(まんまボコスカウォーズですね)

その戦闘画像表示は
プレイヤークラスで処理させるか、地面クラスでさせるか、
どちらでも構いませんか?
戦闘といっても、
stopflgがtrueになったら、タイマー開始、タイマーの終わり間際に
勝敗処理(じゃんけんみたいなレベル)、
タイマー終了後にstopflgをfalse、と、しょぼい流れなので
プレイヤーclass内でさせても問題ないでしょうかね。。。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#96

投稿記事 by ISLe » 7年前

マスはクラスにしないほうが何かと都合が良いと書いたのは別のスレでしたね。
まあ土門さんがしたいようにすれば良いので強制するつもりはありませんが。

わたしが言う地面とは、大地(ground,earth)のことです。
マップを神の視点で管理するマネージャということです。

ちなみに神と呼ぶのは、指示は出すけど行動には介入しない、という意味もあります。
神様は決して直接手を下してはいけないのです。

クラスは実装を隠すもので、実装をクラスにすべきではない、と言われます。
ジャッジクラスは正に実装そのもので、良くない設計だと思われます。
土門 さんが書きました:プレイヤーは、移動が終わる(厳密には移動アニメが終わる)たびに
ジャッジクラスに自分の居場所の情報を渡します。
ジャッジクラスは、受け取ったプレイヤーの座標から
同じ座標(マス)上に別の何かがいるかを地面マネージャクラスから確認し、
リアクションをプレイヤーに指示します。
(プレイヤーは壁と自分の仲間以外のオブジェクトすべてと重なることが出来ますので
重なってからリアクションを仰いでも大丈夫なのです)
ジャッジはプレイヤーが呼び出すのですか?
プレイヤーだけですか?
プレイヤーと重なった相手にはどこからどのタイミングでリアクションの指示が出るのですか?
土門 さんが書きました:(ちなみに「敵」はアイテムやプレイヤーはおろか、自分の仲間など
すべての存在に対して重なることが出来ず、同じマスに入れませんので
移動先になにかが居れば、もうそっちには進めない。
なのでいちいちジャッジクラスを介すこともしておりません。
機能に前提を持たせてはいけないと書きました。
敵であれば進めないというのを判断するのもジャッジクラスであるべきです。
そして移動するオブジェクトは例外を許さずすべてジャッジクラスの判断を仰ぐようにしなければいけません。
土門 さんが書きました:同じマスに敵がいた場合、とりあえず、プレイヤーと敵をその場に
ストップさせることから始まります(ストップしろとのリアクションの指示を出す。
(略)
敵の移動は敵クラスの中に書くと思います。となると、移動フェーズ上で制御しても
敵をストップさせることは出来ませんよね??
マス単位の移動では、移動自体が継続しないですから、移動フェーズをストップするという意味が分からないのですが。
アニメーションフェーズはどこにいってしまったのでしょうか。
土門 さんが書きました:”重なったらお互いを60フレーム制止させる”
これを実装したいのですが、ISLeさんならどうされますか?
アドバイスを頂きたいのですが、、、、、
アニメーションフェーズに60フレーム停止するアニメーションを挿入すれば良いのではないでしょうか。
アニメーションフェーズではキャラの移動演出が行われますが、内部的には移動済みで移動フェーズは停止状態です。
どうして移動フェーズを弄る必要があるのでしょうか。

土門 さんが書きました:もしかして、敵の移動もキャラマネージャタスク内で
行うことできますか?というか、やる方がいいですよね?
敵はフレームごとに移動を実行、mukiを乱数にしてって感じでしょうか。
それが可能なら、上記の場所は、かなりシックリくる感じなんですが。
しかし、敵のタイプも何種類か作る予定なので、乱数と言わず
プレイヤーの方に向かってくる敵も作ります。
色々なタイプを作るものなら
キャラマネージャタスクのソースの量が膨大になりそうですよね?
それが、各敵クラスに書くならクラスごとに分けられてるので
大した量にならない気もしますし、、、
その辺はどのようにすれば合理的なものになりますか?
わたしはゲームの仕様を知らないのでマネージャクラスにどんな機能が必要なのか判断できません。
繰り返しますが、マネージャクラスに前提を持った機能を作ってはいけません。

土門さんは何種類もの敵という前提で機能を作ろうとしているので、ソースの量が膨大になりそうなのでしょう。
前に書いたはずですが、前提を作らなければ、敵が何種類いようが一組のソースを書くだけです。
そしてあとから何種類追加するとしてもそこは変わりません。

土門 さんが書きました:その戦闘画像表示は
プレイヤークラスで処理させるか、地面クラスでさせるか、
どちらでも構いませんか?
戦闘といっても、
stopflgがtrueになったら、タイマー開始、タイマーの終わり間際に
勝敗処理(じゃんけんみたいなレベル)、
タイマー終了後にstopflgをfalse、と、しょぼい流れなので
プレイヤーclass内でさせても問題ないでしょうかね。。。
戦闘でキャラが入り乱れるアニメーションをするなら、戦闘アニメ専用のタスクを作りますね。
移動前のマスで各キャラわさわさ動く程度なら、各キャラにアニメーションフェーズを処理させれば良いと思います。
上位にあるはずの地面に関与させてはいけません。

土門

Re: キャラ同士の重なりについて

#97

投稿記事 by 土門 » 7年前

ISLeさん
回答をありがとうございます。
丁寧な解説で、プログラムセンスのある者ならすぐ理解出来るはずなのでしょう、、
情けないことに自分には難しくて理解出来ません。

>マスはクラスにしないほうが何かと都合が良いと書いたのは別のスレでしたね。

そうなんですが、No93のISLeさんの「地面をクラス化することで〜」の言葉を聞いて
自分は今回マスをクラス化するのは良いのだな、と判断しまして。
実際、いろんな情報を地面に持たせるには構造体かクラスしか無いかと。
で、自分としては質問させて頂きました
”マップ(二次元配列)の1マスに、いろんな情報を格納出来るようにし、
そして移動するキャラとその地面の情報とを比較して、取得すべき結果を返すメソッド、を作ってやる。”
に対して別に否定が無かったので実行した、のが今の形でした。
地面はマップのことかと思いまして。

>わたしが言う地面とは、大地(ground,earth)のことです。
>マップを神の視点で管理するマネージャということです。

私のイメージはまさにジャッジクラスがそうなのですが、、、

>ちなみに神と呼ぶのは、指示は出すけど行動には介入しない、という意味もあります。
>神様は決して直接手を下してはいけないのです。

ジャッジクラスは指示を返します。
面倒だからと直接セッターでキャラをいじる不細工なところがまだありますが、
基本的に、受け取った情報からリアクションを指示するイメージで作りました。

>ジャッジクラスは正に実装そのもので、良くない設計だと思われます。

ジャッジクラスは辺に変数も持ってませんから、
確かに隠蔽も活かせて無いと思います。
でもとりあえずクラスで作ってしまった方がよいと思いました。

>ジャッジはプレイヤーが呼び出すのですか?
>プレイヤーだけですか?
>プレイヤーと重なった相手にはどこからどのタイミングでリアクションの指示が出るのですか?

敵もアイテムも自分にプレイヤーが重なったことを知る術はありません。
それを”見ている”のはジャッジクラスです。
プレイヤーがジャッジクラスの関数を呼び出すで引数で自分の座標を渡すのです。
ジャッジクラスはその座標から、一緒の座標になにがあるかをマップを見て判断するわけです。
全体を見ているクラス、見ることが出来るクラスがジャッジクラスなので
自分の中ではジャッジクラスは神の立場のイメージなんですが、、、
で、ジャッジクラスはプレイヤーと重なっている対象オブジェクトを
わざわざリストの中から座標が同じオブジェクトを抽出するわけです。

しかし、個人的にソレ以外の方法でプレイヤーと重なっている敵オブジェクトを
割り出す術が見当たりません。
なぜなら、二次元配列はあくまで敵がいるかどうかのフラグが立っているだけで
その敵が直接そこにいるわけでは無いですよね?
マップ配列[][]〜みたいに一発で対象の敵を指すことが出来ません。
敵はリストに入っているのです。
リストだと、イテレータでリスト内を頭から移動して対象を探すしかありませんよね?
だから、プレイヤーが敵と重なったというのをマップの二次元配列で判断したとしても、
その敵にこんど指示を出そうものなら、リストからそいつを探す作業が必要となります。
それをジャッジクラスの中でしております。
面倒ですが、リスト内のオブジェクトを一発で指すことが出来ない以上
それしか方法がないと思うのですが、、、。

>マス単位の移動では、移動自体が継続しないですから、
>移動フェーズをストップするという意味が分からないのですが。
>どうして移動フェーズを弄る必要があるのでしょうか。

はい、移動フェーズを止めるのは違ったので
今は入力フェーズのところでストップをかけるようにしてます。
ストップ対象のキャラは入力フェーズから除外させるようにしてます。
上手くイメージ通りにストップしてくれてます。


>繰り返しますが、マネージャクラスに前提を持った機能を作ってはいけません。

現在はマネージャクラスは淡々とリスト内のキャラの更新をしているだけです。

ただ、ジャッジクラスでは
まだそのキャラのリストを覗いて、あーだこーだ判断させたりしてしまいます。


>前に書いたはずですが、前提を作らなければ、敵が何種類いようが一組のソースを書くだけです。
>そしてあとから何種類追加するとしてもそこは変わりません。

『前提を作らない』、この意味がいまいち理解出来ません。
前提を作るな、とはどういうことを指しているのでしょう?
また、「敵が何種類いようが一組のソースで構わない」がイメージ出来ません。
二種類の敵がいて、その移動方法がまったく違えば、
すでに一組のソースじゃ無くならないですか?
そういうことでは無いのでしょうか。。

>移動前のマスで各キャラわさわさ動く程度なら、
>各キャラにアニメーションフェーズを処理させれば良いと思います。
>上位にあるはずの地面に関与させてはいけません。

重なっているキャラの上に、
画像を数フレームかぶせるだけの単純な戦闘演出なので
プレイヤークラスの中で済ませても良いと考えました。
移動フェーズとセットのごとく繋がってるアニメーションフェーズに
移動フェーズを無視してアニメーションフェーズを動かす命令を組み込むより
何倍も簡単に思えたので。。

今回の回答で、どうやら自分はISLeさんのイメージとは
ぜんぜん違う?方法で演出しようとしてしまっているようですね、、
しかし、ISLeさんの言うイメージが難しくて分かりません。

ジャッジクラスは、指示を出すだけです。
プレイヤーはジャッジクラスに自分の居場所を渡し、
リアクションを仰ぎます。
また、敵はなににも重なってはいけません、重なることが出来ません。
なので、自分から次の指示を仰ぐ必要は無いはずです。
すべてが後手になるので、相手からのアクションを待つ必要があります。
なのでジャッジに情報を送りません。
移動する以外は、ジャッジからの指示を延々と待つことになるはずです。

ジャッジは行動に介入してはならないとありますが
リアクションを指示するのは構わないんですよね?
リアクションを指示するのと、行動に介入するとの違いがわかりません。
例えば、プレイヤーにフラグの真偽を指示するのが行動への介入というのなら、
プレイヤーにただの数字を返して、
プレイヤーが受け取った数字に当てはめたリアクションを取るのも
やってることは同じな気がするのですが、、、。
ISLeさんの言う、リアクションの指示と、行動の介入の違いがよくわかりません。

すみません、理解力が無くて。
ただ、自分にはプログラムのセンスは無いんで
理解するにはもう少しの解説か、努力の時間を必要とします。

土門

Re: キャラ同士の重なりについて

#98

投稿記事 by 土門 » 7年前

すみません、一部訂正させてください。

>しかし、個人的にソレ以外の方法でプレイヤーと重なっている敵オブジェクトを
>割り出す術が見当たりません。
>なぜなら、二次元配列はあくまで敵がいるかどうかのフラグが立っているだけで
>その敵が直接そこにいるわけでは無いですよね?
>マップ配列[][]〜みたいに一発で対象の敵を指すことが出来ません。
>敵はリストに入っているのです。
>リストだと、イテレータでリスト内を頭から移動して対象を探すしかありませんよね?
>だから、プレイヤーが敵と重なったというのをマップの二次元配列で判断したとしても、
>その敵にこんど指示を出そうものなら、リストからそいつを探す作業が必要となります。
>それをジャッジクラスの中でしております。
>面倒ですが、リスト内のオブジェクトを一発で指すことが出来ない以上
>それしか方法がないと思うのですが、、、。


これは誤りでした。
ジャッジクラスは、敵がいるフラグを確認後、
listを回してまで相手の敵を探して指示をする必要無かったです。
要は、自分と同じところにプレイヤーが来ていれば、
自分がどうするという指示を敵が仰ぐだけでよかったのですよね、
解決しました。
なんとなくわかってきました。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#99

投稿記事 by ISLe » 7年前

土門さんは設計と実装の区別ができていませんね。
センスの問題ではないのですよ。
単純な発想、考え方の問題です。
コードを書かなくても図にするだけではっきり視覚化できることです。
このスレだけで既に同じことを5回くらい繰り返している感じがします。
これ以上説明しても堂々巡りだと思いますが。
土門 さんが書きました:ジャッジクラスは指示を返します。
面倒だからと直接セッターでキャラをいじる不細工なところがまだありますが、
基本的に、受け取った情報からリアクションを指示するイメージで作りました。
どこにいつ指示を出すか、その仕組みが問題なのです。
設計で手を抜くと実装で無駄なコードを大量に書くハメになります。
土門 さんが書きました:敵もアイテムも自分にプレイヤーが重なったことを知る術はありません。
それを”見ている”のはジャッジクラスです。
プレイヤーがジャッジクラスの関数を呼び出すで引数で自分の座標を渡すのです。
ジャッジクラスはその座標から、一緒の座標になにがあるかをマップを見て判断するわけです。
全体を見ているクラス、見ることが出来るクラスがジャッジクラスなので
自分の中ではジャッジクラスは神の立場のイメージなんですが、、、
で、ジャッジクラスはプレイヤーと重なっている対象オブジェクトを
わざわざリストの中から座標が同じオブジェクトを抽出するわけです。
それは実装の話ですよね。
プレイヤーの問い合わせで、敵やアイテムに指示が発生するという仕組みが良くないのです。
敵やアイテムのリアクションにプレイヤーの存在が必要だという前提を作っているからです。
土門 さんが書きました:『前提を作らない』、この意味がいまいち理解出来ません。
前提を作るな、とはどういうことを指しているのでしょう?
また、「敵が何種類いようが一組のソースで構わない」がイメージ出来ません。
二種類の敵がいて、その移動方法がまったく違えば、
すでに一組のソースじゃ無くならないですか?
そういうことでは無いのでしょうか。。
わたしには「移動方法がまったく違う」の意味が理解できません。
移動方法がまったく違うというのは、世界の理を越えるという意味ですか?
プログラムの実装においてそんなことはあり得ませんよね。
用意したマップの上を移動する以上のことができるわけがないのですから。
土門 さんが書きました:重なっているキャラの上に、
画像を数フレームかぶせるだけの単純な戦闘演出なので
プレイヤークラスの中で済ませても良いと考えました。
移動フェーズとセットのごとく繋がってるアニメーションフェーズに
移動フェーズを無視してアニメーションフェーズを動かす命令を組み込むより
何倍も簡単に思えたので。。
移動フェーズとアニメーションフェーズはまったく異なる存在、時間軸です。
繋がっているとか無視するとかどういう意味なのでしょう。
時間軸上の接点がなければ、移動アニメが終わるまで待つことも、移動アニメ再生中に並行して次の移動先を決める操作を行うことも、フラグ一個で切り替えられる、そういうものです。
以前、状態遷移は分かるかと質問しましたよね。
その後も、何回か繰り返し説明しましたよね。
土門 さんが書きました:また、敵はなににも重なってはいけません、重なることが出来ません。
なので、自分から次の指示を仰ぐ必要は無いはずです。
「敵は~だから」というのは前提ですよね。
土門 さんが書きました:すべてが後手になるので、相手からのアクションを待つ必要があります。
なのでジャッジに情報を送りません。
移動する以外は、ジャッジからの指示を延々と待つことになるはずです。
プレイヤーはプレイヤー、敵は敵、という前提を作っていますよね。
土門 さんが書きました:ジャッジは行動に介入してはならないとありますが
リアクションを指示するのは構わないんですよね?
リアクションを指示するのと、行動に介入するとの違いがわかりません。
例えば、プレイヤーにフラグの真偽を指示するのが行動への介入というのなら、
プレイヤーにただの数字を返して、
プレイヤーが受け取った数字に当てはめたリアクションを取るのも
やってることは同じな気がするのですが、、、。
ISLeさんの言う、リアクションの指示と、行動の介入の違いがよくわかりません。
リアクション指示の内容は問題にしていません。
介入というのは、当事者以外が入り込むこと、です。
プレイヤーの行動にジャッジが直接手を下すのはいけませんが、プレイヤーの問い合わせに対して、敵やアイテムを巻き込むことも介入ですよ。

当事者以外を無視できるように、当事者以外を巻き込まないための方法を説明しているのです。
土門さんは現在、当事者以外を巻き込んでいることに気付いていません。
当事者以外を巻き込むことのデメリットも大きくないと考えているようです。
むしろコードを大量に書くことを良しとしているように感じられます。
そこを理解していただかないことには話が通じませんよね。


プレイヤーのリアクション指示はプレイヤーの問い合わせで発生します。
敵のリアクション指示は敵の問い合わせで発生します。
アイテムのリアクション指示はアイテムの問い合わせで発生します。
プレイヤーも敵もアイテムもキャラなのでキャラ用のコードを一組作ればすべてに対応できます。

移動処理で、敵がいるかどうかではなく、マスが空いているかどうか、というふうに判断していたのも同じことです。
意味を理解してください。

土門 さんが書きました:要は、自分と同じところにプレイヤーが来ていれば、
自分がどうするという指示を敵が仰ぐだけでよかったのですよね、
解決しました。
なんとなくわかってきました。
それもちょっと違う気がしますね。
すべてのキャラは常に指示を仰ぐべきです。
その上で、キャラが重なっていたらどうするかを敵が自分で考えるように実装すべきかと。


前に書いた気がしますけど、ボコスカウォーズは重なる前に演出が発生してたと思います。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: キャラ同士の重なりについて

#100

投稿記事 by ISLe » 7年前

理解したいのなら、闇雲に進むより、このスレを最初から何回も読み直したほうが良い気がします。

閉鎖

“C言語何でも質問掲示板” へ戻る