Shell脚本小游戏(学习记录贴)

最近在学习脚本语言,没有章法,索性就想着使用脚本写一个命令行小游戏,连带着也可以学习脚本的用法,忙碌了一天的时间,将将写完了基础框架,不过对于脚本的用法精进岂止一点,还是收获良多!
以后闲下来的时间也会继续更新这个小游戏的,以下就是全部代码,关于脚本的一些使用可以看脚本内的注释

#!/bin/bash 

# @Auth     hcx
# @WeChat   GAME_SERVER_HCX
# @Tencent  305773778

# -----------------------------------------配置区-----------------------------------------
# config 就是懒不想读文件,就直接写在一起咯
# 事件描述
eventDesc=(
            # id:0
            "你遇到了一只可爱的小怪物,攻击还是逃跑?" 
            # id:1
            "你遇到了一个仙人,他说你骨骼清奇,十分适合修仙."
          )
# 事件选择
eventChoice=(
              # id:0
              "1.当然是打啊?!\n2.小命要紧!快跑!" 
              # id:1
              "1.仙人收我为徒\n2.修什么仙,要相信科学"
            )
# 触发事件
touchEvent=(
             # id:0
             "fight:moster:player-level;none" 
             # id:1
             "attrChange:exp:1000;none"
           )
# 事件配置[描述id,选项id,触发事件id]
eventConfig=(
              # id:0
              "0,0,0" 
              # id:1
              "1,1,1"
            )

# -----------------------------------------配置区-----------------------------------------
# -----------------------------------------方法区-----------------------------------------
# 无事件
none(){
 echo "什么都没有发生~"
}

