遊戲開始的聲音
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<link href="./src/style/minireset.min.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<div class="">
<audio src="/src/static/music/start.wav" id="aStart"></audio>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
增加聲音播放的服務。
src/service/audio.ts
/**
* 服務
* 聲音播放
*/
export default {
start() {
const el = document.querySelector<HTMLAudioElement>('#aStart')
el?.play()
}
}
src/app.ts
......
// 遊戲開始
async gameStart() {
if (this.gameStatus != 'gameStart') {
this.gameStatus = 'gameStart'
//背景圖片關閉
// @ts-ignore
app.style.backgroundImage = 'none';
audio.start()//遊戲開始的聲音
// console.log(promises)
//先加載各種貼圖
await Promise.all(promises)
// console.log(image.get('straw'))
// 調用render方法渲染
canvasStraw.render() // 畫布渲染:草地
canvasWallBrick.render() // 畫布渲染:磚牆
canvasWallSteel.render() // 畫布渲染:鋼牆
canvasTank.render() // 畫布渲染:敵方坦克
canvasWater.render() // 畫布渲染:水域
bullet.render() // 畫布渲染:子彈
boss.render() // 畫布渲染:boss,老巢
player.render() // 畫布渲染:玩家坦克
}
},
......
其他聲音載入
同理。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<link rel="icon" type="image/svg+xml" href="favicon.svg"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Vite App</title>
<link href="./src/style/minireset.min.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<div class="">
<!-- 聲音:遊戲開始 -->
<audio src="/src/static/music/start.wav" id="aStart"></audio>
<!-- 聲音:開火 -->
<audio src="/src/static/music/fire.wav" id="aBulletFire"></audio>
<!-- 聲音:爆炸 -->
<audio src="/src/static/music/blast.wav" id="aBlast"></audio>
<!-- 聲音:增加磚塊 -->
<audio src="/src/static/music/add.wav" id="aAdd"></audio>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
src/service/audio.ts
/**
* 服務
* 聲音播放
*/
export default {
getEl(id: string) {
return document.querySelector<HTMLAudioElement>(`#${id}`)
},
//聲音:遊戲開始
start() {
const el = this.getEl('aStart')
el?.play()
},
//聲音:開火
bulletFire() {
const el = this.getEl('aBulletFire')
el?.play()
},
//聲音:爆炸
blast() {
const el = this.getEl('aBlast')
el?.play()
},
//聲音:增加磚塊
add() {
const el = this.getEl('aAdd')
el?.play()
},
}
src/canvas/Bullet.ts
......
//自定義子彈的渲染函數:子彈創建
createModelsBullet() {
// 子彈的創建需要根據坦克的畫布中的坦克模型數量來決定需要發送多少顆子彈
tank.models.forEach(tItem => {
// 查詢是否存在同樣名稱的坦克的子彈,如果有,表示該坦克已經發射子彈了
const isExists = this.models.some(model => model.tank === tItem)
//如果子彈不存在,放置子彈
if (!isExists) {
this.models.push(new ModelBullet(tItem))
// 敵方坦克開火,發出聲音
audio.bulletFire()
}
})
// console.log(this.models)
}
// 我方坦克發射子彈
addPlayerBullet() {
this.models.push(new ModelBullet(player.models[0]))
// 玩家坦克開火,發出聲音
audio.bulletFire()
}
......
src/model/abstract/AbstractModel.ts
......
/**
* 爆炸效果實現
* 原理:8張gif圖片依次切換顯示。
* @param model 被打炸的模型
* @protected
*/
protected blast(model: IModel) {
// 爆炸的聲音
audio.blast()
......
}
......
遊戲結束時文字處理
優化一下貼圖
src/canvas/abstract/AbstractCanvas.ts
......
// 繪製模型,生成模型實例,只負責創建實例
// protected:子類可以調用,外部不能調用
//num: 渲染多少個數量
// 初始化canvas,創建畫布
protected createCanvas() {
// 元素的寬高就是全局canvas得到寬高
// @ts-ignore
this.el.width = config.canvas.width
// @ts-ignore
this.el.height = config.canvas.height
// 最終元素要放到我們的app的div中
// @ts-ignore
this.el.setAttribute('name', this.name)
// @ts-ignore
this.app.insertAdjacentElement('afterbegin', this.el)
// @ts-ignore
if (!(this.name === 'water' || this.name === 'WallSteel')) {
// @ts-ignore
this.app.appendChild(this.el)
}
}
......
src/app.ts
......
// 遊戲結束
gameOver() {
//關閉遊戲運行的定時器
clearInterval(this.gameInterval)
// 敵方坦克停止
tank.stop()
// 子彈停止
bullet.stop()
this.gameOverText()
},
async gameOverText() {
// @ts-ignore
const el = document.createElement<HTMLCanvasElement>('canvas');
// @ts-ignore
el.width = config.canvas.width
// @ts-ignore
el.height = config.canvas.height
// @ts-ignore
const ctx = el.getContext('2d')
ctx.fillStyle = '#fff'
ctx.font = '80px CascadiaMono'
ctx.textAlign='center'
ctx.textBaseline = 'middle'
ctx.fontWeight=900
ctx.fillText(this.gameStatus==='gameWin'?'遊戲勝利':'遊戲失敗', config.canvas.width/2, config.canvas.height/2)
// @ts-ignore
app.appendChild(el)
}
......