使用canvas写一个小游戏

341 阅读1分钟

前段时间自己写过一个查看不同颜色得分的小游戏,随着点击次数的增多,元素会越来越多,所以后来决定用cavans实现一下,效果如下: 截屏2022-05-19 下午7.17.45.png

1. 首先创建一个canvas

    <div id="grend">
        得分:
        <span id="count">0</span>
    </div>
    <canvas id="canvas" width="400" height="400"></canvas>

2. 创建一个类并设置初始值,

    class CanvasDraw {
      constructor() {
            this.lineCount = 2 //每行的个数
            this.colorNumber = 0xFFFFFF + 1 
            this.index = 0
            this.canvas = document.getElementById('canvas')
            this.count = document.getElementById('count')
            this.width = (this.canvas.offsetWidth - (this.lineCount - 1) * 3) / this.lineCount //每个的宽度,每个块之间有3px的间隔
        }
        //点击错误之后清除并重新开始
        clear() {
            this.canvas.getContext('2d').clearRect(0, 0, 400, 400)
        }
        //点击成功之后个数增加,并计算对应的宽度与当前得分
        next() {
            this.lineCount++
            this.width = (this.canvas.offsetWidth - (this.lineCount - 1) * 3) / this.lineCount
            this.count.innerHTML = +this.count.innerHTML + 10
            this.draw()
        }
    }

3. 创建一个绘制的函数

随机生成一个不同的块,并设置差距在0x0f0f0f的颜色,并绘制到canvas上

 draw() {
            const context = canvas.getContext('2d')
            const count = this.lineCount ** 2,
            randomIndex = Math.random() * count | 0,
            randomColor = this.colorNumber *  Math.random() | 0,
            specialColor = randomColor - 0x0f0f0f > 0? randomColor - 0x0f0f0: randomColor + 0x0f0f0f
            this.index = randomIndex
            for(let i = 0; i < count; i++) {
                context.fillStyle = '#' + (i === randomIndex? specialColor.toString(16).padStart(6, 0): randomColor.toString(16).padStart(6, 0))
                context.fillRect((this.width + 3)  * (i % this.lineCount), (this.width + 3)  * ((i / this.lineCount) | 0), this.width, this.width)
            }
        }

4. 点击canvas的逻辑

判断点击时的位置是不是特殊的块的位置,正确的时候下一步,不正确的话重新开始

        click(e) {
            return new Promise((resolve, reject) => {
                const { offsetX, offsetY } = e
                const row = this.index / this.lineCount | 0, colomn = this.index % this.lineCount
                if(offsetX >= colomn * (this.width + 3) 
                    && offsetX <= (colomn + 1) * (this.width + 3) - 3 
                    && offsetY >= row * (this.width + 3)
                    && offsetY <= (row + 1) * (this.width + 3) - 3) {
                    resolve()
                }else {
                    reject()
                }
            
            })
        }

最终代码与实现效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only" content="策略">
    <title>Document</title>
</head>
<style>
    body {
        height: 100%;
    }

    #container {
        position: absolute;
        width: 400px;
        height: 400px;
        border: 1px solid pink;
        top: 50%;
        left: 50%; 
        transform: translateX(-50%) translateY(-50%);
    }
    #grend {
        text-align: center;
    }
</style>
<body>
    <div id="grend">
        得分:
        <span id="count">0</span>
    </div>
    <div id="container">
        <canvas id="canvas" width="400" height="400"></canvas>
    </div>
</body>
<script>
    const container = document.getElementById('container')

    class CanvasDraw {
        constructor() {
            this.lineCount = 2
            this.colorNumber = 0xFFFFFF + 1
            this.index = 0
            this.canvas = document.getElementById('canvas')
            this.count = document.getElementById('count')
            this.width = (this.canvas.offsetWidth - (this.lineCount - 1) * 3) / this.lineCount
        }

        init() {
            this.lineCount = 2
            this.width = (this.canvas.offsetWidth - (this.lineCount - 1) * 3) / this.lineCount
            this.count.innerHTML = 0
            this.draw()
        }

        draw() {
            const context = canvas.getContext('2d')
            const count = this.lineCount ** 2,
            randomIndex = Math.random() * count | 0,
            randomColor = this.colorNumber *  Math.random() | 0,
            specialColor = randomColor - 0x0f0f0f > 0? randomColor - 0x0f0f0: randomColor + 0x0f0f0f
            this.index = randomIndex
            for(let i = 0; i < count; i++) {
                context.fillStyle = '#' + (i === randomIndex? specialColor.toString(16).padStart(6, 0): randomColor.toString(16).padStart(6, 0))
                context.fillRect((this.width + 3)  * (i % this.lineCount), (this.width + 3)  * ((i / this.lineCount) | 0), this.width, this.width)
            }
        }

        clear() {
            canvas.getContext('2d').clearRect(0, 0, 400, 400)
        }

        next() {
            this.lineCount++
            this.width = (this.canvas.offsetWidth - (this.lineCount - 1) * 3) / this.lineCount
            this.count.innerHTML = +this.count.innerHTML + 10
            this.draw()
        }

        click(e) {
            return new Promise((resolve, reject) => {
                const { offsetX, offsetY } = e
                const row = this.index / this.lineCount | 0, colomn = this.index % this.lineCount
                if(offsetX >= colomn * (this.width + 3) 
                    && offsetX <= (colomn + 1) * (this.width + 3) - 3 
                    && offsetY >= row * (this.width + 3)
                    && offsetY <= (row + 1) * (this.width + 3) - 3) {
                    resolve()
                }else {
                    alert('点击错误,即将重新开始')
                    reject()
                }
            
            })
        }
    }

    const canvasDraw = new CanvasDraw()
    canvasDraw.init()
    container.addEventListener('click', (e) => {
        canvasDraw.click(e).then(() => {
            canvasDraw.clear()
            canvasDraw.next()

        }).catch(e => {
            canvasDraw.clear()
            canvasDraw.init()
        })
    })
</script>
</html>

image.png 完结撒花