浏览代码

feat: 船只游戏

chenlei 1 年之前
父节点
当前提交
b394b88539

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
     "viewerjs": "^1.11.6",
     "vue": "^3.2.13",
     "vue-router": "^4.0.3",
+    "vue3-smooth-dnd": "^0.0.6",
     "vuex": "^4.0.0"
   },
   "devDependencies": {

二进制
src/assets/images/ship-game/Frame-min.png


二进制
src/assets/images/ship-game/Group 493-min.png


二进制
src/assets/images/ship-game/bg-boat-min.png


二进制
src/assets/images/ship-game/bg_-min.png


二进制
src/assets/images/ship-game/chuanxiang-min.png


二进制
src/assets/images/ship-game/di-min.png


二进制
src/assets/images/ship-game/duo-min.png


二进制
src/assets/images/ship-game/gan-min.png


二进制
src/assets/images/ship-game/highlight_Bilge-min.png


二进制
src/assets/images/ship-game/highlight_Cabin-min.png


二进制
src/assets/images/ship-game/highlight_Deck-min.png


二进制
src/assets/images/ship-game/highlight_Mast-min.png


二进制
src/assets/images/ship-game/highlight_hoods-min.png


二进制
src/assets/images/ship-game/highlight_ship-min.png


二进制
src/assets/images/ship-game/icon_cancel-min.png


二进制
src/assets/images/ship-game/jiaban-min.png


二进制
src/assets/images/ship-game/peng-min.png


二进制
src/assets/videos/scene-1-introduction.mp4


二进制
src/assets/videos/scene-2-introduction.mp4


二进制
src/assets/videos/scene-3-introduction.mp4


+ 6 - 0
src/router/index.js

@@ -4,6 +4,7 @@ import PanoView from "@/views/PanoView.vue"
 import RelicList from "@/views/RelicList.vue"
 import RelicDetail from "@/views/RelicDetail.vue"
 import EpilogueView from "@/views/EpilogueView.vue"
+import ShipGameView from "@/views/ShipGame/ShipGameView.vue"
 // import store from '@/store/index.js'
 
 const routes = [
@@ -32,6 +33,11 @@ const routes = [
     name: 'EpilogueView',
     component: EpilogueView,
   },
+  {
+    path: '/ship-game',
+    name: 'ShipGame',
+    component: ShipGameView,
+  },
 ]
 
 const router = createRouter({

+ 261 - 0
src/views/ShipGame/ShipGameView.vue

@@ -0,0 +1,261 @@
+<template>
+  <div class="ship-game">
+    <div
+      v-if="showBanner"
+      class="ship-game-banner"
+    >
+      <img
+        class="logo"
+        src="@/assets/images/ship-game/Group 493-min.png"
+      >
+
+      <p>
+        选择船只,出现此船只轮廓图和船只构件,选择构件拖拽至线稿船对应区域填充,搭建完整船只
+      </p>
+
+      <button @click="showBanner = false">
+        开始
+      </button>
+    </div>
+
+    <img
+      class="logo2"
+      src="@/assets/images/ship-game/Group 493-min.png"
+    >
+    <p class="tips">
+      长按下方部件并拖动到正确位置,完成船只拼图
+    </p>
+
+    <div class="ship-game-container">
+      <template
+        v-for="item in MODULE_LIST"
+        :key="item.key"
+      >
+        <Container
+          v-if="curDragKey === item.key || checkedModule.includes(item.key)"
+          class="img"
+          group-name="default"
+          :should-animate-drop="() => false"
+          :style="`${item.hightImgStyle} background: url(${checkedModule.includes(item.key) ? item.img : item.hightImg}) no-repeat center / cover`"
+          @drop="res => {
+            checkedModule.push(res.payload.key)
+          }"
+        >
+          <div />
+        </Container>
+      </template>
+    </div>
+
+    <Container
+      behaviour="copy"
+      drag-class="drag-class"
+      class="ship-game-footer drag"
+      group-name="default"
+      :get-child-payload="(x) => MODULE_LIST[x]"
+      @drag-end="() => {
+        curDragKey = ''
+      }"
+    >
+      <Draggable
+        v-for="item in MODULE_LIST"
+        :key="item.key"
+        class="ship-game-footer__item"
+        @mousedown="() => {
+          curDragKey = item.key
+        }"
+      >
+        <img
+          draggable="false"
+          :src="item.img"
+          :style="{width: item.imgWidth}"
+        >
+      </Draggable>
+    </Container>
+
+    <div class="ship-game-footer">
+      <div
+        v-for="item in MODULE_LIST"
+        :key="item.key"
+        :class="['ship-game-footer__item', checkedModule.includes(item.key) && 'checked']"
+      >
+        <span>{{ item.label }}</span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { Container, Draggable } from "vue3-smooth-dnd"
+
+const showBanner = ref(false)
+const MODULE_LIST = [
+  {
+    label: '甲板',
+    img: require('@/assets/images/ship-game/jiaban-min.png'),
+    imgWidth: '252px',
+    hightImg: require('@/assets/images/ship-game//highlight_Deck-min.png'),
+    hightImgStyle: 'right: 18px; bottom: 46px; width: 985px; height: 88px;',
+    key: 'jiaban'
+  },
+  {
+    label: '船底',
+    img: require('@/assets/images/ship-game/di-min.png'),
+    imgWidth: '261px',
+    hightImg: require('@/assets/images/ship-game/highlight_Bilge-min.png'),
+    hightImgStyle: 'right: 43px; bottom: 1px; width: 950px; height: 88px;',
+    key: 'chuandi'
+  },
+  {
+    label: '船舱',
+    img: require('@/assets/images/ship-game/chuanxiang-min.png'),
+    imgWidth: '166px',
+    hightImg: require('@/assets/images/ship-game/highlight_Cabin-min.png'),
+    hightImgStyle: 'left: 322px; bottom: 70px; z-index: 2; width: 223px; height: 155px;',
+    key: 'chuancang'
+  },
+  {
+    label: '船舵',
+    img: require('@/assets/images/ship-game/duo-min.png'),
+    imgWidth: '203px',
+    hightImg: require('@/assets/images/ship-game/highlight_hoods-min.png'),
+    hightImgStyle: 'left: 22px; bottom: 53px; z-index: 2; width: 272px; height: 107px;',
+    key: 'chuanduo'
+  },
+  {
+    label: '船篷',
+    img: require('@/assets/images/ship-game/peng-min.png'),
+    imgWidth: '104px',
+    hightImg: require('@/assets/images/ship-game/highlight_ship-min.png'),
+    hightImgStyle: 'left: 198px; bottom: 81px; z-index: 2; width: 158px; height: 146px;',
+    key: 'chuanpeng'
+  },
+  {
+    label: '桅杆',
+    img: require('@/assets/images/ship-game/gan-min.png'),
+    imgWidth: '206px',
+    hightImg: require('@/assets/images/ship-game/highlight_Mast-min.png'),
+    hightImgStyle: 'left: 200px; top: 0; z-index: 2; width: 806px; height: 509px;',
+    key: 'weigan'
+  }
+]
+const curDragKey = ref('')
+const checkedModule = ref([])
+</script>
+
+<style lang="less" scoped>
+.drag-class {
+  width: auto !important;
+}
+
+.ship-game {
+  height: 100vh;
+  background: #F3EAE3;
+
+  &-container {
+    position: absolute;
+    top: 40px;
+    left: 50%;
+    width: 1144px;
+    height: 611px;
+    transform: translateX(-50%);
+    background: url('@/assets/images/ship-game/bg-boat-min.png') no-repeat center / cover;
+
+    .img {
+      position: absolute;
+      transition: all linear .2s;
+    }
+  }
+  .logo2 {
+    position: absolute;
+    top: 76px;
+    left: 62px;
+    width: 460px;
+  }
+  .tips {
+    position: absolute;
+    top: 212px;
+    left: 94px;
+    width: 300px;
+    font-size: 22px;
+    color: #2E5A89;
+    line-height: 37px;
+  }
+  &-footer {
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    display: flex;
+    gap: 18px;
+    padding: 18px;
+    background: #AEAEAE;
+    z-index: 1;
+
+    &.drag {
+      background: transparent;
+      z-index: 2;
+
+      .ship-game-footer__item {
+        background: transparent;
+      }
+    }
+    &__item {
+      flex: 1;
+      display: flex !important;
+      align-items: center;
+      justify-content: center;
+      position: relative;
+      padding: 19px;
+      height: 182px;
+      border-radius: 10px;
+      box-sizing: border-box;
+      background: #524B4B;
+
+      img {
+        width: 100%;
+        cursor: pointer;
+      }
+      span {
+        position: absolute;
+        left: 21px;
+        bottom: 9px;
+        color: white;
+        font-size: 22px;
+      }
+    }
+  }
+  &-banner {
+    position: absolute;
+    top: 0;
+    left: 0;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    width: 100vw;
+    height: 100vh;
+    background: url("@/assets/images/ship-game/bg_-min.png") no-repeat center /
+      cover;
+    z-index: 2;
+
+    p {
+      padding: 20px 0 120px;
+      width: 714px;
+      font-size: 22px;
+      color: #2e5a89;
+      line-height: 37px;
+      text-align: center;
+    }
+    button {
+      width: 90px;
+      height: 40px;
+      line-height: 40px;
+      border-radius: 5px;
+      color: #f3eae3;
+      font-size: 26px;
+      background: #2e5a89;
+    }
+  }
+}
+</style>

