本系列文已改編成書「甚麼?網頁也可以做派對遊戲?使用 Vue 和 babylon.js 打造 3D 派對遊戲吧!」
書中不只重構了程式架構、改善了介面設計,還新增了 2 個新遊戲呦!ˋ( ° ▽、° )
新遊戲分別使用了陀螺儀與震動回饋,趕快買書來研究研究吧!ლ(╹∀╹ლ)
在此感謝深智數位的協助,歡迎大家前往購書,鱈魚感謝大家 (。・∀・)。
助教:「所以到底差在哪啊?沒圖沒真相,被你坑了都不知道。(´。_。`)」
鱈魚:「你對我是不是有甚麼很深的偏見啊 (っ °Д °;)っ,來人啊,上連結!」
讓我們持續完成大廳細節。
room-id-chip 現在看起來好像還行捏 …(´● ω ●`),不然來換個字體好了。
在 App.vue 引入字體。
src\App.vue
...
<style lang="sass">
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100;300;400;500;700;900&display=swap')
@import url('https://fonts.googleapis.com/css2?family=Chakra+Petch&family=Noto+Sans+TC:wght@100;300;400;500;700;900&display=swap')
...
</style>
回到 room-id-chip 中,變更字體。
src\components\room-id-chip.vue
...
<style scoped lang="sass">
.room-id
...
font-family: 'Chakra Petch', sans-serif
</style>
完成!
大家有點子的話可以自行魔改。(´,,•ω•,,)
如同首頁的按鈕一樣,我們也把大廳內的主選單加上裝飾吧。
為了不要讓畫面太花,這裡的按鈕只有 hover 的時候才會出現裝飾效果。
src\views\game-console-lobby.vue
<template>
<background-polygons-pattern class="absolute inset-0" />
<div class="absolute inset-0 flex">
<div class="flex w-full h-full">
<!-- 選單 -->
<div class="w-1/3 flex flex-col p-12">
<div class="flex flex-col flex-1 justify-center items-center gap-14">
...
<btn-base
label="開始遊戲"
...
>
<template #default="{ state }">
<transition name="opacity">
<div
v-if="state.hover"
class="btn-content absolute inset-0"
>
<div class="polygon-lt">
<polygon-base
size="13rem"
shape="round"
fill="spot"
/>
</div>
<div class="polygon-rb">
<polygon-base
size="13rem"
shape="round"
fill="fence"
opacity="0.2"
/>
</div>
</div>
</transition>
</template>
</btn-base>
<btn-base
label="結束派對"
...
>
<template #default="{ state }">
<transition name="opacity">
<div
v-if="state.hover"
class="btn-content absolute inset-0"
>
<div class="polygon-lt">
<polygon-base
size="13.4rem"
shape="square"
fill="spot"
/>
</div>
<div class="polygon-rb">
<polygon-base
size="13.3rem"
shape="square"
fill="fence"
opacity="0.2"
/>
</div>
</div>
</transition>
</template>
</btn-base>
</div>
...
</div>
...
</div>
</div>
</template>
...
<style scoped lang="sass">
.btn-content
background: #62a88a
.polygon-lt
position: absolute
left: -6rem
top: -6rem
.polygon-rb
position: absolute
right: -6rem
bottom: -6rem
</style>
裝飾出現了,不過感覺有點死板,那就加個動畫吧!
<template>
...<div class="absolute inset-0 flex">
<div class="flex w-full h-full">
<!-- 選單 -->
<div class="w-1/3 flex flex-col p-12">
<div class="flex flex-col flex-1 justify-center items-center gap-14">
...
<btn-base
label="開始遊戲"
...
>
<template #default="{ state }">
<transition name="opacity">
<div
...
>
<div class="polygon-lt">
<polygon-base
class="polygon-beat"
...
/>
</div>
<div class="polygon-rb">
<polygon-base
class="polygon-beat"
...
/>
</div>
</div>
</transition>
</template>
</btn-base>
<btn-base
label="結束派對"
...
>
<template #default="{ state }">
<transition name="opacity">
<div
...
>
<div class="polygon-lt">
<polygon-base
class="polygon-swing"
...
/>
</div>
<div class="polygon-rb">
<polygon-base
class="polygon-swing"
...
/>
</div>
</div>
</transition>
</template>
</btn-base>
</div>
...
</div>
...
</div>
</div>
</template>
...
<style scoped lang="sass">
...
.polygon-lt
position: absolute
left: -6rem
top: -6rem
animation: polygon-rotate 50s infinite linear
.polygon-rb
position: absolute
right: -6rem
bottom: -6rem
animation: polygon-rotate 40s infinite linear
@keyframes polygon-rotate
0%
transform: rotate(0deg)
100%
transform: rotate(360deg)
.polygon-beat
animation: polygon-beat 1.4s infinite
.polygon-swing
animation: polygon-swing 1.8s infinite
@keyframes polygon-beat
0%
transform: scale(1)
animation-timing-function: cubic-bezier(0.000, 0.000, 1.000, 0.000)
50%
transform: scale(0.9)
animation-timing-function: cubic-bezier(0.000, 1.000, 1.000, 1.000)
100%
transform: scale(1)
@keyframes polygon-swing
0%
transform: scale(1)
animation-timing-function: cubic-bezier(0.870, 0.000, 0.180, 0.995)
50%
transform: scale(0.9)
animation-timing-function: cubic-bezier(0.870, 0.000, 0.260, 1.375)
100%
transform: scale(1)
</style>
感覺好多了 ♪(´▽`)
希望頭像會自動依照玩家代號(例如:1P、2P)自動更換顏色。
這裡我們先定義代表玩家的顏色,新增 utils 模組,用來集中各類功能。
src\common\utils.ts
const playerColorNames = [
'red', 'purple', 'indigo',
'light-blue', 'teal', 'light-green',
'yellow', 'orange', 'brown', 'blue-grey'
];
/** 取得玩家顏色 */
export function getPlayerColor({ codeName }: { codeName: string }) {
if (!codeName.includes('P')) {
return 'grey';
}
try {
const index = parseInt(codeName.replaceAll('P', ''), 10) - 1;
return playerColorNames?.[index] ?? 'grey';
} catch (error) {
return 'grey';
}
}
接著調整 player-avatar 內容:
<template>
<q-avatar
:color="color"
text-color="white"
size="6rem"
>
{{ props.codeName }}
</q-avatar>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { getPlayerColor } from '../common/utils';
...
const color = computed(() =>
getPlayerColor({ codeName: props.codeName })
);
</script>
...
最後回到 game-console-lobby,多加幾個 player-avatar 看看顏色變化。
src\views\game-console-lobby.vue
<template>
...
<div class="absolute inset-0 flex">
<div class="flex w-full h-full">
<!-- 選單 -->
<div class="w-1/3 flex flex-col p-12">
...
<!-- 玩家清單 -->
<transition-group
name="list"
tag="div"
class="flex justify-center items-center gap-4 h-32"
>
<player-avatar
player-id="1P"
code-name="1P"
/>
<player-avatar
player-id="2P"
code-name="2P"
/>
<player-avatar
player-id="3P"
code-name="3P"
/>
</transition-group>
</div>
...
</div>
</div>
</template>
成功變出不同顏色的玩家惹。◝( •ω• )◟
以上程式碼已同步至 GitLab,大家可以前往下載: