iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
Modern Web

派對動物嗨起來!系列 第 14

D14 - 裝飾大廳細節

  • 分享至 

  • xImage
  •  

本系列文已改編成書「甚麼?網頁也可以做派對遊戲?使用 Vue 和 babylon.js 打造 3D 派對遊戲吧!」

書中不只重構了程式架構、改善了介面設計,還新增了 2 個新遊戲呦!ˋ( ° ▽、° )

新遊戲分別使用了陀螺儀與震動回饋,趕快買書來研究研究吧!ლ(╹∀╹ლ)

在此感謝深智數位的協助,歡迎大家前往購書,鱈魚感謝大家 (。・∀・)。

助教:「所以到底差在哪啊?沒圖沒真相,被你坑了都不知道。(´。_。`)」

鱈魚:「你對我是不是有甚麼很深的偏見啊 (っ °Д °;)っ,來人啊,上連結!」

Yes


讓我們持續完成大廳細節。

房間 ID

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>

完成!

Untitled

大家有點子的話可以自行魔改。(´,,•ω•,,)

主選單

如同首頁的按鈕一樣,我們也把大廳內的主選單加上裝飾吧。

為了不要讓畫面太花,這裡的按鈕只有 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>

ezgif-3-1b9c1e3208.gif

裝飾出現了,不過感覺有點死板,那就加個動畫吧!

<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>

ezgif-4-defa9106fb.gif

感覺好多了 ♪(´▽`)

玩家頭像

希望頭像會自動依照玩家代號(例如: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>

Untitled

成功變出不同顏色的玩家惹。◝( •ω• )◟

總結

  • 完成 room-id-chip 基本樣式
  • 完成主選單樣式
  • 完成 player-avatar 樣式

以上程式碼已同步至 GitLab,大家可以前往下載:

GitLab - D14


上一篇
D13 - 來布置一下吧
下一篇
D15 - 加入派對
系列文
派對動物嗨起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言