HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0916
なまこ緩やかに追尾22解決


なまこ

リンク

2020/9/16(Wed) 01:53:24|NO.91376

プログラミングを始めたばかりの者です。
上下左右のキーで操作できる自機に対して敵は自機が近くにいるときに追尾し、遠くに自機がいる場合は適当に画面内で移動するプログラムが知りたいです。
ぜひ助けてほしいです。よろしくお願いします。



この記事に返信する


GENKI

リンク

2020/9/16(Wed) 22:12:26|NO.91382

まずはやりたいことを分解してみましょう。どこまで出来ていて、どこが出来ていないのか、どこがわからないのかが見えないと先に進めません。

> 上下左右のキーで操作できる自機に対して
ここまでは出来ていると考えていいでしょうか。

> 敵は自機が近くにいるときに追尾し、遠くに自機がいる場合は
おそらくここが、この質問で聞きたいポイントなのだと思います。

> 適当に画面内で移動する
この動作はできていますか?

と、いうように理解したのですが、あっていますか?


回答待つのもなんなので予想で回答を続けます。

> 敵は自機が近くにいるときに追尾し、遠くに自機がいる場合は
さらにこれを分解します。

> 敵は自機が近くにいるとき…遠くに自機がいる場合
敵と自機の距離を調べて、距離に応じて敵の動作を切り替えればよさそうです。

> 追尾し
ゲームジャンルや敵キャラの特徴づけ等によってどのアルゴリズムを採用するかは変わって来ます。
しかしここはとりあえず手軽なアルゴリズムを一つ…敵が進む方向を常に自機方向に指定すると、自機を追いかける動作になります。



なまこ

リンク

2020/9/17(Thu) 00:54:06|NO.91384

GENKIさん

回答ありがとうございます!

> 上下左右のキーで操作できる自機に対して
上下左右の自機操作はできます。

> 敵は自機が近くにいるときに追尾し、遠くに自機がいる場合は
自機が近くにいたら追尾するプログラムが知りたいです。

> 適当に画面内で移動する
適当に画面内で移動するプログラムはできていません。


予想の回答もしていただきありがとうございます。
どのようなプログラムで自機が近くにいるときに追尾し、遠くに自機がいる場合は適当に画面内で移動するのか教えていただきたいです。
分からないことが多く、申し訳ありません。よろしくお願いします。



GENKI

リンク

2020/9/18(Fri) 23:41:15|NO.91396

> > 適当に画面内で移動する
> 適当に画面内で移動するプログラムはできていません。

「適当」ってある意味難しいんですよね…。
まずは移動方法ですが、追尾にも利用できる移動方法がいいと思います。つまり方向と速度を与えて移動させる方法です。
方向を自機とは関係なく「適当」に決めてあげれば結果的に適当に動きます。「適当」のルール付けをどうするかはお好みでですね。


> 自機が近くにいたら追尾するプログラムが知りたいです。

NO.91382 で回答済みです。…と言っても回答では分からなかったから再度の質問なんですよね。
回答の中でどこが分からなかったのか、教えていただければ私もわかりません。具体的にどこがわからないと教えていただければ回答のやりようがあるのですが。
距離を調べる方法ですか?指定の方向に動かす方法ですか?敵を移動する方法ですか?うーん、他になにがあるかな…?



なまこ

リンク

2020/9/19(Sat) 23:43:11|NO.91403

GENKIさん
回答ありがとうございます!

説明不足で分かりづらく本当に申し訳ありません…
回答していただいてとてもありがたいです…。


>「適当」ってある意味難しいんですよね…。
「適当」だと確かに難しいですよね…。「適当」というのは訂正して、自機が近くにいない場合その場に居続け、近くに自機がいた場合追尾し離れたら移動した場所に居続けるというプログラムを作ることは可能でしょうか?もし可能であればどのような式を書けば作れるのか教えていただきたいです。
下記のプログラムは敵が自機をずっと追尾するものです。自分で画像を保存して表示していたものを画像を保存しなくていいように文字(自や敵)に置き換えたのですが、置き換えの書き方がわからず実行ができていません。すみません…。一応このような形で追尾のプログラムを書いています…。この式をどのように直せば自機が近くにいるときに追尾する敵ができますでしょうか。


>NO.91382 で回答済みです。…
理解が足らず本当に申し訳ないです…。距離を調べる方法・指定の方向に動かす方法・敵を移動する方法がわからないため教えていただきたいです。
よろしくお願いいたします。


title "追いかける"
wx=800:wy=600 ; 画面サイズ
screen 0,wx,wy
color 0,200,100:boxf 0,0,800,800


