张延森 3 年之前
父節點
當前提交
6cd92d0ae7

+ 14
- 5
src/components/BackPage.vue 查看文件

@@ -4,18 +4,24 @@
4 4
     <!-- :style="HomeStyle" -->
5 5
     <div class="index-image">
6 6
       <img :src="backHome" class="bg-image" />
7
+      <CloudVue />
7 8
       <slot></slot>
8
-      <div class="GrassGIFBox">
9
+      <!-- <div class="GrassGIFBox">
9 10
         <GrassGIF />
10
-      </div>
11
+      </div> -->
11 12
     </div>
12 13
   </div>
13 14
 </template>
14 15
 
15 16
 <script >
16
-import backHome from '../assets/BackImage/backHome.jpg'
17
+import backHome from '@/assets/BackImage/backHome.jpg'
18
+import CloudVue from '@/components/Cloud.vue'
19
+
17 20
 export default {
18 21
   name: 'BackPage',
22
+  components: {
23
+    CloudVue,
24
+  },
19 25
   setup() {
20 26
     return {
21 27
       backHome
@@ -32,10 +38,13 @@ export default {
32 38
   .bg-image {
33 39
     width: 100vw;
34 40
   }
41
+}
42
+</style>
43
+
44
+<style lang="less">
35 45
   .GrassGIFBox {
36 46
     position: absolute;
37 47
     bottom: 0vh;
38 48
     z-index: 0;
39 49
   }
40
-}
41
-</style>
50
+</style>

+ 37
- 0
src/components/Cloud.vue 查看文件

@@ -0,0 +1,37 @@
1
+<template>
2
+  <div class="motion-cloud">
3
+    <img :src="cloudImage" alt="">
4
+  </div>
5
+</template>
6
+
7
+<script setup>
8
+import cloudImage from '@/assets/BackImage/cloud.png'
9
+import { onMounted } from 'vue';
10
+
11
+onMounted(() => {
12
+  console.log('---------onMounted-----')
13
+})
14
+</script>
15
+
16
+<style lang="less" scoped>
17
+.motion-cloud {
18
+  width: 160px;
19
+  animation: fadefloat 120s linear infinite;
20
+  animation-fill-mode: forwards;
21
+  
22
+
23
+  & > img {
24
+    width: 100%;
25
+  }
26
+
27
+  @keyframes fadefloat {
28
+    0%, 100% { opacity: 0; }
29
+    5%, 90% { opacity: 1; }
30
+  }
31
+
32
+  @keyframes flyfloat {
33
+    from { transform: translateX(100%) translateZ(0); }
34
+    to { transform: translateX(-15%) translateZ(0); }
35
+  }
36
+}
37
+</style>

+ 20
- 0
src/components/RightGrass.vue 查看文件

@@ -0,0 +1,20 @@
1
+<template>
2
+  <div class="left-grass">
3
+    
4
+  </div>
5
+</template>
6
+
7
+<script setup>
8
+
9
+</script>
10
+
11
+<style lang="less" scoped>
12
+.left-grass {
13
+  width: 25vw;
14
+  height: 28vw;
15
+  position: absolute;
16
+  right: 0;
17
+  bottom: 0;
18
+  overflow: hidden;
19
+}
20
+</style>

+ 11
- 0
src/pages/game/algorithm/background.js 查看文件

@@ -0,0 +1,11 @@
1
+import { designWidth, designHeight, scale } from './design';
2
+import backImage from '@/assets/BackImage/framebg.jpg'
3
+
4
+export function drawBg ({ two, center }) {
5
+  const bgTexture = two.makeTexture(backImage);
6
+
7
+  const bgBox = two.makeRectangle(center.x, center.y, designWidth, designHeight);
8
+  bgBox.noStroke();
9
+  bgBox.fill = bgTexture;
10
+  bgBox.scale = scale;
11
+}

+ 80
- 0
src/pages/game/algorithm/bullet.js 查看文件

@@ -0,0 +1,80 @@
1
+import Two from "two.js";
2
+import { scale, desginCageRadius, pedestalOffsetX, pedestalOffsetY, cageNum } from './design'
3
+import bulletImage from '@/assets/RoundaboutImage/2-13.png';
4
+
5
+// 子弹的核心逻辑
6
+export default ({two, center, speed}) => {
7
+  const _event = new Two.Events()
8
+
9
+  // 子弹个数 = 轿厢个数
10
+  const num = cageNum;
11
+  // 子弹宽度 = 轿厢宽度
12
+  const bulletRadius = desginCageRadius;
13
+
14
+  // 子弹其实位置与底座是一致的
15
+  const x = center.x + pedestalOffsetX * scale;
16
+  const y = center.y + pedestalOffsetY * scale;
17
+
18
+  // 弹夹
19
+  let clip = [];
20
+  // 在膛子弹
21
+  let current = null;
22
+  
23
+  // 绘制子弹
24
+  function drawBullets () {
25
+    const bulletTexture = two.makeTexture(bulletImage);
26
+  
27
+    const list = Array(num).fill().map((_, inx) => {
28
+      const arc = two.makeCircle(x, y, bulletRadius)
29
+      arc.id = `bullet-${inx}`
30
+      // arc.fill = 'black'
31
+      arc.fill = bulletTexture
32
+      arc.noStroke()
33
+      arc.scale = scale;
34
+      arc.visible = false; // 默认不显示, 即不上膛
35
+  
36
+      return arc
37
+    })
38
+
39
+    return list;
40
+  }
41
+
42
+  // 子弹上膛
43
+  function bulletLoad() {
44
+    current = clip.shift()
45
+    if (current) {
46
+      current.visible = true
47
+    }
48
+  }
49
+  
50
+  // 子弹飞行
51
+  function fly() {
52
+    if (!current) return;
53
+    const { top, height } = current.getBoundingClientRect()
54
+    current.position = new Two.Vector(current.position.x, current.position.y + speed)
55
+
56
+    // 子弹飞行事件
57
+    _event.dispatchEvent('shooting', { 
58
+      bullet: current,
59
+      cancel: () => {
60
+        two.removeEventListener('update', fly);
61
+        _event.dispatchEvent('afterShoot');
62
+      },
63
+     })
64
+  }
65
+
66
+  // 射击
67
+  function shoot() {
68
+    _event.dispatchEvent('beforeShoot')
69
+    two.addEventListener('update', fly)
70
+  }
71
+
72
+  // 弹夹
73
+  clip = drawBullets()
74
+  
75
+  return {
76
+    on: _event.on.bind(_event),
77
+    bulletLoad,
78
+    shoot,
79
+  }
80
+}

+ 100
- 0
src/pages/game/algorithm/cage.js 查看文件

@@ -0,0 +1,100 @@
1
+// 辅助逻辑的颜色,
2
+const colorList = ['#f5222d', '#d4380d', '#d46b08', '#d48806', '#d4b106', '#7cb305', '#389e0d', '#08979c', '#096dd9', '#531dab']
3
+import { desginRadius, desginCageRadius, cageNum, scale, primaryColor } from './design';
4
+
5
+// 绘制目标轿厢
6
+export function drawTargeCages({ two, center }) {
7
+  // 摩天轮半径
8
+  const wheelRaduis = desginRadius * scale;
9
+  const perAngle = Math.PI / cageNum // 2 * Math.PI / ( cageNum * 2 ) 分成 轿厢 * 2 的分数, 最终效果是每隔一个空白,一个轿厢
10
+  const offsetAngle = perAngle / 2;
11
+  // 轿厢半径
12
+  const cageRadius = desginCageRadius * scale;
13
+  
14
+  // 绘制
15
+  const list = Array(cageNum).fill().map((_, inx) => {
16
+    const startAngle = 2 * inx * perAngle - offsetAngle; // 实际效果图是圆形有固定大小的, 不能直接从 0° 开始, 需要从 0 - offset 开始
17
+    // const endAngle = startAngle + perAngle
18
+
19
+    // 1、计算扇形边上的中心坐标
20
+    const cx = center.x + Math.cos(startAngle + perAngle / 2) * wheelRaduis
21
+    const cy = center.y + Math.sin(startAngle + perAngle / 2) * wheelRaduis
22
+
23
+    // 2、轿厢
24
+    const rect = two.makeCircle(cx, cy, cageRadius);
25
+    rect.id = `mnt-${inx}`
26
+    // rect.fill = colorList[inx] // 取消这个注释, 有助于梳理逻辑
27
+    rect.noFill()
28
+    rect.stroke = primaryColor
29
+    rect.linewidth = 2
30
+    rect.dashes = [4]
31
+    rect.__$angle = startAngle;  // 轿厢的初始弧度
32
+    rect.__$mnt = null; // 当前实体轿厢 也就是已经被击中的轿厢
33
+
34
+    return rect
35
+  })
36
+
37
+  // 是否击中
38
+  const checkHit = (bullet) => {
39
+    // next 是否继续下一轮验证
40
+    // error 是否发生了错误
41
+    let res = { next: true, error: false }
42
+
43
+    // 可接受校验偏差范围
44
+    const offset = cageRadius / 3;
45
+    
46
+    const rect2 = bullet.getBoundingClientRect();
47
+    const x = rect2.left + rect2.width / 2
48
+    const y = rect2.top + rect2.height / 2
49
+
50
+    // 如果子弹 y 坐标超过警戒线
51
+    if (y < (center.y + wheelRaduis + offset)) {
52
+      res.next = false;
53
+      res.error = true;
54
+      return res;
55
+    }
56
+
57
+    // 遍历所有目标轿厢, 看看是否在轿厢的一定范围内
58
+    const cage = list.filter((it) => {
59
+      const rect = it.getBoundingClientRect();
60
+
61
+      const left = rect.left + offset
62
+      const right = rect.right - offset
63
+      const top = rect.top + offset
64
+      const bottom = rect.bottom - offset
65
+
66
+      // 如果当前子弹的中心点位于目标轿厢矩形范围内
67
+      // 则代表击中
68
+      return x >= left && x <= right &&
69
+        y >= top && y <= bottom;
70
+    })[0]
71
+
72
+    // 未找到对应的目标轿厢
73
+    if (!cage) {
74
+      res.next = true;
75
+      res.error = false;
76
+      return res;
77
+    };
78
+    
79
+    // 如果目标轿厢已经挂载了一个
80
+    if (cage.__$mnt) {
81
+      res.next = false;
82
+      res.error = true;
83
+      return res;
84
+    }
85
+
86
+    // 否则挂载到当前轿厢
87
+    cage.__$mnt = bullet;
88
+    bullet.position = cage.position;
89
+
90
+    res.next = false;
91
+    res.error = false;
92
+    return res;
93
+  }
94
+
95
+  return {
96
+    list,
97
+    cageRadius,
98
+    checkHit,
99
+  }
100
+}

+ 21
- 0
src/pages/game/algorithm/counter.js 查看文件

@@ -0,0 +1,21 @@
1
+import { designCounterWidth, designCounterHeight, counterOffsetX, counterOffsetY, cageNum, scale, primaryColor } from './design'
2
+import countImage from '@/assets/RoundaboutImage/计数.png'
3
+
4
+// 剩余子弹计数器
5
+export function drawCounter({ two, center }) {
6
+  // 子弹个数 = 轿厢个数
7
+  const num = cageNum;
8
+
9
+  const x = center.x + counterOffsetX * scale;
10
+  const y = center.y + counterOffsetY * scale;
11
+
12
+  const counterTexture = two.makeTexture(countImage);
13
+  const counterBox = two.makeRectangle(x, y, designCounterWidth, designCounterHeight);
14
+  counterBox.noStroke();
15
+  counterBox.fill = counterTexture;
16
+  counterBox.scale = scale;
17
+  // 初始值是弹夹中子弹数量
18
+  const counter = two.makeText(num, x, y, { fill: primaryColor, weight: 700 })
19
+
20
+  return counter
21
+}

+ 27
- 0
src/pages/game/algorithm/design.js 查看文件

@@ -0,0 +1,27 @@
1
+// 圆心特指大转盘的圆心
2
+export const designWidth = 640; // 设计稿宽度
3
+export const designHeight = 1234;
4
+
5
+export const desginRadius = 247.5; // 设计稿轮盘半径
6
+
7
+export const desginLightRadius = 289; // 设计稿光效半径
8
+
9
+export const cageNum = 8; // 目标轿厢个数
10
+export const desginCageRadius = 51; // 设计稿轿厢半径
11
+
12
+export const designCounterWidth = 160;  // 设计稿子弹计数器半径
13
+export const designCounterHeight = 49;
14
+export const counterOffsetX = 224; // 距离圆心的横向距离
15
+export const counterOffsetY = 424; // 距离圆心的横向距离
16
+
17
+export const designPedestalWidth = 224; // 设计稿底座宽度
18
+export const designPedestalHeight = 153; // 设计稿底座宽度
19
+export const pedestalOffsetX = 0; // 距离圆心的横向距离
20
+export const pedestalOffsetY = 424; // 距离圆心的横向距离
21
+
22
+
23
+
24
+// 缩放比
25
+export const scale = window.screen.width / designWidth;
26
+// 设计稿主题色
27
+export const primaryColor = '#F19805';

+ 37
- 0
src/pages/game/algorithm/effect.js 查看文件

@@ -0,0 +1,37 @@
1
+import { desginLightRadius, scale } from './design'
2
+import lightImage from '@/assets/RoundaboutImage/round.png'
3
+
4
+// 绘制光圈
5
+export function drawLight({ two, center }) {
6
+  const lightArc = two.makeCircle(center.x, center.y, desginLightRadius);
7
+  const lightTexture = two.makeTexture(lightImage);
8
+  lightArc.noStroke();
9
+  lightArc.fill = lightTexture;
10
+  lightArc.opacity = 0; // 默认不显示
11
+  lightArc.scale = scale;
12
+  
13
+  // 成功之后的特效
14
+  let shakeTimes = 0;
15
+  const shake = () => {
16
+    if (shakeTimes >= 10) {
17
+      return
18
+    }
19
+
20
+    const opStep = shakeTimes % 2 === 1 ? -0.04 : 0.04
21
+    lightArc.opacity += opStep;
22
+    if (lightArc.opacity >= 1 || lightArc.opacity <= 0) {
23
+      shakeTimes += 1;
24
+    }
25
+  }
26
+
27
+  return {
28
+    start: () => {
29
+      two.addEventListener('update', shake);
30
+    },
31
+    stop: () => {
32
+      two.removeEventListener('update', shake);
33
+      shakeTimes = 0;
34
+      lightArc.opacity = 0;
35
+    }
36
+  }
37
+}

+ 124
- 0
src/pages/game/algorithm/index.js 查看文件

@@ -0,0 +1,124 @@
1
+import Two from "two.js";
2
+import { cageNum } from './design';
3
+import { drawBg } from './background';
4
+import { drawLight } from './effect';
5
+import { drawWheel } from './wheel';
6
+import { drawTargeCages } from './cage';
7
+import { drawPedestal } from './pedestal';
8
+import drawBullets from './bullet';
9
+import { drawCounter } from './counter';
10
+
11
+export default ({ el, center, rotateSpeed = 0.015, speed = -5 }) => {
12
+    
13
+  // 修复一个单页面应用, 不能重复加载图片的bug
14
+  Two.Texture.ImageRegistry = new Two.Registry();
15
+
16
+  // 初始化
17
+  const two = new Two({
18
+    type: Two.Types.svg,
19
+    fullscreen: true,
20
+  }).appendTo(el);
21
+
22
+  // 事件发射器
23
+  const _evt = new Two.Events();
24
+
25
+  // 绘制背景
26
+  drawBg({ two, center });
27
+
28
+  // 绘制胜利光效
29
+  const light = drawLight({ two, center });
30
+  
31
+  // 目标轿厢
32
+  const cages = drawTargeCages({ two, center })
33
+
34
+  // 绘制摩天轮
35
+  const wheel = drawWheel({ two, center, rotateSpeed, cages: cages.list });
36
+  
37
+  // 绘制底座
38
+  const pedestal = drawPedestal({ two, center })
39
+
40
+  // 绘制子弹计数器, 224 是设计稿上底座与计数器之间距离
41
+  const counter = drawCounter({ two, center })
42
+
43
+  // 绘制子弹
44
+  const clip = drawBullets({two, center, speed })
45
+
46
+  // 整体绘制结束  
47
+  two.update();
48
+
49
+  // 下面是业务逻辑部分
50
+
51
+  // 游戏结束
52
+  function gameOver(isSuccess) {
53
+    // 停止摩天轮旋转
54
+    wheel.stop();
55
+
56
+    const t = setTimeout(() => {
57
+      clearTimeout(t)      
58
+      _evt.dispatchEvent('gameOver', { isSuccess })
59
+    }, 0)
60
+  }
61
+
62
+  // 监测子弹射击
63
+  clip.on('beforeShoot', () => {
64
+    pedestal.play() // 绳子甩动效果
65
+  })
66
+  // 监测子弹停止射击
67
+  clip.on('afterShoot', () => {
68
+    pedestal.stop(); // 绳子停止甩动
69
+    clip.bulletLoad(); // 子弹上膛
70
+    counter.value -= 1; // 计数器 - 1
71
+  })
72
+  // 监测子弹停止射击
73
+  clip.on('shooting', ({bullet, cancel}) => {
74
+    const { next, error } = cages.checkHit(bullet);
75
+    if (next) return;
76
+
77
+    cancel(); // 子弹停止飞行
78
+
79
+    // 游戏失败
80
+    if (error) {
81
+      gameOver(false);
82
+      return;
83
+    }
84
+
85
+    // 击中轿厢
86
+    const isSuccess = !counter.value
87
+    if (isSuccess) {
88
+      light.start() // 启动灯光特效
89
+      gameOver(isSuccess)
90
+    } else {
91
+      const t = setTimeout(() => {
92
+        clearTimeout(t)
93
+        _evt.dispatchEvent('bingo', { isSuccess })
94
+      }, 0) 
95
+    }
96
+  })
97
+  
98
+  // 绑定 dom click 事件 触发子弹发射
99
+  function handleClick() {
100
+    clip.shoot();
101
+  }
102
+  el.addEventListener('click', handleClick);
103
+
104
+  return {
105
+    two,
106
+    raduis: wheel.raduis,
107
+    on: _evt.on.bind(_evt),
108
+    play: () => {
109
+      clip.bulletLoad() // 先上膛一颗子弹
110
+      wheel.rotate();
111
+      two.play();
112
+    },
113
+    pause: () => {
114
+      wheel.stop();
115
+      two.pause();
116
+    },
117
+    destroy: () => {
118
+      two.unbind('update');
119
+      two.pause();
120
+      el.removeChild(two.renderer.domElement);
121
+      el.removeEventListener('click', handleClick);
122
+    }
123
+  }
124
+}

+ 45
- 0
src/pages/game/algorithm/pedestal.js 查看文件

@@ -0,0 +1,45 @@
1
+import Two from "two.js";
2
+import { designPedestalWidth, designPedestalHeight, pedestalOffsetX, pedestalOffsetY, scale } from './design'
3
+import pedestalImage from '@/assets/RoundaboutImage/2-14.png'
4
+import ropeImage1 from '@/assets/RoundaboutImage/2-15.png'
5
+import ropeImage2 from '@/assets/RoundaboutImage/2-16.png'
6
+import ropeImage3 from '@/assets/RoundaboutImage/2-17.png'
7
+import ropeImage4 from '@/assets/RoundaboutImage/2-18.png'
8
+import ropeImage5 from '@/assets/RoundaboutImage/2-19.png'
9
+import ropeImage6 from '@/assets/RoundaboutImage/2-20.png'
10
+import ropeImage7 from '@/assets/RoundaboutImage/2-21.png'
11
+import ropeImage8 from '@/assets/RoundaboutImage/2-22.png'
12
+import ropeImage9 from '@/assets/RoundaboutImage/2-23.png'
13
+const ropeImageList = [
14
+  ropeImage1,
15
+  ropeImage2,
16
+  ropeImage3,
17
+  ropeImage4,
18
+  ropeImage5,
19
+  ropeImage6,
20
+  ropeImage7,
21
+  ropeImage8,
22
+  ropeImage9,
23
+];
24
+
25
+// 绘制底座
26
+export function drawPedestal ({ two, center }) {
27
+  const x = center.x + pedestalOffsetX * scale;
28
+  const y = center.y + pedestalOffsetY * scale;
29
+  //
30
+  const pedestalTexture = two.makeTexture(pedestalImage);
31
+  const pedestalBox = two.makeRectangle(x, y, designPedestalWidth, designPedestalHeight);
32
+  pedestalBox.noStroke();
33
+  pedestalBox.fill = pedestalTexture;
34
+  pedestalBox.scale = scale;
35
+
36
+  // 绘制底座上的绳子
37
+  const ropeSequence = two.makeImageSequence(ropeImageList, x, y, 40); // 40 是不断调式出来的频率, 需要跟 speed 匹配
38
+  ropeSequence.scale = new Two.Vector(scale, scale);
39
+
40
+  return {
41
+    position: pedestalBox.position,
42
+    play: () => ropeSequence.play(),
43
+    stop: () => ropeSequence.stop(),
44
+  };
45
+}

+ 40
- 0
src/pages/game/algorithm/wheel.js 查看文件

@@ -0,0 +1,40 @@
1
+import Two from "two.js";
2
+import { scale, desginRadius } from './design'
3
+import wheelImage from '@/assets/RoundaboutImage/2-09.png';
4
+
5
+// 绘制摩天轮
6
+export function drawWheel({ two, center, rotateSpeed, cages }) {
7
+  const wheelArc = two.makeCircle(center.x, center.y, desginRadius);
8
+  const wheelTexture = two.makeTexture(wheelImage);
9
+  wheelArc.noStroke();
10
+  wheelArc.fill = wheelTexture;
11
+  wheelArc.scale = scale;
12
+
13
+  // 实际半径
14
+  const raduis = desginRadius * scale;
15
+  // 每个轿厢在大轮盘所在圆的弧度
16
+  const perAngle = Math.PI / cages.length;
17
+  
18
+  // 摩天轮与轿厢旋转
19
+  let rotateAngle = 0;
20
+  const wheelRotate = () => {
21
+    rotateAngle += rotateSpeed
22
+    wheelArc.rotation = rotateAngle
23
+    cages.forEach(cage => {
24
+      const angle = cage.__$angle + rotateAngle + perAngle / 2  // 除以2是为了视觉上轿厢与摩天轮的轴对齐
25
+      const cx = center.x + Math.cos(angle) * raduis
26
+      const cy = center.y + Math.sin(angle) * raduis
27
+      cage.position = new Two.Vector(cx, cy)
28
+      // 如果有对应的挂载物
29
+      if (cage.__$mnt) {
30
+        cage.__$mnt.position = cage.position
31
+      }
32
+    })
33
+  }
34
+
35
+  return {
36
+    raduis,
37
+    rotate: () => two.addEventListener('update', wheelRotate),
38
+    stop: () => two.removeEventListener('update', wheelRotate),
39
+  }
40
+}

src/pages/game/game.js → src/pages/game/game.js.old 查看文件

@@ -352,8 +352,9 @@ export default function game ({ el, center, onError, onSuccess, onBingo }) {
352 352
 
353 353
   // 重复绘制内容
354 354
   two.bind('update', () => {
355
-    rotate()
356 355
     if (!isFinished) {
356
+      rotate()
357
+
357 358
       if (isShooting) {
358 359
         shooting()
359 360
       }
@@ -361,7 +362,7 @@ export default function game ({ el, center, onError, onSuccess, onBingo }) {
361 362
       successShake()
362 363
     }
363 364
   })
364
-
365
+  
365 366
   // 绑定 dom click 事件 触发子弹发射
366 367
   const handleClick = () => {
367 368
     if (!isFinished && !isShooting) {

+ 53
- 32
src/pages/game/index.vue 查看文件

@@ -1,20 +1,26 @@
1 1
 <template>
2
-  <div ref="el" />
3
-  <FireWorkListVue ref="firesRef" :center="center" :raduis="raduis" />
4
-  <MusicOnce ref="bingoRef" :src="bingoMusic" />
5
-  <MusicOnce ref="failRef" :src="failMusic" />
6
-  <MusicOnce ref="successRef" :src="successMusic" />
2
+  <div>
3
+    <div ref="el" />
4
+    <FireWorkListVue ref="firesRef" :center="center" :raduis="raduis" />
5
+    <MusicOnce ref="bingoRef" :src="bingoMusic" />
6
+    <MusicOnce ref="failRef" :src="failMusic" />
7
+    <MusicOnce ref="successRef" :src="successMusic" />
8
+    
9
+    <!-- <div class="GrassGIFBox">
10
+      <GrassGIF />
11
+    </div> -->
12
+  </div>
7 13
 </template>
8 14
 
9 15
 <script setup>
10 16
 import { onBeforeUnmount, onMounted, ref } from 'vue'
11 17
 import { useRouter } from 'vue-router'
12 18
 import FireWorkListVue from '@/components/FireWorkList.vue'
13
-import game from './game.js'
19
+import createGame from './algorithm'
14 20
 import { gameOver, gameStart } from '@/utils/api.js'
15 21
 
16 22
 const el = ref()
17
-const destroyRef = ref()
23
+const gameRef = ref()
18 24
 const firesRef = ref()
19 25
 const router = useRouter()
20 26
 const raduis = ref(150)
@@ -27,40 +33,55 @@ const bingoRef = ref()
27 33
 const failRef = ref()
28 34
 const successRef = ref()
29 35
 
36
+// 游戏失败
37
+const handleGameOverError = () => {
38
+  failRef.value.play()
39
+  const t = setTimeout(() => {
40
+    localStorage.setItem('loadSign', '1')
41
+    router.push('/OverPage?type=lose')
42
+    clearTimeout(t)
43
+  }, 1000)
44
+}
45
+
46
+// 游戏通关
47
+const handleGameSuccess = () => {
48
+  gameOver()
49
+  successRef.value.play()
50
+  firesRef.value.toggle()
51
+  // alert('你真牛逼')
52
+  const t = setTimeout(() => {
53
+    localStorage.setItem('loadSign', '1')
54
+    router.push('/OverPage?type=win')
55
+    clearTimeout(t)
56
+  }, 2000)
57
+}
58
+
30 59
 const center = {
31 60
   x: document.body.offsetWidth / 2,
32 61
   y: document.body.offsetHeight / 2
33 62
 }
34 63
 
35 64
 const gameInit = () => {
36
-  destroyRef.value = game({
65
+  const game = createGame({
37 66
     el: el.value,
38 67
     center,
39
-    onError: () => {
40
-      failRef.value.play()
41
-      const t = setTimeout(() => {
42
-        localStorage.setItem('loadSign', '1')
43
-        router.push('/OverPage?type=lose')
44
-        clearTimeout(t)
45
-      }, 1000)
46
-    },
47
-    onSuccess: () => {
48
-      gameOver()
49
-      successRef.value.play()
50
-      firesRef.value.toggle()
51
-      // alert('你真牛逼')
52
-      const t = setTimeout(() => {
53
-        localStorage.setItem('loadSign', '1')
54
-        router.push('/OverPage?type=win')
55
-        clearTimeout(t)
56
-      }, 2000)
57
-    },
58
-    onBingo: () => {
59
-      bingoRef.value.play()
68
+  })
69
+
70
+  game.on('bingo', () => {
71
+    bingoRef.value.play()
72
+  })
73
+  game.on('gameOver', ({ isSuccess }) => {
74
+    if (isSuccess) {
75
+      handleGameSuccess()
76
+    } else {
77
+      handleGameOverError()
60 78
     }
61 79
   })
62 80
 
63
-  raduis.value = destroyRef.value.raduis
81
+  game.play()
82
+
83
+  gameRef.value = game;
84
+  raduis.value = game.raduis
64 85
 }
65 86
 
66 87
 onMounted(() => {
@@ -69,8 +90,8 @@ onMounted(() => {
69 90
 })
70 91
 
71 92
 onBeforeUnmount(() => {
72
-  if (destroyRef.value) {
73
-    destroyRef.value.destroy()
93
+  if (gameRef.value) {
94
+    gameRef.value.destroy()
74 95
   }
75 96
 })
76 97
 </script>

+ 2
- 5
src/utils/initial.js 查看文件

@@ -32,7 +32,7 @@ function initSDK (url) {
32 32
  * 分享
33 33
  * @param {*} opt
34 34
  */
35
-export function share (opt) {
35
+export function share (opt = {}) {
36 36
   const { origin, pathname } = window.location
37 37
   // const defaultLink = origin + pathname
38 38
   const defaultImg = `${origin}${pathname}img/share.jpg`
@@ -67,10 +67,7 @@ export function Login () {
67 67
     window.localStorage.setItem("token", e.token);//保存数据
68 68
 
69 69
     try {
70
-      share({
71
-        title: '为岸线圆梦,摩天轮圆满大作战!',
72
-        desc: '快来助力华侨城欢乐滨江摩天轮挂轿厢'
73
-      })
70
+      share()
74 71
     } catch (error) {
75 72
       console.error(error)
76 73
     }