Teach you step by step to develop a brick-breaking game with vue3

Teach you step by step to develop a brick-breaking game with vue3

Preface

I wrote a few examples using vue3, and I feel that the composition API of Vue3 is well designed. I changed my habits a bit, but it would be nice to write two more. This time I am writing about a game that I found very fun in my childhood - Breakout. It is fun to play when I am bored and the playability is quite high. This time I tried to use vite+vue3 packaging directly. Vite is also ready to use out of the box. Its feature is that it can also clear dead code and package on demand, so the packaging speed is also very fast. Students who have not used it can try it.

Game Effects

Game Requirements

  1. Create a scene
  2. Create a ball and a bunch of hit blocks
  3. Create a movable block that can be controlled to move left and right
  4. When the ball hits the left and right upper boundaries and the moving block, it bounces back
  5. The game ends when the ball hits the lower boundary

Full code

<template>

    <button @click="stop">Stop</button>
    <button @click="start">Game start</button>
    <div style="color: red; text-align: center;font-size: 25px">score:{{scroce}}</div>

    <div class="box" :style="{width :boxWidth +'px', height:boxHeight +'px'}">
        <div class="str">{{str}}</div>
        <div class="kuaiBox">
            <div class="kuai" v-for="(item,index) in arr" :key="index" :style="{opacity :item.active ? '0':'1'}"></div>
        </div>
        <div class="ball" :style="{left :x + 'px', top : y + 'px', width : ball +'px', height: ball+'px'}"></div>
        <div class="bottomMove"
             :style="{left :mx + 'px' , top : my + 'px',width :moveBottomW +'px',height : moveBottomH+'px' }"></div>
    </div>
</template>

<script setup>
    import {onMounted, onUnmounted, reactive, toRefs} from 'vue'

    const boxWidth = 500, // Scene width boxHeight = 300, // Scene height ball = 10, // Ball width and height moveBottomH = 5, // Move block height moveBottomW = 100 // Move block quick reading const strArr = 'Congratulations, challenge successful!!'

    //Use reactive to save some observable information const state = reactive({
        x: boxWidth / 2 - ball / 2, // The default position of the ball's x-axis position is in the middle y: boxHeight - ball - moveBottomH, // The default position of the ball's y-axis position is in the middle mx: boxWidth / 2 - moveBottomW / 2, // The default position of the moving block is in the middle my: boxHeight - moveBottomH, // The default position of the moving block's y-axis position is in the middle // Array of hit blocks arr: Array.from({length: 50}, (_, index) => {
            return {
                index,
                active: false
            }
        }),
        str: '', // Returns the word "successful challenge" scroce: 0 // Score })
    // Use toRefs to deconstruct the information of the observed object for template use const {x, y, mx, my, arr, str, scroce} = toRefs(state)
    let timer = null, // ball timer speed = 3, // ball speed map = {x: 10, y: 10},
        timer2 = null, // Challenge success word display timer index = 0 // Challenge success word display index value // Challenge success word display method const strFun = () => {
        if (strArr.length === index) clearInterval(timer2)
        state.str += strArr.substr(index, 1)
        index++
    }

    
    //Method for moving the ball// 1. Here, the map object is used to record the coordinate information to determine whether the ball bounces when it hits the left, right, top, and moving blocks// 2. Loop through the bricks to detect when the ball collides with the bricks and disappears const moveBall = () => {
        const {offsetTop, offsetHeight, offsetLeft, offsetWidth} = document.querySelector('.bottomMove')
        if (state.x <= 0) {
            map.x = speed
        } else if (state.x > boxWidth - ball) {
            map.x = -speed
        }
        if (state.y <= 0) {
            map.y = speed
        }
        if (state.y >= offsetTop - offsetHeight &&
            state.y <= offsetTop + offsetHeight &&
            state.x >= offsetLeft &&
            state.x < offsetLeft + offsetWidth) {
            map.y = -speed
        }
        if (state.y > boxHeight) {
            clearInterval(timer)
            alert('game over')
            window.location.reload()
        }
        Array.from(state.arr).forEach((item, index) => {
            const {
                offsetLeft,
                offsetTop,
                offsetWidth,
                offsetHeight
            } = document.querySelectorAll('.kuai')[index]
            if (state.x > offsetLeft
                && state.x < offsetLeft + offsetWidth
                && state.y > offsetTop
                && state.y < offsetTop + offsetHeight) {
                if (!state.arr[index].active) {
                    state.scroce += 100
                }
                state.arr[index].active = true
            }
        })
        if (Array.from(state.arr).every(item => item.active)) {
            clearInterval(timer)
            timer2 = setInterval(strFun, 1000)
        }
        state.x = state.x += map.x
        state.y = state.y += map.y
    }

    //Method to move the block left and right, catch the ball const bottomMove = ev => {
        if (ev.code === 'Space') clearInterval(timer)
        switch (ev.key) {
            case 'ArrowRight':
                state.mx += 100
                break
            case 'ArrowLeft':
                state.mx -= 100
                break
        }
        state.mx = state.mx < 0 ? 0 : state.mx
        state.mx = state.mx > boxWidth - moveBottomW ? boxWidth - moveBottomW : state.mx
    }
    // Pause the game const stop = () => {
        clearInterval(timer)
    }
    // Start the game const start = () => {
        timer = setInterval(moveBall, 20)
    }
    
    // Bind moving block event onMounted(() => {
        document.addEventListener('keyup', bottomMove)
    })
    // Move out of the moving block event onUnmounted(() => {
        clearInterval(timer)
    })