*game1
mx=400:my=300 ; プレイヤーの座標
msp=4 ; プレイヤーの移動スピード
ms=22 ; 円のサイズ
ex=50:ey=50 ; 蛇1の座標
frame=0


;自機
stick key,%11111 ; キー入力
;limit p1,p2,p3(一定範囲内の整数を返す) 対象となる値,最小値,最大値
if key&1 : mx=limit( mx-msp, 0, wx ) ; 左移動
if key&4 : mx=limit( mx+msp, 0, wx ) ; 右移動
if key&2 : my=limit( my-msp, 0, wy ) ; 上移動
if key&8 : my=limit( my+msp, 0, wy ) ; 下移動
repeat
pos mx-ms,my-ms mes "自"
loop




;敵
dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める
if dist<(ms*2) : goto *gameover ; 衝突していたら*gameoverへ

ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; Y座標を動かす


redraw 0 ; 画面更新開始
color 0,200,100:boxf 0,0,800,800


;敵
repeat
pos ex-ms,ey-ms ;50-22,50-22
pos 0,0 mes "敵"
loop


redraw 1 ; 画面更新終わり
await 1000/60 ; 1/60秒で画面を更新
frame++ ; フレームを進める
goto *game1 ; 繰り返す


*gameover
; つかまった時の処理
font msgothic,120
color 0,0,65:pos 50,50
mes "つかまえた!"
stop



GENKI

リンク

2020/9/20(Sun) 16:39:41|NO.91406

とりあえず動くようにしてみた。
追尾機能はありません。

title "追いかける" wx=800:wy=600 ; 画面サイズ screen 0,wx,wy color 0,200,100:boxf 0,0,800,800 mx=400:my=300 ; プレイヤーの座標 msp=4 ; プレイヤーの移動スピード ms=22 ; 円のサイズ ex=50:ey=50 ; 蛇1の座標 frame=0 *game1 redraw 0 ; 画面更新開始 color 0,200,100:boxf 0,0,800,800 ;自機 stick key,%11111 ; キー入力 ;limit p1,p2,p3(一定範囲内の整数を返す) 対象となる値,最小値,最大値 if key&1 : mx=limit( mx-msp, 0, wx ) ; 左移動 if key&4 : mx=limit( mx+msp, 0, wx ) ; 右移動 if key&2 : my=limit( my-msp, 0, wy ) ; 上移動 if key&8 : my=limit( my+msp, 0, wy ) ; 下移動 pos mx-ms,my-ms color mes "自" ;敵 dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める if dist<(ms*2) : goto *gameover ; 衝突していたら*gameoverへ ;ex=alien(ex,mx) ; 敵のX座標を動かす ;ey=alien(ey,my) ; Y座標を動かす ;敵 ;pos ex-ms,ey-ms ;50-22,50-22 pos ex, ey color mes "敵" redraw 1 ; 画面更新終わり await 1000/60 ; 1/60秒で画面を更新 frame++ ; フレームを進める goto *game1 ; 繰り返す *gameover ; つかまった時の処理 font msgothic,120 color 0,0,65:pos 50,50 mes "つかまえた!" redraw 1 stop
追尾については後で書きますが、まずは見比べてみて何が問題で動かなかったのかを確認してもらえればと。



GENKI

リンク

2020/9/20(Sun) 17:28:39|NO.91407

スクリプトありがとうございます。
なるほど、スクリプトを見せてもらったおかげで現状が分かった気がします。


> 距離を調べる方法
dist = sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) ; 敵と自機との距離
距離を求める場合、「三平方の定理」を使用します。中3数学の範囲になります。

ついでに言うと、衝突判定のしきい値として使用しているmsはこういうふうに使います。
if dist<ms : goto *gameover ; msは衝突判定円の半径
「サイズ」と書くと直径なのか半径なのかわかりにくいので明確にしたほうがいいでしょう。


> 敵を移動する方法
自機を動かすときと同じで、現在座標に対して移動したい方向に距離を足してあげれば移動できます。
問題はどの方向(XとY)にどのくらい足せばいいか、なので


> 指定の方向に動かす方法
ベクトルを習っていると簡単なんですが、中学の理科と高校2年(数学B)の範囲です。
習っててもよくわからんという人もいます。大丈夫。


; 追尾 ex = ex + double(mx - ex) / dist * msp ey = ey + double(my - ey) / dist * msp pos ex, ey color mes "敵"
これ「mx - ex」が方向であり敵から自機までのX方向の距離。
全体の距離で割って移動したい距離をかける「msp / dist」ことでx方向の移動距離が出ます。「三角形と比の定理」中3数学の範囲。


