Project address -> Uploaded to Github

Project address -> Code cloud

Project Demo Address

  • Let’s draw the UI
function draw_line() {
    ctx.strokeStyle = 'black'
    for (var i = w; i < canvas.height; i += w) {
        ctx.moveTo(0, i)
        ctx.lineTo(canvas.width, i)
        ctx.stroke()
    }
    for (var i = w; i < canvas.width; i += w) {
        ctx.moveTo(i, 0)
        ctx.lineTo(i, canvas.height)
        ctx.stroke()
    }
    // Draw the first canvas as a parameter. The starting coordinates and width and height of the canvas are the same as the size of the first canvas.
    ctx2.drawImage(canvas, 0.0, canvas.width, canvas.height)
}
Copy the code

First of all, we are not using one canvas, because the background cannot be cleared when we move the black block, and the clearRect(x, y, width, height) method will clear all the colors of the specified area, so we use two canvas, The two canvas are irrelevant. So the second Canvas context draws the first canvas.

  • This is the description of the required properties
// Define variables
var w = 100         // The width and height of a black block
var blocks = []     // An array of all black block information objects
var flag = false    // Only the last black block flag is allowed to be true, because the rule of the game is that only the last black block can be clicked
var speed = 2       // The black block moves faster as you score points
var num = 0         / / score
var requestId = 0   // The return value of the requestAnimationFrame() method to stop the animation
Copy the code
  • Ready to play
// Ready to start the game
function ready_game() {
    // Initialize variables at the start of the game
    blocks = []
    flag = false
    speed = 2
    num = 0
    ctx.clearRect(0.0, canvas.width, canvas.height)
    score.textContent = 'Score:' + num

    ctx.fillStyle = 'black'
    var x = 0
    for (var i = 0; i < canvas.height; i += w) {
        // Randomly produce black blocks in the X-axis position
        x = ~~(Math.random() * 3) * w
        var obj = { x: x, y: i }
        ctx.fillRect(x, i, w, w)
        if (i == 300) {
            ctx.fillStyle = 'white'
            ctx.font = '20px consolas'
            ctx.fillText('Start the game', x + 10, i + w / 2)
            obj.flag = true
        }
        // Add mouse click events
        addClick_event(obj)
        // Store the current black block object into the array
        blocks.push(obj)
    }
}
Copy the code
  • Method to add mouse click events
// Add a click event at the specified location
function addClick_event(obj) {
    canvas2.addEventListener('click'.function (e) {
        var cli_x = e.x - 10
        var cli_y = e.y - 10
        /// If you click on the black box with the text description to start the game
        if(cli_x > obj.x && cli_x < obj.x + w && cli_y > obj.y && cli_y < obj.y + w && obj.flag && ! flag) { start_game()// Start the game
        } else destroy_block(e) // Destroy the black block})}Copy the code
  • Start the game
// Start the game
function start_game() {
    blocks.pop()
    num++
    score.textContent = 'Score:' + num
    flag = true
    // Start animation
    animate()
}
Copy the code
  • Black block moving method
// Block moves
function destroy_block(e) {
    if(! flag)return
    var cli_x = e.x, cli_y = e.y
    blocks.forEach(function (val, index) {
        if (cli_x > val.x && cli_x < val.x + w && cli_y > val.y && cli_y < val.y + w) {
            // The black blocks beyond the height will be destroyed, which is not necessary because the game is over if the black blocks are beyond the height.
            // But I didn't think about it at first, and then I didn't want to change it
            if (index === blocks.length - 1) {
                blocks.pop()
                num++
                score.textContent = 'Score:' + num
            }
        }
    })
}
Copy the code
  • Animation method
/ / animation
function animate() {
    ctx.clearRect(0.0, canvas.width, canvas.height)
    ctx.fillStyle = 'black'
    // Iterate over the black blocks in the number group, increasing their y value continuously
    blocks.forEach(function (val, index) {
        ctx.fillRect(val.x, val.y += speed, w, w)
        // if (val.y > canvas.height) {
            // blocks.splice(index, 1)
        // }
    })

    // If you run out of black blocks on the screen, immediately draw another one
    if (blocks.length === 0) {
        ctx.fillStyle = 'black'
        var x = ~~(Math.random() * 3) * w
        var obj = { x: x, y: - 100. }
        ctx.fillRect(obj.x, obj.y, w, w)
        blocks.unshift(obj)
        addClick_event(obj)
    }
    // If the value of the first black block in the array exceeds 0, then a black block is generated on top of it. This and the if criterion above make the screen constantly generate new black blocks
    if (blocks[0].y > 0) {
        ctx.fillStyle = 'black'
        var x = ~~(Math.random() * 3) * w
        var obj = { x: x, y: - 100. }
        ctx.fillRect(obj.x, obj.y, w, w)
        blocks.unshift(obj)
        addClick_event(obj)
    }
    // Speed will increase with the score
    speed = num / 10 + 2
    requestId = requestAnimationFrame(animate)

    if (blocks[blocks.length - 1].y >= canvas.height) {
        // End the animation
        cancelAnimationFrame(requestId)
        // Game over
        game_over()
    }
}
Copy the code
  • Game over
// Game over
function game_over() {
    alert('Game over, please start again! ')
    ready_game()
}
Copy the code

Renderings are displayed