• ベストアンサー

ActionScriptでアナログ時計

ActionScriptでアナログ時計を作ったのですが、いまいちスクリプトの意味が分かりません。 _rootのタイムラインに長針・短針・秒針をまとめたムービークリップを配置し(Y軸に対して水平)、そのムービークリップの1フレーム目に以下のフレームアクションを記入しました。 now = new Date(); theHour = now.getHours(); theMin = now.getMinutes(); theSec = now.getSeconds(); ここまでは現在の時間を取得しているという事が分かりますが、問題は以下です。hour、min、secはそれぞれ短針、長針、秒針のMCの名前です。 hour._rotation = (theHour*30)+(theMin/2)-90; min._rotation = theMin*6-90; sec._rotation = theSec*6-90; この2,3行目については、「分・秒ともに60回で360°を一周するから、一度に6°ずつ動く。それに分または秒を掛けたものがそのMCの角度になる。Y軸に水平になっているから90を引くことで12時のところが起点になる」という理解でよろしいでしょうか。 問題は1行目です。theHourに30を掛けるのは12時間*30°で360°になるからで、その後が分かりません。

  • Flash
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
noname#35109
noname#35109
回答No.1

なんか,書かれているスクリプトは複雑ですね。 アナログ時計 http://www17.ocn.ne.jp/~wolves/SCHOOL/lecture/lectureS1_4.html このような感じに最初から針を縦に作れば90度引く必要はないと思いますが, なぜ横向きに作るのでしょうかね。よくわかりません。 縦向きに作るとシンプルになりますよ。 this.onEnterFrame = function() { now = new Date(); theHour = myTime.getHours(); theMin = myTime.getMinutes(); theSec = myTime.getSeconds(); hour._rotation = (theHour*30)+(theMin/2)-90; min._rotation = theMin*6-90; sec._rotation = theSec*6-90; } みたいな感じに。 >> 問題は1行目です。 >> theHourに30を掛けるのは12時間*30°で360° >> になるからで、その後が分かりません。 最初に横向きに針を作ったから90度がでてくるので, ちょっと,90度は無視します。 針は縦向きに作ったとしておきます。 hour._rotation = (theHour*30)+(theMin/2); まず1日は12時間ではなく,24時間です hour._rotation = (theHour*30)+(theMin/2); hour._rotation = (24*30)+(theMin/2); hour._rotation = 720+(theMin/2); 1日で720度回転する。つまり360度を2回回転させるわけです。 実際に,時計の長針は1日で2回回転しますよね。 だから,式は合っています。 また,1時間は60分です。 (theMin/2); =(60/2); =(30); 長針は,1時間で 360/12 =30 度 回転しますね。 =(30); は,この 30 です。 hour._rotation = (theHour*30)+(theMin/2); ~例1~ もしちょうど1時だと, hour._rotation = (1*30)+(0/2); hour._rotation = (30)+(0); hour._rotation = 30; と言うことです。 1時間で,長針は 360/12 = 30 度 回転します。 つまり1時の向きに向きます。 ~例2~ 1時30分だと, hour._rotation = (1*30)+(30/2); hour._rotation = (30)+(15); hour._rotation = 45; 実際の時計の長針も,1時30分には45度傾きます。 とこういうことですけど… 90を入れるとややこしいので, 90を入れずに,色々な数字を代入してやると,なるほど,式は合っているとわかると思います。 と言うより,実際の針の動きになるように,定数を入れて行くと書かれてあるような式になるわけです。 数学が苦手なので,ちゃんとした "証明" にはなっていませんが, 考えていたら結局書かれているような式になりますよ。 最初に書いたURLの式は,こんなのです。 _root.Hneedle._rotation = (H*30)+(M*0.5); _root.Mneedle._rotation = M*6; _root.Sneedle._rotation = S*6; 針の名前がちがうので,針の名前を合わせると,こうなります。 hour._rotation = (H*30)+(M*0.5); min.._rotation = M*6; sec._rotation = S*6; ご質問にある式から90を取るとこうです。 hour._rotation = (theHour*30)+(theMin/2); min._rotation = theMin*6; sec._rotation = theSec*6; 考えた人によって書き方は変わります。 でも,書き方が違うだけで同じ式ですね。 現実の針の動きを数式化しているのです。 あまり良い説明だとは思えませんが,一応,自分なりの説明です。

