龍神録でのbossを動かす関数がよく分からない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
COFE
記事: 97
登録日時: 14年前

龍神録でのbossを動かす関数がよく分からない

#1

投稿記事 by COFE » 14年前

前回も同じようなトピックを立てさせていただいたのですがどこかに行ってしまったので新しく建てさせていただきます
龍神録26章で登場したmove_boss_pos関数というものが登場しました
この説明には

>move_boss_pos関数では x1以上x2以下 y1以上y1以下の範囲でdist離れた位置にtカウントで移動させる関数です。
>適当にあっちこっち向かせてよい位置を決めています。
>1000回試して無理なら諦めます。

とありますが全部何が何だかわかりません
私が作りたい関数はxとyの位置にtimeで移動するというものです
でも龍神録のmove_boss_pos関数は引数x,yを二つとっていたりしますよね
何故そんなことが必要なのでしょうか?
あとdistは何に使うのですか?
そして何故angle=rang(PI);が必要なのでしょうか?
コレを改造してx,yの場所にtカウントで移動するという関数にするにはどうすればよいでしょうか?

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#2

投稿記事 by COFE » 14年前

私の日本語が変でした
後で読んでて恥ずかしいです
一番聞きたかったことは

>コレを改造してx,yの場所にtカウントで移動するという関数にするにはどうすればよいでしょうか?(コレ=move_boss_pos関数)

です。
上の文が分からなかったらこっちだけでもいいので解答お願いします

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 龍神録でのbossを動かす関数がよく分からない

#3

投稿記事 by jay » 14年前

改造よりも自分で作ってしまった方が後でメンテナンスがしやすいですし、経験にもなると思いますが・・・

それはさておき本題ですが
一つの座標(x,y)を指定し、そこにtカウントで移動させるですね

これには今いる座標と目標の座標との角度を求め
その方向に今いる座標と目標の座標との距離の分だけtカウント掛けて移動させてやればいいと思います。

角度を求めるにはatan2関数
距離を求めるにはsqrt関数が一般的かと思われます

「tカウント掛けて進む」の部分は単純にすすむべき距離をtで割ってやれば、1F毎にすすむ距離が 進むべき距離/t となるので
結果的に今いる座標から目標の座標まで進むにはtカウント掛ることになります。
但し等速運動になりますが。


move_boss_pos関数について解説

>引数x,yを二つとっていたりしますよね
横方向はX1以上X2以下、縦方向はY1以上Y2以下
それぞれこの決められた範囲内で移動させるそうです
X1は移動範囲の左端
X2は移動範囲の右端
Y1は移動範囲の上端
Y2は移動範囲の下端
と考えてもらえれば間違いはないと思います、つまりこれらで囲まれた範囲が移動可能範囲ですね。

>あとdistは何に使うのですか?

コード:

x+=cos(angle)*dist;//そちらに移動させる
y+=sin(angle)*dist;
を見る限りdistは移動距離を表し、distの値だけ移動させているようです。

>そして何故angle=rang(PI);が必要なのでしょうか?
横方向はX1以上X2以下、縦方向はY1以上Y2以下の範囲内でdistだけ移動させる、というのは説明しましたが
「どの方向に進む」のかをこれで決めているようです。
PIは弧度方で180度ですので±180度の角度をランダムに取得することで、結果的に360度全ての角度からランダムに角度を取得しているようです。


やっぱり他のお方が作った仕様を分かりやすく解説するのは難しいモノですね(苦笑)
分かりやすいかと聞かれると自信ないですがw
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#4

投稿記事 by COFE » 14年前

うーん、ありがとうございます。move_boss関数のやってることは分かりました。
でも、input_phyとcalc_phyがよく分からなくなってきました。

コード:

//物理的計算をさせる登録をする(指定時間tで定位置に戻す)
void input_phy(int t){//t=移動にかける時間
        double ymax_x,ymax_y;
        if(t==0)t=1;
        boss.phy.flag=1;//登録オン
        boss.phy.cnt=0;//カウンタ初期化
        boss.phy.set_t=t;//移動にかける時間をセット
        ymax_x=boss.x-BOSS_POS_X;//移動したい水平距離
        boss.phy.v0x=2*ymax_x/t;//水平成分の初速度
        boss.phy.ax =2*ymax_x/(t*t);//水平成分の加速度
        boss.phy.prex=boss.x;//初期x座標
        ymax_y=boss.y-BOSS_POS_Y;//移動したい鉛直距離
        boss.phy.v0y=2*ymax_y/t;//鉛直成分の初速度
        boss.phy.ay =2*ymax_y/(t*t);//鉛直成分の加速度
        boss.phy.prey=boss.y;//初期y座標
}

コード:

