• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

SynaGl0w

Members
  • Content count

    2
  • Joined

  • Last visited

Community Reputation

226 Neutral

About SynaGl0w

  • Rank
    Newbie
  1. Feel free to play around, modify, and change it however you want.    It was a real learning experience, but the chance that I will revisit this and improve upon it is next to nothing.
  2. Way back while learning BASH scripting I made a tetris clone, as is common practice when learning a new language. Being a C++ guy, the result was horrible to look at. You can also tell that I got lazy with comments. Plenty of unfinished things as well. Behold:   #!/bin/bash #----------------------------------------------------------------------------- # A tetromino stacking game written entirely in BASH script! =D # # Because I can... # #----------------------------------------------------------------------------- # Version 0.1 Beta: # - The game is functional # - Todo: # - Overtime bonus to score after all 10 lines of level 10 are cleared # - Highscores #============================================================================= #============================================================================= #----------------------------------------------------------------------------- # [ Global Variables ] #----------------------------------------------------------------------------- #============================================================================= declare -r TETRIBASHTITLE="TetriBASH" declare -ri TETRIBASHVERSION=0 declare -ri TETRIBASHSUBVERS=1 declare -r TETRIBASHRELEASE="Beta" declare -r TETRIBASHDATE="2010 - 2012" declare -r TETRIBASHINFO="A tetromino stacking game written entirely in" declare -r TETRIBASHINFO2="BASH script! =D" declare -r TETRIBASHINFO3="Because I can..." declare -i TETRIBASHSTATE=0 # Indicates the current game state declare -i TETRIBASHDEBUG=0 # Value of 1 enables debug mode declare TIMESTART="0.0" # Start time of a frame declare TIMEEND="0.0" # End time of a frame declare DELTATIME="0.0" # Time elapsed for the frame declare ACCUMULATOR="0.0" # Primary gameplay accumulator declare -ri TERMULT=2 # and chaos # Multiplier to determin tetromino block width in characters (Do not change!) declare -ri TERMWIDTH=$(tput cols) # Character width of the terminal declare -ri TERMHEIGHT=$(tput lines) # Character height of the terminal declare -ri GAMEWIDTH=34 # Width of the game area declare -ri GAMEOFFSETX=$((($TERMWIDTH / 2) - ($GAMEWIDTH / 2))) # X offset of the game area declare -ri GAMEOFFSETY=2 # Y offset of the game area declare -ri GAMEBLOCKSIZE=4 # Width and height of the game block array declare -ri GAMEBLOCKAREA=$(($GAMEBLOCKSIZE * $GAMEBLOCKSIZE)) # Size of the game block array declare -i GAMESCORE=0 # Game score declare -i GAMESCOREMULTDEF=33 # Score Multiplier Default declare -i GAMESCOREMULT=33 # Score Multiplier declare -i GAMESCOREMULTINC=100 # Score Multiplier increase per level declare -i GAMELEVEL=0 # Game level declare -i GAMELINES=0 # Number of lines cleared declare -i GAMELINESPERLEVEL=10 # Number of lines that need to be cleared to advance in level declare -i GAMELEVELLINES=0 # Number of lines cleared this level declare -i GAMEFAILUREMAX=10 # NUmber of blocks to place after failure before showing Game Over message declare -i GAMEFAILURECOUNT=0 # Number of blocks placed on top of eachother declare -i GAMEFAILURE=0 # Indicates a game is determined to be lost declare -i GAMECURRENT=0 # Current active block ID declare -i GAMECURRENTROT=0 # Current active block rotation declare -i GAMENEXT=0 # The next block ID declare -i GAMERUNNING=0 # Indicates the game is running declare -a GAMECURRENTARRAY # Current active block array declare -a GAMENEXTARRAY # Next block array declare -a GAMEBLOCKBUFFER # Current active block rotation buffer declare -i GAMECLEARINPROGRESS=0 # Indicates a line clear is in progress declare -i GAMEOVERINPROGRESS=0 # Indicates game over is in progress declare -i GAMELINESTOCLEAR=0 # Number of lines that need clearing declare -a GAMELINESBUFFER # Lists of lines that need clearing declare -i GAMECLEARANIMFRAMES=3 # Number of frames of clearing animation declare -r GAMECLEARCHAR=":" declare -i GAMEBLOCKX=0 # X position of active game block relative to terminal declare -i GAMEBLOCKY=0 # Y position of active game block relative to terminal declare -i GAMEBLOCKAPX=0 # X position of active game block relative to the play area declare -i GAMEBLOCKAPY=0 # Y position of active game block relative to the play area declare GAMEINTERVAL="0.5" # Fall rate in seconds declare GAMECLEARINTERVAL="0.2" # Clear rate in seconds declare GAMEOVERINTERVAL="5.0" # Game Over message interval in seconds declare -i FRAMEUPDATED=0 # Indicates drawing has been done in the current frame declare -ri TBASHW=10 # Width of the play area in blocks declare -ri TBASHH=20 # Height of the play area in blocks declare -ri TBASHSIZE=$(($TBASHW * $TBASHH)) # Size of the play area array declare -ri TBASHAREAOFFSETX=$GAMEOFFSETX # X offset of play area including border declare -ri TBASHAREAOFFSETY=$GAMEOFFSETY # Y offset of play area including border declare -ri TBASHAREAW=$((($TBASHW * $TERMULT) + 2)) # Width of play area including border declare -ri TBASHAREAH=$(($TBASHH + 2)) # Height of play area including border declare -ri TBASHOFFSETX=$(($TBASHAREAOFFSETX + 1)) # X offset of play area declare -ri TBASHOFFSETY=$(($TBASHAREAOFFSETY + 1)) # Y offset of play area declare -ri TBASHGAMEOVEROFFSETX=$(($TBASHAREAOFFSETX + 2)) declare -ri TBASHGAMEOVEROFFSETY=$(($TBASHAREAOFFSETY + ($TBASHAREAH / 2) - 2)) declare -ri TBASHGAMEOVERWIDTH=$(($TBASHAREAW - 4)) declare -ri TBASHGAMEOVERHEIGHT=3 declare -ri TBASHSCOREW=10 declare -ri TBASHSCOREH=3 declare -ri TBASHSCOREOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX)) declare -ri TBASHSCOREOFFSETY=$GAMEOFFSETY declare -ri TBASHSCOREVALUEX=$(($TBASHSCOREOFFSETX + 1)) declare -ri TBASHSCOREVALUEY=$(($TBASHSCOREOFFSETY + 1)) declare -ri TBASHLEVELW=10 declare -ri TBASHLEVELH=3 declare -ri TBASHLEVELOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX)) declare -ri TBASHLEVELOFFSETY=$(($GAMEOFFSETY + 1 + $TBASHSCOREH)) declare -ri TBASHLEVELVALUEX=$(($TBASHLEVELOFFSETX + 1)) declare -ri TBASHLEVELVALUEY=$(($TBASHLEVELOFFSETY + 1)) declare -ri TBASHLINESW=10 declare -ri TBASHLINESH=3 declare -ri TBASHLINESOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX)) declare -ri TBASHLINESOFFSETY=$(($GAMEOFFSETY + 1 + $TBASHSCOREH + 1 + $TBASHLEVELH)) declare -ri TBASHLINESVALUEX=$(($TBASHLINESOFFSETX + 1)) declare -ri TBASHLINESVALUEY=$(($TBASHLINESOFFSETY + 1)) declare -ri TBASHNEXTW=10 declare -ri TBASHNEXTH=6 declare -ri TBASHNEXTOFFSETX=$(($TBASHAREAW + 2 + $GAMEOFFSETX)) declare -ri TBASHNEXTOFFSETY=$(($GAMEOFFSETY + $TBASHAREAH - $TBASHNEXTH)) declare -ri TBASHNEXTVALUEX=$(($TBASHNEXTOFFSETX + 1)) declare -ri TBASHNEXTVALUEY=$(($TBASHNEXTOFFSETY + 1)) declare -ri MAINTITLEW=49 declare -ri MAINTITLEH=5 declare -ri MAINTITLEX=$((($TERMWIDTH / 2) - ($MAINTITLEW / 2))) declare -ri MAINTITLEY=1 declare -r MAINTITLELINE1="\e[0;31m ______ __ _ ____ ___ _____ __ __\e[0m" declare -r MAINTITLELINE2="\e[1;31m /_ __/___ / /______(_) __ )/ | / ___// / / /\e[0m" declare -r MAINTITLELINE3="\e[0;33m / / / _ \\/ __/ ___/ / __ / /| | \\__ \\/ /_/ / \e[0m" declare -r MAINTITLELINE4="\e[1;33m / / / __/ /_/ / / / /_/ / ___ |___/ / __ / \e[0m" declare -r MAINTITLELINE5="\e[1;37m/_/ \\___/\\__/_/ /_/_____/_/ |_/____/_/ /_/ \e[0m" declare -ri TBASHABOUTW=49 declare -ri TBASHABOUTH=7 declare -ri TBASHABOUTX=$((($TERMWIDTH / 2) - ($TBASHABOUTW / 2))) declare -ri TBASHABOUTY=$(($MAINTITLEH + 5)) declare -ri MAINMENUW=15 declare -ri MAINMENUH=4 declare -ri MAINMENUX=$((($TERMWIDTH / 2) - ($MAINMENUW / 2))) declare -ri MAINMENUY=$(($MAINTITLEH + $MAINTITLEY + 3)) declare -ri MAINMENUITEMCOUNT=4 declare -a MAINMENUITEMS MAINMENUITEMS[0]="New Game\e[0m" MAINMENUITEMS[1]="High Scores\e[0m" MAINMENUITEMS[2]="About\e[0m" MAINMENUITEMS[3]="Exit\e[0m" declare -a MAINMENUITEMY MAINMENUITEMY[0]=$MAINMENUY MAINMENUITEMY[1]=$(($MAINMENUY + 2)) MAINMENUITEMY[2]=$(($MAINMENUY + 4)) MAINMENUITEMY[3]=$(($MAINMENUY + 6)) declare -i MAINMENUSELECTION=0 declare -r MAINMENUITEMNOTSEL=" \e[0;33m" declare -r MAINMENUITEMSELECT="\e[1;37m??> \e[1;33m" declare -ri MENUBOTTOMDECORX=$MAINTITLEX declare -ri MENUBOTTOMDECORY=$(($TERMHEIGHT - 5)) declare -r SCREENINFOSTRING=$(printf "%s %d.%d %s" "$TETRIBASHTITLE" $TETRIBASHVERSION $TETRIBASHSUBVERS "$TETRIBASHRELEASE") declare -ri SCREENINFOSTRINGX=$((($TERMWIDTH / 2) - (${#SCREENINFOSTRING} / 2))) declare -ri SCREENINFOSTRINGY=$(($TERMHEIGHT - 1)) declare -r BH="?" declare -r BV="?" declare -r BTL="?" declare -r BTR="?" declare -r BBL="?" declare -r BBR="?" declare -r BLK1="\e[43m\e[1;33m[]" declare -r BLK2="\e[42m\e[1;32m()" declare -r BLK3="\e[46m\e[1;36m::" declare -r BLK4="\e[41m\e[1;31m[]" declare -r BLK5="\e[44m\e[1;34m{}" declare -r BLK6="\e[47m\e[1;37m++" declare -r BLK7="\e[45m\e[1;35m<>" declare -a TBASHARRAY #================================== Block 1 ================================== declare -a BLK1ARRAY=(0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0) declare -a BLK1ARRAYR2=(0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0) declare -a BLK1ARRAYR3=(0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0) declare -a BLK1ARRAYR4=(0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0) #================================== Block 2 ================================== declare -a BLK2ARRAY=(0 0 0 0 0 2 2 0 0 2 2 0 0 0 0 0) #================================== Block 3 ================================== declare -a BLK3ARRAY=(0 0 0 0 3 3 3 3 0 0 0 0 0 0 0 0) declare -a BLK3ARRAYR2=(0 0 3 0 0 0 3 0 0 0 3 0 0 0 3 0) declare -a BLK3ARRAYR3=(0 3 0 0 0 3 0 0 0 3 0 0 0 3 0 0) #================================== Block 4 ================================== declare -a BLK4ARRAY=(0 0 0 0 4 4 0 0 0 4 4 0 0 0 0 0) declare -a BLK4ARRAYR2=(0 4 0 0 4 4 0 0 4 0 0 0 0 0 0 0) #================================== Block 5 ================================== declare -a BLK5ARRAY=(0 0 0 0 0 5 5 0 5 5 0 0 0 0 0 0) declare -a BLK5ARRAYR2=(5 0 0 0 5 5 0 0 0 5 0 0 0 0 0 0) #================================== Block 6 ================================== declare -a BLK6ARRAY=(0 0 0 0 6 6 6 0 0 0 6 0 0 0 0 0) declare -a BLK6ARRAYR2=(0 6 0 0 0 6 0 0 6 6 0 0 0 0 0 0) declare -a BLK6ARRAYR3=(6 0 0 0 6 6 6 0 0 0 0 0 0 0 0 0) declare -a BLK6ARRAYR4=(0 6 6 0 0 6 0 0 0 6 0 0 0 0 0 0) #================================== Block 7 ================================== declare -a BLK7ARRAY=(0 0 0 0 7 7 7 0 7 0 0 0 0 0 0 0) declare -a BLK7ARRAYR2=(7 7 0 0 0 7 0 0 0 7 0 0 0 0 0 0) declare -a BLK7ARRAYR3=(0 0 7 0 7 7 7 0 0 0 0 0 0 0 0 0) declare -a BLK7ARRAYR4=(0 7 0 0 0 7 0 0 0 7 7 0 0 0 0 0) #============================================================================= #----------------------------------------------------------------------------- # [ Function Declarations ] #----------------------------------------------------------------------------- #============================================================================= function ZeroTetriBashArray() { for((i=0; i<TBASHSIZE; i++)); do { TBASHARRAY[$i]=0 } done } function GameOverClearTetriBashArray() { for((i=0; i<TBASHSIZE; i++)); do { TBASHARRAY[$i]=8 } done } function ZeroBlockBuffer() { for((i=0; i<GAMEBLOCKAREA; i++)); do { GAMEBLOCKBUFFER[$i]=0 } done } function ZeroLinesBuffer() { for((i=0; i<TBASHH; i++)); do { GAMELINESBUFFER[$i]=0 } done } function DrawBorder() { if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then { return 1 } fi local BWIDTH=$(($3 - 2)) local BHEIGHT=$(($4 - 2)) local BVERTVPOS=$(($2 + 1)) local BVERTHPOS=$1 printf "\e[%d;%dH${BTL}" $2 $1 for((i=0; i<BWIDTH; i++)); do { printf "${BH}" } done printf "${BTR}" for((i=0; i<BHEIGHT; i++)); do { printf "\e[%d;%dH${BV}" $BVERTVPOS $BVERTHPOS BVERTVPOS=$(($BVERTVPOS + 1)) } done BVERTVPOS=$(($2 + 1)) BVERTHPOS=$(($1 + $3 - 1)) for((i=0; i<BHEIGHT; i++)); do { printf "\e[%d;%dH${BV}" $BVERTVPOS $BVERTHPOS BVERTVPOS=$(($BVERTVPOS + 1)) } done printf "\e[%d;%dH${BBL}" $(($2 + $4 - 1)) $1 for((i=0; i<BWIDTH; i++)); do { printf "${BH}" } done printf "${BBR}" return 0 } function DrawTetriBashArray() { local BLAPOS=0 for((i=0; i<TBASHH; i++)); do { for((j=0; j<TBASHW; j++)); do { BLAPOS=$((($i * $TBASHW) + $j)) case ${TBASHARRAY[$BLAPOS]} in 1) printf "\e[%d;%dH${BLK1}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 2) printf "\e[%d;%dH${BLK2}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 3) printf "\e[%d;%dH${BLK3}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 4) printf "\e[%d;%dH${BLK4}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 5) printf "\e[%d;%dH${BLK5}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 6) printf "\e[%d;%dH${BLK6}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 7) printf "\e[%d;%dH${BLK7}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 8) printf "\e[%d;%dH::\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; esac } done } done FRAMEUPDATED=1 } function DrawTetriBashArrayEx() { local BLAPOS=0 for((i=0; i<TBASHH; i++)); do { for((j=0; j<TBASHW; j++)); do { BLAPOS=$((($i * $TBASHW) + $j)) case ${TBASHARRAY[$BLAPOS]} in 0) printf "\e[%d;%dH \e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 1) printf "\e[%d;%dH${BLK1}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 2) printf "\e[%d;%dH${BLK2}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 3) printf "\e[%d;%dH${BLK3}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 4) printf "\e[%d;%dH${BLK4}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 5) printf "\e[%d;%dH${BLK5}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 6) printf "\e[%d;%dH${BLK6}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; 7) printf "\e[%d;%dH${BLK7}\e[0m" $(($TBASHOFFSETY + $i)) $(($TBASHOFFSETX + ($j * 2)));; esac } done } done FRAMEUPDATED=1 } function HUDDrawArea() { DrawBorder $TBASHAREAOFFSETX $TBASHAREAOFFSETY $TBASHAREAW $TBASHAREAH FRAMEUPDATED=1 } function HUDDrawGameOver() { DrawBorder $TBASHGAMEOVEROFFSETX $TBASHGAMEOVEROFFSETY $TBASHGAMEOVERWIDTH $TBASHGAMEOVERHEIGHT printf "\e[%d;%dH\e[1;31m Game Over! \e[0m" $(($TBASHGAMEOVEROFFSETY + 1)) $(($TBASHGAMEOVEROFFSETX + 1)) FRAMEUPDATED=1 } function HUDDrawScore() { DrawBorder $TBASHSCOREOFFSETX $TBASHSCOREOFFSETY $TBASHSCOREW $TBASHSCOREH printf "\e[%d;%dH\e[1;33mScore\e[0m" $(($TBASHSCOREOFFSETY + 0)) $(($TBASHSCOREOFFSETX + 2)) FRAMEUPDATED=1 } function HUDDrawLevel() { DrawBorder $TBASHLEVELOFFSETX $TBASHLEVELOFFSETY $TBASHLEVELW $TBASHLEVELH printf "\e[%d;%dH\e[1;33mLevel\e[0m" $(($TBASHLEVELOFFSETY + 0)) $(($TBASHLEVELOFFSETX + 2)) FRAMEUPDATED=1 } function HUDDrawLines() { DrawBorder $TBASHLINESOFFSETX $TBASHLINESOFFSETY $TBASHLINESW $TBASHLINESH printf "\e[%d;%dH\e[1;33mLines\e[0m" $(($TBASHLINESOFFSETY + 0)) $(($TBASHLINESOFFSETX + 2)) FRAMEUPDATED=1 } function HUDDrawNext() { DrawBorder $TBASHNEXTOFFSETX $TBASHNEXTOFFSETY $TBASHNEXTW $TBASHNEXTH printf "\e[%d;%dH\e[1;33mNext\e[0m" $(($TBASHNEXTOFFSETY + 0)) $(($TBASHNEXTOFFSETX + 2)) FRAMEUPDATED=1 } function HUDUpdateScore() { printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHSCOREVALUEY $TBASHSCOREVALUEX $GAMESCORE FRAMEUPDATED=1 } function HUDUpdateLevel() { printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHLEVELVALUEY $TBASHLEVELVALUEX $GAMELEVEL FRAMEUPDATED=1 } function HUDUpdateLines() { printf "\e[%d;%dH\e[1;36m%d\e[0m" $TBASHLINESVALUEY $TBASHLINESVALUEX $GAMELINES FRAMEUPDATED=1 } function HUDUpdateNext() { local BLAPOS=0; local VY=$TBASHNEXTVALUEY; case $GAMENEXT in 0) GAMENEXTARRAY=("${BLK1ARRAY[@]}");; 1) GAMENEXTARRAY=("${BLK2ARRAY[@]}");; 2) GAMENEXTARRAY=("${BLK3ARRAY[@]}");; 3) GAMENEXTARRAY=("${BLK4ARRAY[@]}");; 4) GAMENEXTARRAY=("${BLK5ARRAY[@]}");; 5) GAMENEXTARRAY=("${BLK6ARRAY[@]}");; 6) GAMENEXTARRAY=("${BLK7ARRAY[@]}");; esac printf "\e[%d;%dH" $TBASHNEXTVALUEY $TBASHNEXTVALUEX for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) case ${GAMENEXTARRAY[$BLAPOS]} in 0) printf "\e[0m ";; 1) printf "${BLK1}";; 2) printf "${BLK2}";; 3) printf "${BLK3}";; 4) printf "${BLK4}";; 5) printf "${BLK5}";; 6) printf "${BLK6}";; 7) printf "${BLK7}";; *) printf "\e[0m ";; esac } done VY=$(($VY + 1)) printf "\e[%d;%dH" $VY $TBASHNEXTVALUEX } done FRAMEUPDATED=1 } function DrawTetriBashHUD() { HUDDrawArea HUDDrawScore HUDDrawLevel HUDDrawLines HUDDrawNext HUDUpdateScore HUDUpdateLevel HUDUpdateLines HUDUpdateNext FRAMEUPDATED=1 } function FillArrayDemoBlocks() { TBASHARRAY[15]=1 TBASHARRAY[16]=1 TBASHARRAY[17]=1 TBASHARRAY[26]=1 TBASHARRAY[21]=2 TBASHARRAY[22]=2 TBASHARRAY[31]=2 TBASHARRAY[32]=2 TBASHARRAY[38]=3 TBASHARRAY[48]=3 TBASHARRAY[58]=3 TBASHARRAY[68]=3 TBASHARRAY[51]=4 TBASHARRAY[52]=4 TBASHARRAY[62]=4 TBASHARRAY[63]=4 TBASHARRAY[75]=5 TBASHARRAY[76]=5 TBASHARRAY[84]=5 TBASHARRAY[85]=5 TBASHARRAY[103]=6 TBASHARRAY[113]=6 TBASHARRAY[114]=6 TBASHARRAY[115]=6 TBASHARRAY[138]=7 TBASHARRAY[146]=7 TBASHARRAY[147]=7 TBASHARRAY[148]=7 } function DrawTetriBashTitle() { printf "\e[%d;%dH${MAINTITLELINE1}" $MAINTITLEY $MAINTITLEX printf "\e[%d;%dH${MAINTITLELINE2}" $(($MAINTITLEY + 1)) $MAINTITLEX printf "\e[%d;%dH${MAINTITLELINE3}" $(($MAINTITLEY + 2)) $MAINTITLEX printf "\e[%d;%dH${MAINTITLELINE4}" $(($MAINTITLEY + 3)) $MAINTITLEX printf "\e[%d;%dH${MAINTITLELINE5}" $(($MAINTITLEY + 4)) $MAINTITLEX FRAMEUPDATED=1 } function DrawTetriBashMenuDecor() { printf "\e[%d;%dH \e[0m" $MENUBOTTOMDECORY $MENUBOTTOMDECORX printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 1)) $MENUBOTTOMDECORX printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 2)) $MENUBOTTOMDECORX printf "\e[%d;%dH \e[0m" $(($MENUBOTTOMDECORY + 3)) $MENUBOTTOMDECORX FRAMEUPDATED=1 } function DrawTetriBashVersionString() { printf "\e[%d;%dH%s\e[0m" $SCREENINFOSTRINGY $SCREENINFOSTRINGX "$SCREENINFOSTRING" FRAMEUPDATED=1 } function DrawTetriBashMainMenu() { for((i=0; i<MAINMENUITEMCOUNT; i++)); do { if [ $i -eq $MAINMENUSELECTION ]; then { printf "\e[%d;%dH${MAINMENUITEMSELECT}${MAINMENUITEMS[$i]}" ${MAINMENUITEMY[$i]} $MAINMENUX } else { printf "\e[%d;%dH${MAINMENUITEMNOTSEL}${MAINMENUITEMS[$i]}" ${MAINMENUITEMY[$i]} $MAINMENUX } fi } done FRAMEUPDATED=1 } function SetMainMenuSelection() { if [ -z "$1" ]; then { return 1 } fi if [ $1 -lt 0 ] || [ $1 -ge $MAINMENUITEMCOUNT ]; then { return 1 } fi if [ $1 -eq $MAINMENUSELECTION ]; then { return 0 } fi printf "\e[%d;%dH${MAINMENUITEMNOTSEL}${MAINMENUITEMS[$MAINMENUSELECTION]}" ${MAINMENUITEMY[$MAINMENUSELECTION]} $MAINMENUX MAINMENUSELECTION=$1 printf "\e[%d;%dH${MAINMENUITEMSELECT}${MAINMENUITEMS[$MAINMENUSELECTION]}" ${MAINMENUITEMY[$MAINMENUSELECTION]} $MAINMENUX FRAMEUPDATED=1 return 0 } function ChangeMainMenuSelectionUp() { local NEXTITEM=$MAINMENUSELECTION if [ $NEXTITEM -eq 0 ]; then { NEXTITEM=$(($MAINMENUITEMCOUNT - 1)) } else { NEXTITEM=$(($NEXTITEM - 1)) } fi SetMainMenuSelection $NEXTITEM } function ChangeMainMenuSelectionDown() { local NEXTITEM=$MAINMENUSELECTION if [ $NEXTITEM -eq $(($MAINMENUITEMCOUNT - 1)) ]; then { NEXTITEM=0 } else { NEXTITEM=$(($NEXTITEM + 1)) } fi SetMainMenuSelection $NEXTITEM } function GameSetCurrentBlock() { case $GAMECURRENT in 0) GAMECURRENTARRAY=("${BLK1ARRAY[@]}");; 1) GAMECURRENTARRAY=("${BLK2ARRAY[@]}");; 2) GAMECURRENTARRAY=("${BLK3ARRAY[@]}");; 3) GAMECURRENTARRAY=("${BLK4ARRAY[@]}");; 4) GAMECURRENTARRAY=("${BLK5ARRAY[@]}");; 5) GAMECURRENTARRAY=("${BLK6ARRAY[@]}");; 6) GAMECURRENTARRAY=("${BLK7ARRAY[@]}");; esac GAMEBLOCKX=$(($TBASHOFFSETX + ($GAMEBLOCKSIZE * 2) - 2)) GAMEBLOCKY=$TBASHOFFSETY GAMEBLOCKAPX=3 GAMEBLOCKAPY=0 } function GameDrawCurrentBlock() { local BLAPOS=0 for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) case ${GAMECURRENTARRAY[$BLAPOS]} in 1) printf "\e[%d;%dH${BLK1}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 2) printf "\e[%d;%dH${BLK2}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 3) printf "\e[%d;%dH${BLK3}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 4) printf "\e[%d;%dH${BLK4}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 5) printf "\e[%d;%dH${BLK5}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 6) printf "\e[%d;%dH${BLK6}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 7) printf "\e[%d;%dH${BLK7}\e[0m\e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; esac } done } done FRAMEUPDATED=1 } function GameClearCurrentBlock() { local BLAPOS=0 for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) case ${GAMECURRENTARRAY[$BLAPOS]} in 1) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 2) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 3) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 4) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 5) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 6) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; 7) printf "\e[%d;%dH\e[0m \e[1;1H" $(($GAMEBLOCKY + $i)) $(($GAMEBLOCKX + ($j * 2)));; esac } done } done FRAMEUPDATED=1 } function GameGenerateBlock() { GAMECURRENTROT=0 GAMECURRENT=$GAMENEXT GAMENEXT=$(($RANDOM % 7)) GameSetCurrentBlock GameDrawCurrentBlock HUDUpdateNext } function GameCommitBlock() { local BLAPOS=0 local BLKX=0 local BLKY=0 for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) BLKX=$(($j + $GAMEBLOCKAPX)) BLKY=$(($i + $GAMEBLOCKAPY)) if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then { continue } fi if [ $BLKY -gt $(($TBASHH - 1)) ]; then { continue } fi if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then { if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]} -gt 0 ]; then { GAMEFAILURE=1 } fi TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]=${GAMECURRENTARRAY[$BLAPOS]} } fi } done } done if [ $GAMEFAILURE -eq 0 ]; then { GAMESCORE=$(($GAMESCORE + 1)) HUDUpdateScore } fi } function GameEraseLine() { local BLAPOS=0 local YPOSSTART=0 if [ -z "$1" ]; then { return 0 } fi YPOSSTART=$1 if [ $1 -gt $(($TBASHH - 1)) ]; then { return 0 } fi for((k=YPOSSTART; k>0; k--)); do { for((j=0; j<TBASHW; j++)); do { BLAPOS=$((($k * $TBASHW) + $j)) TBASHARRAY[$BLAPOS]=${TBASHARRAY[$(($BLAPOS - $TBASHW))]} } done } done return 1 } function GameClearLines() { local BLAPOS=0 for((i=0; i<GAMELINESTOCLEAR; i++)); do { GameEraseLine ${GAMELINESBUFFER[$i]} } done DrawTetriBashArrayEx GAMESCORE=$(($GAMESCORE + (($GAMELINESTOCLEAR * ($GAMELEVEL + 1)) * ($GAMESCOREMULT * ($GAMELEVEL + 1))))) GAMELINES=$(($GAMELINES + $GAMELINESTOCLEAR)) GAMELEVELLINES=$(($GAMELEVELLINES + $GAMELINESTOCLEAR)) if [ $GAMELEVELLINES -ge $GAMELINESPERLEVEL ] && [ $GAMELEVEL -lt 10 ]; then { GAMELEVELLINES=$(($GAMELEVELLINES - $GAMELINESPERLEVEL)) GAMELEVEL=$(($GAMELEVEL + 1)) GAMESCOREMULT=$(($GAMESCOREMULTDEF + ($GAMELEVEL * $GAMESCOREMULTINC))) GAMEINTERVAL=$(echo "$GAMEINTERVAL - 0.03" | bc) HUDUpdateLevel } fi HUDUpdateScore HUDUpdateLines } function GameDetectLines() { local BLAPOS=0 local BLKCOUNT=0 local LINECLEARS=0 ZeroLinesBuffer for((i=0; i<TBASHH; i++)); do { BLKCOUNT=0 for((j=0; j<TBASHW; j++)); do { BLAPOS=$((($i * $TBASHW) + $j)) if [ ${TBASHARRAY[$BLAPOS]} -gt 0 ]; then { BLKCOUNT=$(($BLKCOUNT + 1)) } fi } done if [ $BLKCOUNT -eq $TBASHW ]; then { GAMELINESBUFFER[$LINECLEARS]=$i LINECLEARS=$(($LINECLEARS + 1)) } fi } done if [ $LINECLEARS -gt 0 ]; then { GAMELINESTOCLEAR=$LINECLEARS GAMECLEARINPROGRESS=1 ACCUMULATOR="0.0" GameDrawLineClear return 1 } fi return 0 } function GameDrawLineClear() { local BLAPOS=0 for((i=0; i<GAMELINESTOCLEAR; i++)); do { for((j=0; j<TBASHW; j++)); do { BLAPOS=$(((${GAMELINESBUFFER[$i]} * $TBASHW) + $j)) printf "\e[%d;%dH${GAMECLEARCHAR}${GAMECLEARCHAR}\e[0m" $(($TBASHOFFSETY + ${GAMELINESBUFFER[$i]})) $(($TBASHOFFSETX + ($j * 2))) } done } done FRAMEUPDATED=1 } function GameCheckMoveLeft() { local BLAPOS=0 local BLKX=0 local BLKY=0 for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) BLKX=$(($j + $GAMEBLOCKAPX)) BLKY=$(($i + $GAMEBLOCKAPY)) if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then { continue } fi if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then { if [ $(($BLKX - 1)) -lt 0 ]; then { return 0 } fi if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX - 1))]} -gt 0 ]; then { return 0 } fi } fi } done } done return 1 } function GameCheckMoveRight() { local BLAPOS=0 local BLKX=0 local BLKY=0 for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) BLKX=$(($j + $GAMEBLOCKAPX)) BLKY=$(($i + $GAMEBLOCKAPY)) if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then { continue } fi if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then { if [ $(($BLKX + 1)) -gt $(($TBASHW - 1)) ]; then { return 0 } fi if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX + 1))]} -gt 0 ]; then { return 0 } fi } fi } done } done return 1 } function GameCheckMoveDown() { local BLAPOS=0 local BLKX=0 local BLKY=0 for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) BLKX=$(($j + $GAMEBLOCKAPX)) BLKY=$(($i + $GAMEBLOCKAPY)) if [ $BLKX -lt 0 ] || [ $BLKX -gt $(($TBASHW - 1)) ]; then { continue } fi if [ ${GAMECURRENTARRAY[$BLAPOS]} -gt 0 ]; then { if [ $(($BLAPOS + $GAMEBLOCKSIZE)) -lt $GAMEBLOCKAREA ]; then { if [ ${GAMECURRENTARRAY[$(($BLAPOS + $GAMEBLOCKSIZE))]} -gt 0 ]; then { continue } fi } fi if [ $(($BLKY + 1)) -gt $(($TBASHH - 1)) ]; then { return 0 } fi if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX + $TBASHW))]} -gt 0 ]; then { return 0 } fi } fi } done } done return 1 } function GameMoveBlockLeft() { GameCheckMoveLeft if [ $? -eq 1 ]; then { GameClearCurrentBlock GAMEBLOCKAPX=$(($GAMEBLOCKAPX - 1)) GAMEBLOCKX=$(($GAMEBLOCKX - 2)) GameDrawCurrentBlock } fi } function GameMoveBlockRight() { GameCheckMoveRight if [ $? -eq 1 ]; then { GameClearCurrentBlock GAMEBLOCKAPX=$(($GAMEBLOCKAPX + 1)) GAMEBLOCKX=$(($GAMEBLOCKX + 2)) GameDrawCurrentBlock } fi } function GameMoveBlockDown() { if [ ! -z "$1" ]; then { if [ $1 -eq 1 ]; then { if [ $GAMEFAILURE -eq 0 ]; then { ACCUMULATOR="0.0" } else { return } fi } fi } fi GameCheckMoveDown if [ $? -eq 1 ]; then { GameClearCurrentBlock GAMEBLOCKAPY=$(($GAMEBLOCKAPY + 1)) GAMEBLOCKY=$(($GAMEBLOCKY + 1)) GameDrawCurrentBlock } else { GameCommitBlock GameDetectLines if [ $? -eq 0 ]; then { GameGenerateBlock } fi } fi } function GameCheckRotate() { local NEWROT=0 local BLAPOS=0 local BLKX=0 local BLKY=0 if [ -z "$1" ]; then { return 0 } fi if [ $1 -eq 0 ]; then { if [ $GAMECURRENTROT -eq 0 ]; then { NEWROT=3 } else { NEWROT=$(($GAMECURRENTROT - 1)) } fi } else { if [ $GAMECURRENTROT -eq 3 ]; then { NEWROT=0 } else { NEWROT=$(($GAMECURRENTROT + 1)) } fi } fi ZeroBlockBuffer if [ $GAMECURRENT -eq 0 ]; then { case $NEWROT in 0) GAMEBLOCKBUFFER=("${BLK1ARRAY[@]}");; 1) GAMEBLOCKBUFFER=("${BLK1ARRAYR2[@]}");; 2) GAMEBLOCKBUFFER=("${BLK1ARRAYR3[@]}");; 3) GAMEBLOCKBUFFER=("${BLK1ARRAYR4[@]}");; esac } elif [ $GAMECURRENT -eq 1 ]; then { GAMEBLOCKBUFFER=("${BLK2ARRAY[@]}") return 1 } elif [ $GAMECURRENT -eq 2 ]; then { case $NEWROT in 0) GAMEBLOCKBUFFER=("${BLK3ARRAY[@]}");; 1) GAMEBLOCKBUFFER=("${BLK3ARRAYR2[@]}");; 2) GAMEBLOCKBUFFER=("${BLK3ARRAY[@]}");; 3) GAMEBLOCKBUFFER=("${BLK3ARRAYR3[@]}");; esac } elif [ $GAMECURRENT -eq 3 ]; then { case $NEWROT in 0) GAMEBLOCKBUFFER=("${BLK4ARRAY[@]}");; 1) GAMEBLOCKBUFFER=("${BLK4ARRAYR2[@]}");; 2) GAMEBLOCKBUFFER=("${BLK4ARRAY[@]}");; 3) GAMEBLOCKBUFFER=("${BLK4ARRAYR2[@]}");; esac } elif [ $GAMECURRENT -eq 4 ]; then { case $NEWROT in 0) GAMEBLOCKBUFFER=("${BLK5ARRAY[@]}");; 1) GAMEBLOCKBUFFER=("${BLK5ARRAYR2[@]}");; 2) GAMEBLOCKBUFFER=("${BLK5ARRAY[@]}");; 3) GAMEBLOCKBUFFER=("${BLK5ARRAYR2[@]}");; esac } elif [ $GAMECURRENT -eq 5 ]; then { case $NEWROT in 0) GAMEBLOCKBUFFER=("${BLK6ARRAY[@]}");; 1) GAMEBLOCKBUFFER=("${BLK6ARRAYR2[@]}");; 2) GAMEBLOCKBUFFER=("${BLK6ARRAYR3[@]}");; 3) GAMEBLOCKBUFFER=("${BLK6ARRAYR4[@]}");; esac } elif [ $GAMECURRENT -eq 6 ]; then { case $NEWROT in 0) GAMEBLOCKBUFFER=("${BLK7ARRAY[@]}");; 1) GAMEBLOCKBUFFER=("${BLK7ARRAYR2[@]}");; 2) GAMEBLOCKBUFFER=("${BLK7ARRAYR3[@]}");; 3) GAMEBLOCKBUFFER=("${BLK7ARRAYR4[@]}");; esac } fi for((i=0; i<GAMEBLOCKSIZE; i++)); do { for((j=0; j<GAMEBLOCKSIZE; j++)); do { BLAPOS=$((($i * $GAMEBLOCKSIZE) + $j)) BLKX=$(($j + $GAMEBLOCKAPX)) BLKY=$(($i + $GAMEBLOCKAPY)) if [ ${GAMEBLOCKBUFFER[$BLAPOS]} -gt 0 ]; then { if [ $BLKY -gt $(($TBASHH - 1)) ] || [ $BLKX -gt $(($TBASHW - 1)) ] || [ $BLKX -lt 0 ]; then { return 0 } fi if [ ${TBASHARRAY[$((($BLKY * $TBASHW) + $BLKX))]} -gt 0 ]; then { return 0 } fi } fi } done } done GAMECURRENTROT=$NEWROT return 1 } function GameRotateBlockLeft() { GameCheckRotate 0 if [ $? -eq 1 ]; then { GameClearCurrentBlock GAMECURRENTARRAY=("${GAMEBLOCKBUFFER[@]}") GameDrawCurrentBlock } fi } function GameRotateBlockRight() { GameCheckRotate 1 if [ $? -eq 1 ]; then { GameClearCurrentBlock GAMECURRENTARRAY=("${GAMEBLOCKBUFFER[@]}") GameDrawCurrentBlock } fi } function InitGame() { GAMESCORE=0 GAMELEVEL=0 GAMELINES=0 GAMEFAILURE=0 GAMEFAILURECOUNT=0 GAMEOVERINPROGRESS=0 GAMECLEARINPROGRESS=0 GAMELINESTOCLEAR=0 GAMESCOREMULT=$(($GAMESCOREMULTDEF + ($GAMELEVEL * $GAMESCOREMULTINC))) GAMECURRENT=$(($RANDOM % 7)) GAMENEXT=$(($RANDOM % 7)) GAMEINTERVAL="0.5" ACCUMULATOR="0.0" ZeroTetriBashArray DrawTetriBashArray GameSetCurrentBlock GameDrawCurrentBlock } function SetGameStateMenu() { TETRIBASHSTATE=1 GAMERUNNING=0 clear DrawTetriBashTitle DrawTetriBashMainMenu DrawTetriBashMenuDecor DrawTetriBashVersionString } function SetGameStatePlay() { clear TETRIBASHSTATE=2 GAMERUNNING=1 InitGame DrawTetriBashHUD } function SetGameStateAbout() { clear TETRIBASHSTATE=3 GAMERUNNING=0 DrawTetriBashTitle DrawTetriBashVersionString DrawBorder $TBASHABOUTX $TBASHABOUTY $TBASHABOUTW $TBASHABOUTH printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO}\e[0m" $(($TBASHABOUTY + 1)) $(($TBASHABOUTX + 1)) printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO2}\e[0m" $(($TBASHABOUTY + 2)) $(($TBASHABOUTX + 1)) printf "\e[%d;%dH\e[1;32m${TETRIBASHINFO3}\e[0m" $(($TBASHABOUTY + 4)) $(($TBASHABOUTX + 1)) } function SetGameStatePause() { clear TETRIBASHSTATE=4 GAMERUNNING=0 } function SetGameStateExit() { clear TETRIBASHSTATE=0 GAMERUNNING=0 } function ExecuteMainMenuSelection() { case $MAINMENUSELECTION in 0) SetGameStatePlay;; 2) SetGameStateAbout;; 3) SetGameStateExit;; esac } #============================================================================= #----------------------------------------------------------------------------- # [ TetriBASH Script ] #----------------------------------------------------------------------------- #============================================================================= # Clear Screen clear stty -echo -icanon time 0 min 0 SetGameStateMenu # Game Loop while true; do { TIMESTART=$(date +%s.%N) KEY=$(dd bs=1 count=1 2> /dev/null; echo ".") KEY=${KEY%.} if [ $TETRIBASHSTATE -eq 1 ]; then { case $KEY in q) SetGameStateExit;; w) ChangeMainMenuSelectionUp;; a) ChangeMainMenuSelectionUp;; s) ChangeMainMenuSelectionDown;; d) ChangeMainMenuSelectionDown;; k) ExecuteMainMenuSelection;; # ?) printf "$KEY" ;; esac } elif [ $TETRIBASHSTATE -eq 2 ]; then { if [ $GAMERUNNING -eq 1 ]; then { if [ $GAMECLEARINPROGRESS -eq 1 ]; then { case $KEY in q) SetGameStateMenu;; esac if [[ $(echo "if (${ACCUMULATOR} > ${GAMECLEARINTERVAL}) 1" | bc) -eq 1 ]]; then { GameClearLines GAMECLEARINPROGRESS=0 GAMELINESTOCLEAR=0 GameGenerateBlock } fi } elif [ $GAMEOVERINPROGRESS -eq 1 ]; then { case $KEY in q) SetGameStateMenu;; esac if [[ $(echo "if (${ACCUMULATOR} > ${GAMEOVERINTERVAL}) 1" | bc) -eq 1 ]]; then { SetGameStateMenu } fi } else { case $KEY in q) SetGameStateMenu;; w) DrawTetriBashArray;; a) GameMoveBlockLeft;; s) GameMoveBlockDown 1;; d) GameMoveBlockRight;; j) GameRotateBlockLeft;; l) GameRotateBlockRight;; # ?) printf "%d\n" "'$KEY" ;; esac if [[ $(echo "if (${ACCUMULATOR} > ${GAMEINTERVAL}) 1" | bc) -eq 1 ]]; then { GameMoveBlockDown if [ $GAMEFAILURE -eq 1 ]; then { GAMEFAILURECOUNT=$(($GAMEFAILURECOUNT + 1)) if [ $GAMEFAILURECOUNT -eq $GAMEFAILUREMAX ]; then { GAMEOVERINPROGRESS=1 ACCUMULATOR="0.0" GameOverClearTetriBashArray DrawTetriBashArray HUDDrawGameOver } fi GAMEINTERVAL=$(echo "$GAMEINTERVAL - 0.05" | bc) } fi ACCUMULATOR=$(echo "$ACCUMULATOR - $GAMEINTERVAL" | bc) } fi } fi } fi } elif [ $TETRIBASHSTATE -eq 3 ]; then { case $KEY in q) SetGameStateMenu;; esac } elif [ $TETRIBASHSTATE -eq 4 ]; then { case $KEY in q) SetGameStateExit ;; w) DrawTetriBashArray ;; a) DrawBorder 4 2 10 10 ;; s) DrawTetriBashHUD ;; d) DrawTetriBashTitle;; ?) printf "%d\n" "'$KEY" ;; esac } else { break } fi if [ $FRAMEUPDATED -eq 1 ]; then { if [ $TETRIBASHDEBUG -eq 1 ]; then { if [ $TETRIBASHSTATE -eq 2 ]; then { printf "\e[1;2H\e[1;32mDebug:BlkPos(%d,%d) BlkTerm(%d,%d) Delta(%2.3g) Accu(%2.3g) LC(%d) \e[0m" $GAMEBLOCKAPX $GAMEBLOCKAPY $GAMEBLOCKX $GAMEBLOCKY $DELTATIME $ACCUMULATOR $GAMECLEARINPROGRESS } fi } fi printf "\e[1;1H" FRAMEUPDATED=0 } fi TIMEEND=$(date +%s.%N) DELTATIME=$(echo "$TIMEEND - $TIMESTART" | bc) if [ $TETRIBASHSTATE -eq 2 ] && [ $GAMERUNNING -eq 1 ]; then { ACCUMULATOR=$(echo "$ACCUMULATOR + $DELTATIME" | bc) } fi } done # Clean Up printf "\e[0m" clear stty sane exit 0   I attached the script file as well, just drop the .txt.   The controls are as follows: K - Select menu item Q - quit or back WASD - menu nav and block movement J and L - rotate piece   Don't hold down keys too long or the key buffer will sometimes fill up quicker than it gets emptied (does not seem to happen as quickly while running slower in a VM) .