SSブログ

【Macでゲームを作ろう】ブロック崩しを作っていく第6回 [AppleScript辞書はつくれるか?]

今回はボールがラケットではね返る処理とゲームオーバー処理を作っていきたいと思います。

 

今回新しく使うのは

    setAlphaValue_(n) 

    ※ nは0.0~1.0の実数値です。

です。

 

順番が逆にはなりますが、まずは、ゲームオーバーの表示処理を作成します。

ブロック崩しでのゲームオーバーといえば、一般的に玉が下に落ちてしまったらゲームオーバーということになりますよね。

今までは下側の壁でも跳ね返っていましたが、これをやめて、下から飛び出したらゲームオーバーという処理をしていきます。

はじめに配置をそれっぽい位置に移動して、『Game Over』の文字を表示させるために Label を配置します。そのLabelの文字の大きさをちょっといじっています。(おこのみで)

ss11-1.png

ラベルの文字を操作するためにの宣言をしておきます。

    property textLabel1 : missing value


ss11-2.png リンクも忘れずに

 

最初は使わないので、アプリケーションが起動してウインドウが表示される『前』に実行される、’awakeFromNib’ハンドラを追加してその中に必要なコードを入力しましょう。


    on awakeFromNib()

        textLabel1's setStringValue_("") --|表示している文字を空にする|

    end awakeFromNib

 

ついでに、ボタンが真ん中の邪魔な部分に移動してますが、それをゲーム中はどうにかしたいので操作するための宣言をしておきましょう。

    property Button1 : missing value

 


ss11-3.png リンクも忘れずに

 

次はラケットに当たったら跳ね返る部分


    on moveBall()

        set {tamaX,tamaY} to {tamaX + moveX, tamaY + moveY}

        set {Xposition1, Yposition1} to {(tamaX + tamaW - tamaSizeX), (tamaY + tamaH - tamaSizeY)}

        set {Xposition2, Yposition2} to {(tamaX + tamaW + tamaSizeX), (tamaY + tamaH + tamaSizeY)}

        if (Xposition1 < 0) or (Xposition2 > viewX) then set moveX to 0 - moveX

        if (Yposition1 < 0) or (Yposition2 > viewY) then set moveY to 0 - moveY

        set decisionX to my abs((padX + padSizeX) - (tamaX + tamaW))

        set decisionY to my abs((padY + padSizeY) - (tamaY + tamaH - tamaSizeY))

        if (decisionX < padSizeX) and (decisionY < padSizeY) then set moveY to my abs(moveY)

        set BollPosition to {x:tamaX, y:tamaY}

        image1's setFrameOrigin_(BollPosition)

    end moveBall


    on abs(n) --|絶対値|

        return (n ^ 2) ^ 0.5

    end abs


『ラケットの左右の範囲内であり、ボールの下側がラケットのある高さになった時』に玉の動きを上側に向けています。

自作で abs(n)関数を作っていますが、これは絶対値を計算する関数です。Applesriptってこんな簡単な関数が実は用意されていません。他にも三角関数やら自然対数やら…。

絶対値はマイナスの符号を持たない数値のことですから、数学で出てくる『マイナス×マイナス=プラス』を利用して絶対値を求めてみました。

もっとも、この関数では5桁以上の大きな数字は扱えないかも。


次は下に落ちてしまった場合のGameOver処理です。

前回までは下にも壁があって跳ね返る設定でしたが、これを外し、下からはみ出したらどうするか決定します。

 

    on moveBall()

        set {tamaX,tamaY} to {tamaX + moveX, tamaY + moveY}

        set {Xposition1, Yposition1} to {(tamaX + tamaW - tamaSizeX), (tamaY + tamaH - tamaSizeY)}

        set {Xposition2, Yposition2} to {(tamaX + tamaW + tamaSizeX), (tamaY + tamaH + tamaSizeY)}

        if (Xposition1 < 0) or (Xposition2 > viewX) then set moveX to 0 - moveX

        --if (Yposition1 < 0) or (Yposition2 > viewY) then set moveY to 0 - moveY (この行は削除)

        if Yposition2 > viewY then set moveY to 0 - moveY --|上側は跳ね返る。この条件だけ残す|

        if Yposition1 < 0 then --|下側は飛び出たらGameOver|

            tell TimerObj to invalidate() --|まずタイマーを停止|

            textLabel1's setStringValue_("Game Over !") --|文字表示|

            set flg to false --|タイマー動作のスイッチの名残|

        end if

        set decisionX to my abs((padX + padSizeX) - (tamaX + tamaW))

        set decisionY to my abs((padY + padSizeY) - (tamaY + tamaH - tamaSizeY))

        if (decisionX < padSizeX) and (decisionY < padSizeY) then set moveY to my abs(moveY)

        set BollPosition to {x:tamaX, y:tamaY}

        image1's setFrameOrigin_(BollPosition)

    end moveBall


