//debug. if( 0 ) { addEventListener( "load", async function() { let seek = 0; let seek2 = -1; let place; //クッキー読み込み console.log( document.cookie ); let cookies = new Object(); let pairs = document.cookie.split( '; ' ); for( let i = 0; i < pairs.length; i++ ) { let pair = pairs[ i ].split( '=' ); cookies[ pair[ 0 ] ] = pair[ 1 ]; } if( cookies.navicontinue ) { document.cookie = "navicontinue=; max-age=0"; seek = cookies.naviseek; seek2 = cookies.naviseek2 - 1; seek2 = 0; // seekAtEndOfPart = cookies.naviseekAtEndOfPart; //check. // if( seek2 == -2 ) { // seek -= 1; //check. // if( seek == -1 ) seek = 0; // seek2 = seekAtEndOfPart; // } place = decodeURIComponent( cookies.naviplace ); console.log( "cookie loaded:", seek, seek2, place ); } await srcnavi( a_navi, seek, seek2, place ); let restart = function() { let seek, seek2, place; //クッキー書き込み seek = this.seek; seek2 = this.seek2; place = this.place; document.cookie = "naviseek=" + encodeURIComponent( seek ) + "; "; document.cookie = "naviseek2=" + encodeURIComponent( seek2 ) + "; "; // document.cookie = "naviseekAtEndOfPart=" + encodeURIComponent( seekAtEndOfPart ) + "; "; document.cookie = "naviplace=" + encodeURIComponent( place ) + "; "; document.cookie = "navicontinue=" + encodeURIComponent( "true" ) + "; "; console.log( "cookie wrote:", seek, seek2, place ); location.reload(); }.bind( timeline ); addEventListener( "keydown", function( e ) { switch( e.which ) { case 67: this.calcAndApplyPosition(); break; case 82: //r restart(); break; case 68: //クッキー削除 document.cookie = "key1=; max-age=0"; break; case 8: //BS //check. if( ! this.placeBak ) { alert( "placeBak が「" + this.placeBak + "」なので戻れません" ); return false; } this.seek2 -= 2; //check. if( this.seek2 < 0 ) { this.seek -= 1; //check. if( this.seek < 0 ) { this.seek = 0; } this.seek2 = this.seekAtEndOfPart; } this.place = this.placeBak; restart(); default: console.log( e.which ); return true; } }.bind( timeline ) ); ondblclick = function() { restart(); }.bind( timeline ); } ); } //---セリフ設定部 a_navi = { navis : [ { id : "", script : function() {/* this.huki.style.borderColor = "magenta"; this.huki.style.color = "#a09"; this.showChar(); こんにちは~! それではわたくし3Dスリーディーお姉さんが説明させていただきます。 */}, }, { id : "", script : function() {/* 終了する場合は私を『ダブルクリック』するか、 『私とフキダシを、2本の指で同時タッチ』してください。 */}, }, { id : "", script : function() {/* なお、わたしがしゃべっているあいだ、画面に表示されているリンクをクリックして別のページへ移動することはできますし、 */}, }, { id : "", script : function() {/* 画面を動かしてこのページの別の場所を読んでもらっても大丈夫です。 でも別の場所を読んでいるときにわたしのこのフキダシをクリックして私のおしゃべりを進めると、私がゆびさすところへ向かってグイーンと 勝手に画面が動くことがあります。 */}, }, { id : "", script : function() {/* :testcanvas this.test( 2 ); では、このカラフルな「まる」がたくさん動いているプログラムについて説明していきますヨ! どうぞよろしくお願いいたします★ :testcanvas それではさっそく! :testcanvas このプログラムは、大きく分けて2つのファイルで作られています。 :h4_html this.test( 1 ); 1つはこの「作ったプログラムをインターネットブラウザで表示するためのプログラム」です。 「HTMLエイチ ティー エム エル」と呼ばれています。 もう1つは、 :h4_js this.test( 1 ); この JavaScriptジャバ スクリプト プログラムです。 このJavaScriptプログラムが、カラフルな「まる」を動かすメインのプログラムなんです。 :h4_html では、ざっと説明していきますね :h4_html this.test( 1 ); インターネットブラウザは、ユーザーによってこのHTMLファイルのURLを指定されると、 :L1@loader1 そのファイルの一番最初から読んでいきます。 :L2@loader1 まずHEADヘッドタグがあり、 :L3@loader1 HEADタグの中へ入って、METAメタタグがあります。 :L4@loader1 このSCRIPTスクリプトタグでは、メインのJavaScriptプログラムを読み込んでいます。 読み込み始めると、そのファイルの中へ入っていきます。 :h4_js this.test( 2 ); このファイルの中へ入ります。 メイン・プログラムですね。 :L1@js1 中へ入ると、一番最初のここから読み込んでいきます。 このファイルでは、JavaScriptのプログラムだけが書かれています。 まずはクラスAppアップを、 :L48@js1 ここまで読み込んで定義して、 :L50@js1 もうひとつ、クラスBallボールを、 :L86@js1 ここまで読み込んで定義しています。 このファイルに書かれているプログラムは、この2つのクラスの定義だけです。 :L86@js1 ブラウザはファイルの最後まで読み込むと、もとのファイルへ戻ります。 つまり… :L4@loader1 ここに戻ります。 メインのJavaScriptプログラムを読み込んだら、 :L5@loader1 つづいてSCRIPTスクリプトタグがありまして、 :L6@loader1,L9@loader1 関数が一個、定義されています。 … さっきから定義、定義って「テーギってなんなの?」って思いませんか? :L6@loader1,L9@loader1 定義ていぎというのはですね。 :L6@loader1,L9@loader1 たとえば、大勢の人がいて、 多くのものがあって、 これから何か大きな催し物もよおしものをやろうっていうときに、 :L6@loader1,L9@loader1 誰にどんな役割を担当して動いてもらって、 どんなものが必要で、そのものをみんながわかるようにどんな呼び名で呼ぶのかを決めないと、 催し物は動き出しませんよね? :L6@loader1,L9@loader1 それと同じように、 :L6@loader1,L9@loader1 プログラムでも最初にどんなクラスや関数、変数があってどういう動きをするものなのか、どんな値を入れるのかを決めて、それぞれどんな名前にするのかも決めます。 そういう取り決めを行って はじめてプログラムは動き出します。 :L6@loader1,L9@loader1 そのような事前の取り決めを、プログラムでは「定義ていぎ」と呼んでいます。 :L6@loader1,L9@loader1 テーキ定期券ではないし、ステーキ厚い肉でもない、
定義ていぎ」です★ :L6@loader1,L9@loader1 お話は戻りまして、 :L11@loader1 ここまでHEADタグを読んだら、 :L13@loader1 つづいてBODYボディタグが来まして、 :L14@loader1,L16@loader1 その中にCANVASキャンバスタグがあります。 :testcanvas this.test( 2 ); CANVASキャンバスタグとは、この画面のことです。 JavaScriptを使ってこの画面にコンピューターグラフィックスを描くことができます。 :L20@loader1 そしてここまで読み込むと、すべての読み込みが完了です。 「すべての読み込みが完了した」ということで、ブラウザは 「onloadオン ロードイベント、レッツゴー!」という動きをします。 つまり、 :L13@loader1 this.test( 2 ); このBODYタグの設定で、onload="..."と書かれている、この中身の "onloadx()オン ロード エックス" をJavaScriptプログラムの一部として実行してくれるんです。 とうとうJavaScriptが動き始めるぞ!という感じですねー :L13@loader1 このBODYタグに書かれた onloadx() というのは… :L6@loader1,L9@loader1 this.test( 1 ); ズバリ、これです。 :L7@loader1 この中へ入っていきまして、 このnew Appニュー アップ(...)が実行されると、 :L2@js1 this.test( 2 ); このクラス App の constructor() というところに来るんです。 ちょっと難しいですか? :L2@js1 constructorとは「コンストラクタ」と読みます。 英単語としては「建設する人」という意味だそうです。 クラスAppを動かすために「まず初期設定を行うもの」と覚えておくと良いと思います。 :L2@js1 経験のあるプログラマーの人でさえ、 constructorという単語は「やや難しい単語を使っているな」と思っているくらいなので、みなさんが「難しい」と感じるのも無理もないですよ。 :L3@js1 それでコンストラクタが行う初期設定とは、 このようなCANVASキャンバスの設定、 さっき見た「まる」がたくさん動いていた画面のことですね。 その設定を行ったり、 :L9@js1 「まる」をたくさん作成~~ :L10@js1 forフォー文を使って、各色ごとに「まる」を作っています。 この行は赤で、 :L11@js1 緑、 :L12@js1 青、 :L13@js1 ピンク、 :L14@js1 水色、 :L15@js1 黄色と、いろいろな色を順次、for文で切り替えていきますよ、という意味になっています。 :L17@js1 そして、for文の中の1行目で1つの「まる」を作っています。 for文で切り替えた色である colorカラー をここで指定しています。 それで その色の「まる」を作っているんです。 :L17@js1 new Ballニュー ボール(...)なので、 :L51@js1,L58@js1 this.test( 1 ); このBallクラスのコンストラクタに来ます。初期設定ですねー。 内容を見ると、いくつかの数値を初期設定しているだけのようですね。 :L58@js1 というわけで初期設定をしてここまで来ましたら、 もとの場所に戻りましょう。 :L17@js1 そうやって、「まる」が1つできたところで、 :L18@js1,L21@js1 今 初期設定した一部の値を、「乱数」の値に変更します。 乱数(randomランダム)にしているので、 :testcanvas this.test( 2 ); このようにバラバラに動いて楽しい感じになるんですね! バラバラでしょ? :L22@js1 そしてこれで「まる」が1つ完成したので、完成した「まる」を配列に入れます。 :L23@js1 for文で色の数だけ繰り返して「まる」を全部作り終わると、 :L24@js1 ここでAppのコンストラクタ(初期設定)が終わります。 :L7@loader1 そしてここに戻ってくるわけですね。onloadx()の中です。 :L8@loader1 以上で準備は終わって、次にstart()スタートメソッドを実行します。 いよいよプログラムが動き出しますよ~ startメソッドは :L1@js1 Appクラスの、 :L2@js1 …これはコンストラクタで… :L25@js1 その次のここ! Appのstartメソッド :L27@js1 この中で、setIntervalセット インターバルという「JavaScriptの基本の関数」の1つを実行してます。 setIntervalは「定期的に指定のメソッドを実行する」というもので、 これのおかげで、 :testcanvas this.test( 2 ); こういうアニメができるんです! setIntervalセット インターバルは「コンマ何秒の世界」なので、アニメのひとコマのレベルで繰り返し実行してくれます★ :L27@js1 その1コマとして、setIntervalが呼び出しているメソッドは、Appのframeフレームというメソッドです。 すぐ近くの…。 :L35@js1 これですね。 でもこのframeメソッドの説明はちょっと後にしましょう。 :L27@js1 setIntervalは定期的にframeメソッドを呼び出すというアニメの設定をして、 :L28@js1 その後、ここに来まして、start()メソッドが終了します。 :L8@loader1 そしてHTMLファイルのここに戻ってきます。 :L9@loader1 ここに来て、onloadx()も終了し、 :L13@loader1 さらにこのBODYタグのonload="onloadx()"の"onloadx()"の末尾まつびまで戻ってくるんです。 ブラウザは、 :L13@loader1 1. ファイルを全部読み終わった、 2. だからonloadイベントレッツゴーした、 3. BODYタグに書かれているonload="onloadx()"の"onloadx()"を実行した! そうやって全部終わってしまうと、このひと続きの流れはそれで終わり。その後は何もしなくなります。プログラムの終わりです。 …ところが! :L27@js1 ここで定期的なアニメの設定をしているので、 「定期的にframeメソッドを実行する」 という動きを、止めない限りずっと続けることになります。 :L27@js1 …ということで、 大丈夫ですか?疲れていませんか? 休憩きゅうけいするのもプログラミングとしては大切なので覚えておきましょう。 :L35@js1 …ということで、 後にしていた、このframeメソッドの説明に戻ってきました。 :L36@js1 各色の「まる」について、 :L37@js1 frameメソッドを呼び出しています。 このballはさっきnew Ball(...)で初期設定したり、乱数に変更したりして作ったものです。 Ballクラスですから、 :L50@js1 このBallクラスの、 :L59@js1 これ! :L60@js1,L61@js1 frameメソッドは、まず「まる」の位置(x,y)を変更しています。 :L62@js1,L74@js1 this.test( 1 ); 位置を変更したらチェック! :L63@js1 ”右の壁にぶつかりましたか~?” :L64@js1 ぶつかったなら、方向を反対にします★ これ、横方向の増分(addXアッド エックス)に-1を掛けると値が反対になり、動く方向が逆になるんです。 たとえば、5だったものに、-1を掛けると-5になります。 :L60@js1 それというのは、ここで「まる」の位置(xエックス)に「5」を足すなら右に5ずつ移動するんですが、 反転して、「-5」を足すなら(5を引くなら)左に5ずつ移動する、と。 そういうことなんです。 :L60@js1 右端の * 1.25 については気にしないでください。微調整しているものです。 :L66@js1 つづけて、”左の壁にぶつかったんですか~?” :L67@js1 ぶつかったなら、方向を反転します。 :L69@js1 ”下の壁にぶつかっちゃいましたか~?” :L70@js1 ぶつかったなら、方向を反転します。 yなので、上下方向の反転ですね。 :L72@js1 ”上の壁にぶつかりましたか~?” :L73@js1 方向を反転します。 :L73@js1 これで、「まる」は壁にぶつかるとね返る…という動きを表現できるんですねぇ。 x,yの増分に-1をかけるだけだなんて、めっちゃ簡単よね! :L73@js1 実はこのプログラムの作者(web6047管理人)も「あれ?そうなんだ?」と思ったそうです。 :L75@js1 ここでframeは終わりまして… :L37@js1 ここに戻ってきます。 for文がすべて終わったら、 :L39@js1 ドロウです! 描画ですね。 Appのdrawドロウはすぐ下の :L41@js1 これです。 :L42@js1 まず色を白にして、 :L43@js1 全体を消去! :L44@js1 次にfor文でそれぞれの「まる」について、 :L45@js1 ドロウ! Ballのdrawは、 :L76@js1 これ! 「まる」を描きたいので、 :L78@js1 アーク(arc)というメソッドで、下絵(まる)を描き、 :L81@js1 半透明モードにして、 :L82@js1 色を その「まる」の色にして、 :L83@js1 下絵を塗りつぶします。フィル! :L84@js1 なお、この行のコメント(先頭の//)を取り外すと、残像がなくなりますよ。 :testcanvas this.test( 2 ); この残像…きれいですけど、どうしてこうなったのか…作者もわからないそうです。 偶然 残像になって「イイゾ!」と言ってそのままにしたんだとか… :testcanvas もっと!こう! 「知的に筋道立ててこう考えたからこうできたんだゾ」って、 できないんですかねぇ? :testcanvas 壁の反転のときも「あれ?そうなんだ?」 プログラマーってそんなもんなの??(プンプン) :L45@js1 …ともかく、BallのdrawからAppのdrawに戻りまして、 :L46@js1 for文をすべて終えたら、 :L47@js1 Appのdrawも終わるので、 :L39@js1 Appのframeのここに戻ってきます。 :L40@js1 これでsetIntervalセット インターバルによる1コマ(frameメソッド呼び出し)が終わったわけです。 :L40@js1 位置を変えて、ドロウして、(1コマ) 位置を変えて、ドロウして、(1コマ) 位置を変えて、ドロウして、(1コマ) :L40@js1 そして! :testcanvas this.test( 3 ); このようなアニメになっているんです★ :testcanvas どうですか? ざっと説明してきましたが、だいたいの流れはつかめましたか? わかりづらいところもあったと思いますが、がんばってお勉強してくださいね。 みなさんのプログラミングの一助いちじょになれば幸いです。 :testcanvas パチパチパチパチパチ */}, }, { id : "testcanvas", script : function() {/* それではまた、サイナラ~! ・ ・ ・ 消えまーす。 :testcanvas this.hideChar(); */}, }, ], }