> 自機が近くにいない場合その場に居続け、近くに自機がいた場合追尾し離れたら移動した場所に居続ける
条件によって動作を分けるのでif文を使用します。
分岐条件は距離なのでdistを使えばいいでしょう。

「その場に居続け」は、ex, eyの中身を変更しなければいいだけです。
追尾は、さっき書きましたね。



> ex=alien(ex,mx) ; 敵のX座標を動かす
> ey=alien(ey,my) ; Y座標を動かす
これだけは何をしようとしていたのか理解できませんでした。
自機の足跡を遅れて追いかける感じかなとも思ったのですがどうも違うようで…外部モジュールの関数かなにかでしょうか。



ねこ

リンク

2020/9/27(Sun) 23:44:37|NO.91462

GENKIさん

回答ありがとうございます。
返信が大変遅くなってしまい申し訳ありませんでした。

>とりあえず動くようにしてみた。
追尾機能はありません。
文字に置き換えてのプログラムを書いてくださりありがとうございました。
追尾の動作は何とか書けました。下記のプログラムが追尾のプログラムです。


No.91403で、私が「自機が近くにいない場合その場に居続け、近くに自機がいた場合追尾し離れたら移動した場所に居続けるというプログラム」を質問させていただき、それに対してGENKIさんから細かい説明やヒントを回答していただいたのですが数日考えましたが、どうしても思うように動きません。ここまで詳しく教えていただいたのに私の知識が足らず申し訳ありません。どんな式を書けば「」で書いた内容の動きになるのか、ヒントではなく正解をぜひ教えていただきたいです。何度も回答のお時間をいただきありがとうございます。再度よろしくお願いいたします。



title "追いかける"
wx=800:wy=600 ; 画面サイズ
screen 0,wx,wy
color 0,200,100:boxf 0,0,800,800


mx=400:my=300 ; プレイヤーの座標
msp=4 ; プレイヤーの移動スピード
ms=8 ; 衝突判定円の半径
ex=50:ey=50 ; 敵の座標
frame=0


*game1
redraw 0 ; 画面更新開始
color 0,200,100:boxf 0,0,800,800


;自機
stick key,%11111 ; キー入力
;limit p1,p2,p3(一定範囲内の整数を返す) 対象となる値,最小値,最大値
;mx=400:my=300 プレイヤーの座標 :msp=4 移動量
;wx=800:wy=600 画面サイズ
if key&1 : mx=limit( mx-msp, 0, wx ) ; 左移動
if key&4 : mx=limit( mx+msp, 0, wx ) ; 右移動
if key&2 : my=limit( my-msp, 0, wy ) ; 上移動
if key&8 : my=limit( my+msp, 0, wy ) ; 下移動
pos mx-ms,my-ms
color
mes "自"


dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める
if dist<(ms*2) : goto *gameover ; 衝突していたら*gameoverへ

;新しい座標=aline(現在の座標,追いかける座標)
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす


;蛇1
gsel 0
pos ex-ms,ey-ms ;50-22,50-22
color 255,255,255:gmode 4,0,0,256 ;画像背景の透明化
color
mes "敵"


redraw 1 ; 画面更新終わり
await 1000/60 ; 1/60秒で画面を更新
frame++ ; フレームを進める
goto *game1 ; 繰り返す

*gameover
; つかまった時の処理
font msgothic,120
color 0,0,65:pos 50,50
mes "つかまえた!"
redraw 1
stop

#defcfunc alien int value, int value2

; 敵が追いかけてくる関数
esp=2 ; 敵の移動スピード
res=limit( value2-value, -esp, esp )
return value+res



GENKI

リンク

2020/9/29(Tue) 01:17:33|NO.91479

すばらしいです。ちゃんと動くスクリプトになっているし、追尾も出来てますね。
なるほどalien はそういう実装の自作関数でしたか。ここまで出来てればあと数行で出来ます。


> 「自機が近くにいない場合その場に居続け、近くに自機がいた場合追尾し離れたら移動した場所に居続けるというプログラム」

全く同じ質問…スクリプトを見る限りはまったくぜんぜん理解できないとは思えないのですがそうですか。
できれば「ここはこう理解したつもりだけど、結果がこんなふうだからあっていない気がする」とか、教えていただければ説明しようがあるのですが…。とりあえず説明してみます。


まずはやりたいことの文章を分解します。

・自機が近くにいない場合(または自機が離れたら)、その場に居続ける
・自機が近くにいた場合、追尾する

この2つの動作に別れます。「自機が離れたら」と「自機が近くにいない」は、自機と敵の今現在の距離の事を指していてどちらも近くにいない場合を指す同じことなので一緒にしています。