# 事件解析
doEvent(){
  # 切割字符串 (${event//oldStr/newStr}) 只是其中的一种方法,也可以用tr等等
  # 将分隔符替换为空格并加上圆括号本质就是拼接了一个数组的格式,但缺点显而易见,元素中不能含有空格
  index=$1
  eventParamIds=(${eventConfig[index]//,/ })
  eventDescId=${eventParamIds[0]}
  eventChoiceId=${eventParamIds[1]}
  touchEventId=${eventParamIds[2]}
  touchEventCommondArr=(${touchEvent[touchEventId]//;/ })
  echo "${eventDesc[eventDescId]}"
  echo -e "${eventChoice[eventChoiceId]}"
  read choice
  choice=`expr $choice - 1`
  while [ $choice -ge ${#touchEventCommondArr[*]} -o $choice -lt 0 ]
  do
    echo "请输入正确的选项"
    read choice
  done
  echo "世间种种奇遇~骚年切莫心急~让奇遇飞一会儿~"
  ${touchEventCommondArr[choice]//:/ }
}

# 参数为百分比值
updateBar(){
  num=`expr $1 / 2`
  str=$(seq -s '' ${num} | sed 's/[0-9]//g')
  blankStr=''
  if [ $1 = 100 ]
  then
    echo "正在加载[${str}${blankStr}]$1%"
  else
    blankStr=$(seq -s ' ' `expr 50 - ${num}` | sed 's/[0-9]//g')
    echo -ne "正在加载[${str}${blankStr}]$1%\r"
  fi
}

# 假进度条
loading(){
  for i in {1..100}
  do
    updateBar ${i}
    # 这里为了表现明显一些,休眠20ms
    # sleep 0.02
  done
}

workDir=$(cd `dirname $0`; pwd)
saveFilePath=${workDir}/save.data

# 读取存档
getAttr(){
  echo `cat ${saveFilePath} | grep -w $1 | awk -F '=' '{print $2}' | sed 's/\"//g' | tr -d '\r'`
}

# 更新存档
updateAttr(){
  if [ ! -n "$2" ]
  then
    return
  fi
  # 将函数运行结果赋予变量使用$()包裹即可,或者``包裹
  value=`getAttr $1`
  if [ -n "${value}" ]
  then
    sed -i "" "s/$1=.*/$1=$2/g" $saveFilePath
  else
    echo -e "$1=$2">>$saveFilePath
  fi 
}

# 属性改变
attrChange(){
  changeAttrName=$1
  beforeAttrValue=`eval echo '$'"$changeAttrName"`
  attrIsNone=true
  if [ -n "$beforeAttrValue" ]
  then
    attrIsNone=false
  fi
  changeValue=$2
  case $changeAttrName in
    "exp")
      if [ $attrIsNone = true ]
      then
        exp=0
      fi
      exp=`expr $exp + $changeValue`
      # -gt 大于号
      if [ 0 -gt $exp ]
      then
        exp=0
      fi
      # -lt 小于号
      needUpgradeLevelNum=0
      while [ `expr \( $level + $needUpgradeLevelNum \) \* 10` -lt $exp ]
      do
        needUpgradeLevelNum=`expr $needUpgradeLevelNum + 1`
        exp=`expr $exp - \( \( $level + $needUpgradeLevelNum \) \* 10 \)`
      done
      updateAttr exp $exp
      if [ ! $needUpgradeLevelNum -eq 0 ]
      then 
        attrChange level $needUpgradeLevelNum
        echo "实力突飞猛进,感觉自己更加强大!"
      else
        echo "感觉实力又有精进!"
      fi
    ;;
    "level")
      if [ $attrIsNone = true ]
      then
        level=1
      fi
      afterLevel=`expr $level + $changeValue`
      # 升级事件,增加属性值
      for i in $(seq $level $afterLevel)
      do
        attrChange hp `expr $i \* 100`
        attrChange atk `expr $i \* 3`
        attrChange def `expr $i \* 1`
      done
      level=$afterLevel
      updateAttr level $level
    ;;
    "atk")
      if [ $attrIsNone = true ]
      then
        atk=1
      fi
      atk=`expr $atk + $changeValue`
      updateAttr atk $atk
    ;;
    "def")
      if [ $attrIsNone = true ]
      then
        def=1
      fi
      def=`expr $def + $changeValue`
      updateAttr def $def
    ;;
    "hp")
      if [ $attrIsNone = true ]
      then
        hp=100
      fi
      hp=`expr $hp + $changeValue`
      updateAttr hp $hp
    ;;
    "killMosterNum")
      if [ $attrIsNone = true ]
      then
        killMosterNum=0
      fi
      killMosterNum=`expr $killMosterNum + $changeValue`
      updateAttr killMosterNum $killMosterNum
    ;;
  esac
}
# 展示玩家属性
showPlayerProp(){
  echo "昵称:${nickname}"
  echo "称号:${title}"
  echo "职业:${occupation}"
  echo "等级:${level}"
  echo "经验:${exp}/`expr $level \* 10`"
  echo "血量:${hp}"
  echo "攻击:${atk}"
  echo "防御:${def}"
  echo "技能:${skill}"
  echo "当前地图:${map}"
  echo "杀怪数:${killMosterNum}"
}
# -----------------------------------------方法区-----------------------------------------

# -----------------------------------------事件区-----------------------------------------
# 战场信息输出
echoFightDetail(){
  echo "怪物名称:我可爱么"
  echo "怪物等级:$mosterLevel"
  echo "[血量]HP: $tmpMosterHp/$mosterHp"
  echo "[攻击]ATK: $mosterAtk"
  echo "[防御]DEF: $mosterDef"
  echo "     ^^^     "
  echo "     ^^^     "
  echo "     |||     "
  echo "角色:$nickname"
  echo "等级:$level"
  echo "[血量]HP: $tmpHp/$hp"
  echo "[攻击]ATK: $atk"
  echo "[防御]DEF: $def"
}
# 战斗方法  参数1:目标类型    参数2:目标等级范围
fight(){
  # 清屏
  reset
  # 目标类型
  targetType=$1
  # 目标等级随机范围
  targetLevelRound=$2
  # 解析等级随机范围
  if [ -n "$targetLevelRound" -o "$targetLevelRound" = "player-level" ]
  then
    targetLevelRound="`expr $level - 1`-`expr $level + 1`"
  fi
  targetLevelMin=`echo -n $targetLevelRound | awk -F '-' '{print $1}'`
  targetLevelMax=`echo -n $targetLevelRound | awk -F '-' '{print $2}'`
  mosterLevel=`expr $[$RANDOM%$targetLevelMax] + $targetLevelMax - $targetLevelMin`
  mosterHp=`expr $mosterLevel \* 100`
  mosterAtk=`expr $mosterLevel \* 10`
  mosterDef=`expr $mosterLevel \* 10`
  tmpHp=$hp
  tmpMosterHp=$mosterHp
  echoFightDetail
  echo -n "回车以攻击 输入run逃跑 "
  read continue
  if [ "$continue" = "run" ]
  then
    echo "没事,修炼修炼,再来复仇!"
    return
  fi
  reset
  round=1
  while [ $tmpMosterHp -gt 0 -a $tmpHp -gt 0 ]
  do
    playerDmg=`expr $atk - $mosterDef`
    if [ $playerDmg -lt 0 ]
    then
      playerDmg=1
    fi
    tmpMosterHp=`expr $tmpMosterHp - $playerDmg`
    if [ $tmpMosterHp -lt 0 ]
    then
      tmpMosterHp=0
    fi
    mosterDmg=`expr $mosterAtk - $def`
    if [ $mosterDmg -lt 0 ]
    then
      mosterDmg=1
    fi
    tmpHp=`expr $tmpHp - $mosterDmg `
    if [ $tmpHp -lt 0 ]
    then
      tmpHp=0
    fi
    round=`expr $round + 1`
    echo "第${round}回合"
    echoFightDetail
    if [ $tmpHp = 0 -o $tmpMosterHp = 0 ]
    then
      break
    fi
    echo -n "回车以攻击 输入run逃跑 "
      read continue
    if [ "$continue" = "run" ]
    then
      echo "没事,修炼修炼,再来复仇!"
      return
    fi
    reset
  done
  if [ $tmpHp = 0 ]
  then
    echo "啊!你死了"
    echo "怪物不屑的对你说,小样儿回去修炼吧,打败我还早得很!"
  fi
  if [ $tmpMosterHp = 0 ]
  then
    echo "怪物被你一棒打死!"
    getExp=`expr $mosterLevel \* 100`
    echo "你挥一挥衣袖,带走了${getExp}经验"
    attrChange exp $getExp
    attrChange killMosterNum 1
  fi
}
# -----------------------------------------事件区-----------------------------------------

# --------------------------------------游戏主流程开始--------------------------------------
reset
echo "welcome to my little game"
sleep 0.618
echo "it's a beautiful and wonderful world of games"
sleep 0.618
echo -ne "so now,you should load save to continue game?(y/n) "
read needLoading
nickname='玩家'
level=1
exp=0
atk=1
def=1
hp=100
occupation=0
skill={"普通攻击"}
map=1
killMosterNum=0
title="一个普通玩家"
if [ "$needLoading" = "y" ] 
then
  echo "let me see what you have on data~"
  sleep 0.618
  # 这里才是真正的加载!没想到吧hhhhhhh
  if [ ! -f "${saveFilePath}" ] 
  then
    echo "oh~You're so naughty,nothing data to loading~"
    sleep 0.618
    echo "but don't worry about.just create one for you, my kitty"
    # 创建存档文件,赋予完全控制权限
    touch "${saveFilePath}"
    chmod 777 ${saveFilePath}
    sleep 0.618
    echo "now,enjoy self,enjoy play,let we run to the game world!"
  else
    source ${saveFilePath}
  fi
  loadThings=("sky" "flower" "meat" "no food no game!!!")
  # 你想看出点什么?看出什么了?你在做梦哈哈哈,这里只是假的加载而已,骗鬼的啦!
  for thing in "${loadThings[@]}"; do
    echo "just loading ${thing} now!";
    loading
  done
else
  # 读取昵称
  echo "but waaaaaaait a moment! let me get your nickname,so what?"
  echo -n "tell me your nickname:"
  read nickname
fi
echo "okk~ ${nickname}!let's start a wonderful journey~"
echo "gogogo!"
echo "into the game world now!"
# 没错还是假的加载,但是我就是要加~略略略
loading 
reset
eventNum=${#eventConfig[*]}
while true
do
  echo "这里是神奇的摸鱼世界,请输入你的选择"
  echo "1:探索事件"
  echo "2:查看属性"
  read choice
  while [ ! $choice = 1 -a ! $choice = 2 ]
  do
    echo "请输入正确的选择哦~"
  done
  reset
  case $choice in
    1)
      doEvent $[$RANDOM%$eventNum]
    ;;
    2)
      showPlayerProp
    ;;
  esac
  read tmpKey
  reset
done
# --------------------------------------游戏主流程结束--------------------------------------

你可能感兴趣的:(Shell脚本小游戏(学习记录贴))