//物理的キャラクタ移動計算
void calc_phy(){
        double t=boss.phy.cnt;
        boss.x=boss.phy.prex-((boss.phy.v0x*t)-0.5*boss.phy.ax*t*t);//現在いるべきx座標計算
        boss.y=boss.phy.prey-((boss.phy.v0y*t)-0.5*boss.phy.ay*t*t);//現在いるべきy座標計算
        boss.phy.cnt++;
        if(boss.phy.cnt>=boss.phy.set_t)//移動にかける時間分になったら
                boss.phy.flag=0;//オフ
}
僕の考えが正しかったらinput_phyで移動データを代入後、calc_phyで毎ループごとに計算させているんですよね?
ただ、v0xとかaxとかがよく分からないです
calc_boss関数は
calc_boss(double bossidoukyorix,double bossidoukyoriy,int spd,int t){
boss.x=sin(bossidoukyorix)*spd
boss.y=cos(bossidoukyoriy)*spd
if(t==移動時間){
bossidoukyorix=0;
bossidoukyoriy=0;
}
こんな感じでいいのかなと思ったのですがいいんでしょうか?
というか質問ばかりでもあれなので一旦プログラム作ってきますね

それとあまり関係ないのですが龍神録のソースが読みづらい気がする乗って僕だけですかね(グローバル変数だからかな)

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#5

投稿記事 by COFE » 14年前

あれ?
input_phy関数とinput_phy_pos関数の違いは何ですか?

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 龍神録でのbossを動かす関数がよく分からない

#6

投稿記事 by jay » 14年前

calc_phyで毎ループごとに計算させているのは正解のようですね
input_phyで移動データを代入というより登録と言った方が正しいと思いますが、意味としてはほぼ同じなのでこちらも正解かと。

input_phy関数とinput_phy_pos関数の違いですが
input_phy_posはmove_boss_pos関数で
input_phyはenter_boss関数でそれぞれ呼ばれていますね

input_phy_pos関数はmove_boss_pos関数に渡した値を処理した上で呼び出されていました。
つまり実際にボスの移動を登録している部分かと思われます。

input_phy関数はボスの登場時や弾幕終了時にボスを定位置(中央やや上)に戻すのに呼び出されているようです。


で、先程2つの関数とにらめっこしてみましたが、処理事態は全く同じようです。
ただinput_phy関数はボスを定位置に戻すためだけに使っているので、引数は減っているようです(移動する場所が固定のため)
input_phy_pos関数はそれ以外の移動登録に使用されているようです。


僕なんかが説明するより、コレを作ったDixqさんご本人が説明された方がよっぽど早くて分かりやすいんじゃないか。
と今気づきましたw
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#7

投稿記事 by COFE » 14年前

そうですよねー
やっぱり作者直々の解説を頂きたいところですw
あ、でもjayさんのもすごく分かりやすいです
いまboss_shot.cppの内容を書き直してるところですがなかなかうまいこといかず四苦八苦しています
とりあえずDixqさん待ちますね

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

Re: 龍神録でのbossを動かす関数がよく分からない

#8

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

私も龍神録の隅から隅まで詳しくないですが、いつでもDixqさんが現れるとも限らないので解析してみませんか?

「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2

printfを使って数値の変化を追うだけで色々分かって来ると思いますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#9

投稿記事 by COFE » 14年前

softya(ソフト屋) さんが書きました:私も龍神録の隅から隅まで詳しくないですが、いつでもDixqさんが現れるとも限らないので解析してみませんか?

「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2

printfを使って数値の変化を追うだけで色々分かって来ると思いますよ。
解析して自分で調べてもいいんですが僕はもっと根本的なところからわかってないんです
a0xとかphyとか意味のわからない用語がたくさんあります
それにグローバル変数だらけでDixqさんがどの処理をどのようにしているのか分からいのです
僕的には等速運動でボスを動かせればそれだけでいいのですが、それも儘なりません
必要な関数と不要な関数の違いが分からないのです
boss.hagoromoなんて反魂蝶意外では使わなさそうな変数がボスメインループに存在したりしてより一層ややこしくなっています
正直私にはわかりません
この辺は作った人にしか分からないことだと思います
ぶっちゃけ龍神録はスパゲッティコードじゃないでしょうか?
私の読み方が悪いだけかもしれませんが理解にかなりの時間を要しました
23章まではやっている内容が分かりやすかったのでなんとか読めたのですが、私は物理演算が分かりません
よって26章でやっている処理がわからないんです
何を消していいのか何を残すのか何をどう変えれば等速直線運動する処理に変わるのかボスのメインループはどう読んでどう改造すればいいのか……
こんな状態でデバッガ使ってもいみわからない値がいっぱい出てくるだけです
変数の内容がわからないのではありません、関数の挙動が全然分からないのです
私はDixqさんを待ちます
確かに常駐しているわけではないでしょうがそのうち来てくれると思いますし

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

Re: 龍神録でのbossを動かす関数がよく分からない

#10

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

龍神録のようなゲームを作るのを目的とされるなら、ZEROから作った方が勉強になると思います。
無理をして理解・移植しなくて良いのでは無いでしょうか。
雑魚の動きがわかるなら、雑魚の延長線でボスを作ればよいだけだと思います。

結局、座標はboss.xとboss.yを計算すれば良いので、
boss.phy.prexやらboss.phy.v0xやらboss.phy.axは加速度運動式用の変数なので不要なのです。
これらを構造体から削除して関連関数を削除しても代わりに等速度運動式を入れれば問題ありません。
calc_phy()は、意味的にcalc_boss_pos()とかに名前を変えないとマズイでしょが。
ぶっちゃけ龍神録はスパゲッティコードじゃないでしょうか?
私の読み方が悪いだけかもしれませんが理解にかなりの時間を要しました
私は、そのようには感じません。
言われるとおり、多少変数がごちゃごちゃしてる気もしますが、こういうのをスパゲッティコードとは言いません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#11

投稿記事 by COFE » 14年前

スパゲッティはgotoを多用した奴に使う言葉でしたね、勘違いしていました、すいません
それで今オリジナルのmove_boss.cppを作っているのですが

コード:

#include "../include/GV.h"

double bossposatan2(double x,double y){
	return atan2(y-boss.y,x-boss.x);
}

void input_move_boss(double x,double y,int spd){
	boss.move.x=x;
	boss.move.y=y;
	boss.move.spd=spd;
	boss.move.flag=1;
}

void move_boss(double x,double y,int spd){
	double angle=bossposatan2(x,y);
	boss.x+=sin(angle)*spd;
	boss.y+=cos(angle)*spd;
        if(boss.x>x || boss.y>y) boss.move.flag=0;
}
こんな形になりました
でも、一個問題なのが

コード:

if(boss.x>x || boss.y>y) boss.move.flag=0;
これって、最初書いていたときには「ボスの移動したい座標に到達したら移動フラグを折る」というのを考えていました
でもよくよく挙動を見ると上に移動するときと右に移動するときはコレで問題ないのですが、下に移動するときと左に移動するときになにもしないまま速攻デフラグが折れてしまいます
そりゃこんな書き方しているんですから当然ちゃあ当然ですが、この挙動何とかするにはどうすればいいですか?
それ以前にsin,cosの使い方はこれでいいのでしょうか?

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 龍神録でのbossを動かす関数がよく分からない

#12

投稿記事 by Dixq (管理人) » 14年前

不在にしてすみません。

> 私は物理演算が分かりません

特に物理演算は使っていませんよ。
確かに物理で習う式を利用していますが、一般的に言われる物理演算をしているわけではないと思います。

> 解析して自分で調べてもいいんですが僕はもっと根本的なところからわかってないんです
> a0xとかphyとか意味のわからない用語がたくさんあります

aは加速度、vは速度、v0は初速度、spdはスピード、angは角度、cntはカウンタなどを表しています。
関数名に関して、calcは計算、phyは物理的なを意味しています。

> 変数の内容がわからないのではありません、関数の挙動が全然分からないのです

龍神録の館は設計のお手本を紹介したものではありません。
最初はポインタや難しい構文は一切使わずなんとか初心者にも難しくない内容でゲームの作り方が紹介できないかと作り始めたものです
(結局そんなことはできなかったわけですが)
設計についての理解がある程度あり、カプセル化の利点を理解されているなら、また違った設計をすることをお勧めします。
ゲームプログラミングの館の「ゲームプログラミング設計」のコーナーでグローバル変数を使わない設計の方法を紹介しています。
よければ参考にして下さい。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 龍神録でのbossを動かす関数がよく分からない

#13

投稿記事 by ISLe » 14年前

以下のコードでtフレーム後に(x,y)に到達します。
角度も速度も三角関数も使わず素直に等速度運動の式を用いました。
tメンバを勝手に作ってしまったので適当な他のメンバに当てはめてください。

コード:

#include "../include/GV.h"
 
void input_move_boss(double x,double y,int t) {
    boss.move.x=x;
    boss.move.y=y;
    boss.move.t=t;
    boss.move.flag=1;
}
 
void move_boss() {
    boss.x = boss.move.x + (boss.x - boss.move.x) * (boss.move.t - 1) / boss.move.t;
    boss.y = boss.move.y + (boss.y - boss.move.y) * (boss.move.t - 1) / boss.move.t;
	--boss.move.t;
    if (boss.move.t <= 0) boss.move.flag=0;
}

COFE
記事: 97
登録日時: 14年前

Re: 龍神録でのbossを動かす関数がよく分からない

#14

投稿記事 by COFE » 14年前

>ISleさん
本当にありがとうございました
ずっと求めてた挙動はこれです
ずっとずっとこれをもとめて関数を作っては失敗の繰り返しでした
今までこんな関数がのどから手が出るほどほしかったです
ありがとうございました

>Dixqさん
龍神録ってこんなに難しいのにこれでも初心者向けなんですね
こんどC++に書き換えながら1から学んで行こうと思います(softyaさんにもZEROからといわれたことですし)

皆さんありがとうございました

閉鎖

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