[VB.net] 再談使圖片捲動的「拉霸遊戲機」(六) - 實做一個水果盤遊戲機

水果盤的主要元件「圖片捲動控制項」及把它們做成九個一組的「拉霸控制項」都完成了,就可以繼續安排使用者介面的佈局和計算得分的邏輯,配上音效後基本上已經可以運作了。

先說一下計算獎分的條件:
1.因為允許了 User 自行選擇結果圖片的開出範圍,所以獎分的計算要有充分的靈活彈性。否則當 User 只選擇一種圖片時盤盤都是清一色莊家會輸光光。
2.使用圖片數越少則連成線的機率越大,所以有必要先建立一張機率表做為參考。

水果盤的主要元件「圖片捲動控制項」及把它們做成九個一組的「拉霸控制項」都完成了,就可以繼續安排使用者介面的佈局和計算得分的邏輯,配上音效後基本上已經可以運作了。

先說一下計算獎分的條件:

  1. 因為允許了 User 自行選擇結果圖片的開出範圍,所以獎分的計算要有充分的靈活彈性。否則當 User 只選擇一種圖片時盤盤都是清一色莊家會輸光光。
  2. 使用圖片數越少則連成線的機率越大,所以有必要先建立一張機率表做為參考。


     
  3. 又因為圖片有 0-9 共 10  種號碼,每個號碼的計分比重也要有不同才合理,下面函式會根據使用圖片數和上面表格的機率值去建立一組基本常數。
  4. User 可在最大限額內押注任何數量的籌碼,程式會把這些籌碼依序分配到0至7的連線位置上。因此每個連線位置的押分會有所不同,計算獎分時要一併考慮到。
  5. 函式也同時替不同的圖號建立了不同的加權值,屆時若某一號開出三連線則得分就可依下式算出:

    「該線押分」 * 連線機率倍數 * (最小圖號倍數 + 圖片號 * 圖號加權倍數)
    
        '---依據目前使用圖片數參考機率表換算獎金---
        Sub 取得計算參數(機率值 As Double)
            連線機率獎金 = If(使用圖片總數 = 1, 0, 1 / 機率值)
            連線機率倍數 = If(使用圖片總數 = 1, 0.8, (使用圖片總數) * 連線機率獎金 ^ (1 / 3))
            最小圖號倍數 = If(使用圖片總數 = 1, 0.2, 0.5)   '---只用一種圖片時每局都是清一色所以用圖號差異配分---
            圖號加權倍數 = 2 * (1 - 最小圖號倍數) / 10      '---自動換算圖號加權值---
        End Sub
    


  6. 程式中實際計算獎分的程式碼如下:
  7. 變數 e 為拉霸停止轉動後發出事件所帶的參數,它是一個名為「結果資料結構」的 Structure 描述了該局最後轉動停止時的所有情況。

    
            '---處理連線獎金---
            Dim 各圖號連線統計(ku_09_Bar.圖片總數 - 1) As Integer      '---設一個陣列統計各圖片的分數---
            Dim 連線獎金總額 As Integer = 0
            Dim 八線全押 As Boolean = True
            Dim 該線押分 As Integer = 0
            Dim 該線得分 As Integer = 0
            Dim 清一色獎金 As Integer
            取得計算參數(機率表(使用圖片總數, e.全盤的連線總數))
            For i = 0 To UBound(e.三連線結果)
                該線押分 = e.三連線結果(i).該線押分
                If 該線押分 = 0 Then 八線全押 = False
                If e.三連線結果(i).三連線 Then
                    Debug.WriteLine("第 " & i & " 線有3個 " & e.三連線結果(i).圖片號 & ".")
                    該線得分 = 該線押分 * 連線機率倍數 * (最小圖號倍數 + e.三連線結果(i).圖片號 * 圖號加權倍數)
                    各圖號連線統計(e.三連線結果(i).圖片號) += 該線得分
                    連線獎金總額 += 該線得分
                End If
            Next
    

  8. 「結果資料結構」定義在控制項裡,結構內容可參考[前二篇貼文]。
  9. 下圖是一個計算分數的例子,User 使用5張圖片,開出結果2號圖片有一組三連線,該線押分為15分,其計算過程為:
    1. 連線機率獎金 = 1 / 0.247813 = 4.0353
    2. 連線機率倍數 = 5 * 4.0353 ^ (1/3) = 7.9602
    3. 最小圖號倍數 = 0.5
    4. 圖號加權倍數 = 2 * (1-0.5) / 10 = 0.1
    5. 該線押分 = 15
    6. 連線圖號 = 2
    7. 得分為 = 15 * 7.9602 * (0.5 + 2 * 0.1) = 83.58299 = 四捨五入為 84 分.

      image

 