文章全体は、「…の場合は〜する。そうでない場合は〜する。」なのでif文を使います。
if文の使い方は大丈夫ですよね?上記の文章でif文を起こしてみます。

if 自機が近くにいる { 追尾する } else { その場に居続ける }
「追尾する」はalien 関数で実装済みですね。
「その場に居続ける」は、ex,eyの値は前回値を使用すればよいので何もする必要はありません。

if 自機が近くにいる { ;新しい座標=aline(現在の座標,追いかける座標) ex=alien(ex,mx) ; 敵のX座標を動かす ey=alien(ey,my) ; 敵のY座標を動かす }
と、ここまでは大丈夫ですか?



ねこ

リンク

2020/9/29(Tue) 03:43:51|NO.91480

GENKIさん

毎回丁寧に回答していただきありがとうございます。


if文の使い方は問題ありません。ありがとうございます。
理解していないところを明確に説明せず失礼しました…。
お恥ずかしいのですが、「?」で示した部分が分からないです。


if() {
;新しい座標=aline(現在の座標,追いかける座標)
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす
} else {

}

ー機が近くにいる と △修両譴傍鐶海韻襦,僚颪方がわかりません…。

仮に近くにいるとき追尾するものを敵2と表して初期位置を
gx=100:gy=200 ; 敵2の座標
として、,賄┐箸竜離を求める式の dist=abs(gx-mx)+abs(gy-my) ですか?

△禄藉位置である gx=100:gy=200 でしょうか?


書き方がめちゃくちゃかもしれません…
再度ご教授いただければ幸いです。



GENKI

リンク

2020/9/29(Tue) 23:59:09|NO.91489

こちらこそ長々とお付き合いいただきありがとうございます。
書き方は大丈夫です。最初に比べればずいぶんわかりやすくなりました。


> ー機が近くにいる (…略…)の書き方がわかりません…。

まずは「自機が近くにいる」を考えてみてください。
簡単に書いてはいますが、状況的には「自機の位置 と 敵の位置 との距離が近い」ということです。
「距離が近い」とは「距離がある値より小さい(または以下)」ということです。
「ある値」は閾値(しきいち)と呼びます。意味はググってください。

まとめると「自機の位置 と 敵の位置 との距離が しきい値 より小さい」となります。
ということで、こうなります。

if 「自機の位置 と 敵の位置 との距離」 < 「しきい値」 { ex=alien(ex,mx) ; 敵のX座標を動かす ey=alien(ey,my) ; 敵のY座標を動かす }
しきい値の大きさは動かしながら適当に決めてください。100とか200とかぐらい?


> ,賄┐箸竜離を求める式の dist=abs(gx-mx)+abs(gy-my) ですか?

gx,gyじゃなくてex,eyですよね。タイプミスかな。

「自機の位置 と 敵の位置 との距離」の正確な値は、この式では出せません。
(mx,my)を仮に(0,0)として、distが同じ値になるような(ex,ey)を紙に書いてみてください。ひし形の図形になるはずです。このことから正確な距離が出せていないことがわかりますよね。この程度の精度でも問題ないのであれば、この式を使って実装してもそれっぽく動作します。
正確な距離の方を使いたい場合は、 NO.91407 で書きましたのでもう一度確認してみてください。


> △修両譴傍鐶海韻襦,僚颪方がわかりません…。

敵が「その場に居続ける」ということは、前のループで「mes "敵"」を実行した瞬間と同じ座標にいるということです。
前回「mes "敵"」が実行された後、「goto *game1」で「*game1」にジャンプして、「ex=alien(ex,mx)」の行まで到着したこの瞬間までの間に敵座標(ex,ey)は変化していますか?
紙に図と変数の値リストを書きながら、スクリプトを1行ずつ追いかけていくとわかりやすいと思います。


> △禄藉位置である gx=100:gy=200 でしょうか?

,解決したらこの値を入れて実行してみてください。百聞は一見にしかずだと思います。



ねこ

リンク

2020/9/30(Wed) 04:00:34|NO.91492

GENKIさん

本当にありがとうございます。


>gx,gyじゃなくてex,eyですよね。タイプミスかな。
タイプミスでした。すみません…


title "追いかける"
wx=800:wy=600 ; 画面サイズ
screen 0,wx,wy
color 0,200,100:boxf 0,0,800,800


mx=400:my=300 ; プレイヤーの座標
msp=4 ; プレイヤーの移動スピード
ms=8 ; 衝突判定円の半径
ex=50:ey=50 ; 敵の座標
frame=0


