Skip to content
歡迎來票選你最喜歡的元件! 也可以告訴我任何你想說的話喔!(*´∀`)~♥

彈珠檯 util

網頁變成彈珠台,一起打彈珠吧 ( ´ ▽ ` )ノ°

技術關鍵字

名稱 描述
Matter-js2D 物理引擎
物理模擬模擬真實世界物理現象,如重力、碰撞、速度等物理效果
向量計算處理方向、加速度、速度等等數學運算
JS 動畫基於 JavaScript 實現的動畫,達成更複雜、精準的動畫控制,常見套件有 GSAP、anime.js 等
Vue Directive自定義 Vue 指令,用於封裝 DOM 操作邏輯和重複行為

使用範例

基本用法

使用 v-pinball-mech 指令可以將 DOM 變成各種機關

滑鼠左右鍵同時按下即可開啟發射器,觸控裝置則是長按後開啟

發射器出現時彈珠會靜止,拖曳可調整方向與力道,放開後發射彈珠


彈珠台( Pinball )是由 雷蒙·莫洛尼 於西元 1934 年發明彈珠台上通常會有各種機械裝置,例如 彈簧翻板 等,這些裝置可以影響球的 運動軌跡 ,並且提供額外的 挑戰和樂趣彈珠台曾被視為賭博遊戲,因此在美國一度被禁止 長達 40 年 ,最後由 羅傑·夏普在法庭上證明 彈珠台的 技術性並非賭博 ,才得以合法化。《3D 彈珠台:太空軍校生》 原型出自 Maxis 發行的 《Full Tilt! Pinball》之後由 微軟 精簡移植,隨 Windows 95 起、到 Windows XP 期間的多個 Windows 版本內建。後續因 相容性維護成本 等因素,在 Windows Vista 後不再隨系統附帶。
查看範例原始碼
vue
<template>
  <div class="relative w-full flex flex-nowrap">
    <div
      v-pinball-mech
      class="wall absolute bottom-0 left-0 hidden h-4 w-full rounded-full md:block"
    />

    <div
      v-pinball-mech
      class="wall hidden w-4 rounded-full md:block"
    />

    <div class="text w-full flex flex-col justify-center gap-10 md:p-10">
      <span>
        {{ t('history.p1.start') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p1.pinball_en') }}</b>
        {{ t('history.p1.middle') }}
        <ins v-pinball-mech="'spinner'">{{ t('history.p1.inventor') }}</ins>
        {{ t('history.p1.end') }}
      </span>

      <span>
        {{ t('history.p2.start') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p2.spring') }}</b>

        <ins v-pinball-mech="'spinner'">{{ t('history.p2.flipper') }}</ins>
        {{ t('history.p2.middle') }}
        <ins v-pinball-mech="'spinner'">{{ t('history.p2.trajectory') }}</ins>
        {{ t('history.p2.connector') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p2.challenge') }}</b>
      </span>

      <span>
        {{ t('history.p3.start') }}
        <ins v-pinball-mech="'spinner'">{{ t('history.p3.duration') }}</ins>
        {{ t('history.p3.middle') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p3.hero') }}</b>
        <a
          href="https://en.wikipedia.org/wiki/Roger_Sharpe_(pinball)"
          target="_blank"
          rel="noopener"
        >
          {{ t('history.p3.link_text') }}
        </a>
        {{ t('history.p3.connector') }}
        <ins v-pinball-mech="'spinner'">
          {{ t('history.p3.skill') }}
        </ins>
        {{ t('history.p3.end') }}
      </span>

      <span>
        <ins v-pinball-mech="'spinner'">{{ t('history.p4.game_title') }}</ins>
        {{ t('history.p4.middle') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p4.company') }}</b>
        {{ t('history.p4.connector') }}
        <ins v-pinball-mech="'spinner'">{{ t('history.p4.original_title') }}</ins>
      </span>

      <span>
        {{ t('history.p5.start') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p5.microsoft') }}</b>
        {{ t('history.p5.middle_1') }}
        <ins v-pinball-mech="'spinner'">Windows 95</ins>
        {{ t('history.p5.middle_2') }}
        <ins v-pinball-mech="'spinner'">Windows XP</ins>
        {{ t('history.p5.end') }}
      </span>

      <span>
        {{ t('history.p6.start') }}
        <b v-pinball-mech="bumperOptions">{{ t('history.p6.compatibility') }}</b>

        <b v-pinball-mech="bumperOptions">{{ t('history.p6.maintenance') }}</b>
        {{ t('history.p6.middle') }}
        <ins v-pinball-mech="'spinner'">Windows Vista</ins>
        {{ t('history.p6.end') }}
      </span>
    </div>

    <div
      v-pinball-mech
      class="wall hidden w-4 rounded-full md:block"
    />

    <div class="fixed left-0 z-[9999] w-screen flex translate-y-1/2 justify-around gap-6 opacity-60 -bottom-1">
      <div
        v-for="i in 35"
        :key="i"
        v-pinball-mech="bumperOptions"
        class="aspect-square w-6 shrink-0 rounded-full bg-orange-300"
      />
    </div>

    <util-pinball />
  </div>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import UtilPinball from '../util-pinball.vue'
import { vPinballMech } from '../v-pinball-mech'

const { t } = useI18n()

const bumperOptions = {
  type: 'bumper',
  radius: 999,
} as const
</script>

<style lang="sass" scoped>
.text
  b
    background: light-dark(#ffe685, #615630)
    padding: 0 0.2em
    white-space: nowrap
  ins
    white-space: nowrap

.wall
  background: light-dark(#F0F0F0, #3f3f46)
</style>

原理

使用 Matter.js 進行 2D 物理模擬,並使用 Vue Directive 將 DOM 元素轉換成物理物件。

原始碼

API

Props

interface Props {
  /** 重力加速度
   *
   * x, y 為加速度的方向,scale 為加速度的大小
   */
  gravity?: Matter.Gravity;
  ballRadius?: number;
}

v0.57.0