Skip to content

Minecraft Block Wrapper wrapper

Hey, ever played Minecraft?

Just between us, Codfish here is an old-timer, even published a map on Bahamut back in the day. (´,,•ω•,,)

Not long ago, Google dropped a Minecraft 15th Anniversary Easter egg.

Minecraft 15th Anniversary Easter Egg

Haven't seen it? Check it out quick! ˋ( ° ▽、° )

I was so touched, I decided to make my own version! Though, my tech skills weren't quite there, so it took ages to whip up... (›´ω`‹ )

Let's turn web elements into Minecraft blocks together and dig, dig, dig away on our little webpage! ᕕ( ゚ ∀。)ᕗ

Turn up the volume! 🔊

Makes digging blocks feel even better! ◝(≧∀≦)◟

Examples

Basic Usage

Hold down the mouse button to start digging an element. Keep holding, and after a bit, you'll dig it away.

Double-click the hole to put the element back. ( ´ ▽ ` )ノ

Actually, I am a block (´,,•ω•,,)
View Example Source Code
vue
<template>
  <div class="w-full flex flex-col items-center gap-14 border border-gray-300 p-6">
    <wrapper-minecraft-block class="w-1/2">
      <div class="select-none border py-20 text-center">
        {{ t('我是方塊') }}
      </div>
    </wrapper-minecraft-block>

    <!-- 必須放置一個 world 元件 -->
    <wrapper-minecraft-world />
  </div>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import WrapperMinecraftBlock from '../wrapper-minecraft-block.vue'
import WrapperMinecraftWorld from '../wrapper-minecraft-world.vue'

const { t } = useI18n()
</script>

More Blocks

You can specify different block types too! ( ´ ▽ ` )ノ

View Example Source Code
vue
<template>
  <div class="w-full flex flex-wrap justify-center gap-4 p-6">
    <div class="flex flex-wrap justify-center gap-4">
      <wrapper-minecraft-block>
        <img
          src="/low/profile.webp"
          width="200"
          height="200"
          class="pointer-events-none select-none border rounded"
        >
      </wrapper-minecraft-block>

      <wrapper-minecraft-block block-type="sand">
        <img
          src="/low/profile-2.webp"
          width="200"
          height="200"
          class="pointer-events-none select-none border rounded"
        >
      </wrapper-minecraft-block>
    </div>

    <wrapper-minecraft-block block-type="stone">
      <img
        src="/low/painting-codfish-bakery.webp"
        width="420"
        height="260"
        class="pointer-events-none select-none border rounded"
      >
    </wrapper-minecraft-block>

    <!-- 必須放置一個 world 元件 -->
    <wrapper-minecraft-world />
  </div>
</template>

<script setup lang="ts">
import WrapperMinecraftBlock from '../wrapper-minecraft-block.vue'
import WrapperMinecraftWorld from '../wrapper-minecraft-world.vue'
</script>

How It Works

It's mainly composed of two components: World and Block.

  • World provides the 3D scene.

  • Block handles the interactions.

Here's the concept:

We use babylon.js to create a 3D scene covering the entire webpage. Then, we use CSG (Constructive Solid Geometry) to cut meshes, creating a "hole" effect, and initialize the particle systems needed for each block.

The Block component manages interactions, sounds, crack animations, and state, notifying the World of various events via an EventBus.

Source Code

API

Props

interface Props {
  /** 方塊種類。初始化後不可變更 */
  blockType?: BlockType;
  /** 初始化是否為挖掉的狀態 */
  isInitDug?: boolean;
}

Emits

const emit = defineEmits<{
  digging: [];
  dug: [];
  place: [];
}>()

Slots

defineSlots<{
  default?: () => unknown;
}>()

v0.38.7