*game1
redraw 0 ; 画面更新開始
color 0,200,100:boxf 0,0,800,800


;自機
stick key,%11111 ; キー入力
;limit p1,p2,p3(一定範囲内の整数を返す) 対象となる値,最小値,最大値
;mx=400:my=300 プレイヤーの座標 :msp=4 移動量
;wx=800:wy=600 画面サイズ
if key&1 : mx=limit( mx-msp, 0, wx ) ; 左移動
if key&4 : mx=limit( mx+msp, 0, wx ) ; 右移動
if key&2 : my=limit( my-msp, 0, wy ) ; 上移動
if key&8 : my=limit( my+msp, 0, wy ) ; 下移動
pos mx-ms,my-ms
color
mes "自"



;敵
dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める
if dist<(ms*2) : goto *gameover ; 衝突していたら*gameoverへ

;新しい座標=aline(現在の座標,追いかける座標)
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす


;敵と自機の距離
if dist = sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) < 100 {
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす
}else{
dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める
}

;敵
gsel 0
pos ex-ms,ey-ms ;50-22,50-22
color 255,255,255:gmode 4,0,0,256 ;画像背景の透明化
color
mes "敵"


redraw 1 ; 画面更新終わり
await 1000/60 ; 1/60秒で画面を更新
frame++ ; フレームを進める
goto *game1 ; 繰り返す

*gameover
; つかまった時の処理
font msgothic,120
color 0,0,65:pos 50,50
mes "つかまえた!"
redraw 1
stop

#defcfunc alien int value, int value2

; 敵が追いかけてくる関数
esp=2 ; 敵の移動スピード
res=limit( value2-value, -esp, esp )
return value+res


すみません、どうしてもわかりません。
どうすればよいのでしょうか…
プログラミングができなさ過ぎて本当に申し訳ないです。
;敵と自機の距離  のところです。
よろしくお願いします。



GENKI

リンク

2020/9/30(Wed) 23:11:39|NO.91503

> プログラミングができなさ過ぎて本当に申し訳ないです。

大丈夫。諦めず探求することが出来るのであれば上達します。


> ;新しい座標=aline(現在の座標,追いかける座標)
> ex=alien(ex,mx) ; 敵のX座標を動かす
> ey=alien(ey,my) ; 敵のY座標を動かす

この部分をif文の中に移動して、敵の動き方を条件によって切り替える。というのが今回のポイントの一つです。
ということで、この3行はすでにif文内に移動済みなので削除です。


> if dist = sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) < 100 {

こ、これは… if文と変数を理解していないということがはっきりと読み取れます。
なまこさ…あれ?ねこさん?いつの間に入れ替わって?? …きっと中は同じ方ですよね。
ねこさんは普段は、他の方が書かれたスクリプトをコピペしてプログラムをされていることと思います。最初のうちはそれでいいのですが、限界はすぐにやってきます。そして今がその限界です。プログラムの記述の意味を少しずつ理解していきましょう。

まず、if文というのは条件式が正しければ、最初の{〜}内の命令を実行する命令文です。
ねこさんが書かれたスクリプトを見ると条件式の部分は次のようになっています。
 ○○ = □□ < △△
=と<があって、これでは何を比較しているのかわかりません。(「比較」は大丈夫でしょうか。中1数学の範囲です。)
おそらく距離を求める式として NO.91407 に書いた1行を何も考えずにそのままコピペしただけだと思います。

NO.91407
> dist = sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) )

では次に、これが私が提示した距離を求める式です。
もうこの際、sqrt以降の式が何をどう計算しているのかは理解できていなくてもいいと思います。
しかし sqrt(…) の計算結果を変数 dist に代入しているという部分ぐらいは読み取れなければ今後プログラムを続けていくことは困難です。まずは落ち着いて、書いてあるスクリプトを何度も見て、前後の文章も読んで、分かる範囲ででも理解するように努めてみてください。
そうすれば、上記1行を実行した結果、変数distに入っている値が何なのかわかると思います。

初心を思い出して、復習してみるのもいいかもしれません。ベテランでも復習すると新しい発見に出会うことはよくあります。
HSP入門編
https://hsp.tv/make/enroll.html


> }else{
> dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める
> }

