Powerpoint VBAを使おう!

Powerpoint VBAやExcelのVBAで遊んでいます。Word VBAも始めました。

線に沿う玉の運動を描く⑤

前の続きです。
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

f:id:chemiphys:20170116203310p:plain
slopeという名前の閉じた図形が必要です。そいつとの衝突判定をします。
f:id:chemiphys:20170116204254g:plain
玉は勝手に作る仕組みです。

APIを使ってなくても,よく強制終了する。。なんのせいだろうか・

現時点での問題点・・ ほとんど問題点だらけなんですが,

とにかくめりこみます。判定方法をしっかり見ないといけない。適切にNodeを参照できているのか,またはめり込むわけですので,持ち上げていって衝突が切れる場所を探させて浮上させるか。

Topを上げていって衝突判定をさせればいいからできなくはない。どうしても速度の幅によってめり込むから浮上まで含めて判定とすればいいかなぁ。


そうそう,コーディングしてて,さらにクラスモジュールの中にさらにクラスモジュールがある場合とか,同じオブジェクトの受け渡しに悩みます。

標準モジュールで TSlide ballクラスで bSlide HanteiクラスでhSlideとなっていますが,同じものを受け渡しているつもりです。

対象のスライドが変わったときに変えれるようにしたい,という意思があります。

同じ名前を別々のモジュールで使ってたら混乱もしますし,かといって頭文字をこんなふうにしててもそのうちかぶったりするし,

多数のクラスモジュールを組み合わせて使う場合に受け渡す変数の名前ってどうしていったらいいものか。 pプライベートとか pプロパティとかあたりの気持ちでpをとりあえずつけるのは好きなんですが,

こうやって部品部品に分けていくと変数をきちんとしないといろいろと問題が発生してしまう。

やっぱこういう時にきちんとカプセル化を学んで適用していって,お互いに影響を及ぼさないようにしていかないといけないのかな。

そろそろPublicで楽をしてちゃあだめということかなぁ。そんな気はするなぁ。

そこらへんをまずきちっとしてから,センサー部分をいじくるべきかなぁ ( ´Д`)=3

楽しい悩みですけどね!