線に沿う玉の運動を描く⑤
前の続きです。
chemiphys.hateblo.jp
前のリンクを貼るとか,いろいろな作法がまだ身につかないですね。勢いでどんどん言葉を並べてしまう(;´▽`A``
さて,やりたかったものを引っ張り出してきました。
これに取り組める力をつけるためにクラスモジュール利用に取り組んでいるわけです。
まず,どうやって部品に分けるのが妥当なんだろうと考えました。
・動くボールを1つのクラスにするのは必要だよな。
・この仕組みのキーはセンサー部分だから,センサー部分を切り離すことは必須だよな。
これは必ず実装することにして,全貌を組んでみて,各ポイントをブラッシュアップしたり,センサー部分の判断させ方を変えたりするべきたよな。
まずはこのくらいのことを頭に入れ,前のコードを書き換えてみることにしました。
次の通りです。まだひどいもんです。スタート地点として見てください。
標準モジュール
Option Explicit Public Const Rate As Currency = 1 Const SID = 1 Sub Test() Dim TSlide As Slide: Set TSlide = ActivePresentation.Slides(SID) Dim Ball1 As Ball: Set Ball1 = New Ball Dim shpSlope As Shape: Set shpSlope = TSlide.Shapes("slope") ActivePresentation.SlideShowSettings.Run Ball1.Draw TSlide, 40, RGB(255, 255, 0), 20, 20 Ball1.V = 2 Do Ball1.Move TSlide, shpSlope Ball1.shpBall.TextFrame.TextRange = " " DoEvents Loop Until Ball1.X > 700 End Sub
Ball.cls
Option Explicit Public Vx As Currency Public Vy As Currency Public V As Currency Public X As Currency Public Y As Currency Public shpCollide As Shape Public shpBall As Shape Sub Draw(bslide As Slide, 直径 As Long, 色 As Long, pX As Long, pY As Long) Set shpBall = bslide.Shapes.AddShape(msoShapeOval, pX, pY, 直径, 直径) shpBall.Fill.ForeColor.RGB = 色 shpBall.Line.ForeColor.RGB = RGB(0, 0, 0) shpBall.Line.Weight = 2 End Sub Sub Move(bslide As Slide, pshpCollide As Shape) Set shpCollide = pshpCollide Dim 判定 As Hantei: Set 判定 = New Hantei 判定.Judge bslide, shpBall, shpCollide If 判定.blnCollide = True Then Vx = V * Cos(判定.sglAngle) * Rate Vy = V * Sin(判定.sglAngle) * Rate Else Vx = 0 Vy = V * Rate End If shpBall.Left = shpBall.Left + Vx shpBall.Top = shpBall.Top + Vy X = shpBall.Left Y = shpBall.Top End Sub
Hantei.cls
Option Explicit Public sglAngle As Single Public blnCollide As Boolean Sub Judge(hSlide As Slide, shp1 As Shape, shp2 As Shape) Dim lngShapeCount As Long Dim NextShp1 As Shape lngShapeCount = hSlide.Shapes.Count hSlide.Shapes.Range(Array(shp1.ZOrderPosition, shp2.ZOrderPosition)).Duplicate.MergeShapes msoMergeIntersect If hSlide.Shapes.Count = lngShapeCount Then blnCollide = False Exit Sub Else blnCollide = True Dim shpDupe As Shape Set shpDupe = hSlide.Shapes(hSlide.Shapes.Count) End If Dim shpNodes As ShapeNodes: Set shpNodes = shpDupe.Nodes Dim sglMinPtX As Single: sglMinPtX = shpNodes(1).Points(1, 1) Dim MinPtXIndex As Long: MinPtXIndex = 1 Dim i As Long For i = 1 To shpNodes.Count - 1 If shpNodes(i).Points(1, 1) < sglMinPtX Then sglMinPtX = shpNodes(i).Points(1, 1) MinPtXIndex = i End If Next Dim NextPtXIndex As Long If shpNodes(MinPtXIndex + 1).Points(1, 1) - shpNodes(MinPtXIndex).Points(1, 1) < 2 And MinPtXIndex + 2 <= shpNodes.Count Then NextPtXIndex = MinPtXIndex + 2 Else NextPtXIndex = MinPtXIndex + 1 End If sglAngle = Atn((shpNodes(NextPtXIndex).Points(1, 2) - shpNodes(MinPtXIndex).Points(1, 2)) / (shpNodes(NextPtXIndex).Points(1, 1) - shpNodes(MinPtXIndex).Points(1, 1))) shpDupe.Delete End Sub
slopeという名前の閉じた図形が必要です。そいつとの衝突判定をします。
玉は勝手に作る仕組みです。
APIを使ってなくても,よく強制終了する。。なんのせいだろうか・
現時点での問題点・・ ほとんど問題点だらけなんですが,
とにかくめりこみます。判定方法をしっかり見ないといけない。適切にNodeを参照できているのか,またはめり込むわけですので,持ち上げていって衝突が切れる場所を探させて浮上させるか。
Topを上げていって衝突判定をさせればいいからできなくはない。どうしても速度の幅によってめり込むから浮上まで含めて判定とすればいいかなぁ。
そうそう,コーディングしてて,さらにクラスモジュールの中にさらにクラスモジュールがある場合とか,同じオブジェクトの受け渡しに悩みます。
標準モジュールで TSlide ballクラスで bSlide HanteiクラスでhSlideとなっていますが,同じものを受け渡しているつもりです。
対象のスライドが変わったときに変えれるようにしたい,という意思があります。
同じ名前を別々のモジュールで使ってたら混乱もしますし,かといって頭文字をこんなふうにしててもそのうちかぶったりするし,
多数のクラスモジュールを組み合わせて使う場合に受け渡す変数の名前ってどうしていったらいいものか。 pプライベートとか pプロパティとかあたりの気持ちでpをとりあえずつけるのは好きなんですが,
こうやって部品部品に分けていくと変数をきちんとしないといろいろと問題が発生してしまう。
やっぱこういう時にきちんとカプセル化を学んで適用していって,お互いに影響を及ぼさないようにしていかないといけないのかな。
そろそろPublicで楽をしてちゃあだめということかなぁ。そんな気はするなぁ。
そこらへんをまずきちっとしてから,センサー部分をいじくるべきかなぁ ( ´Д`)=3
楽しい悩みですけどね!