AHK版俄罗斯方块,碉堡了
下载链接:https://pan.baidu.com/s/1qZGs4kk 密码:jzl9
使用方法:
键盘的上下左右键控制!剩下的自己摸索!!
;------------------------------------------------------------------------------- ; ; ManyTetris 0.17 ; Customizable Pocket Tetris ; Danny Ben Shitrit (aka Icarus) 2008 ; ;------------------------------------------------------------------------------- NameString := "ManyTetris" VersionString := "0.17" #SingleInstance Force Gosub Init Gosub Main Return ;------------------------------------------------------------------------------- ; MAINS ;------------------------------------------------------------------------------- Init: SetWorkingDir %A_ScriptDir% IniFile = %NameString%.ini OnMessage(0x06, "WM_ACTIVATE") ; Capture gui focus ColorString := "Options_OnColor,Options_OffColor,Options_GuiColor,Options_FontColor" IniHelper( "Read", IniFile, "GUI", ColorString . ",Options_Inverse" ) IniHelper( "Read", IniFile, "Sound", "Options_EnableSound" ) IniHelper( "Read", IniFile, "Recent", "Options_LastGame,Options_WinX,Options_WinY" ) Score_MaxScore := Score_GetMaxScore( Options_LastGame ) If( Options_Inverse ) { Loop Parse, ColorString, `, %A_LoopField% := InverseColor( %A_LoopField% ) } Game_PushDownSpeed := 20 Game_IsPaused := false ; Arrange games drop down list Loop games\*.txt { SplitPath A_LoopFilename,,,,OutNameNoExt If( A_Index = 1 and Not FileExist( "games\" . Options_LastGame . ".txt" ) ) Options_LastGame := OutnameNoExt If( A_Index <> 1 ) Gui_GamesDdl .= "|" Gui_GamesDdl .= OutNameNoExt } Game_ReadGameConfig( Options_LastGame ) Loop %Game_Piece0% { PieceID := A_Index StringSplit PiecePart, Game_Piece%A_Index%, %A_Space% Game_PieceStates%PieceID% := PiecePart0 Loop %PiecePart0% { StateID := A_Index Game_Piece%PieceID%_State%StateID% := PiecePart%A_Index% } } Active_DropSpeed := Game_DropSpeed Gosub Game_BuildGui Return Main: Game_PiecesDropped := 0 Active_PlaceNewPiece() SetTimer Game_ProgressGame, -%Active_DropSpeed% Return GuiEscape: GuiClose: Gosub SaveSettings ExitApp Return ;------------------------------------------------------------------------------- ; GAME ;------------------------------------------------------------------------------- Game_ReadGameConfig( file ) { Local FileString, ThisLine FileRead FileString, games\%file%.txt Game_Piece0 := 1 Loop Parse, FileString, `n,`r { ThisLine = %A_LoopField% If( SubStr( ThisLine, 1, 1 ) = "#" ) { StringTrimLeft, ThisLine, ThisLine, 1 StringSplit Param, ThisLine, %A_Space% Game_%Param1% := Param%Param0% Continue } If( ThisLine = "" or SubStr( ThisLine,1,1 ) = ";" ) Continue If( ThisLine = "*" ) { StringTrimRight Game_Piece%Game_Piece0%, Game_Piece%Game_Piece0%, 1 Game_Piece0++ } Else If( ThisLine = "=" ) { StringTrimRight Game_Piece%Game_Piece0%, Game_Piece%Game_Piece0%, 1 Game_Piece%Game_Piece0% .= " " } Else { Game_Piece%Game_Piece0% .= ThisLine . "|" } } ; Set some defaults, in case the game configuration file does not contain ; all the elements. ; Mainly for backwards compatibility with older game templates. If( Game_LineScore = "" ) Game_LineScore := 10 If( Game_PieceScore = "" ) Game_PieceScore := 2 If( Game_PausePenalty = "" ) Game_PausePenalty := 5 } Game_BuildGui: Gui Margin,2,2 Gui Color, %Options_GuiColor%,%Options_GuiColor% Gui Font, c%Options_FontColor% W := Game_Cols * ( Game_BoxSize+1 ) - 83 Gui Add, DDL, -TabStop w%W% vGui_GamesDdl, %Gui_GamesDdl% GuiControl ChooseString, Gui_GamesDdl, %Options_LastGame% Gui Add, Button, 0x8000 x+2 yp w80 hp+1 -wrap vGui_StartButton gGame_RestartGame, Start W := Game_Cols * ( Game_BoxSize+1 ) - 1 Gui Font, s12 Bold Gui Add, Text, x2 y+2 w%W% h21 vGui_Score Center Border, 0 Game_UpdateScore( 0 ) Game_UpdateScore( "Top: " . Score_MaxScore, true ) Gui Font, s9 Norm X := 2 Y := 48 W := Game_BoxSize Loop %Game_Rows% { i := A_Index Loop %Game_Cols% { j := A_Index Gui Add, ListView, x%X% y%Y% w%W% h%W% vGuiBox_%i%_%j% -TabStop -E0X200 0x4000 +Background%Options_OffColor% DataBox_%i%_%j% := 0 X += W + 1 } Y += W + 1 X := 2 } GuiControl Focus, Gui_StartButton Gui Show, x%Options_WinX% y%Options_WinY%,%NameString% %VersionString% Return Game_RestartGame: Gui Submit, NoHide Options_LastGame := Gui_GamesDdl Gosub Reload Return Game_ProgressGame: Game_ProgressGame() Return Game_ProgressGame() { Global ; Drops a piece by one row if possible ; Else, remove the completed lines if any ; And create a new piece on top If( Not Active_DropPiece() ) { Game_SetNewDropSpeed() If( Active_PrevDropSpeed ) Active_PrevDropSpeed := Active_DropSpeed Active_CheckCompletedLines() Active_PlaceNewPiece() SetTimer Game_ProgressGame, -%Active_DropSpeed% } } Game_SetNewDropSpeed() { Global If( Game_DropSpeedPoints ) Active_DropSpeed := Game_DropSpeed - ( Trim( Game_Score/Game_DropSpeedPoints )*Game_DropSpeedIncrease ) Else Active_DropSpeed := Game_DropSpeed - ( Game_PiecesDropped*Game_DropSpeedIncrease ) If( Active_DropSpeed < Game_MaxDropSpeed ) Active_DropSpeed := Game_MaxDropSpeed ;Tooltip % Active_DropSpeed ; DEBUG SPEED } Game_DataToGui( fromRow, toRow ) { ; Reads a range of rows in the data grid, and reflect it in the GUI ;_____________________________________________________________________________ Local Row, Color Loop %toRow% { Row := fromRow + A_Index - 1 Loop %Game_Cols% { Col := A_Index Color := DataBox_%Row%_%Col% ? Options_OnColor : Options_OffColor GuiControl ,+Background%Color%, GuiBox_%Row%_%Col% } } } Game_GameOver() { ; Called when we can longer place new pieces ;_____________________________________________________________________________ Local Row, Col SetTimer Game_ProgressGame, Off Critical SoundPlay( "Over" ) Loop %Game_Rows% { Active_RemoveRow( Game_Rows ) Game_DataToGui( 1, Game_Rows ) Sleep 50 } Critical Off Game_SaveHighScore() Sleep 2000 Game_UpdateScore( 0 ) Active_DropSpeed := Game_DropSpeed Gosub Main } Game_UpdateScore( score, displayOnly=false ) { Global Game_Score If( score = 0 ) { Game_Score := 0 GuiControl,,Gui_Score, 0 } Else If( not displayOnly ) { Game_Score += score GuiControl,,Gui_Score, % Game_Score } Else { GuiControl,,Gui_Score, % score } } Game_SaveHighScore() { Global If( Game_Score > Score_MaxScore ) { Score_MaxScore := Game_Score Score_SetMaxScore( Options_LastGame, Score_MaxScore ) } } ;------------------------------------------------------------------------------- ; ACTIVE ;------------------------------------------------------------------------------- Active_PlaceNewPiece() { ; Gets a random piece and places it at the top of the board ; Ends the game if it cannot place that piece ;_____________________________________________________________________________ Local Col, Row, Failed, PieceRows Random Active_Piece, 1, %Game_Piece0% Game_PiecesDropped++ Active_PieceStates := Game_PieceStates%Active_Piece% Active_PieceState := 1 Active_PieceString := Game_Piece%Active_Piece%_State1 StringSplit PieceRow, Game_Piece%Active_Piece%_State1, | Active_BaseRow := 1 Active_PieceCols := StrLen( PieceRow1 ) Active_BaseCol := Round( 1 + (Game_Cols/2) - (Active_PieceCols/2 ) ) ; Update the data grid Failed := false Col := Active_BaseCol Row := Active_BaseRow Loop Parse, Active_PieceString { If( A_LoopField = "+" ) { If( DataBox_%Row%_%Col% <> 1 ) DataBox_%Row%_%Col% := 2 Else Failed := true } Else If( A_LoopField = "|" ) { Col := Active_BaseCol-1 Row++ } Col++ } Active_PieceRows := Row ; Update the GUI If( Failed ) { Game_DataToGui( 1, Active_PieceRows ) Game_GameOver() } Else { SoundPlay( "Piece" ) Game_DataToGui( 1, Active_PieceRows ) } Return true } Active_PieceCanMove( fromRow, toRow, rowOffset, colOffset ) { ; Gets a range of rows to check and row+col offsets and returns true if the ; piece (that was found in the range of rows) can move to the specified ; offsets. ;_____________________________________________________________________________ Local Result, OldRow, OldCol, NewRow, NewCol Result := true Loop %Active_PieceRows% { OldRow := Active_BaseRow + Active_PieceRows - A_Index NewRow := OldRow+rowOffset Loop %Game_Cols% { OldCol := A_Index NewCol := OldCol+ColOffset If( ( DataBox_%OldRow%_%OldCol% = 2 ) and ( DataBox_%NewRow%_%NewCol% = 1 or NewRow > Game_Rows or NewCol < 1 or NewCol > Game_Cols ) ) { Result := false Break } } } Return Result } Active_LockPiece( fromRow, toRow ) { ; Locks a piece in place, in the data grid only (not GUI) ; It will replace all the 2 values in the specified row range to 1 ;_____________________________________________________________________________ Local Row, Col Loop %toRow% { Row := fromRow + A_Index - 1 Loop %Game_Cols% { Col := A_Index If( DataBox_%Row%_%Col% = 2 ) DataBox_%Row%_%Col% := 1 } } } Active_DropPiece() { ; Drops the piece by one line ; If it is unable to, it will lock the piece in place (convert 2s to 1s) ;_____________________________________________________________________________ Local OldRow, NewRow ; If cant drop piece anymore, change active piece to static and return false If( Not Active_PieceCanMove( Active_BaseRow, Active_BaseRow + Active_PieceRows, 1, 0 ) ) { Active_LockPiece( Active_BaseRow, Active_BaseRow+Active_PieceRows-1 ) Return false } Critical Loop %Active_PieceRows% { OldRow := Active_BaseRow + Active_PieceRows - A_Index NewRow := OldRow+1 Loop %Game_Cols% { Col := A_Index If( DataBox_%OldRow%_%Col% = 2 ) { DataBox_%OldRow%_%Col% := 0 DataBox_%NewRow%_%Col% = 2 } } } If( Active_DropSpeed > Game_PushDownSpeed ) SoundPlay( "Step" ) Game_DataToGui( Active_BaseRow, Active_PieceRows+1 ) Active_BaseRow++ SetTimer Game_ProgressGame, -%Active_DropSpeed% Critical Off Return true } Active_MovePiece( dir ) { ; Moves a piece one block to the right (1) or left (-1) ; Returns false on failure ;_____________________________________________________________________________ Local OldCol, NewCol ; If cant move piece anymore, return false If( Not Active_PieceCanMove( Active_BaseRow, Active_BaseRow + Active_PieceRows, 0, dir ) ) { Return false } Critical Loop %Active_PieceRows% { Row := Active_BaseRow + A_Index - 1 Loop %Game_Cols% { OldCol := dir < 0 ? A_Index : Game_Cols - A_Index + 1 NewCol := OldCol + dir If( DataBox_%Row%_%OldCol% = 2 ) { DataBox_%Row%_%OldCol% := 0 DataBox_%Row%_%NewCol% := 2 } } } Active_BaseCol += dir Game_DataToGui( Active_BaseRow, Active_PieceRows+1 ) Critical Off Return true } Active_PieceCanRotate( fromState, toState ) { ; Returns true if the active piece can rotate ;_____________________________________________________________________________ Local Result, Row, Col Result := true ; Check GUI edges If( Active_BaseCol < 1 or Active_BaseCol+Active_PieceCols-1 > Game_Cols ) Result := false ; Check collision with other pieces Loop %Active_PieceRows% { If( not Result ) Break Row := Active_BaseRow+A_Index-1 Loop %Active_PieceCols% { Col := Active_BaseCol+A_Index-1 If( DataBox_%Row%_%Col% = 1 ) { Result := false Break } } } Return Result } Active_RotatePiece() { ; Rotates a piece ;_____________________________________________________________________________ Local Col, Row, NewPieceState NewPieceState := Active_PieceState < Active_PieceStates ? Active_PieceState+1 : 1 ; If cant move piece anymore, return false If( Not Active_PieceCanRotate( Active_PieceState, NewPieceState ) ) { Return false } Else { Critical Active_PieceState := NewPieceState Active_PieceString := Game_Piece%Active_Piece%_State%Active_PieceState% Row := Active_BaseRow Col := Active_BaseCol Loop Parse, Active_PieceString { If( A_LoopField = "+" ) DataBox_%Row%_%Col% := 2 Else If( A_LoopField = "-" ) DataBox_%Row%_%Col% := 0 Else If( A_LoopField = "|" ) { Col := Active_BaseCol-1 Row++ } Col++ } Critical Off } Game_DataToGui( Active_BaseRow, Active_PieceRows+1 ) Return true } Active_CheckCompletedLines() { ; Check for completed lines and update the score (even if there are no ; completed lines) Local Row, FullRow Critical ; Identify rows for removal Loop %Game_Rows% { FullRow := true Row := Game_Rows-A_Index+1 Loop %Game_Cols% { Col := A_Index If( DataBox_%Row%_%Col% <> 1 ) { FullRow := false Continue } } If( FullRow ) { Active_ScoreFactor++ Active_CycleScore += ( Active_ScoreFactor * Game_LineScore ) Active_RemoveRow( Row ) Active_CheckCompletedLines() Game_DataToGui( 1, Game_Rows ) Return } } If( Active_CycleScore ) { Gui Submit, NoHide SoundPlay( "Line", true ) Game_UpdateScore( Active_CycleScore ) } Else { Gui Submit, NoHide Game_UpdateScore( Game_PieceScore ) } Active_ScoreFactor := 0 Active_CycleScore := 0 Critical Off } Active_RemoveRow( targetRow ) { Local Col, Row, HigherRow Critical Loop % targetRow-1 { Row := targetRow-A_Index+1 HigherRow := Row-1 Loop %Game_Cols% { Col := A_Index DataBox_%Row%_%Col% := DataBox_%HigherRow%_%Col% } } ; Reset first row to zeros Loop %Game_Cols% { Col := A_Index DataBox_1_%Col% := 0 } Critical Off } Active_DropKeyReleased: ; Called by timer whenever the Down key is pressed. ; Will restore original drop speed when key is released. If( not GetKeyState( "Down", "P" ) ) { SetTimer Active_DropKeyReleased, Off Active_DropSpeed := Active_PrevDropSpeed Active_PrevDropSpeed := 0 } Return ;------------------------------------------------------------------------------- ; SCORE ;------------------------------------------------------------------------------- Score_GetMaxScore( game ) { Global IniFile NiceGameName := RegExReplace( game, "[\W]" ) IniRead Result, %IniFile%, Score, %NiceGameName%, 0 Return Result } Score_SetMaxScore( game, score ) { Global IniFile NiceGameName := RegExReplace( game, "[\W]" ) IniWrite %score%, %IniFile%, Score, %NiceGameName% } ;------------------------------------------------------------------------------- ; DEBUG ;------------------------------------------------------------------------------- Debug_ShowGrid() { Local Row, Col, Result Result := "" Loop %Game_Rows% { Row := A_Index Loop %Game_Cols% { Col := A_Index Result .= DataBox_%Row%_%Col% . " " } Result .= "`n" } Msgbox % Result } ;------------------------------------------------------------------------------- ; MISC ;------------------------------------------------------------------------------- IniHelper( op, file, section, keys ) { ; Reads or writes specific keys from an INI section, and sets the values as ; global variables ;_____________________________________________________________________________ Global StringSplit iniKey, keys, `, Loop %iniKey0% { If( op = "Read" ) { IniKey := % iniKey%A_Index% IniRead %IniKey%, %file%, %section%, %IniKey% } Else If( op = "Write" ) { IniValue := % iniKey%A_Index% IniValue := %IniValue% IniKey := iniKey%A_Index% IniWrite %IniValue%, %file%, %section%, %IniKey% } } } InverseColor( color ) { SetFormat Integer, H Result := "" Loop Parse, Color { Result .= 0xF - A_LoopField StringReplace Result, Result, 0x } SetFormat Integer, D Return Result } SoundPlay( sound, wait=false ) { Global Options_EnableSound If( Not Options_EnableSound ) Return Wait := wait ? "WAIT" : "" SoundPlay sounds\%sound%.wav, %WAIT% } Trim( num ) { StringSplit NumElement, num, . Return %NumElement1% } SaveSettings: Gui +LastFound WinGetPos Options_WinX, Options_WinY IniHelper( "Write", IniFile, "Recent", "Options_LastGame,Options_WinX,Options_WinY" ) Game_SaveHighScore() Return Reload: Gosub SaveSettings Reload Return WM_ACTIVATE() { Global NameString, Game_IsPaused IfWinActive %NameString% ahk_Class AutoHotkeyGUI { If( Game_IsPaused ) Gosub p } Else If( !Game_IsPaused ) Gosub p } ;------------------------------------------------------------------------------- ; HOTKEYS ;------------------------------------------------------------------------------- #IfWinActive ManyTetris ahk_Class AutoHotkeyGUI Right:: If( Game_IsPaused ) Gosub p Active_MovePiece( 1 ) Return Left:: If( Game_IsPaused ) Gosub p Active_MovePiece( -1 ) Return Up:: If( Game_IsPaused ) Gosub p Active_RotatePiece() Return Down:: If( Game_IsPaused ) Gosub p ; If key is already pushed, do nothing (the Active_DropKeyReleased is working) If( Active_PrevDropSpeed ) Return SetTimer Game_ProgressGame, Off Active_PrevDropSpeed := Active_DropSpeed Active_DropSpeed := Game_PushDownSpeed SetTimer Active_DropKeyReleased, 20 Gosub Game_ProgressGame Return p:: Game_IsPaused := !Game_IsPaused If( Game_IsPaused ) SetTimer Game_ProgressGame, Off Else { If( Game_Score > 0 ) Game_Score -= Game_PausePenalty SetTimer Game_ProgressGame, -%Active_DropSpeed% } Return
为啥现在不能运行了?ahk这么不稳定,每次新版本就会导致原来能用的脚本不能再用么?
错误信息是什么?
有点意思,66666
66666
?
[…] AHK版俄罗斯方块:非常经典的小游戏,值得大家收藏! […]
不过画质不大好
哈哈 ,只是一个简单实例,如果有需要可以自己完善一下!
有意思!!! ❓ 💡 💡
谢谢