</script>

<style>

    .bottomMove {
        width: 100px;
        height: 10px;
        background: red;
        position: absolute;
        transition-duration: 100ms;
        transition-timing-function: ease-out;
    }

    .ball {
        width: 20px;
        height: 20px;
        background-color: red;
        border-radius: 50%;
        position: absolute;
    }

    .kuaiBox {
        display: flex;
        flex-wrap: wrap;
    }

    .kuai {
        width: 30px;
        height: 10px;
        background: red;
        margin: 10px;
        transition-duration: 100ms;
        transition-timing-function: ease-in;
    }

    .str {
        text-align: center;
        font-size: 50px;
        color: red;

    }

    .box {

        justify-content: center;
        width: 500px;
        height: 500px;
        margin: 0 auto;
        position: relative;
        border: 5px solid red;
        overflow: hidden;
    }

    .picker {
        width: 50px;
        height: 50px;
    }
</style>

at last

I will continue to use vue3 and write more examples in the future.

Attached is the address of the brick breaking game

shinewen189.github.io/nigo-ball-v…

This is the end of this article about developing a brick-breaking game with vue3. For more relevant vue3 brick-breaking game content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • An example of refactoring a jigsaw puzzle game using vue3

<<:  How to quickly create tens of millions of test data in MySQL

>>:  The difference and usage of Ctrl+z, Ctrl+c and Ctrl+d in Linux commands

Recommend

How to adjust the log level of nginx in Docker

Table of contents Intro Nginx Dockerfile New conf...

HTML adaptive table method

<body style="scroll:no"> <tabl...

Common naming rules for CSS classes and ids

Public name of the page: #wrapper - - The outer e...

Example of how to configure the MySQL database timeout setting

Table of contents Preface 1. JDBC timeout setting...

Docker binding fixed IP/cross-host container mutual access operation

Preface Previously, static IPs assigned using pip...

Use href in html to pop up a file download dialog box when clicking a link

I learned a new trick today. I didn’t know it befo...

How to use Vue-router routing

Table of contents 1. Description 2. Installation ...

InnoDB type MySql restore table structure and data

Prerequisite: Save the .frm and .ibd files that n...

How to use CSS to display multiple images horizontally in the center

Let me first talk about the implementation steps:...

Recommend several MySQL related tools

Preface: With the continuous development of Inter...

A very detailed explanation of Linux C++ multi-thread synchronization

Table of contents 1. Mutex 1. Initialization of m...

Tutorial on installing MySQL 5.7.9 using RPM package under CentOS 7

Recorded MySQL 5.7.9 installation tutorial, share...

MySQL 8.0 upgrade experience

Table of contents Preface 1. First completely uni...

Quickly install MySQL5.7 compressed package on Windows

This article shares with you how to install the M...