+ 12 - 0
yarn.lock

@@ -5797,6 +5797,11 @@ slice-ansi@^4.0.0:
     astral-regex "^2.0.0"
     is-fullwidth-code-point "^3.0.0"
 
+smooth-dnd@^0.12.1:
+  version "0.12.1"
+  resolved "https://registry.npmmirror.com/smooth-dnd/-/smooth-dnd-0.12.1.tgz#cdb44c972355659e32770368b29b6a80e0ed96f1"
+  integrity sha512-Dndj/MOG7VP83mvzfGCLGzV2HuK1lWachMtWl/Iuk6zV7noDycIBnflwaPuDzoaapEl3Pc4+ybJArkkx9sxPZg==
+
 sockjs@^0.3.24:
   version "0.3.24"
   resolved "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz"
@@ -6317,6 +6322,13 @@ vue-template-es2015-compiler@^1.9.0:
   resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz"
   integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
 
+vue3-smooth-dnd@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.npmmirror.com/vue3-smooth-dnd/-/vue3-smooth-dnd-0.0.6.tgz#7a41f8625345aa0a6cc167d3cbf8c29baf276b4d"
+  integrity sha512-CH9ZZhEfE7qU1ef2rlfgBG+nZtQX8PnWlspB2HDDz1uVGU7fXM0Pr65DftBMz4X81S+edw2H+ZFG6Dyb5J81KA==
+  dependencies:
+    smooth-dnd "^0.12.1"
+
 vue@^3.2.13:
   version "3.3.8"
   resolved "https://registry.npmmirror.com/vue/-/vue-3.3.8.tgz"