彈珠檯 util
網頁變成彈珠台,一起打彈珠吧 ( ´ ▽ ` )ノ°
技術關鍵字
| 名稱 | 描述 |
|---|---|
| Matter-js | 2D 物理引擎 |
| 物理模擬 | 模擬真實世界物理現象,如重力、碰撞、速度等物理效果 |
| 向量計算 | 處理方向、加速度、速度等等數學運算 |
| 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;
}