实现效果:
- 四个功能按键:攻击,技能,治疗,投降
- 战斗日志:记录玩家和怪物的对战细节
- 至少有一个血条归零时判断胜者(或平局),并出现重新开始游戏按钮
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 = []
},
attackMonster() {
this.currentRound++
const attackValue = getRandomValue(5, 12)
this.monsterHealth -= attackValue
this.addLogMessage("player", "attack", attackValue)
this.attackPlayer()
},
attackPlayer() {
const attackValue = getRandomValue(8, 15)
this.playerHealth -= attackValue
this.addLogMessage("monster", "attack", attackValue)
},
specialAttackMonster() {
this.currentRound++
const attackValue = getRandomValue(10, 25)
this.monsterHealth -= attackValue
this.addLogMessage("player", "attack", attackValue)
this.attackPlayer()
},
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>
<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>
<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>