#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include #include #include #include #include #Region Global declarations Global Enum $X, $Y, $WIDTH, $HEIGHT Global $hGUI, $hSettingsGUI ;Static controls Global Const $__STATICCONSTANT_ClassName = "Static" Global Const $STN_CLICKED = 0 Global Const $STN_DBLCLK = 1 ;Settings Global $iGameMode = 0, $iTileSize = 0, $aHighScore[3] Global Enum $GMODE_BEGINNER, $GMODE_INTERMEDIATE, $GMODE_EXPERT Global Enum $TILESZ_SMALL, $TILESZ_MEDIUM, $TILESZ_JUMBO Global $sSettingsFile = "Mine.ini" ;Settings GUI Controls Global $ahSet_Level[3], $ahSet_Size[3], $hStartGame, $ahSet_BestTimes[3][2] ;Main Grid Global $aGrid[1][3] ;[index][ControlID, Tile Value, Tile State] Global Enum $TLE_CTL, $TLE_VALUE, $TLE_STATE ;Tile states Global Const $TILE_CONCEALED = 0x01 Global Const $TILE_REVEALED = 0x02 Global Const $TILE_FLAGGED = 0x04 Global Const $TILE_MARKED = BitOR(0x08, $TILE_CONCEALED) ;Mouse events Global Const $MSE_BTN_NONE = 0x00 Global Const $MSE_BTN_PRIMARY = 0x01 Global Const $MSE_BTN_SECONDARY = 0x02 Global Const $MSE_BTN_DUAL = 0x04 Global Const $MSE_BTN_MASK = 0x0F Global Const $MSE_EVT_NONE = 0x00 Global Const $MSE_EVT_BTNPRESSED = 0x10 Global Const $MSE_EVT_BTNRELEASED = 0x20 Global Const $MSE_EVT_CURSORMOVED = 0x40 Global Const $MSE_EVT_BTNHELD = 0x80 Global Const $MSE_EVT_MASK = 0xF0 ;Highlighting styles Global Enum $HLSTYLE_NONE, $HLSTYLE_SINGLE, $HLSTYLE_MULTI ;Other controls Global $hNewGame, $hSettings, $hMessage Global $ahDigitBmps[12], $ahFaceBmps[12] Global $iDigitW = 20, $iDigitH = 35 Global $aiFacePos[4] = [0, 0, 40, 40] Global $ahGameTimer[3], $ahMineCounter[3] Global $hTimer ;timerinit() time stamp ;Dingbats for mines etc. Global Enum $CHR_CHR, $CHR_FONT Global $asMineChar[2] = [ChrW(0xF0AE), "Wingdings"] Global $asFlaggedChar[2] = ["O", "Wingdings"] Global $asMarkChar[2] = [ChrW(0xF073), "Webdings"] Global $asWrongChar[2] = [ChrW(0xF078), "Webdings"] Global $asSettingsChar[2] = ["@", "Webdings"] ;bitmap indices Global Enum $FACE_HAPPY_START = 0, $FACE_HAPPY_END = 8, _ $FACE_WORRY, $FACE_WIN, $FACE_LOSE, $FACE_COUNT Global Enum $LCD7_MINUS = 10, $LCD7_OFF, $LCD7_COUNT ;Grid/Tile parameters (populated when loading settings) Global $iGridH, $iGridW, $iMineCnt Global $iTileW, $iTileH Global $iFontSize ;Flags for timer, blocking input on end game Global $fStarted, $fFinished, $iGameTime, $iCurMineCnt, $iRemTileCnt ;Tile Background Colour Scheme Global Const $iColConcealed = 0xCCCCCCC Global Const $iColRevealed = 0xEEEEEE Global Const $iColMine = 0xFF9999 Global Const $iColWin = 0xFFCC66 Global Const $iColHiglight = $iColRevealed Global $aColNumerals[9] = [0, 0x0000C0, 0x00AA00, 0xAA0000, _ 0x000088, 0x880000, 0x00AAAA, 0xAAAAAA, 0] Global $aMousePos[2] #EndRegion Global declarations Opt("MouseCoordMode", 2) CreateBitmaps($ahFaceBmps, $ahDigitBmps) InitSettings() Main() #Region Settings Func InitSettings() ;Generate the settings window $hSettingsGUI = GUICreate("Settings", 490, 148) GUICtrlCreateGroup("Level", 10, 8, 100, 95) $ahSet_Level[0] = GUICtrlCreateRadio("Beginner", 20, 25, 80, 20) $ahSet_Level[1] = GUICtrlCreateRadio("Intermediate", 20, 50, 80, 20) $ahSet_Level[2] = GUICtrlCreateRadio("Expert", 20, 75, 80, 20) GUICtrlCreateGroup("Tile Size", 120, 8, 100, 95) $ahSet_Size[0] = GUICtrlCreateRadio("Small", 135, 25, 80, 20) $ahSet_Size[1] = GUICtrlCreateRadio("Medium", 135, 50, 80, 20) $ahSet_Size[2] = GUICtrlCreateRadio("Jumbo", 135, 75, 80, 20) GUICtrlCreateGroup("Fastest Mine Sweepers", 230, 8, 250, 130) GUICtrlCreateLabel("Beginner:", 245, 35, 60, 20, $SS_RIGHT) GUICtrlCreateLabel("Intermediate:", 245, 70, 60, 20, $SS_RIGHT) GUICtrlCreateLabel("Expert:", 245, 105, 60, 20, $SS_RIGHT) $ahSet_BestTimes[0][0] = GUICtrlCreateLabel("", 315, 35, 70, 20) $ahSet_BestTimes[1][0] = GUICtrlCreateLabel("", 315, 70, 70, 20) $ahSet_BestTimes[2][0] = GUICtrlCreateLabel("", 315, 105, 70, 20) $ahSet_BestTimes[0][1] = GUICtrlCreateLabel("", 390, 35, 80, 20) $ahSet_BestTimes[1][1] = GUICtrlCreateLabel("", 390, 70, 80, 20) $ahSet_BestTimes[2][1] = GUICtrlCreateLabel("", 390, 105, 80, 20) $hStartGame = GUICtrlCreateButton("Start Game", 60, 110, 100, 25, $BS_DEFPUSHBUTTON) ImportSettings() GUISetState(@SW_SHOW, $hSettingsGUI) EndFunc ;==>InitSettings Func ImportSettings() ;Populate the settings window from INI file GUICtrlSetData($ahSet_BestTimes[0][0], IniRead($sSettingsFile, "Scores", "BegName", "Anonymous")) GUICtrlSetData($ahSet_BestTimes[1][0], IniRead($sSettingsFile, "Scores", "IntName", "Anonymous")) GUICtrlSetData($ahSet_BestTimes[2][0], IniRead($sSettingsFile, "Scores", "ExpName", "Anonymous")) $aHighScore[0] = IniRead($sSettingsFile, "Scores", "BegScore", "999") $aHighScore[1] = IniRead($sSettingsFile, "Scores", "IntScore", "999") $aHighScore[2] = IniRead($sSettingsFile, "Scores", "ExpScore", "999") For $i = 0 To 2 GUICtrlSetData($ahSet_BestTimes[$i][1], StringFormat("%d Seconds", $aHighScore[$i])) Next Switch IniRead($sSettingsFile, "Settings", "GameMode", $GMODE_BEGINNER) Case $GMODE_EXPERT GUICtrlSetState($ahSet_Level[2], $GUI_CHECKED) Case $GMODE_INTERMEDIATE GUICtrlSetState($ahSet_Level[1], $GUI_CHECKED) Case Else GUICtrlSetState($ahSet_Level[0], $GUI_CHECKED) EndSwitch Switch IniRead($sSettingsFile, "Settings", "TileSize", $TILESZ_SMALL) Case $TILESZ_JUMBO GUICtrlSetState($ahSet_Size[2], $GUI_CHECKED) Case $TILESZ_MEDIUM GUICtrlSetState($ahSet_Size[1], $GUI_CHECKED) Case Else GUICtrlSetState($ahSet_Size[0], $GUI_CHECKED) EndSwitch EndFunc ;==>ImportSettings Func SaveSettings() ;Save back to the INI file IniWrite($sSettingsFile, "Scores", "BegName", GUICtrlRead($ahSet_BestTimes[0][0])) IniWrite($sSettingsFile, "Scores", "IntName", GUICtrlRead($ahSet_BestTimes[1][0])) IniWrite($sSettingsFile, "Scores", "ExpName", GUICtrlRead($ahSet_BestTimes[2][0])) IniWrite($sSettingsFile, "Scores", "BegScore", $aHighScore[0]) IniWrite($sSettingsFile, "Scores", "IntScore", $aHighScore[1]) IniWrite($sSettingsFile, "Scores", "ExpScore", $aHighScore[2]) Switch $iGameMode Case 2 IniWrite($sSettingsFile, "Settings", "GameMode", $GMODE_EXPERT) Case 1 IniWrite($sSettingsFile, "Settings", "GameMode", $GMODE_INTERMEDIATE) Case Else IniWrite($sSettingsFile, "Settings", "GameMode", $GMODE_BEGINNER) EndSwitch Switch $iTileSize Case 2 IniWrite($sSettingsFile, "Settings", "TileSize", $TILESZ_JUMBO) Case 1 IniWrite($sSettingsFile, "Settings", "TileSize", $TILESZ_MEDIUM) Case Else IniWrite($sSettingsFile, "Settings", "TileSize", $TILESZ_SMALL) EndSwitch EndFunc ;==>SaveSettings #EndRegion Settings #Region Game Generation Func InitGUI() ;generate the game window Local $aGUIDims, $aiOffset[2] Local Enum $W, $H ReDim $aGrid[0][0] Switch $iGameMode Case $GMODE_EXPERT $iGridH = 16 $iGridW = 30 $iMineCnt = 99 Case $GMODE_INTERMEDIATE $iGridH = 16 $iGridW = 16 $iMineCnt = 40 Case Else $iGridH = 8 $iGridW = 8 $iMineCnt = 10 EndSwitch Switch $iTileSize Case $TILESZ_JUMBO $iTileW = 40 Case $TILESZ_MEDIUM $iTileW = 33 Case Else $iTileW = 25 EndSwitch $iTileH = $iTileW ;~ ;$iFontSize = Floor($iTileW / 4) + 6 ;Change font size based on tile size ReDim $aGrid[$iGridH * $iGridW][3] If $hGUI Then GUIDelete($hGUI) $hGUI = GUICreate("Bomb Mopper", $iTileW * $iGridW + 50, $iTileH * $iGridH + 125) GUISetBkColor(0xEEEEEE) $aGUIDims = WinGetClientSize($hGUI) $aiOffset[$X] = 0.25 * $aGUIDims[$W] - (1.5 * $iDigitW) $aiOffset[$Y] = 30 - ($iDigitH / 2) For $i = 0 To 2 $ahMineCounter[$i] = _GUICtrlStatic_Create($hGUI, $aiOffset[$X] + ($i * $iDigitW), $aiOffset[$Y], $iDigitW, $iDigitH, $SS_BITMAP) Next $aiOffset[$X] -= 2 $aiOffset[$Y] -= 2 GUICtrlCreateLabel("", $aiOffset[$X], $aiOffset[$Y], 3 * $iDigitW + 4, $iDigitH + 4, BitOR($SS_GRAYFRAME, $WS_BORDER)) $aiOffset[$X] = 0.75 * $aGUIDims[$W] - (1.5 * $iDigitW) $aiOffset[$Y] = 30 - ($iDigitH / 2) For $i = 0 To 2 $ahGameTimer[$i] = _GUICtrlStatic_Create($hGUI, $aiOffset[$X] + ($i * $iDigitW), $aiOffset[$Y], $iDigitW, $iDigitH, $SS_BITMAP) Next $aiOffset[$X] -= 2 $aiOffset[$Y] -= 2 GUICtrlCreateLabel("", $aiOffset[$X], $aiOffset[$Y], 3 * $iDigitW + 4, $iDigitH + 4, BitOR($SS_GRAYFRAME, $WS_BORDER)) $aiFacePos[$X] = ($aGUIDims[$W] / 2) - 20 $aiFacePos[$Y] = 10 $hNewGame = _GUICtrlStatic_Create($hGUI, $aiFacePos[$X], $aiFacePos[$Y], $aiFacePos[$WIDTH], $aiFacePos[$HEIGHT], BitOR($SS_BITMAP, $SS_NOTIFY)) _SendMessage($hNewGame, $STM_SETIMAGE, $IMAGE_BITMAP, $ahFaceBmps[4]) $hSettings = GUICtrlCreateButton($asSettingsChar[$CHR_CHR], $aGUIDims[$W] - 35, $aGUIDims[$H] - 35, 30, 30, BitOR($BS_PUSHLIKE, $BS_CENTER, $BS_VCENTER)) GUICtrlSetFont(-1, 12, -1, -1, $asSettingsChar[$CHR_FONT]) $hMessage = GUICtrlCreateLabel("", 5, $aGUIDims[$H] - 35, $aGUIDims[$W] - 45, 30, $SS_CENTER) GUICtrlSetState(-1, $GUI_DISABLE) GUICtrlSetData($hMessage, "Pilfered from Robert Donner && Curt Johnson" & @CRLF & "for Educational Use Only") Local $iRow, $iCol GUICtrlCreateGroup("", 20, 68, $aGUIDims[$W] - 40, $aGUIDims[$H] - 108) For $i = 0 To UBound($aGrid) - 1 $iRow = Floor($i / $iGridW) $iCol = Mod($i, $iGridW) $aGrid[$i][$TLE_CTL] = GUICtrlCreateLabel("", ($iCol * $iTileW) + 25, ($iRow * $iTileH) + 80, $iTileW, $iTileH, BitOR($SS_CENTER, $SS_CENTERIMAGE), $WS_EX_STATICEDGE) GUICtrlSetBkColor(-1, $iColConcealed) GUICtrlSetFont(-1, $iFontSize, $FW_BOLD) Next GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") EndFunc ;==>InitGUI Func NewGame() GUISetState(@SW_HIDE, $hGUI) $fStarted = False $fFinished = False SetCounter($ahGameTimer) SetCounter($ahMineCounter, $iMineCnt) SetFace(EyeTrack()) For $i = 0 To UBound($aGrid) - 1 GUICtrlSetData($aGrid[$i][$TLE_CTL], "") GUICtrlSetFont($aGrid[$i][$TLE_CTL], $iFontSize, -1, -1, "") GUICtrlSetColor($aGrid[$i][$TLE_CTL], 0) GUICtrlSetBkColor($aGrid[$i][$TLE_CTL], $iColConcealed) $aGrid[$i][$TLE_VALUE] = "" $aGrid[$i][$TLE_STATE] = $TILE_CONCEALED Next LayMines() $iCurMineCnt = $iMineCnt $iRemTileCnt = UBound($aGrid) - $iMineCnt GUISetState(@SW_SHOW, $hGUI) EndFunc ;==>NewGame Func LayMines() Local $iTileCnt = UBound($aGrid), $aRndIdx[$iTileCnt] Local $iRand, $iTmp ;shuffle the order in which mines are layed. For $i = 0 To $iTileCnt - 1 $aRndIdx[$i] = $i Next For $i = $iTileCnt - 1 To 0 Step -1 $iRand = Random(0, $i, 1) $iTmp = $aRndIdx[$i] $aRndIdx[$i] = $aRndIdx[$iRand] $aRndIdx[$iRand] = $iTmp Next ;Lay the mines For $i = 0 To $iMineCnt - 1 $aGrid[$aRndIdx[$i]][$TLE_VALUE] = $asMineChar[$CHR_CHR] Next ;determine the numbers behind the tiles. Local $aNeighbours For $i = 0 To UBound($aGrid) - 1 If $aGrid[$i][$TLE_VALUE] == $asMineChar[$CHR_CHR] Then ContinueLoop $aNeighbours = GetNeighbours($i) For $j = 0 To UBound($aNeighbours) - 1 If $aGrid[$aNeighbours[$j]][$TLE_VALUE] == $asMineChar[$CHR_CHR] Then $aGrid[$i][$TLE_VALUE] += 1 Next Next EndFunc ;==>LayMines #EndRegion Game Generation #Region Gui Message Processing Func Main() Local $aMsg, $iLastSetTime While 1 $aMsg = GUIGetMsg($GUI_EVENT_ARRAY) If $aMsg[1] = $hSettingsGUI Then ProcessSettingsGUIMsg($aMsg[0]) ;New game window is generated if settings change, so enusre $hGUI is valid before proceeding. If Not ($hGUI And WinExists($hGUI)) Then ContinueLoop If $aMsg[1] = $hGUI Then ProcessMainGUIMsg($aMsg[0]) ;update the clock if need be If $fStarted Then $iGameTime = Floor(TimerDiff($hTimer) / 1000) If $iGameTime <> $iLastSetTime Then SetCounter($ahGameTimer, $iGameTime) $iLastSetTime = $iGameTime EndIf EndIf WEnd EndFunc ;==>Main Func ProcessSettingsGUIMsg($iMsg) ;Settings window is open... Switch $iMsg Case $GUI_EVENT_CLOSE ;If the main game window exists, switch back to the game window without saving. ;otherwise assume we want to start a new game (first game only) If Not $hGUI Then ContinueCase GUISetState(@SW_HIDE, $hSettingsGUI) GUISetState(@SW_SHOW, $hGUI) Case $hStartGame ;Start a new game - read settings from controls If GUICtrlRead($ahSet_Level[2]) = $GUI_CHECKED Then $iGameMode = $GMODE_EXPERT ElseIf GUICtrlRead($ahSet_Level[1]) = $GUI_CHECKED Then $iGameMode = $GMODE_INTERMEDIATE Else $iGameMode = $GMODE_BEGINNER EndIf If GUICtrlRead($ahSet_Size[2]) = $GUI_CHECKED Then $iTileSize = $TILESZ_JUMBO ElseIf GUICtrlRead($ahSet_Size[1]) = $GUI_CHECKED Then $iTileSize = $TILESZ_MEDIUM Else $iTileSize = $TILESZ_SMALL EndIf SaveSettings() InitGUI() NewGame() GUISetState(@SW_HIDE, $hSettingsGUI) GUISetState(@SW_SHOW, $hGUI) EndSwitch EndFunc ;==>ProcessSettingsGUIMsg Func ProcessMainGUIMsg($iMsg) Local $iFaceIdx, $iMouseEvent = GetMouseEvent($iMsg) ;new game button (face) is handled in WM_COMMAND function Switch $iMsg Case $GUI_EVENT_CLOSE SaveSettings() Exit Case $hSettings GUISetState(@SW_HIDE, $hGUI) GUISetState(@SW_SHOW, $hSettingsGUI) EndSwitch If $iMouseEvent Then $aMousePos = MouseGetPos() $iFaceIdx = EyeTrack() ;default to happy face EndIf Switch $iMouseEvent Case BitOR($MSE_BTN_PRIMARY, $MSE_EVT_BTNRELEASED) If LeftClickTile(GetGridIdx()) Then ;check if we need to start the timer If Not ($fStarted Or $fFinished) Then $hTimer = TimerInit() $fStarted = True EndIf EndIf Case BitOR($MSE_BTN_PRIMARY, BitAND($iMouseEvent, $MSE_EVT_MASK)) ;primary: all other states (press, drag or hold) DoHighlight($HLSTYLE_SINGLE) $iFaceIdx = $FACE_WORRY Case BitOR($MSE_BTN_SECONDARY, $MSE_EVT_BTNPRESSED) RightClickTile(GetGridIdx()) Case BitOR($MSE_BTN_DUAL, $MSE_EVT_BTNRELEASED) DualClickTile(GetGridIdx()) Case BitOR($MSE_BTN_DUAL, BitAND($iMouseEvent, $MSE_EVT_MASK)) ;Dual: all other DoHighlight($HLSTYLE_MULTI) $iFaceIdx = $FACE_WORRY EndSwitch If (Not $fFinished) And $iMouseEvent Then SetFace($iFaceIdx) EndFunc ;==>ProcessMainGUIMsg Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $nNotifyCode = BitShift($wParam, 16) Local $hCtrl = $lParam Switch $hCtrl Case $hNewGame Switch $nNotifyCode Case $STN_CLICKED ;our static cotrols can't be handled with GuiGetMsg() NewGame() EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND #EndRegion Gui Message Processing #Region Tile Clicking Functions Func LeftClickTile($iIndex) Local $aNeighbours If $iIndex < 0 Then Return False If $iIndex >= UBound($aGrid) Then Return False ;tile must not be flagged as mine, or already uncovered If Not BitAND($aGrid[$iIndex][$TLE_STATE], $TILE_CONCEALED) Then Return False ;stepped on a mine. If $aGrid[$iIndex][$TLE_VALUE] == $asMineChar[$CHR_CHR] Then GUICtrlSetBkColor($aGrid[$iIndex][$TLE_CTL], $iColMine) Return LoseGame() EndIf ;reveal tile $aGrid[$iIndex][$TLE_STATE] = $TILE_REVEALED GUICtrlSetBkColor($aGrid[$iIndex][$TLE_CTL], $iColRevealed) GUICtrlSetFont($aGrid[$iIndex][$TLE_CTL], $iFontSize, $FW_BOLD, -1, "") GUICtrlSetData($aGrid[$iIndex][$TLE_CTL], $aGrid[$iIndex][$TLE_VALUE]) ;set the colour when stepped on. Switch $aGrid[$iIndex][$TLE_VALUE] Case 1 To 8 GUICtrlSetColor($aGrid[$iIndex][$TLE_CTL], $aColNumerals[$aGrid[$iIndex][$TLE_VALUE]]) Case "" ;tile is blank, so reveal all neighbouring tiles. $aNeighbours = GetNeighbours($iIndex) For $i = 0 To UBound($aNeighbours) - 1 LeftClickTile($aNeighbours[$i]) Next EndSwitch $iRemTileCnt -= 1 ;Remaining tiles If Not $iRemTileCnt Then WinGame() Return True EndFunc ;==>LeftClickTile Func RightClickTile($iIndex) If $iIndex < 0 Then Return False If $iIndex >= UBound($aGrid) Then Return False Switch $aGrid[$iIndex][$TLE_STATE] Case $TILE_FLAGGED $iCurMineCnt += 1 SetCounter($ahMineCounter, $iCurMineCnt) $aGrid[$iIndex][$TLE_STATE] = $TILE_MARKED GUICtrlSetData($aGrid[$iIndex][$TLE_CTL], $asMarkChar[$CHR_CHR]) GUICtrlSetFont($aGrid[$iIndex][$TLE_CTL], $iFontSize, -1, -1, $asMarkChar[$CHR_FONT]) GUICtrlSetColor($aGrid[$iIndex][$TLE_CTL], 0x0000FF) Case $TILE_MARKED $aGrid[$iIndex][$TLE_STATE] = $TILE_CONCEALED GUICtrlSetData($aGrid[$iIndex][$TLE_CTL], "") GUICtrlSetColor($aGrid[$iIndex][$TLE_CTL], 0) Case $TILE_CONCEALED $iCurMineCnt -= 1 SetCounter($ahMineCounter, $iCurMineCnt) GUICtrlSetColor($aGrid[$iIndex][$TLE_CTL], 0) GUICtrlSetData($aGrid[$iIndex][$TLE_CTL], $asFlaggedChar[$CHR_CHR]) GUICtrlSetFont($aGrid[$iIndex][$TLE_CTL], $iFontSize, $FW_BOLD, -1, $asFlaggedChar[$CHR_FONT]) $aGrid[$iIndex][$TLE_STATE] = $TILE_FLAGGED Case Else Return False EndSwitch Return True EndFunc ;==>RightClickTile Func DualClickTile($iIndex) Local $aNeighbours, $iProxMineCnt = 0 DoHighlight($HLSTYLE_NONE) If $iIndex < 0 Then Return False If $iIndex >= UBound($aGrid) Then Return False ;Only revealed number tiles can be dual clicked If Not Int($aGrid[$iIndex][$TLE_VALUE]) Then Return False If $aGrid[$iIndex][$TLE_STATE] <> $TILE_REVEALED Then Return False ;Check neigbouring "flagged as mine" tile count is correct, otherwise fail. $aNeighbours = GetNeighbours($iIndex) For $i = 0 To UBound($aNeighbours) - 1 If $aGrid[$aNeighbours[$i]][$TLE_STATE] == $TILE_FLAGGED Then $iProxMineCnt += 1 Next If $iProxMineCnt <> $aGrid[$iIndex][$TLE_VALUE] Then Return False ;Click all neighboring tiles. For $i = 0 To UBound($aNeighbours) - 1 LeftClickTile($aNeighbours[$i]) Next Return True EndFunc ;==>DualClickTile #EndRegion Tile Clicking Functions #Region Tile Highlighting Func DoHighlight($iHLStyle = $HLSTYLE_NONE) Static $iLastIndex = -1, $iLastHLStyle = $HLSTYLE_NONE Local $iIndex = -1 Local $fDeHighlight = False, $fHighlight = False If $fFinished Then Return If $iHLStyle = $HLSTYLE_NONE Then ;Release highlighting - triggered by completing a dual click ($HLSTYLE_MULTI -> $HLSTYLE_NONE) ;there's no trigger for completing a left click - it should work but is not needed. $iIndex = -1 $fDeHighlight = True Else $iIndex = GetGridIdx() If ($iIndex <> $iLastIndex) Or ($iHLStyle <> $iLastHLStyle) Then ;left click is initiated ($HLSTYLE_NONE -> $HLSTYLE_SINGLE) ;OR dual click has been initiated ($HLSTYLE_XXXX -> $HLSTYLE_MULTI), ;OR mouse has moved with the left button (and possibly right) held down $fHighlight = True $fDeHighlight = True EndIf EndIf If $fDeHighlight Then If $iLastHLStyle = $HLSTYLE_SINGLE Then Highlight($iLastIndex, False) Else MultiHighlight($iLastIndex, False) EndIf EndIf If $fHighlight Then If $iHLStyle = $HLSTYLE_SINGLE Then Highlight($iIndex) Else MultiHighlight($iIndex) EndIf EndIf $iLastIndex = $iIndex $iLastHLStyle = $iHLStyle EndFunc ;==>DoHighlight Func Highlight($iIndex, $fHightlightOn = True) Local $iTgtCol = $iColHiglight If Not $fHightlightOn Then $iTgtCol = $iColConcealed If $iIndex < 0 Then Return False If $iIndex >= UBound($aGrid) Then Return False ;must be concealed tile to highlight If Not BitAND($aGrid[$iIndex][$TLE_STATE], $TILE_CONCEALED) Then Return False GUICtrlSetBkColor($aGrid[$iIndex][$TLE_CTL], $iTgtCol) Return True EndFunc ;==>Highlight Func MultiHighlight($iIndex, $fHightlightOn = True) Local $aNeighbours, $iTgtCol = $iColHiglight If Not $fHightlightOn Then $iTgtCol = $iColConcealed If $iIndex < 0 Then Return False If $iIndex >= UBound($aGrid) Then Return False ;Must be uncovered number tile to highlight neighbours If Not Int($aGrid[$iIndex][$TLE_VALUE]) Then Return False If $aGrid[$iIndex][$TLE_STATE] <> $TILE_REVEALED Then Return False $aNeighbours = GetNeighbours($iIndex) For $i = 0 To UBound($aNeighbours) - 1 If BitAND($aGrid[$aNeighbours[$i]][$TLE_STATE], $TILE_CONCEALED) Then GUICtrlSetBkColor($aGrid[$aNeighbours[$i]][$TLE_CTL], $iTgtCol) EndIf Next Return True EndFunc ;==>MultiHighlight #EndRegion Tile Highlighting #Region Win/Lose Func WinGame() Local $iScore, $sName $fStarted = False $fFinished = True SetFace($FACE_WIN) ;make the grid look pretty For $i = 0 To UBound($aGrid) - 1 If $aGrid[$i][$TLE_VALUE] = $asMineChar[$CHR_CHR] Then GUICtrlSetBkColor($aGrid[$i][$TLE_CTL], $iColMine) Else GUICtrlSetBkColor($aGrid[$i][$TLE_CTL], $iColWin) EndIf Next ;check & update high score if need be $iScore = $iGameTime If $iScore < $aHighScore[$iGameMode] Then $sName = InputBox("Highscore", "Enter your name:", GUICtrlRead($ahSet_BestTimes[$iGameMode][0]), "", 120, 140) If Not $sName Then $sName = "Anonymous" GUICtrlSetData($ahSet_BestTimes[$iGameMode][0], $sName) GUICtrlSetData($ahSet_BestTimes[$iGameMode][1], StringFormat("%d Seconds", $iScore)) $aHighScore[$iGameMode] = $iScore SaveSettings() GUISetState(@SW_HIDE, $hGUI) GUISetState(@SW_SHOW, $hSettingsGUI) EndIf EndFunc ;==>WinGame Func LoseGame() $fStarted = False $fFinished = True SetFace($FACE_LOSE) For $i = 0 To UBound($aGrid) - 1 If $aGrid[$i][$TLE_STATE] == $TILE_FLAGGED Then ;show where flags are in the wrong place If $aGrid[$i][$TLE_VALUE] <> $asMineChar[$CHR_CHR] Then GUICtrlSetData($aGrid[$i][$TLE_CTL], $asWrongChar[$CHR_CHR]) GUICtrlSetFont($aGrid[$i][$TLE_CTL], $iFontSize, -1, -1, $asWrongChar[$CHR_FONT]) GUICtrlSetColor($aGrid[$i][$TLE_CTL], 0) EndIf ContinueLoop EndIf ;reveal undiscovered mines If $aGrid[$i][$TLE_VALUE] == $asMineChar[$CHR_CHR] Then GUICtrlSetData($aGrid[$i][$TLE_CTL], $aGrid[$i][$TLE_VALUE]) GUICtrlSetFont($aGrid[$i][$TLE_CTL], $iFontSize, -1, -1, $asMineChar[$CHR_FONT]) GUICtrlSetColor($aGrid[$i][$TLE_CTL], 0) EndIf Next EndFunc ;==>LoseGame #EndRegion Win/Lose #Region Static controls & Bitmap generation Func _GUICtrlStatic_Create($hWnd, $iX, $iY, $iWidth, $iHeight, $iStyle = -1, $iExStyle = -1) ;we want to create static controls with the $SS_BITMAP style for the counters & face. ;GuiCtrlCreatePic only works when loading images from external files. If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0) EndIf Local $iForcedStyle = BitOR($__UDFGUICONSTANT_WS_VISIBLE, $__UDFGUICONSTANT_WS_CHILD) If $iStyle = -1 Then $iStyle = $iForcedStyle Else $iStyle = BitOR($iStyle, $iForcedStyle) EndIf If $iExStyle = -1 Then $iExStyle = 0 Local $nCtrlID = __UDF_GetNextGlobalID($hWnd) If @error Then Return SetError(@error, @extended, 0) Local $hStatic = _WinAPI_CreateWindowEx($iExStyle, $__STATICCONSTANT_ClassName, "", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd, $nCtrlID) Return $hStatic EndFunc ;==>_GUICtrlStatic_Create Func CreateBitmaps(ByRef $ahFaceBmps, ByRef $ahDigitBmps) _GDIPlus_Startup() CreateDigBitmaps($ahDigitBmps) CreateFaceBitmaps($ahFaceBmps) _GDIPlus_Shutdown() EndFunc ;==>CreateBitmaps Func CreateDigBitmaps(ByRef $ahDigitBmps) If UBound($ahDigitBmps) <> $LCD7_COUNT Then Return SetError(1, 0, False) Local $hDigGraphic, $iw, $ih ;$iw = 0.65 * $ih - Suggested aspect for digit box. $ih = $iDigitH $iw = $iDigitW Local $aiBox[4], $iHMar, $iMar, $iHThk, $iThk, _ $iLIEdge, $iLOEdge, $iRIEdge, $iROEdge, _ $iTIEdge, $iTOEdge, $iBIEdge, $iBOEdge, _ $iMTEdge, $iMBEdge, $iLMPoint, $iRMPoint, _ $iTMPoint, $iBMPoint, $iBoxYCtr ;Mask for which segments should light up. ;$array[0-9]: numerals 0-9, [10]: minus sign, [11]: all off ;0x01 = seg1, 0x2 = seg2, 0x4 = seg3 etc.. Local $aiNumEnc[$LCD7_COUNT] = [ _ 0x3F, 0x06, 0x5B, 0x4F, _ 0x66, 0x6D, 0x7D, 0x07, _ 0x7F, 0x6F, 0x40, 0x00] ;x,y points for drawing a segment polygon. Local $aiSeg[7][2] = [[6]] ;Brushes Local $hLitBrush, $hUnlitBrush, $iBackCol $iBackCol = BitOR(0xFF000000, $iColHiglight) $hLitBrush = _GDIPlus_BrushCreateSolid(0xFFC00000) $hUnlitBrush = _GDIPlus_BrushCreateSolid(0xFF202020) $hUnlitBrush = _GDIPlus_BrushCreateSolid(BitOR(0xFF000000, $iColConcealed)) ;Segment thickness & margin $iHThk = Ceiling($iw / 16) ;Half segment thickness $iHMar = Ceiling($iHThk / 4) ;Half margin $iThk = 2 * $iHThk $iMar = 2 * $iHMar ;Reference positions on x OR y axis $iBoxYCtr = $ih / 2 $iLOEdge = $iHThk $iLIEdge = $iLOEdge + $iThk $iROEdge = $iw - $iHThk $iRIEdge = $iROEdge - $iThk $iTOEdge = $aiBox[$Y] + $iHThk $iTIEdge = $iTOEdge + $iThk $iBOEdge = $ih - $iHThk $iBIEdge = $iBOEdge - $iThk $iMTEdge = $iBoxYCtr - $iHThk $iMBEdge = $iBoxYCtr + $iHThk $iLMPoint = $iLOEdge + $iHThk $iRMPoint = $iROEdge - $iHThk $iTMPoint = $iTOEdge + $iHThk $iBMPoint = $iBOEdge - $iHThk ;For each digit we want to generate For $i = 0 To $LCD7_COUNT - 1 $ahDigitBmps[$i] = _GDIPlus_BitmapCreateFromScan0($iw, $ih) $hDigGraphic = _GDIPlus_ImageGetGraphicsContext($ahDigitBmps[$i]) _GDIPlus_GraphicsSetSmoothingMode($hDigGraphic, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hDigGraphic, $iBackCol) ;Define polygon for each segment For $j = 0 To 6 Switch $j Case 0 $aiSeg[1][0] = $iLMPoint $aiSeg[1][1] = $iTMPoint - $iHMar $aiSeg[2][0] = $iLIEdge - $iHMar $aiSeg[2][1] = $iTOEdge $aiSeg[3][0] = $iRIEdge + $iHMar $aiSeg[3][1] = $iTOEdge $aiSeg[4][0] = $iRMPoint $aiSeg[4][1] = $iTMPoint - $iHMar $aiSeg[5][0] = $iRIEdge - $iHMar $aiSeg[5][1] = $iTIEdge $aiSeg[6][0] = $iLIEdge + $iHMar $aiSeg[6][1] = $iTIEdge Case 1 $aiSeg[1][0] = $iRMPoint + $iHMar $aiSeg[1][1] = $iTMPoint $aiSeg[2][0] = $iROEdge $aiSeg[2][1] = $iTIEdge $aiSeg[3][0] = $iROEdge $aiSeg[3][1] = $iMTEdge $aiSeg[4][0] = $iRMPoint + $iHMar $aiSeg[4][1] = $iBoxYCtr - $iHMar $aiSeg[5][0] = $iRIEdge $aiSeg[5][1] = $iMTEdge - $iMar $aiSeg[6][0] = $iRIEdge $aiSeg[6][1] = $iTIEdge + $iHMar Case 2 $aiSeg[1][0] = $iRMPoint + $iHMar $aiSeg[1][1] = $iBMPoint $aiSeg[2][0] = $iROEdge $aiSeg[2][1] = $iBIEdge $aiSeg[3][0] = $iROEdge $aiSeg[3][1] = $iMBEdge $aiSeg[4][0] = $iRMPoint + $iHMar $aiSeg[4][1] = $iBoxYCtr + $iHMar $aiSeg[5][0] = $iRIEdge $aiSeg[5][1] = $iMBEdge + $iMar $aiSeg[6][0] = $iRIEdge $aiSeg[6][1] = $iBIEdge - $iHMar Case 3 $aiSeg[1][0] = $iLMPoint $aiSeg[1][1] = $iBMPoint + $iHMar $aiSeg[2][0] = $iLIEdge - $iHMar $aiSeg[2][1] = $iBOEdge $aiSeg[3][0] = $iRIEdge + $iHMar $aiSeg[3][1] = $iBOEdge $aiSeg[4][0] = $iRMPoint $aiSeg[4][1] = $iBMPoint + $iHMar $aiSeg[5][0] = $iRIEdge - $iHMar $aiSeg[5][1] = $iBIEdge $aiSeg[6][0] = $iLIEdge + $iHMar $aiSeg[6][1] = $iBIEdge Case 4 $aiSeg[1][0] = $iLMPoint - $iHMar $aiSeg[1][1] = $iBMPoint $aiSeg[2][0] = $iLOEdge $aiSeg[2][1] = $iBIEdge $aiSeg[3][0] = $iLOEdge $aiSeg[3][1] = $iMBEdge $aiSeg[4][0] = $iLMPoint - $iHMar $aiSeg[4][1] = $iBoxYCtr + $iHMar $aiSeg[5][0] = $iLIEdge $aiSeg[5][1] = $iMBEdge + $iMar $aiSeg[6][0] = $iLIEdge $aiSeg[6][1] = $iBIEdge - $iHMar Case 5 $aiSeg[1][0] = $iLMPoint - $iHMar $aiSeg[1][1] = $iTMPoint $aiSeg[2][0] = $iLOEdge $aiSeg[2][1] = $iTIEdge $aiSeg[3][0] = $iLOEdge $aiSeg[3][1] = $iMTEdge $aiSeg[4][0] = $iLMPoint - $iHMar $aiSeg[4][1] = $iBoxYCtr - $iHMar $aiSeg[5][0] = $iLIEdge $aiSeg[5][1] = $iMTEdge - $iMar $aiSeg[6][0] = $iLIEdge $aiSeg[6][1] = $iTIEdge + $iHMar Case 6 $aiSeg[1][0] = $iLMPoint $aiSeg[1][1] = $iBoxYCtr $aiSeg[2][0] = $iLIEdge $aiSeg[2][1] = $iMTEdge $aiSeg[3][0] = $iRIEdge $aiSeg[3][1] = $iMTEdge $aiSeg[4][0] = $iRMPoint $aiSeg[4][1] = $iBoxYCtr $aiSeg[5][0] = $iRIEdge $aiSeg[5][1] = $iMBEdge $aiSeg[6][0] = $iLIEdge $aiSeg[6][1] = $iMBEdge EndSwitch ;Draw "lit" or "unlit" segment as defined in mask If BitAND($aiNumEnc[$i], 2 ^ $j) Then _GDIPlus_GraphicsFillPolygon($hDigGraphic, $aiSeg, $hLitBrush) Else _GDIPlus_GraphicsFillPolygon($hDigGraphic, $aiSeg, $hUnlitBrush) EndIf Next $ahDigitBmps[$i] = _GDIPlus_BitmapCreateDIBFromBitmap($ahDigitBmps[$i]) Next _GDIPlus_BrushDispose($hLitBrush) _GDIPlus_BrushDispose($hUnlitBrush) Return True EndFunc ;==>CreateDigBitmaps Func CreateFaceBitmaps(ByRef $ahFaceBmps) If UBound($ahFaceBmps) <> $FACE_COUNT Then Return SetError(1, 0, False) Local $hGraphic, $iw, $ih $iw = $aiFacePos[$WIDTH] $ih = $aiFacePos[$HEIGHT] Local $iMar, $iEyeballSz, $iWryEyeballSz, $iSmileArcRto Local $aiFaceBox[4], $aiEyeBox[2][4], $aiEyeBalls[2][$FACE_COUNT][2], _ $aiSmileBox[4], $aiWorryBox[4], $aiFrownBox[4], _ $aiShadesPnts[6][2], $aiDeadEyePnts[8][2] ;Create brushes Local $hFaceBrush, $hWhiteBrush, $hBlackBrush, _ $hEyeBrush, $hShadesBrush, $hBlackPen, $iBackCol $iBackCol = BitOR(0xFF000000, $iColHiglight) $hBlackBrush = _GDIPlus_BrushCreateSolid(0xFF0000000) $hWhiteBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) $hFaceBrush = _GDIPlus_BrushCreateSolid(0xFFEEEE00) $hBlackPen = _GDIPlus_PenCreate(0xFF000000) $hEyeBrush = _GDIPlus_BrushCreateSolid(0xFF0090AA) $hShadesBrush = _GDIPlus_BrushCreateSolid(0x80000000) ;some params $iMar = 6 $iEyeballSz = 2 $iWryEyeballSz = 4 $iSmileArcRto = 0.6 ;Define bounds for face, eyes, mouth etc. $aiFaceBox[$X] = $iMar $aiFaceBox[$Y] = $iMar $aiFaceBox[$WIDTH] = ($iw - 1) - 2 * $iMar $aiFaceBox[$HEIGHT] = ($ih - 1) - 2 * $iMar $aiEyeBox[0][$WIDTH] = $aiFaceBox[$WIDTH] / 4 $aiEyeBox[0][$HEIGHT] = $aiFaceBox[$HEIGHT] / 5 $aiEyeBox[0][$X] = 0.3 * $aiFaceBox[$WIDTH] + ($aiFaceBox[$X] - $aiEyeBox[0][$WIDTH] / 2) $aiEyeBox[0][$Y] = 0.33 * $aiFaceBox[$HEIGHT] + ($aiFaceBox[$Y] - $aiEyeBox[0][$HEIGHT] / 2) $aiEyeBox[1][$WIDTH] = $aiEyeBox[0][$WIDTH] $aiEyeBox[1][$HEIGHT] = $aiEyeBox[0][$HEIGHT] $aiEyeBox[1][$X] = 0.7 * $aiFaceBox[$WIDTH] + ($aiFaceBox[$X] - $aiEyeBox[0][$WIDTH] / 2) $aiEyeBox[1][$Y] = $aiEyeBox[0][$Y] $aiWorryBox[$WIDTH] = 0.33 * $aiFaceBox[$WIDTH] $aiWorryBox[$HEIGHT] = 0.25 * $aiFaceBox[$HEIGHT] $aiWorryBox[$X] = 0.5 * $aiFaceBox[$WIDTH] + ($aiFaceBox[$X] - $aiWorryBox[$WIDTH] / 2) $aiWorryBox[$Y] = 0.7 * $aiFaceBox[$HEIGHT] + ($aiFaceBox[$Y] - $aiWorryBox[$HEIGHT] / 2) $aiSmileBox[$WIDTH] = $iSmileArcRto * $aiFaceBox[$WIDTH] $aiSmileBox[$HEIGHT] = $iSmileArcRto * $aiFaceBox[$HEIGHT] $aiSmileBox[$X] = ($aiFaceBox[$WIDTH] - $aiSmileBox[$WIDTH]) / 2 + $aiFaceBox[$X] $aiSmileBox[$Y] = ($aiFaceBox[$HEIGHT] - $aiSmileBox[$HEIGHT]) / 2 + $aiFaceBox[$Y] $aiFrownBox = $aiSmileBox $aiFrownBox[$Y] = 0.66 * $aiFaceBox[$HEIGHT] + $aiFaceBox[$Y] ;bounds for eyballs - $box[L/R eye][face index][x/y coord] For $i = 0 To 1 For $j = 0 To $FACE_COUNT - 1 If $j <= $FACE_HAPPY_END Then ; happy faces, (eyes in 9 different positions) $aiEyeBalls[$i][$j][$X] = 0.25 * (Mod($j, 3) + 1) * $aiEyeBox[$i][$WIDTH] + ($aiEyeBox[$i][$X] - $iEyeballSz / 2) $aiEyeBalls[$i][$j][$Y] = 0.25 * (Floor($j / 3) + 1) * $aiEyeBox[$i][$HEIGHT] + ($aiEyeBox[$i][$Y] - $iEyeballSz / 2) Else $aiEyeBalls[$i][$j][$X] = $aiEyeBalls[$i][4][$X] - ($iWryEyeballSz - $iEyeballSz) / 2 $aiEyeBalls[$i][$j][$Y] = $aiEyeBalls[$i][4][$Y] - ($iWryEyeballSz - $iEyeballSz) / 2 EndIf Next Next ;points for drawing glasses frame (alternating start/end points) $aiShadesPnts[0][$X] = $aiFaceBox[$X] $aiShadesPnts[0][$Y] = $aiFaceBox[$HEIGHT] / 2 + $aiFaceBox[$Y] $aiShadesPnts[1][$X] = $aiEyeBox[0][$X] $aiShadesPnts[1][$Y] = $aiEyeBox[0][$HEIGHT] / 2 + $aiEyeBox[0][$Y] $aiShadesPnts[2][$X] = $aiEyeBox[0][$WIDTH] + $aiEyeBox[0][$X] $aiShadesPnts[2][$Y] = $aiShadesPnts[1][$Y] $aiShadesPnts[3][$X] = $aiEyeBox[1][$X] $aiShadesPnts[3][$Y] = $aiShadesPnts[1][$Y] $aiShadesPnts[4][$X] = $aiEyeBox[1][$WIDTH] + $aiEyeBox[1][$X] $aiShadesPnts[4][$Y] = $aiShadesPnts[1][$Y] $aiShadesPnts[5][$X] = $aiFaceBox[$WIDTH] + $aiFaceBox[$X] $aiShadesPnts[5][$Y] = $aiShadesPnts[0][$Y] ;points for drawing dead eyes (alternating start/end points) $aiDeadEyePnts[0][$X] = $aiEyeBox[0][$X] + 1 $aiDeadEyePnts[0][$Y] = $aiEyeBox[0][$Y] + 1 $aiDeadEyePnts[1][$X] = $aiEyeBox[0][$WIDTH] + $aiEyeBox[0][$X] - 1 $aiDeadEyePnts[1][$Y] = $aiEyeBox[0][$HEIGHT] + $aiEyeBox[0][$Y] - 1 $aiDeadEyePnts[2][$X] = $aiDeadEyePnts[1][$X] $aiDeadEyePnts[2][$Y] = $aiDeadEyePnts[0][$Y] $aiDeadEyePnts[3][$X] = $aiDeadEyePnts[0][$X] $aiDeadEyePnts[3][$Y] = $aiDeadEyePnts[1][$Y] $aiDeadEyePnts[4][$X] = $aiEyeBox[1][$X] + 1 $aiDeadEyePnts[4][$Y] = $aiEyeBox[1][$Y] + 1 $aiDeadEyePnts[5][$X] = $aiEyeBox[1][$WIDTH] + $aiEyeBox[1][$X] - 1 $aiDeadEyePnts[5][$Y] = $aiEyeBox[1][$HEIGHT] + $aiEyeBox[1][$Y] - 1 $aiDeadEyePnts[6][$X] = $aiDeadEyePnts[5][$X] $aiDeadEyePnts[6][$Y] = $aiDeadEyePnts[4][$Y] $aiDeadEyePnts[7][$X] = $aiDeadEyePnts[4][$X] $aiDeadEyePnts[7][$Y] = $aiDeadEyePnts[5][$Y] ;draw each face For $i = 0 To $FACE_COUNT - 1 ;prepare $ahFaceBmps[$i] = _GDIPlus_BitmapCreateFromScan0($iw, $ih) $hGraphic = _GDIPlus_ImageGetGraphicsContext($ahFaceBmps[$i]) _GDIPlus_GraphicsSetSmoothingMode($hGraphic, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hGraphic, $iBackCol) ;draw control border and yellow circle _GDIPlus_GraphicsDrawRect($hGraphic, 0, 0, $iw - 1, $ih - 1, $hBlackPen) _GDIPlus_GraphicsDrawEllipse($hGraphic, $aiFaceBox[$X], $aiFaceBox[$Y], $aiFaceBox[$WIDTH], $aiFaceBox[$HEIGHT], $hBlackPen) _GDIPlus_GraphicsFillEllipse($hGraphic, $aiFaceBox[$X], $aiFaceBox[$Y], $aiFaceBox[$WIDTH], $aiFaceBox[$HEIGHT], $hFaceBrush) ;draw (non-dead) eyes & eyeballs If $i > $FACE_HAPPY_END Then $iEyeballSz = $iWryEyeballSz If $i <> $FACE_LOSE Then _GDIPlus_GraphicsDrawEllipse($hGraphic, $aiEyeBox[0][$X], $aiEyeBox[0][$Y], $aiEyeBox[0][$WIDTH], $aiEyeBox[0][$HEIGHT], $hBlackPen) _GDIPlus_GraphicsDrawEllipse($hGraphic, $aiEyeBox[1][$X], $aiEyeBox[1][$Y], $aiEyeBox[1][$WIDTH], $aiEyeBox[1][$HEIGHT], $hBlackPen) _GDIPlus_GraphicsFillEllipse($hGraphic, $aiEyeBox[0][$X], $aiEyeBox[0][$Y], $aiEyeBox[0][$WIDTH], $aiEyeBox[0][$HEIGHT], $hWhiteBrush) _GDIPlus_GraphicsFillEllipse($hGraphic, $aiEyeBox[1][$X], $aiEyeBox[1][$Y], $aiEyeBox[1][$WIDTH], $aiEyeBox[1][$HEIGHT], $hWhiteBrush) _GDIPlus_GraphicsFillEllipse($hGraphic, $aiEyeBalls[0][$i][$X], $aiEyeBalls[0][$i][$Y], $iEyeballSz, $iEyeballSz, $hEyeBrush) _GDIPlus_GraphicsFillEllipse($hGraphic, $aiEyeBalls[1][$i][$X], $aiEyeBalls[1][$i][$Y], $iEyeballSz, $iEyeballSz, $hEyeBrush) EndIf ;draw mouth, and anything else thats missing Switch $i Case $FACE_LOSE For $j = 0 To 7 Step 2 _GDIPlus_GraphicsDrawLine($hGraphic, $aiDeadEyePnts[$j][$X], $aiDeadEyePnts[$j][$Y], $aiDeadEyePnts[$j + 1][$X], $aiDeadEyePnts[$j + 1][$Y], $hBlackPen) Next _GDIPlus_GraphicsDrawArc($hGraphic, $aiFrownBox[$X], $aiFrownBox[$Y], $aiFrownBox[$WIDTH], $aiFrownBox[$HEIGHT], 210, 120, $hBlackPen) Case $FACE_WORRY _GDIPlus_GraphicsFillEllipse($hGraphic, $aiWorryBox[$X], $aiWorryBox[$Y], $aiWorryBox[$WIDTH], $aiWorryBox[$HEIGHT], $hBlackBrush) Case $FACE_WIN _GDIPlus_GraphicsFillEllipse($hGraphic, $aiEyeBox[0][$X], $aiEyeBox[0][$Y], $aiEyeBox[0][$WIDTH], $aiEyeBox[0][$HEIGHT], $hShadesBrush) _GDIPlus_GraphicsFillEllipse($hGraphic, $aiEyeBox[1][$X], $aiEyeBox[1][$Y], $aiEyeBox[1][$WIDTH], $aiEyeBox[1][$HEIGHT], $hShadesBrush) For $j = 0 To 5 Step 2 _GDIPlus_GraphicsDrawLine($hGraphic, $aiShadesPnts[$j][$X], $aiShadesPnts[$j][$Y], $aiShadesPnts[$j + 1][$X], $aiShadesPnts[$j + 1][$Y], $hBlackPen) Next ContinueCase Case Else _GDIPlus_GraphicsDrawArc($hGraphic, $aiSmileBox[$X], $aiSmileBox[$Y], $aiSmileBox[$WIDTH], $aiSmileBox[$HEIGHT], 30, 120, $hBlackPen) EndSwitch $ahFaceBmps[$i] = _GDIPlus_BitmapCreateDIBFromBitmap($ahFaceBmps[$i]) Next ;cleanup _GDIPlus_BrushDispose($hBlackBrush) _GDIPlus_BrushDispose($hWhiteBrush) _GDIPlus_BrushDispose($hFaceBrush) _GDIPlus_BrushDispose($hEyeBrush) _GDIPlus_BrushDispose($hShadesBrush) _GDIPlus_PenDispose($hBlackPen) Return $ahFaceBmps EndFunc ;==>CreateFaceBitmaps #EndRegion Static controls & Bitmap generation #Region Support Functions Func GetNeighbours($iIndex) Local $aNeighbours[8], $iNeighIdx = 0 ;determine the indicies of all neighboring tiles and return these as an array Local $iRow, $iCol $iRow = Floor($iIndex / $iGridW) $iCol = Mod($iIndex, $iGridW) For $i = $iRow - 1 To $iRow + 1 If $i < 0 Or $i >= $iGridH Then ContinueLoop For $j = $iCol - 1 To $iCol + 1 If $j < 0 Or $j >= $iGridW Then ContinueLoop If $i == $iRow And $j == $iCol Then ContinueLoop $aNeighbours[$iNeighIdx] = $i * $iGridW + $j $iNeighIdx += 1 Next Next ReDim $aNeighbours[$iNeighIdx] Return $aNeighbours EndFunc ;==>GetNeighbours Func GetGridIdx() Local $aPos, $aTile[2], $iGridIdx If $fFinished Then Return -1 ;determine which tile the mouse is currently over $aPos = $aMousePos $aPos[$X] -= 25 $aPos[$Y] -= 80 $aTile[$X] = Floor($aPos[0] / $iTileW) $aTile[$Y] = Floor($aPos[1] / $iTileH) If $aTile[$X] < 0 Or $aTile[$X] >= $iGridW Then Return -1 If $aTile[$Y] < 0 Or $aTile[$Y] >= $iGridH Then Return -1 $iGridIdx = $aTile[$Y] * $iGridW + $aTile[$X] Return $iGridIdx EndFunc ;==>GetGridIdx Func GetMouseEvent($iMsg) ;retuns a "button" (none, pimary, seconday, dual) ;combined with what "event" has occured (press, release, move/drag, held) Static $iHeldButtons ;tracks which buttons are currently down. Local $iButton, $iBtnEvent = 0 ;determine which physical button has changed. Switch $iMsg Case $GUI_EVENT_PRIMARYDOWN, $GUI_EVENT_PRIMARYUP $iButton = $MSE_BTN_PRIMARY Case $GUI_EVENT_SECONDARYDOWN, $GUI_EVENT_SECONDARYUP $iButton = $MSE_BTN_SECONDARY EndSwitch Switch $iMsg Case $GUI_EVENT_PRIMARYDOWN, $GUI_EVENT_SECONDARYDOWN ;if another button is already down it is a dual click If BitAND($iHeldButtons, BitNOT($iButton)) Then $iButton = $MSE_BTN_DUAL $iHeldButtons = $iButton $iBtnEvent = BitOR($iHeldButtons, $MSE_EVT_BTNPRESSED) Case $GUI_EVENT_PRIMARYUP, $GUI_EVENT_SECONDARYUP If BitAND($iHeldButtons, $MSE_BTN_DUAL) Then $iButton = $MSE_BTN_DUAL ;ignores the second button release event in a dual click If $iHeldButtons Then $iHeldButtons = BitAND($iHeldButtons, BitNOT($iButton)) ;update our tracker $iBtnEvent = BitOR($iButton, $MSE_EVT_BTNRELEASED) EndIf Case $GUI_EVENT_MOUSEMOVE ;$iHeldButtons may be $MSE_BTN_NONE $iBtnEvent = BitOR($iHeldButtons, $MSE_EVT_CURSORMOVED) Case Else ;nothing has happened, if something is being held report it. If $iHeldButtons Then $iBtnEvent = BitOR($iHeldButtons, $MSE_EVT_BTNHELD) EndSwitch ;A value of 0 is BitOR($MSE_BTN_NONE, $MSE_EVT_NONE) Return $iBtnEvent EndFunc ;==>GetMouseEvent Func SetCounter(ByRef $ahCounter, $iValue = 0) ;limits are (-99 to 999) for anything meaningful Local $aValues[3], $fNegative If $iValue < 0 Then $iValue *= -1 $fNegative = True EndIf $aValues[0] = Int(Mod($iValue / 100, 10)) $aValues[1] = Int(Mod($iValue / 10, 10)) $aValues[2] = Int(Mod($iValue, 10)) If Not $aValues[0] Then $aValues[0] = $LCD7_OFF If Not $aValues[1] Then If $fNegative Then $aValues[1] = $LCD7_MINUS Else $aValues[1] = $LCD7_OFF EndIf Else If $fNegative Then $aValues[0] = $LCD7_MINUS EndIf EndIf _SendMessage($ahCounter[0], $STM_SETIMAGE, $IMAGE_BITMAP, $ahDigitBmps[$aValues[0]]) _SendMessage($ahCounter[1], $STM_SETIMAGE, $IMAGE_BITMAP, $ahDigitBmps[$aValues[1]]) _SendMessage($ahCounter[2], $STM_SETIMAGE, $IMAGE_BITMAP, $ahDigitBmps[$aValues[2]]) EndFunc ;==>SetCounter Func EyeTrack() Local $aPos[2], $iBmpIdx If $fFinished Then Return -1 ;Find where the mouse is relative to the control If $aMousePos[$X] < $aiFacePos[$X] Then $aPos[$X] = 0 ElseIf $aMousePos[$X] < $aiFacePos[$X] + $aiFacePos[$WIDTH] Then $aPos[$X] = 1 Else $aPos[$X] = 2 EndIf If $aMousePos[$Y] < $aiFacePos[$Y] Then $aPos[$Y] = 0 ElseIf $aMousePos[$Y] < $aiFacePos[$Y] + $aiFacePos[$HEIGHT] Then $aPos[$Y] = 1 Else $aPos[$Y] = 2 EndIf ;Determine which happy face should be shown $iBmpIdx = $aPos[$Y] * 3 + $aPos[$X] Return $iBmpIdx EndFunc ;==>EyeTrack Func SetFace($iIndex) Static $iLastIdx = -1 If $iIndex < 0 Then Return False If $iIndex = $iLastIdx Then Return False _SendMessage($hNewGame, $STM_SETIMAGE, $IMAGE_BITMAP, $ahFaceBmps[$iIndex]) EndFunc ;==>SetFace #EndRegion Support Functions