上の壁と下の壁にぶつかると跳ね返るスクリプトをコメントアウト(実行から除外)してます。

その代わりに、上の壁だけ跳ね返る行を増やし、

下の境界(壁だった部分)を超えると、

・タイマーの停止

・Game Over ! の文字を表示

部分を増やしています。


次にスタート処理と終了処理まとめです。

前回までは前回終了した位置からtamaが再スタートしていましたが、この回ではStartボタンが押されたらtamaの位置がリセットされてスタートするようにします。

そのため、適切な位置にスクリプトが移動していますので混乱しないようにお願いします。

 

    global tamaReset

 

    on applicationWillFinishLaunching_(aNotification)

        --set {moveX,moveY} to {5,5}    -- |action1へ移動してます|

        set flg to false

 

        (* tamaの情報取得 action1から移動してきています *)

        set {tamaSizeX, tamaSizeY} to {16, 16}

        set {tamaSizeX, tamaSizeY} to {(tamaSizeX / 2), (tamaSizeY / 2)}

        set origin2 to image1's frame()'s origin

        set {tamaX,tamaY} to {origin2's x, origin2's y}

        set size2 to image1's frame()'s |size|

        set {tamaW, tamaH} to  {size2's width, size2's height}

        set {tamaW, tamaH} to {(tamaW / 2), (tamaH / 2)}

 

        (*  tamaの位置の初期値を保存 *)

        set tamaReset to {tamaX,tamaY}

    end applicationWillFinishLaunching_

 

ウインドウが開いて最初だけ処理される部分でtamaの初期値を取得し、リセット位置を記憶します。


さて最後に、画面の中央でどんと邪魔になってるStartボタン。

このボタンはスタートするためには必要ですが、いざゲームが始まると邪魔以外の何物でもありません。

ゲーム中は消えていてもらうスクリプトを追加します。

 

まずはボタンを見えなくする処理。(ついでにメッセージを空に)


    on action1_(sender)

        if flg is false then

        .

        .

        .

            my timerStart()

            set flg to true

            button1's setAlphaValue_(0.0) -- |ボタンの不透明度(Alpha値)を0.0、つまり透明にします|

            textLabel1's setStringValue_("") -- |ラベルの文字を空にします|

 

        (* |ここは実行されることが無くなったので不要です|

        else

            try

                tell TimerObj to invalidate()

            end try

            set flg to false

        *)

        end if

    end action1_


ゲームオーバー時にボタンを再表示するスクリプト処理。


    on moveBall()

        .

        .

        .

        if Yposition1 < 0 then --|下側は飛び出たらGameOver|

            tell TimerObj to invalidate() --|まずタイマーを停止|

            textLabel1's setStringValue_("Game Over !")

            set flg to false

            button1's setAlphaValue_(1.0) -- |ボタンの不透明度(Alpha値)を1.0、つまり不透明にします|

        end if

        .

        .

        .

    end moveBall

 


これでできました。

では実行してみましょう

 


では今回はここまで。

次回は『あれ』を消します。


 

今回のスクリプト

--

