プレイ日記
おちゃめ ochame_nako
DEFで自作関数を作る場合の注意点をいくつか書いておきます。 その例としてBUTTON2関数を作ってみます。 ボタンを押した瞬間はBUTTON(2)を使えば簡単に取得できるのですが、実は「60fpsで動作」以外の場合は正しく動作はしません。 そこで、それを改善したBUTTON2関数を作ることにします。
24そうだね
プレイ済み
返信[1]
親投稿
おちゃめ ochame_nako
例えば60fpsで動作時以外でも「ボタンを押した瞬間」を取得できるBUTTON2関数を作るにはどうするかというと押した瞬間というのは「前回押してないボタン」かつ「今回押したボタン」が分かればいいのです。 標準のBUTTON関数においてBUTTON(2)とした場合には「前回」ではなく「前フレーム」に押したかどうかしか見てくれないため60fpsを超えているプログラムにおいてはその前フレームの情報が変化しないため1回押しただけで何度も押したことになったり、60fps未満のプログラム(もしくは処理落ちしているプログラム)の場合はその前フレームに押されてなくてBUTTON(2)が動作するフレームにたまたま押していた場合にのみ正常に動作するためボタンを押しても反応したり反応しなかったりするわけです。(上記の場合はVSYNC 3を実行中は押してもそのボタン情報が反映されない)
0そうだね
プレイ済み
返信[2]
親投稿
おちゃめ ochame_nako
以上のことを元にすると押した瞬間を取得できるBUTTON2関数は引数に「前回押したボタン情報」を入れて、「今回押しているボタン情報」とそれを加味した「押した瞬間のボタン情報」を戻せば良いことが分かります。 BUTTON2 A OUT B,C  C=BUTTON()  B=NOT A AND C END これは下記のプログラムに使用すれば使うことが可能です。 WHILE 1  BUTTON2 A OUT B,A  ?B  VSYNC 3 WEND
0そうだね
プレイ済み
返信[3]
親投稿
おちゃめ ochame_nako
ボタンを押した瞬間を取得するためには上記のように前回押したボタン情報が必要です。 そのため前回のボタン情報を引数に入れてグローバル変数に戻すことでこのBUTTON2関数は「DEF内ではローカル変数のみで動作」するようになっています。 しかし、戻り値として欲しいのは「押した瞬間のボタン情報」であり実際のプログラム内では使用しない前回のボタン情報まで取得するためにBUTTON2 A OUT B,Aと長々と書く必要があるというのは使い勝手があまり良くありません。
0そうだね
プレイ済み
返信[4]
親投稿
おちゃめ ochame_nako
そこで関数の使い勝手を向上させるために変数Aをグローバル変数として使うことにします。 DEF BUTTON2()  VAR B,C  C=A  A=BUTTON()  B=NOT C AND A RETURN B END これだとこんな感じですっきりとした使用が可能になります。 VAR A WHILE 1  B=BUTON2()  ?B WEND
0そうだね
プレイ済み
返信[5]
親投稿
おちゃめ ochame_nako
ただし、注意する点としてはAはグローバル変数であるということです。 プチコン3号ではローカル変数とグローバル変数を使用できますが、ローカル変数はDEF内だけで使い捨てられる変数であるだけではなくグローバル変数と同じ変数名を付けてもグローバル変数に影響を与えないという大きなメリットがあります。 DEF内でグローバル変数を使いたいという場合は「DEF内でVARを使って宣言しなければ良い」というのではなくそのDEF内で使用されている同名の変数よりも前に記述しておく必要があります。(実行順ではなく記述順) つまり、この2番目のBUTTON2関数を使うためにはDEF外においてBUTTON2関数のDEFより前にA=0とかVAR Aとか記述する必要があります。 これによって、「すでにグローバル変数として使われている変数」と認識されてDEF内ではグローバル変数として使用可能になります。
1そうだね
プレイ済み
返信[6]
親投稿
おちゃめ ochame_nako
さて、自作関数でグローバル変数を使用する場合は他のグローバル変数との被りが問題となります。 Aなんて変数名だともろ被りの危険性が高いので個人的には特定プログラム内で使うのが前提ではなく汎用の自作関数として公開する場合には変数名の前に_(アンダースコア)を付けるというのを「自分内ルール」としています。(あくまで変数の命名ルールは個人の自由) しかし、_Aとしてもすでに使用されているグローバル変数との被りが気になります。 そこでほぼ絶対に被らないグローバル変数としては公開する関数と同じ変数名を付けることです。 BUTTON2だと関数名と被って分かりづらいため_を付けてその関数内で使われているグローバル変数ということを明確化しています。
0そうだね
プレイ済み
返信[7]
親投稿
おちゃめ ochame_nako
VAR _BUTTON2 WHILE 1  B=BUTON2()  ?B WEND DEF BUTTON2()  VAR A,B,C  C=_BUTTON2  A=BUTTON()  B=NOT C AND A  _BUTTON2=A RETURN B END これだと_BUTTON2がBUTTON2関数内で使われているグローバル変数と一目瞭然ですね。
0そうだね
プレイ済み
返信[8]
親投稿
おちゃめ ochame_nako
DEFによる自作関数は慣れれば難しいことは何もないしこれを使うことでプログラミングがかなり楽になります。 便利で汎用性が高い自作関数を作れば次からはそれを使って作れば良いのでプログラミング効率もどんどん高まります。 ただし、汎用性を高めるとどんどん記述が長くなる場合が多いためやはり使い勝手とのバランスも重要となります。 バランスという面では今回のBUTTON2関数においては3番目のもの(グローバル変数_BUTTON2を使ったもの)がベターだと思いますがいかがでしょうか?
0そうだね
プレイ済み
返信[9]
親投稿
おちゃめ ochame_nako
他にもDEFではこれ以外に知っておくと良い部分がいくつかありますが、それは以前こちらのトピックスで書いたので参考にしてみてください。 https://miiverse.nintendo.net/posts/AYMHAAACAAADVHjYtPmLxg 引数、戻り値の「型」の問題は知らないと理解不能(不可解な誤動作)になってしまいます。 DEFによる自作関数は慣れたら手放すことができません。 初心者の人もどんどん使ってみましょう。
0そうだね
プレイ済み
返信[10]
親投稿
おちゃめ ochame_nako
重要なことを書き漏らしていました。(リンク先には書いているのですが) DEF内でローカル変数とグローバル変数の両方が使えるのですが、グローバル変数ではなくローカル変数として使用する場合に必ずDEF内でVAR(もしくはDIM)を使って宣言してください。 そうでないと上記のように記述した順番でローカル変数になる場合もあればグローバル変数になる場合もあるということで誤動作の要因になるためです。 要するに「グローバル変数を使いたい」という明確な意図があれば宣言せず、DEFより前にその変数を記述する(変数を宣言する)ということをすれば良いのですが、それ以外の場合はDEF内で宣言するということだけなので難しいことは何もありません。 ローカル変数とかよく分からなければとりあえず「DEFの中で宣言しておけば外部に影響を与えず自由に変数が使える」という程度の認識でOKです。
0そうだね
プレイ済み
返信[11]
親投稿
初心者向けとしてまとめるならこんな感じ? ・DEFは関数定義で、関数とは何かを渡して計算結果を返す ・DEFの中はプライベート空間なので、変数宣言しても外部には影響しない ・DEFの中でグローバル変数は参照できる、ただし変数名はプライベート変数が優先される ・DEFでの計算結果は必ず返すこと、OUTであってもRETURNであっても ・DEFの中からDEFの外のラベル参照はしちゃいけない ・DEFに渡す値、返す値の型(整数、実数、文字列)はちゃんと意識すること、呼び方を間違えると予期しない動きをするのでちゃんと型を守ること GOSUBと何が違うの?と言われると、どっちも同じようなことができるけど、GOSUBが関数の考えがなかった昔からのなごりで、DEFの方がRND()とかと同じような呼び方が作れていろいろ楽。 ※厳密にはいろいろ細かいことあったりするけど、使う側の概念としてはこんな感じ?
0そうだね
プレイ済み
返信[12]
親投稿
おちゃめ ochame_nako
たんじぇさんへ どうもありがとうございます。 長くなるため私が省いた項目もありますが、まとめるとそんな感じで間違いはないと思います。 最初に箇条書きを行いそれについて説明しても初心者は「そうなんだ・・・」という程度の理解しか得られないため私の文章は興味を惹く内容、需要を考えてBUTTON(2)の代用関数を作ることから始めました。 BUTTON関数ならば初心者でも良く使うし「BUTTON(2)は押した瞬間を取得できる」というのはヘルプを見ればすぐに分かることですが、「実際は60fps以外では正常動作しない」というのはどこにも書いてないことであり、これをきっかけにすれば「DEFなんて難しそう」ではなく「DEFを使えば便利なんだ」という考えに変わるのではないかと考えたわけです。
0そうだね
プレイ済み
返信[13]
親投稿
おちゃめ ochame_nako
「GOSUBではなくDEFによる自作関数をオススメ」という内容のトピックスにするならばまずはGOSUBで作っておいてそれと同じものをDEFで作ってDEFのメリットを具体的に提示することが重要でしょうね。 初心者のためにあらためて書いておくとDEFによる自作関数(自作命令)もGOSUBも「よく使う処理を1つにまとめたもの」にすぎません。 ただし、DEFとGOSUBはお互いにメリットがあります。 GOSUBのメリットは初心者にとって覚えることが少ない(GOTOの延長として考えることができる)というのが最大のメリットでしょう。 DEFはローカル変数が使える、引数や戻り値を記述することで関数への値の受け渡しが楽などがあります。
0そうだね
プレイ済み
返信[14]
親投稿
アドバイスはみんなが自分が初心者当時に経験したのをアドバイスするのが一番いいかもです。 みんな初心者当時はいろいろな方法で勉強してたし、今の初心者もどんな方法がやりやすいかはいろんな方法あるし、初心者向けの書き方ってやっぱり難しいのが。 わからない=基礎が足りてないか知識を組み合わせできていないなので、知りたいものについて、1つ前の基礎と、1つ後の発展を一緒に説明するといい、と心がけてはいるけど、それでもやっぱりなかなか難しいのが。 それでも当時は紙の資料しかなくて、図書館行ったりしてたけど、いまは検索簡単にできるのが世の中便利な時代になったもんj(ry
0そうだね
プレイ済み
返信[15]
親投稿
プログラムを作るのは、設計(どんなふうにプログラムを作るか)とコードを書く(名前の通りBASICでコードを書く)のに分かれるのもあって全体を簡単に説明するのはなかなかむずかしいけど、 設計としてみると、GOSUB/DEFはどっちも同じ関数化で「再利用とモジュール分割」の考えになるので、「何かの処理を個別で任せられる処理は関数化する」という考えで作るといいかも。 同じような処理、今後またどこかで使いそうな処理、ゲームルール処理中にゲームルールとは関係ない何かの計算処理(数学系とかBG更新とか)などを、関数呼び出しとして使えるようにすることが多いので、そういう単位で分割してプログラムを考えるといいかもです。(学校の係当番と同じで、担当を分ける感じ)
0そうだね
プレイ済み
返信[16]
親投稿
おちゃめ ochame_nako
たんじぇさんへ 私は20年以上前から雑誌やWeb等で初心者向け講座を書いていますが、未だに「(絶対的な)正解」というものが見つからないし、そんなものはないと思っています。 人によって経験や理解度が異なるため「初心者」と漠然に考えるのではなく「どのような初心者か」というのを考えてから記述するというのが初心者講座には必要であると私は考えます。 今回の私の内容は「BUTTON関数を使ったプログラムはある程度作れるけどDEFは(知識として)知っているもののあまり使いこなせていない」という初心者をターゲットにしています。 極めて限定的に思えるかもしれませんが、これに当てはまる人は結構多いのではないかと思います。
0そうだね
プレイ済み
返信[17]
親投稿
おちゃめ ochame_nako
(続き) 初心者にゼロから分かるように解説していったらDEFだけで余裕で本1冊書けるくらいの内容になってしまいますのでMiiverseで講座を書くならば、ある程度「自分が伝えたいこと(≒初心者に理解して欲しいこと)」を選択しない限りは無理ですね。 ちなみに私は基本的に説明書も攻略本も見ないでプレイするタイプなのでひたすら試行錯誤で行っています。 新しい関数があればこれは引数が整数型なのか実数型なのか有効範囲はどの程度なのか、戻り値はどうなのかなどを調べてそれから作り始めます。
0そうだね
プレイ済み
返信[18]
親投稿
おちゃめ ochame_nako
(続き) 「(どんなに経験があろうと)分からないものは分からない」というのは当たり前のことですが、その辺は「配列変数って何?」とか言っている初心者と何ら変わりはありません。 したがって、今も「心の中では初心者」です。 つまり、「初心者」の定義そのものが難しいということです。 技術的に難易度が低いものを扱っているのが初心者講座と思いがちですが、実はそうではなく難易度が低いものを「分からない立場」で「分かるように」書いているもの(さらに言えば「分かる」を「できる」に変えるもの)が本当の初心者講座だと私は考えています。
0そうだね
プレイ済み
返信[19]
親投稿
おちゃめ ochame_nako
(続き) では、それをどうやって実現するかが難しいところですが、「(マンツーマンによるアドバイスでない限りは)誰に向けて書いたものか」を明確にすることが必要になると思います。 これができてない講座というのは案外多いです。 理解を促進するのは興味関心だと思いますが、「誰に向けたものか」が明確にならないと「その人が興味を惹くもの」を書くことはできません。 したがって、平易な技術解説と初心者向け講座は似て非なる物なのです。 だからこそ初心者向け講座を書くのは難しいし、初心者向け講座を書くこと自体が自分自身にとっても勉強になると考えています。
0そうだね
プレイ済み
返信[20]
親投稿
ゲームはまったくもって説明書みないであそぶけど、お仕事的には「言語リファレンスは絶対だ」な世界でやってるので、どうしてもプチコンは「公式がこうなので」という説明になっちゃうかなぁ。 miiverseだとプチコンで初めてプログラムを知る人がほとんどだと思ってるので「わからない=基礎が足りてないか知識を組み合わせできていない」はどうしてもあるし、自分はそれをベースにいろいろ基礎をわかりやすく書いてみてるつもりだけど、それがわかりやすいかどうかはやっぱり人次第なのも。 今のようにいろんな人がいろんな考えで解説して、質問した人とそれをROMってる人に向けて知識のデータベースが作れていけばいいのかなーと。
0そうだね
プレイ済み
返信[21]
親投稿
(個人のプレイ日記なので個人的なことを) ちなみにベーマガチャット時代にメーリングリストに参加してたけど、引っ越してメールも変わってしまった現在だったり。 気づけばあれから20年ですよー。 今の名前は当時からちょっと変えてたりしますが。 あのときのメンバーってほとんど繋がりが無いけど、知っている人をまた見かけられるのはうれしい限りです。 (とはいえチャットでは直接会話した記憶があんまり無かったりも)
0そうだね
プレイ済み
返信[22]
親投稿
※メーリングリストの名前書いたら使用できませんな言葉言われた!
0そうだね
プレイ済み
返信[23]
親投稿
おちゃめ ochame_nako
学校の勉強であれば学年ごとに教える内容が決まっていて3年生ならば基本的に2年生までの内容を理解している上で授業を進めることになりますが、趣味で行うプログラミングの場合はそれはないですからね。 不特定多数に向けた講座の場合はそこが一番難しいところです。 本当にプログラミングを始めたばかりの初心者であれば基本的な入力、出力、判断、分岐、繰り返しの命令と変数についての理解がまずは必要不可欠になってきますが、それを理解しているとなると次にどうするかは決まっているわけではありません。 特定個人に向けたアドバイスであれば何をしたいのかをまずは確認した上で当人のそれまでのコメントやこちらからの返答による対応によって何が理解できていて何が理解できてないのか判断することが可能ですが、雑誌上やWeb上での講座の場合はそれができないため難しいです。
0そうだね
プレイ済み
返信[24]
親投稿
おちゃめ ochame_nako
(続き) とはいえ、特定個人に向けたアドバイスならば簡単かというと自分の想定している理解度と本人の理解度の乖離が大きいとなかなかこちらが伝えたいことが伝わらないこともあるため難しいですね。 アドバイスする側もされる側もそれなりに知識や技術がないとうまくいきません。 アドバイスする側はプログラミングの知識も確か必要ですが、質問者の意図を汲み取る技術、その質問者の知識や技術に合わせた返答をしないといけないためすごい技術を持ったプログラマが教えるのが上手いとは限らないわけです。 これは小学の算数の問題が簡単に解けるからといって小学の算数を簡単に教えられるかというのと同じことです。
0そうだね
プレイ済み
返信[25]
親投稿
質問です。 スプライトが衝突した瞬間を取得するにはどうしたら良いですか?
0そうだね
プレイ済み