ikehata_shin
質問者

お礼

分かりやすい説明本当にありがとうございました。

その他の回答 (1)

  • DPE
  • ベストアンサー率85% (666/776)
回答No.2

末尾に付いている -90 は、#1の方がおっしゃるように、針のムービークリップを最初から 12 時の方向(”↑”というような感じで)にして作り、初期配置も 12 時を指すように配置すれば不要です。 -90 の部分は描画上の都合ですので、とりあえず無視して話を進めます。 周知の通り、1日は 24 時間でアナログ時計の文字盤は1周 360°・ 12 時間なので、短針は1日に時計を2周、つまり 24 時間で 720°回ることになります。 これは、” 360°を 12 時間で回る”という同じ動きを1日に2回繰り返しているだけです。 例えばムービークリップを 90°回転した場合と 450°(← 90°+ 360°)回転した場合とでは、450°の回転は1回転多く回っただけで、ムービークリップの向きそのものはどちらも同じです。 時計の短針もこれと同じことです。 例えば昼の3時と夜の3時では、昼の3時は夜の0時から数えると2周目に入っていますが、短針の向き自体は夜の3時と全く同じです。 ここでは” 24 時間で 720°回転”ではなく、アナログ時計の文字盤通り” 12 時間で 360°回転するもの”と考えます。 短針は 360°÷ 12 = 30 で、1時間に 30°傾きます。 12 時の位置を0°とすると、1時ちょうどには1× 30 = 30°、2時ちょうどには2× 30°= 60°・・・となります。 式にすると  時間× 30° です。 ご質問文のスクリプトでは、変数 theHour には getHours メソッドにより現在の時間が入っています。  > hour._rotation = (theHour*30)+(theMin/2)-90; の theHour*30 は、12 時を基点とした時の、ちょうどの時間(例えば1時0分)での短針の位置を求める計算です。 ---------------------------------------------------------------- ところで、アナログ時計の針の動きをよく見てみますと、短針は”1時間ごとに1回だけ、30°傾く”のではありませんよね。 正確には、”1時間かけて 30°傾いていく”のです。  > hour._rotation = (theHour*30)+(theMin/2)-90; の theMin/2 の部分は、この動作を実現させるための補正です。 1時間は 60 分ですから、60 分かけて 30°傾くのなら、1分あたりの傾斜角度は 30 ÷ 60 = 0.5 で 0.5°となります。 これに現在の分を乗算した値がその分での傾斜角度ですが、実際の短針は、その時間ちょうどの位置の分だけ既に傾いていることになります。 例えば1時 20 分ですと、12 時の位置を0°とするならば、1時0分の短針の角度は  1× 30 = 30° です。 ここから更に 20 分間経過した角度だけ傾いているので、20 分後の傾きである 20 × 0.5 を加算します。 従って、短針のムービークリップ” hour ”の傾きは  hour._rotation = ( 1 * 30 ) + ( 20 * 0.5 ); となります。 変数を使って式にしますと、  hour._rotation = ( theHour * 30 ) + ( theMin * 0.5 ); です。 ********************************** プログラミングでは、一般に小数点の付く計算は嫌われます。 コンピュータも人間と同じく、小数の計算はできればない方が処理は軽いですし、ゴチャゴチャと細かい小数点が付くと、変数がオーバーフロー(桁あふれ)を起こして値が破壊されたり、誤差のために原因がよく分からない不具合が発生しやすくなるからです。 0.5 の乗算くらいなら別に大した問題ではありませんけれど、小数を使わずに済むように別の考え方をしてみましょう。 先述のように、短針は1時間= 60 分かけて 30°傾きます。 60 分で 30°傾くならば、例えば 60 分の 1 / 4 にあたる 15 分では何度傾くでしょうか? いろいろな考え方がありますが、ここでは比を使って考えます。 ” 60 分で 30°傾くなら、15 分では何度傾くか?”を比で表しますと、  60 : 30 = 15 : 角度 となります。 比は、”=”を挟んだ内側同士の積と外側同士の積が等しいという性質があります。 つまり、  60 × 角度 = 30 × 15 が成り立ちますから、正攻法で行くなら  角度 = 30 × 15 ÷ 60 です。 しかし、  60 ×角度 = 30 × 15 この式を、”=”を境にしてよく見比べてください。 60 は 30 の2倍にあたります。 30 が2倍になったのであればその相方の 15 は半分にすると、計算の帳尻が合います。 従って求める角度は、15 の 1 / 2 である 7.5°となります。 こんな小学生レベルの方法(^^;)ではなく、もう少し理論的に考えますと。 正攻法の  角度 = 30 × 15 ÷ 60 の式は、先頭から真っ向に計算していくのはあまり得策ではありません。除算を含む計算は分数で表してみると、約分して計算が簡単になったり計算回数を減らせたりすることができるからです。 この式は、 (↓表示フォントによっては位置がズレますがご容赦ください)       30 × 15  角度 = ──────         60 と表すことができます。 30 と 60 で約分が可能で分子の 30 は消えますから、最終的には  角度 = 15 / 2 で、つまり 15 を2で除算したものが求める角度となります。 15 の部分は実際には現在の分(ご質問文のスクリプトでは変数 theMin )で時刻により変化していますが、「 60 ×角度 = 30 × 現在の分」という関係は現在時刻が何分であっても常に成り立ちます。 ですから、現在の分の半分、変数では theMin を2で除算した角度がその分での短針の傾きを表す補正値となるのです。 ・・・とまあ、真面目に考えますと何だかいっぱしの学問のようですね。 基本的には小学校か中学校で習う割合や比の問題ですが、時間や角度という想像しにくい概念なので、少々難しく見えるだけだと思います。 「 theMin / 2 」と「 theMin * 0.5 」は計算結果はどちらも同じで、式の上ではただの表現の違いにしか見えません。 数学では、「 theMin * 0.5 」が「 theMin / 2 」と同じだとひらめくことが解法につながったり、より速く確実に計算できる場合もあります。 しかし今回の例では、なぜ分を2で割るのか、分になぜ 0.5 を掛けるのか、その理由を考えていくと、この結論に至るまでの過程はまるで違います。時には、単なる表現の違いでは済まない場合もあるのです。 (余談ですが、数学はただ正しい答えを求められるようになればいいのではなくて、理論的な考え方やスジの通った考え方を学ぶ学問だと思います。日本の数学教育は考え方を教える面が欠けているような気がします...) もっとも、式を立てた本当の理由は本人にしか分かりません。 比にして考えますと、結果として「分÷2」の式が出てきます。 ですが式を立てた人はこんな回りくどい思考過程を踏んだのではなく、1分あたりの傾斜角度 0.5 を掛ければいいけれど、「 theMin * 0.5 」だと小数になるが「 theMin / 2 」なら結果は同じで小数がなくなるから都合がいいじゃないかと、直感的にひらめいただけなのかもしれません。