script AppDelegate

    property parent : class "NSObject"

 

    property NSTimer : class "NSTimer"

    global TimerObj

    global flg

 

    property NSEvent : current application's class "NSEvent"

 

    property view1 : missing value

    property image1 : missing value

    property image2 : missing value

 

    property textLabel1 : missing value

    property Button1 : missing value

 

    global viewX,viewY, tamaX,tamaY, moveX,moveY

    global tamaW,tamaH, tamaSizeX,tamaSizeY

    global flg

    global padX,padY, padW, padH, padSizeX,padSizeY

    global mouse0

 

    global tamaReset

 

    on action1_(sender)

        if flg is false then

            (* NSViewの範囲 *)

            set origin1 to view1's frame()'s |size|

            set {viewX,viewY} to {origin1's width, origin1's height}

 

            (* |applicationWillFinishLaunchingへ移動しています|

            set {tamaSizeX, tamaSizeY} to {16, 16}

            set {tamaSizeX, tamaSizeY} to {(tamaSizeX / 2), (tamaSizeY / 2)}

            set origin2 to image1's frame()'s origin

            set {tamaX,tamaY} to {origin2's x, origin2's y}

            set size2 to image1's frame()'s |size|

            set {tamaW, tamaH} to  {size2's width, size2's height}

            set {tamaW, tamaH} to {(tamaW / 2), (tamaH / 2)}

            *)

 

            (* tamaの情報をリセット *)

            set {moveX,moveY} to {5,5}

            set {tamaX,tamaY} to tamaReset

            set BollPosition to {x:tamaX, y:tamaY}

            image1's setFrameOrigin_(BollPosition)

 

            (* Padの情報取得 *)

            set {padSizeX, padSizeY} to {100, 24}

            set {padSizeX, padSizeY} to {(padSizeX / 2), (padSizeY / 2)}

            set origin3 to image2's frame()'s origin

            set {padX,padY} to {origin3's x, origin3's y}

            set size3 to image2's frame()'s |size|

            set {padW, padH} to  {size3's width, size3's height}

            set {padW, padH} to {(padW / 2), (padH / 2)}

 

            (* 現在のマウスの位置を取得 *)

            set {mouseX,mouseY} to my mousePosition()

            set mouse0 to mouseX

 

            my timerStart()

            set flg to true

            button1's setAlphaValue_(0.0)

            textLabel1's setStringValue_("")

 

        (* |ここは実行されることが無くなったので不要です|

        else

            try

                tell TimerObj to invalidate()

            end try

            set flg to false

        *)

        end if

    end action1_

 

    on timerStart()

        try

            set TimerObj to NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(0.01, me, "mainLoop", missing value, true)

            on error

            set TimerObj to missing value

        end try

    end timerStart

 

    on mainLoop()

        my moveBall()

        my movePad()

    end mainLoop

 

    on abs(n) --|絶対値|

        return (n ^ 2) ^ 0.5

    end abs

 

    on moveBall()

        set {tamaX,tamaY} to {tamaX + moveX, tamaY + moveY}

        set {Xposition1, Yposition1} to {(tamaX + tamaW - tamaSizeX), (tamaY + tamaH - tamaSizeY)}

        set {Xposition2, Yposition2} to {(tamaX + tamaW + tamaSizeX), (tamaY + tamaH + tamaSizeY)}

        if (Xposition1 < 0) or (Xposition2 > viewX) then set moveX to 0 - moveX

        --if (Yposition1 < 0) or (Yposition2 > viewY) then set moveY to 0 - moveY

        if Yposition2 > viewY then set moveY to 0 - moveY --|上側は跳ね返る|

        if Yposition1 < 0 then --|下側は飛び出たらGameOver|

            tell TimerObj to invalidate() --|まずタイマーを停止|

            textLabel1's setStringValue_("Game Over !")

            set flg to false

            button1's setAlphaValue_(1.0)

        end if

        set decisionX to my abs((padX + padSizeX) - (tamaX + tamaW))

        set decisionY to my abs((padY + padSizeY) - (tamaY + tamaH - tamaSizeY))

        if (decisionX < padSizeX) and (decisionY < padSizeY) then set moveY to my abs(moveY)

        set BollPosition to {x:tamaX, y:tamaY}

        image1's setFrameOrigin_(BollPosition)

    end moveBall

 

    on movePad()

        set {mouseX,mouseY} to my mousePosition()

        set padX to padX + (mouseX - mouse0)

        set padLeft to padX + padW - padSizeX

        set padRight to padX + padW + padSizeX

        if padLeft < 0 then set padX to padSizeX - padW

        if padRight > viewX then set padX to viewX - padW - padSizeX

        set mouse0 to mouseX

        set padPosition to {x:padX, y:padY}

        image2's setFrameOrigin_(padPosition)

    end movePad


    on mousePosition()

        set mouseLocate to NSEvent's mouseLocation()

        set mouseX to (mouseLocate's x) as integer

        set mouseY to (mouseLocate's y) as integer

        return {mouseX,mouseY}

    end mousePosition

 

    -- IBOutlets

    property theWindow : missing value

 

    on awakeFromNib()

        textLabel1's setStringValue_("") --|表示している文字を空にする|

    end awakeFromNib

 

    on applicationWillFinishLaunching_(aNotification)

        --set {moveX,moveY} to {5,5}    -- |action1へ移動してます|

        set flg to false

 

        (* tamaの情報取得 *)

        set {tamaSizeX, tamaSizeY} to {16, 16}

        set {tamaSizeX, tamaSizeY} to {(tamaSizeX / 2), (tamaSizeY / 2)}

        set origin2 to image1's frame()'s origin

        set {tamaX,tamaY} to {origin2's x, origin2's y}

        set size2 to image1's frame()'s |size|

        set {tamaW, tamaH} to  {size2's width, size2's height}

        set {tamaW, tamaH} to {(tamaW / 2), (tamaH / 2)}


        (*  tamaの位置の初期値を保存 *)

        set tamaReset to {tamaX,tamaY}

    end applicationWillFinishLaunching_


    on applicationShouldTerminateAfterLastWindowClosed_(sender)

        return true

    end applicationShouldTerminateAfterLastWindowClosed_

 

    on applicationShouldTerminate_(sender)

        return current application's NSTerminateNow

    end applicationShouldTerminate_

end script

--



nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。