NO.91479 の最後でこんな事書いたかな…。どうしてここで敵との距離を簡易的に求めようとしたのか、考えてみたのですがわかりませんでした。(´・ω・`)

> 「その場に居続ける」は、ex,eyの値は前回値を使用すればよいので何もする必要はありません。
と書いたとおり、何もする必要はありません。つまりこういうことです。

if … { ;新しい座標=aline(現在の座標,追いかける座標) ex=alien(ex,mx) ; 敵のX座標を動かす ey=alien(ey,my) ; 敵のY座標を動かす }else{ ; 「動かさない」ので前回ループの値をそのまま使う ex=ex ; 敵のX座標を動かさない ey=ey ; 敵のY座標を動かさない }
else以降では、同じ変数に同じ変数の中身を代入するので、そもそも書く必要がないのでこう書けます。

if … { ;新しい座標=aline(現在の座標,追いかける座標) ex=alien(ex,mx) ; 敵のX座標を動かす ey=alien(ey,my) ; 敵のY座標を動かす }
つまり、NO.91479 の最後で書いたとおりです。



ねこ

リンク

2020/10/1(Thu) 02:37:36|NO.91505

> 大丈夫。諦めず探求することが出来るのであれば上達します。
胸にしみます。ありがとうございます。

> ねこさんは普段は、…
恥ずかしいですが、その通りです。卒論をやるにあたって初めてHSPを使い、あまり理解しないまま提出期限が間近なってとても焦った状態で作成しているのが現実です。本当に情けないです。

> なまこさ…あれ?ねこさん?…
ねこもなまこも同一人物です。混乱させてしまってすみません…いつのまにか混合してしまいました。


> dist = sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) )
この式に数字をあてはめて考えたのですが、
dist=sqrt((50-400)*(50-400)+(50-300)*(50-300))
dist=sqrt((-350)*(-350)+(-250)*(-250))
dist=sqrt(122500+62500)
dist=sqrt*60000

この解釈で合っているでしょうか…?
sqrtを調べて「ルート(平方根)値を返す」と出てきたのですが、60000をルートに直すということなのでしょうか?
無知な私にここまで熱心に教えてくださり本当に感謝しています。
たびたびすみませんが、よろしくお願いいたします。


> NO.91479 の最後でこんな事書いたかな…。
どうしても分からずこれなのではないかと強引に解釈してしまいました。すみません。



あらや

リンク

2020/10/1(Thu) 14:02:56|NO.91507

横から失礼します。

>dist=sqrt(122500+62500)
>dist=sqrt*60000

(122500+62500)は【185000】ですよね。。。
60000はどこから。。。
という数字の謎はおいておきまして。

sqrt(60000) と書くのは
√60000 これと(プログラム言語として√の文字は使いませんが)ほぼ同じです。

つまり
>dist=sqrt*60000
√×60000(ルート掛ける6万)的な意味不明な書き方になるのでこれは違います。

60000の平方根は【244.94897……】なので

dist=sqrt(60000)
dist=244.94897(以下省略)

となります。



GENKI

リンク

2020/10/1(Thu) 14:44:27|NO.91508

なるほど。
まあ、落ち着いてください。
焦っても空回りするだけです。
まずは、お茶でも飲んで一息ついてみてください。
睡眠時間は足りてますか?足りてないならまず寝ましょう。時間がなくても寝ましょう。
食事はちゃんと取っていますか?
不健康は品質不良の原因になります。健康大事。

落ち着いたらこのスレを最初からゆっくり読み直してみてください。
そう難しいことではありません。

あ、速読はだめですよ?



GENKI

リンク

2020/10/1(Thu) 22:52:21|NO.91515

もう10月ですから中間の時期ですね。早いところは終わってるところもあると思います。
焦る気持ちはわかります。私も下期後半にPCが死んだときはどうしようかと思ったものです。

さて、スクリプトがここまで書けた物があるなら、真面目に専念すれば2〜3日あれば十分自力解決できる程度の問題だと思います。(とっくに半月が経過していますね。)
そう思うのですが…中学数学がおぼつかない現状を見るともう少し大変かもしれませんね。頑張ってください。


> dist=sqrt(122500+62500)

あらやさんの指摘にある通り、計算間違えてますね。
60000は、122500-62500 をしたのかな?落ち着いてください。深呼吸しましょう。


> dist=sqrt*60000

なるほどsqrtを変数だと思ったわけですね。
プログラミングでは一般的に乗算の記号「*」は省略することが出来ません。これも数学とは違う特徴なので注意が必要ですね。

すでにねこさんが調べられたとおり、sqrtは平方根を計算する「関数」です。計算結果の数値はこれを実行するとわかりやすいと思います。

ex = 50 ey = 50 mx = 400 my = 300 mes (ex-mx) * (ex-mx) mes (ey-my) * (ey-my) mes (ex-mx) * (ex-mx) + (ey-my) * (ey-my) mes sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) dist = sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) mes dist
自分で電卓を叩いてみて、数値を見比べて確認してみてください。
自機(400, 300) から 敵(50, 50) までの距離 dist は 430 となります。方眼紙に図を書いて定規で測ってみてください。大体合ってると思います。


プログラムでの「関数」の概念についても理解されていないようですし、「変数」も怪しい感じなのでこちらを熟読ください。
最低限の文法は身に付けないとコピペでプログラミングするのも限界がありますよ。というか、すでに限界が来ています。

HSP入門編
https://hsp.tv/make/enroll.html

HSP3 プログラミング・マニュアル 3.10.関数
http://www.onionsoft.net/hsp/v33/doclib/hspprog.htm#FUNC

HSP3 プログラミング・マニュアル 4.4.関数と命令の違いについて
http://www.onionsoft.net/hsp/v33/doclib/hspprog.htm#DIFF_FUNC_COMMAND



小中学生でも習得できている言語です。本気になれば難しくはないはずです。



ねこ

リンク

2020/10/2(Fri) 00:30:52|NO.91518

あらやさん

回答ありがとうございます。

計算ミスで+をーと見間違えて計算してしまいました。すみません…

sqrtの使い方を説明してくださりありがとうございます。
√を表しているのだとようやく理解できました。
ありがとうございます。



ねこ

リンク

2020/10/2(Fri) 01:15:46|NO.91519

GENKIさん

体調を気遣ってくださり涙が出ます…
睡眠時間も食生活も問題ないと思います。
本当にありがとうございます。
提出まで残り1か月半もありませんが卒業できるよう頑張ります。


> dist=sqrt(122500+62500)
その通りで、+とーを見間違えてしまいました。すみません…


> 自分で電卓を叩いてみて、数値を見比べて確認してみてください。
sqrt=√なのだとようやく理解できました。計算して430になりました。


GENKIさんが送ってくださったURLの内容を時間をかけてゆっくり読んでメモしました。ありがとうございます。


自機と敵の距離を表す
sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) を下記の「」にいれることでようやくできたと思ったのですが、何が違うのでしょうか…私はまだ理解が足りなすぎるのでしょうか…


if 「自機の位置 と 敵の位置 との距離」 < 100 {
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす
}



GENKI

リンク

2020/10/2(Fri) 23:46:36|NO.91527

> 体調を気遣ってくださり涙が出ます…

健康を軽視していませんか?心身ともに健康な状態でない状態で作業を行えば、業務に重大な損害を与える場合もあります。
涙を流すくらいなら自覚がおありだと思うので、成果のために最低限の休養を取ることをおすすめします。
体調を気遣っているとかそういう話ではなく、心身の健康維持は業務の一環であり休養はその手段の一つという話です。学業も同じですよ。結果のために体調管理してください。


> sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) を下記の「」にいれることでようやくできたと思ったのですが、何が違うのでしょうか…私はまだ理解が足りなすぎるのでしょうか…

スクリプトに書いて実行してみたのですよね?
どんな動きになりましたか?説明もないスクリプトもないでは見ている我々としては何もわかりません。
実行してみたら、どんな動きになって、動きの何を見てどうして何かが違うと思ったのでしょうか?


プログラムに関する質問をするときは、次のような内容を書くようにすると問題解決がスムーズに行くと思います。
・期待した動作 or 動いてほしい動作
・実際に自分がやったこと
・動かしてみた結果
・期待した動作と動かしてみた動作の違い(どういう見方をしたのか、どういう理由で一致しないと判断したのか)

今回は、1つ目はこれまでのやり取りでだいたい分かっているので、2つ目以降が情報不足で答えようがありません。



ねこ

リンク

2020/10/3(Sat) 00:25:37|NO.91528

GENKIさん

回答ありがとうございます。

睡眠も食事も十分に取っているので問題ないです。
体調管理に気を付けて卒論を進めたいと思います。
ありがとうございます。

> スクリプトに書いて実行してみたのですよね?…
詳しく説明せずすみませんでした。
下記のプログラムで実行したのですが、
・普通の追尾になってしまいます。私が求めている一定の距離になったら追尾する動作にはなりませんでした。
・自機の位置 と 敵の位置 との距離のところにsqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) を入れました。

if 「自機の位置 と 敵の位置 との距離」 < 100 {
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす
}

・動かした結果、普通の追尾になってしまいます。
・端と端にいるにも関わらずずっと追尾するので、求めている動作ではないと判断しました。


title "追いかける"
wx=800:wy=600 ; 画面サイズ
screen 0,wx,wy
color 0,200,100:boxf 0,0,800,800


mx=400:my=300 ; プレイヤーの座標
msp=4 ; プレイヤーの移動スピード
ms=8 ; 衝突判定円の半径
ex=50:ey=50 ; 敵の座標
frame=0


*game1
redraw 0 ; 画面更新開始
color 0,200,100:boxf 0,0,800,800


;自機
stick key,%11111 ; キー入力
;limit p1,p2,p3(一定範囲内の整数を返す) 対象となる値,最小値,最大値
;mx=400:my=300 プレイヤーの座標 :msp=4 移動量
;wx=800:wy=600 画面サイズ
if key&1 : mx=limit( mx-msp, 0, wx ) ; 左移動
if key&4 : mx=limit( mx+msp, 0, wx ) ; 右移動
if key&2 : my=limit( my-msp, 0, wy ) ; 上移動
if key&8 : my=limit( my+msp, 0, wy ) ; 下移動
pos mx-ms,my-ms
color
mes "自"



;敵
dist=abs(ex-mx)+abs(ey-my) ; 敵との距離を簡易的に求める
if dist<(ms*2) : goto *gameover ; 衝突していたら*gameoverへ

;新しい座標=aline(現在の座標,追いかける座標)
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす


;敵と自機の距離
;sqrt=ルート(平方根)値を返す
if sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) < 10 {
ex=alien(ex,mx) ; 敵のX座標を動かす
ey=alien(ey,my) ; 敵のY座標を動かす
}else{
ex=ex ;敵のX座標を動かさない
ey=ey ;敵のY座標を動かさない
}

;敵
gsel 0
pos ex-ms,ey-ms ;50-22,50-22
color 255,255,255:gmode 4,0,0,256 ;画像背景の透明化
color
mes "敵"


redraw 1 ; 画面更新終わり
await 1000/60 ; 1/60秒で画面を更新
frame++ ; フレームを進める
goto *game1 ; 繰り返す

*gameover
; つかまった時の処理
font msgothic,120
color 0,0,65:pos 50,50
mes "つかまえた!"
redraw 1
stop

#defcfunc alien int value, int value2

; 敵が追いかけてくる関数
esp=2 ; 敵の移動スピード
res=limit( value2-value, -esp, esp )
return value+res



GENKI

リンク

2020/10/3(Sat) 01:03:52|NO.91529

なるほど、状況がよくわかりました。これだけわかればすぐ回答できます。

> ・普通の追尾になってしまいます。
まず、常に追尾されてしまう問題ですが、自機と敵の位置に関わらず、敵が移動するようにスクリプトに書かれているのでそれが原因です。
自機と敵との距離で動作を判定する箇所の一つ手前に余計な記述があります。
なお、この問題は NO.91503 の最初の方(2個めの引用のあたり)で指摘済みなので、どこを消すかはそちらを参照ください。

> if sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) < 10 {
スクリプトを拝見しましたが、もう一つ問題がありました。
10じゃなくて100ですよね。10だと近すぎて追いかけだしたら逃げ切れません…というか多分近すぎて衝突判定の方が反応すると思います。これでは正しく動作していても動作が確認できません。100や200など適度に大きな値を設定してください。
試行錯誤していて数値を変更したままうっかり元に戻すのを忘れたのだと思います。こういう戻し忘れは簡単な問題を迷宮入りさせる原因になります。十分ご注意ください。



ところで今更ですが、これも読んでおくことをおすすめします。

HSPTV!掲示板 掲示板の使い方 投稿時の注意
http://hsp.tv/play/pforum.php?mode=about



ねこ

リンク

2020/10/3(Sat) 01:44:14|NO.91530

GENKIさん


> ;新しい座標=aline(現在の座標,追いかける座標)
> ex=alien(ex,mx) ; 敵のX座標を動かす
> ey=alien(ey,my) ; 敵のY座標を動かす

> この部分をif文の中に移動して、敵の動き方を条件によって切り替える。というのが今回のポイントの一つです。
ということで、この3行はすでにif文内に移動済みなので削除です。

この3行を削除すればよかったのですね…ありがとうございます。


> if sqrt( (ex-mx) * (ex-mx) + (ey-my) * (ey-my) ) < 10 {
直し忘れていました。100に戻します。ご指摘ありがとうございます。


> 7.質問は、「〜できません」のような漠然とした内容でなく、具体的な状況を書くと返答しやすいです。
具体的な説明をするよう心がけます…
そのほかの内容も今後の参考にさせていただきます。ありがとうございます。


ようやく求めていた動作ができました…!
ここまで長々とお付き合いいただき本当にありがとうございました。
引き続き卒論を進めていきたいと思います。(またスレッドでお見かけするかもしれません…)
ありがとうございました!!



ONION software Copyright 1997-2021(c) All rights reserved.