【Vue】第一个小项目“怪物杀手”

实现效果:

  • 四个功能按键:攻击,技能,治疗,投降
  • 战斗日志:记录玩家和怪物的对战细节
  • 至少有一个血条归零时判断胜者(或平局),并出现重新开始游戏按钮
    在这里插入图片描述
    在这里插入图片描述

Javascript部分:

function getRandomValue(min, max) {
  return Math.floor(Math.random() * (max - min)) + min
}

const app = Vue.createApp({
  data() {
    return {
      playerHealth: 100,
      monsterHealth: 100,
      currentRound: 0,
      winner: null,
      logMessages: [],
    }
  },
  computed: {
    //怪物血条计算
    monsterBarWidth() {
      if (this.monsterHealth < 0) {
        return { width: "0%" }
      }
      return "width:" + this.monsterHealth + "%"
    },
    //玩家血条计算
    playerBarWidth() {
      if (this.playerHealth < 0) {
        return { width: "0%" }
      }
      return "width:" + this.playerHealth + "%"
    },
    mayUseSpecialAttack() {
      return this.currentRound % 3 !== 0
    },
  },
  watch: {
    playerHealth(value) {
      if (value <= 0 && this.monsterHealth <= 0) {
        // 平局
        this.winner = "draw"
      } else if (value <= 0) {
        // 玩家失败
        this.winner = "monster"
      }
    },
    monsterHealth(value) {
      if (value <= 0 && this.playerHealth <= 0) {
        // 平局
        this.winner = "draw"
      } else if (value <= 0) {
        // 玩家获胜
        this.winner = "player"
      }
    },
  },
  methods: {
    //游戏重开 吧
    startGame() {
      this.playerHealth = 100
      this.monsterHealth = 100
      this.currentRound = 0
      this.winner = null
      this.logMessages = []
    },
    //普通攻击,伤害值5~12
    attackMonster() {
      this.currentRound++
      const attackValue = getRandomValue(5, 12)
      this.monsterHealth -= attackValue
      this.addLogMessage("player", "attack", attackValue)
      this.attackPlayer()
    },
    //怪物攻击,伤害值8~15
    attackPlayer() {
      const attackValue = getRandomValue(8, 15)
      this.playerHealth -= attackValue
      this.addLogMessage("monster", "attack", attackValue)
    },
    //技能,伤害值10~25,使用后有两回合冷却
    specialAttackMonster() {
      this.currentRound++
      const attackValue = getRandomValue(10, 25)
      this.monsterHealth -= attackValue
      this.addLogMessage("player", "attack", attackValue)
      this.attackPlayer()
    },
    //治疗,8~20治疗值
    healPlayer() {
      this.currentRound++
      const healValue = getRandomValue(8, 20)
      if (this.playerHealth + healValue > 100) {
        this.playerHealth = 100
      } else {
        this.playerHealth += healValue
      }
      this.addLogMessage("player", "heal", healValue)
      this.attackPlayer()
    },
    //投降
    surrender() {
      this.winner = "monster"
    },
    //对战日志,最新战况插入数组头部
    addLogMessage(who, what, value) {
      this.logMessages.unshift({
        actionBy: who,
        actionType: what,
        actionValue: value,
      })
    },
  },
})

app.mount("#game")

Html部分

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Basics</title>
    <link
      href="https://fonts.googleapis.com/css2?family=Jost:wght@400;700&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="app.js" defer></script>
  </head>

  <body>
    <header>
      <h1>Monster Slayer</h1>
    </header>
    <div id="game">
      <!-- 怪物血条 -->
      <section id="monster" class="container">
        <h2>Monster Health</h2>
        <div class="healthbar">
          <div class="healthbar__value" :style="monsterBarWidth"></div>
        </div>
      </section>
      <!-- 玩家血条 -->
      <section id="player" class="container">
        <h2>Your Health</h2>
        <div class="healthbar">
          <div class="healthbar__value" :style="playerBarWidth"></div>
        </div>
      </section>
      <!-- winner中有值(monster||player||draw)时出现游戏结束面板 -->
      <section class="container" v-if="winner">
        <h2>Game Over!</h2>
        <h3 v-if="winner == 'monster'">You lost!</h3>
        <h3 v-else-if="winner == 'player'">You won!</h3>
        <h3 v-else>It`s a draw!</h3>
        <button @click="startGame">Star New Game</button>
      </section>
      <!-- winner还没出现,则显示四个功能按钮 -->
      <section id="controls" v-else>
        <button @click="attackMonster">ATTACK</button>
        <button :disabled="mayUseSpecialAttack" @click="specialAttackMonster">
          SPECIAL ATTACK
        </button>
        <button @click="healPlayer">HEAL</button>
        <button @click="surrender">SURRENDER</button>
      </section>
      <!-- 对战日志 -->
      <section id="log" class="container">
        <h2>Battle Log</h2>
        <ul>
          <li v-for="logMessage in logMessages">
            <span
              :class="{'log--player': logMessage.actionBy === 'player', 'log--monster': logMessage.actionBy === 'monster'}"
              >{{ logMessage.actionBy === 'player' ? 'Player' : 'Monster'
              }}</span
            >
            <span v-if="logMessage.actionType === 'heal'">
              heals himself for
              <span class="log--heal">{{ logMessage.actionValue }}</span></span
            >
            <span v-else>
              attacks and deals
              <span class="log--damage">{{ logMessage.actionValue }}</span>
            </span>
          </li>
        </ul>
      </section>
    </div>
  </body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值