関連するQ&A

  • Flash Lite 1.1 アナログ時計 秒針の動き

    Flash Lite 1.1 ベースで、 携帯待ち受け用のアナログ時計を制作しています。 現在は秒針の動き一秒に6度動くように設定しているのですが、 一秒に6度動く様な「カチッカチッ」と言う動きではなく、 その間の動きも滑らかに動くように設定したいと考えています。 色々なサイトで詳細を検索したいのですが、 満足のいく解答を探す事ができませんでした。 興味のある方など解答をいただけると幸いです。 <現在使用しているソース:12fps> hr = fscommand2("GetTimeHours"); min = fscommand2("GetTimeMinutes"); sec = fscommand2("GetTimeSeconds"); hour._rotation = hr*30+min*0.5; minute._rotation = min*6; second._rotation = sec*6;

  • FLASH日付・時計待ちうけ

    こんばんは。 Flash Professional 8で日付と時計の待ちうけを作成しようとしています。 まず時計を作成していたのですが、ムービープレビューでは秒は問題なく動作しているのですが、携帯に転送すると秒が動かず、ページ切り替えすると進んだ秒になり、また動きません。 何が問題なのかわからないので是非教えてください。 尚、レイヤー1(上)にスクリプト、レイヤー2(2)背景イラストを入れております。また、フレームは1だとムービープレビューでも秒が動かないのでフレームを挿入して2にしました。 スクリプトは以下の通りです。 hh = fscommand2("GetTimeHours"); //時の取得 mm = fscommand2("GetTimeMinutes"); //分の取得 ss = fscommand2("GetTimeSeconds"); //秒の取得 if(hh<=9){ hour1 = 0; hour2 = substring(hh, 1, 1); }else{ hour1 = substring(hh, 1, 1); hour2 = substring(hh, 2, 1); } if(mm<=9){ min1 = 0; min2 = substring(mm, 1, 1); }else{ min1 = substring(mm, 1, 1); min2 = substring(mm, 2, 1); } if(ss<=9){ sec1 = 0; sec2 = substring(ss, 1, 1); }else{ sec1 = substring(ss, 1, 1); sec2 = substring(ss, 2, 1); } また、日付2008年02月03日と言うように表示させる方法も簡単な作成の仕方があれば教えて下さい。 宜しくお願いします。

    • ベストアンサー
    • Flash
  • Flash(ActionScript3.0)

    Flash(ActionScript3.0)でゲーム制作を行っています。 ActionScriptもFlashも最近初めて触れた初心者で、分からないことがたくさん湧いてきて困っています。 よろしければご回答お願い致します。 インスタンスをドラッグすることができる、という要素と、 インスタンスをクリックすると45度回転する、という要素を同時に入れたいのですが、 同時にプログラムを組むとドラッグだけをすることができず、 どうしてもドラッグ後に45度回転してしまいます。 (プログラムのソースはネットから拾ってきたものです)。 どうすればドラッグと回転を分けることができるのでしょうか。 プログラム自体は以下のように組みました。 ご回答いただければ嬉しいです。 よろしくお願い致します。 //インスタンスの回転プログラム mc1.addEventListener(MouseEvent.CLICK, kaiten); function kaiten(event:MouseEvent) { mc1.rotation += 45; } //インスタンスのドラッグプログラム //インスタンスの0点からのマウス座標用変数 var mc1X:int; var mc1Y:int; //マウスがインスタンスを押したらsec1開始 mc1.addEventListener(MouseEvent.MOUSE_DOWN,sec1); //sec1 マウスダウン座標確認、sec2開始 function sec1(event:MouseEvent):void { mc1X = event.localX; mc1Y = event.localY; addEventListener(MouseEvent.MOUSE_MOVE,sec2); } //sec2 インスタンス移動 function sec2(event):void { mc1.x = mouseX-mc1X; mc1.y = mouseY-mc1Y; //低FPSマウス移動スムーズ対応 event.updateAfterEvent(); } //マウスが離れたらsec3開始 stage.addEventListener(MouseEvent.MOUSE_UP,sec3); mc1.addEventListener(MouseEvent.MOUSE_OUT,sec3); //sec3 sec2停止 function sec3(event):void { removeEventListener(MouseEvent.MOUSE_MOVE,sec2); }

  • ActionScriptで、押したボタンの判別方法を教えてください。

    ActionScriptで、押したボタンの判別方法を教えてください。 ActionScript3.0で作成しています。 6フレームの【oya_mc】というムービークリップの各フレームに フレーム1ラベル[m1]に【ko1_mc】 フレーム2ラベル[m2]に【ko2_mc】 フレーム3ラベル[m3]に【ko3_mc】 フレーム4ラベル[m4]に【ko4_mc】 フレーム5ラベル[m5]に【ko5_mc】 フレーム6ラベル[m6]に【ko6_mc】 というムービークリップを配置しています。 配置しているムービークリップには、それぞれ6個のボタンを呼び出して配置しています。 【btn1】【btn2】【btn3】【btn4】【btn5】【btn6】 【btn3】を押したときに【oya_mc】を3フレーム目に移動。 【btn6】を押したときに【oya_mc】を6フレーム目に移動。 というようにしたいのですが、なかなかうまくいきません。 FLASH初心者ですが、どうかご指導よろしくお願いします。 【ko1_mc】に書いたスクリプトを抜粋して書きます。 ------- for(var i:int = 1; i <= 6; i++){ this["btn" + i].addEventListener(MouseEvent.CLICK,Down); function Down(mo:Event):void{ MovieClip(parent).gotoAndPlay("m"+i); } } ------- よろしくお願いします。

    • ベストアンサー
    • Flash
  • Flash MX ActionScriptのEnterFrame

    Flash 初心者です。 クリップアクションの、 onClipEvent (enterFrame) { } がいまいちよくわかりません。 フレームが1フレームだけのルートのタイムラインに、 何の動きもないムービークリップオブジェクト(これも1フレームのみ)を1つ置いたとします。 そのムービークリップに、例えば、 onClipEvent (enterFrame) { _rotation+=20; } とアクションをつけたとします。 これを再生すると、回転し続けますよね。 これはルートのタイムラインが1フレームだけでも、 それがループしていると考えると、納得できるのですが、 1フレーム目に、this.stop();を記述しても、 回転し続けます。 enterframeとはどのように解釈すればいいのですか? ルートのタイムラインが再生される度に呼び出されるということでは ないのでしょうか? よろしくお願い致します。

  • ActionScript3.0フレーム移動について

    お世話になります。 Flash ActionScript3.0で、ボタンをクリックしたら、 階層違いのシーンに移動するという 単純なところでつまずいています。 一番上の階層には、 1フレーム目 フレームラベル "a" 2フレーム目 フレームラベル "b" として、それぞれ this.stop();を書いてあります。 "a""b"には、それぞれムービークリップが配置してあって、 今やりたいことは、"a"に配置してあるムービークリップの 2つ下(中?)の階層にあるボタンをクリックしたら、一番上の階層の"b"に移動して、 "b"に配置してあるムービークリップを表示するようにしたいのです。 "a"のムービークリップのボタンのあるフレームには、 this.stop(); button01.addEventListener(MouseEvent.CLICK,jumpB); function jumpB(event:MouseEvent):void { MovieClip(parent.parent).gotoAndStop("b"); } と書いてみましたが、 [TypeError: Error #1009: null のオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。] と怒られます。 試しに MovieClip(stage).gotoAndStop("b"); とか、"b"に配置してあるムービークリップにインスタンス名"b_mc"を与えて MovieClip(parent.parent).b_mc.play(); などと苦し紛れにやってみましたが、すべて同じように怒られます。 どのようにすれば、下の階層から一番上の階層の別フレームに 移動することができますでしょうか? よろしくお願い致します。

  • AS3 ムービークリップの配置について

    ステージ上に、ムービークリップ mc1 mc2 があるとします。 mc2の24フレーム目の中に、mc3を配置し、mc2の24フレーム目にこんなプログラムを書くとします。 //一秒後に、mc3を移動      mc3.y=260;      mc3.x=MovieClip(parent).mc1.x; すると、mc3の配置は、mc2を基準としたx.y軸で配置されてしまいます。 (すいません。 言葉での説明が難しいです。) 私は、ステージを基準として配置したいのですが、いったいどのように書けばいいですか? ちなみに以下のようにすると私の求めていた結果が得られました。 ステージ上の見えない所に mc3を置いて、mc2の24フレームに      MovieClip(parent).mc3.y=260      MovieClip(parent).mc3.x=mc.x; 正直言葉での説明が難しく、わかりにくいかと思いますが回答よろしくお願いします。

    • ベストアンサー
    • Flash
  • Perl 水曜日に処理を変えたい

    人の作ったものですが、月曜午前0時で処理を切り替えるようになっています。 これを水曜午前0時に変更するにはどうすればいいでしょうか? 長いですがよろしくお願いします。 sub GetNextWDayTime { my $time = time; my ($sec, $min, $hour, $wday) = (localtime($time))[0,1,2,6]; my $now = ($wday * 60 * 60 * 24) + ($hour * 60 * 60) + ($min * 60) + $sec; my $next = ($_[0] * 60 * 60 * 24) + ($_[1] * 60 * 60) + ($_[2] * 60) + $_[3]; #if $next is small, $next is next week. if($next < $now){ $time = $time + (60 * 60 * 24 * 7); } $time = $time + (($_[0] - $wday) * 60 * 60 * 24); $time = $time + ($_[3] - $sec); $time = $time + (($_[2] - $min) * 60); $time = $time + (($_[1] - $hour) * 60 * 60); return $time; } sub GetLastWDayTime { my $time = time; my ($sec, $min, $hour, $wday) = (localtime($time))[0,1,2,6]; my $now = ($wday * 60 * 60 * 24) + ($hour * 60 * 60) + ($min * 60) + $sec; my $last = ($_[0] * 60 * 60 * 24) + ($_[1] * 60 * 60) + ($_[2] * 60) + $_[3]; #if $last is large, $last is next week. if($last > $now){ $time = $time - (60 * 60 * 24 * 7); } $time = $time + (($_[0] - $wday) * 60 * 60 * 24); $time = $time + ($_[3] - $sec); $time = $time + (($_[2] - $min) * 60); $time = $time + (($_[1] - $hour) * 60 * 60); return $time; }

    • ベストアンサー
    • Perl
  • Error#1009 時計のシーン移動ボタン

    こんにちは、Flash初心者です。 アクションスクリプト3.0にて、時計を作っています。 時計は完成したものの、シーンを移動するボタンを作成したところ、 TypeError: Error #1009: Cannot access a property or method of a null object reference. at sushi_fla::MainTimeline/updateDate2()[sushi_fla.MainTimeline::frame4:13] このようなエラーメッセージが出てきました。 ■1フレーム目■ 1フレーム目のプログラムにTOPに戻るボタンのプログラムを記載しています。 top2nd_btn.addEventListener(MouseEvent.CLICK, fl_top22); function fl_top22(event:MouseEvent):void { gotoAndPlay(1,"TOP"); } ■2フレーム目■ プログラムソースは、下記の通りで、2フレーム目に記載しております。 //時計のプログラム addEventListener(Event.ENTER_FRAME, updateDate2); function updateDate2(event:Event):void { //Dateクラスの設定 var dateObj = new Date(); //時間 tanshin2_mc.rotation = dateObj.hours*360/12 + dateObj.minutes*360/12/60; //分 choshin2_mc.rotation = dateObj.minutes*360/60 + dateObj.seconds*360/60/60; //秒 secondhand2_mc.rotation = dateObj.seconds*360/60 + dateObj.milliseconds*360/60/1000; } //この画面でストップ stop(); このソースでタイムラインの秒針Byoshin・長針Choshin・短針Tanshinの3つを動かしております。 (Bisuやバックグランドは飾りです) アドビヘルプだと、Null にプロパティがないそうですが、時計は、永遠に回り続けるため、一つのフレームでアクションが完結することがありません。 その為、フレームを変えてもうまく行きませんでした。 初心者でどこが駄目なのかわからず、泣きそうです。 お分かりになる方がおりましたら、お知らせくださいませ。 どうぞ、よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • 【ActionScript】ムービークリップ間の変数の受け渡しのやり方は?

    ムービークリップ間の変数の受け渡しがいまいちわかりません。 例えば、 ・_root.mc1 及び、 ・_root.mc1.mc2 というインスタンスがあった場合、 _root.mc1.mc2 のフレームに a = 100; と書き、 _root.mc1 のフレームに trace(_root.mc1.mc2.a); と書いても「undifined」と出るだけです。 (上層の値を下層で受けることはできるんですが、この例のように下層→上層の受け渡しはできないのです。) どうすればインスタンス間の変数の受け渡しができるのでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • Flash