算分數的方式確定了之後,再來處理音效部分:

  1. 從早期 Windows98 的「立體彈珠台」中找到了一些可用的音效 wave 檔,用在幾個需要音效的地方:
    1. [加速]按下啟動鍵後的加速階段。
    2. [等速]持續在最高速運轉的等速階段。
    3. [減速]開始減速階段。
    4. [中獎]開出有三連線時。
    5. [都沒中]都沒有任何三連線時的一個單音。
    6. [得分]把獎分從得分區倒入使用者籌碼區的連續音。
    7. [快速兌現]使用者不想慢慢等待獎分轉入時,按下快速兌現鍵時的音效。
  2. 因為當初為了營造九個圖框不同步的視覺效果,規劃讓九個「圖片捲動控制項」有各自的轉動快慢,此時却成了負擔。因為這就無法指定[加速][等速][減速]音效的播放時機,加速還 OK,但等速和減速的時間點就要再做動態調整了。最後改了一下「圖片捲動控制項」再加上二個事件傳回來。
  3. 在進入「等速階段」和「減速階段」時各再傳回一個事件通知呼叫端:本控制項已經運行到了哪個階段。
    1. 「圖片捲動控制項」做的更改:

      
          Select Case 已捲動列數
              Case Is >= 減速階段起點列數                 '---停止前減速階段---
                  If Not _已送出減速 Then
                      RaiseEvent 開始減速了(Me)
                      _已送出減速 = True
                  End If
                  位移 = 2 + (畫格高 / 4) * ((應捲動總列數 - 已捲動列數) / (應捲動總列數 - 減速階段起點列數)) ^ 3
                  當下暫停毫秒數 = _基本暫停毫秒數 / 2
              Case Is < 加速階段終點列數                  '---啟動後加速階段---
                  位移 = 2 + (畫格高 / 4) * (已捲動列數 / 加速階段終點列數) ^ 1.2
                  當下暫停毫秒數 = _基本暫停毫秒數
              Case Else                                   '---極速階段---
                  If Not _已送出等速 Then
                      RaiseEvent 開始等速了(Me)
                      _已送出等速 = True
                  End If
                  位移 = 畫格高 / 2
                  當下暫停毫秒數 = _基本暫停毫秒數
          End Select
      
    2. 「九格拉霸控制項」也要修改,於收到事件後做出統計,當九個圖框都發出的事件全數收到後再用事件傳回給表單去做播放:

      
          Sub 收集減速報告(sender As ku_01_Bar)
              已減速的控制項數量 += 1
              If 已減速的控制項數量 = 9 Then
                  已減速的控制項數量 = 0
                  RaiseEvent 開始減速(Me)
              End If
          End Sub
          Sub 收集等速報告(sender As ku_01_Bar)
              已等速的控制項數量 += 1
              If 已等速的控制項數量 = 9 Then
                  已等速的控制項數量 = 0
                  RaiseEvent 開始等速(Me)
              End If
          End Sub
      


    3. 表單也要做出配合如下:

      
          Private Sub Ku_09_Bar1_開始啟動(sender As System.Windows.Forms.ku_09_Bar) Handles Ku_09_Bar1.開始啟動
              Play(音效名稱列舉常數.啟動, AudioPlayMode.Background)
          End Sub
          Private Sub Ku_09_Bar1_開始減速(sender As System.Windows.Forms.ku_09_Bar) Handles Ku_09_Bar1.開始減速
              Play(音效名稱列舉常數.減速, AudioPlayMode.Background)
          End Sub
          Private Sub Ku_09_Bar1_開始等速(sender As System.Windows.Forms.ku_09_Bar) Handles Ku_09_Bar1.開始等速
              Play(音效名稱列舉常數.等速, AudioPlayMode.BackgroundLoop)
          End Sub
      


  4. 有音效就要有靜音功能,這裡用了 WinAPI 的 SendMessage 去控制混音器的 mute 作用。
  5. 以下是音效部分的 Code(wave 檔已事先放到資源中):

    
    #Region "---音效---"
        Private Const WM_APPCOMMAND As Integer = &H319
        Private Const APPCOMMAND_VOLUME_MUTE As Integer = &H80000
        Private Const APPCOMMAND_VOLUME_DOWN As Long = &H90000
        Private Const APPCOMMAND_VOLUME_UP As Long = &HA0000
        Declare Function SendMessageW Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        Enum 音效名稱列舉常數
            啟動
            等速
            減速
            停止
            中獎
            都沒中
            得分
            快速兌現
        End Enum
        Sub Play(資源名稱 As 音效名稱列舉常數, mode As AudioPlayMode)
            Dim obj As System.IO.UnmanagedMemoryStream = Nothing
            obj = CType(My.Resources.ResourceManager.GetObject(資源名稱), System.IO.UnmanagedMemoryStream)
            Select Case 資源名稱
                Case 音效名稱列舉常數.啟動 : obj = My.Resources.__start_00
                Case 音效名稱列舉常數.等速 : obj = My.Resources.__continue_02
                Case 音效名稱列舉常數.減速 : obj = My.Resources.__slowdown
                Case 音效名稱列舉常數.停止 : obj = My.Resources.__stop
                Case 音效名稱列舉常數.中獎 : obj = My.Resources.__win_01
                Case 音效名稱列舉常數.都沒中 : obj = My.Resources.__loss_00
                Case 音效名稱列舉常數.得分 : obj = My.Resources.__getmoney
                Case 音效名稱列舉常數.快速兌現 : obj = My.Resources.Get_coin
            End Select
            If 音效開關 Then My.Computer.Audio.Play(obj, mode)
        End Sub
        Private Sub 音效() Handles btn_音效開關.Click, lbl_音效圖示.Click
            Play(音效名稱列舉常數.停止, AudioPlayMode.Background)
            SendMessageW(Me.Handle, WM_APPCOMMAND, 0, CType(APPCOMMAND_VOLUME_DOWN, IntPtr))
            SendMessageW(Me.Handle, WM_APPCOMMAND, 0, CType(APPCOMMAND_VOLUME_UP, IntPtr))
            音效開關 = Not 音效開關
            lbl_音效圖示.ForeColor = If(音效開關, 主色盤(128), Color.FromArgb(50, 50, 50))
            btn_音效開關.Text = If(音效開關, "靜音", "音效")
            If Not 音效開關 Then
                SendMessageW(Me.Handle, WM_APPCOMMAND, 0, CType(APPCOMMAND_VOLUME_MUTE, IntPtr))
            End If
        End Sub
    #End Region
    
    


以下是執行時的影片。

 

貼文先告一段落,接下來是最後一部分[讓它可以在網路上和 Server 及其他玩家進行互動]。

因為加上了[介面風格]功能使得原始碼和 DLL 變得不方便提供下載了(那是替公司寫的元件)但是整個「水果盤拉霸遊戲機」程式碼仍可從最近幾篇貼文中取過來參考。

 

執行檔下載:[ku_LarBar_demo.rar

 

 

 


ku3