JavaScript game development (3) (notes)

The material can go to a big guy and put it directly in the source code of github, see the appendix.

7. Horizontal scrolling games that support mobile devices

Using the parts we learned earlier, the combination becomes a game.

Have you ever played games like "Crazy Jet" (mobile game), this part tries to make a simple horizontal board game similar to it.

Prepare

html

<!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">
    <title>JavaScript 2D Game</title>
    <link rel="stylesheet" href="./stylte.css">
</head>

<body>
    <canvas id="canvas1"></canvas>
    <img src="./player.png" id="playerImage" alt="playerImage">
    <img src="./backgroundImage.png" id="backgroundImage" alt="backgroundImage">
    <img src="./worm.png" id="enemyImage" alt="enemyImage">

    <script src="./script.js"></script>

    <script src="./script.js"></script>
</body>

</html>

css

body{
    
    
    background: black;
}

#canvas1{
    
    
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%,-50%);
    border: 5px solid white;
}

#playerImage,#backgroundImage,#enemyImage{
    
    
    display: none;
}

JavaScript

window.addEventListener('DOMContentLoaded',function(){
    
    
    const canvas = this.document.getElementById('canvas1');
    const ctx = canvas.getContext('2d');
    canvas.width = 800;
    canvas.height = 720;
    let enemies = [];


    // 输入处理
    class InputHandler{
    
    
       
    }

    class Player{
    
    


    }

    class Background{
    
    

    }

    class Enemy{
    
    

    }


    function handleEnemies(){
    
    

    }


    function displayStatusText(){
    
    

    }



    function animate(){
    
    

        requestAnimationFrame(animate);
    }

    animate();

});

7.1 Simple movement of characters

We control the movement of the character through the following code

window.addEventListener('DOMContentLoaded',function(){
    
    
    const canvas = this.document.getElementById('canvas1');
    const ctx = canvas.getContext('2d');
    canvas.width = 800;
    canvas.height = 720;
	let enemies = [];

    // 输入处理
    class InputHandler{
    
    
        constructor(){
    
    
            this.keys = [];
            // 加入上、下、左、右按键,此处使用 indexof保证键唯一,就无视本次输入
            window.addEventListener('keydown',e=>{
    
    
                if ((e.key === 'ArrowDown' ||
                     e.key === 'ArrowUp' ||
                     e.key === 'ArrowLeft' ||
                     e.key === 'ArrowRight') &&
                    this.keys.indexOf(e.key) === -1) {
    
    
                    this.keys.push(e.key)
                }
                console.log(e.key,this.keys);
            });

            // 移除按键
            window.addEventListener('keyup',e=>{
    
    
                if( e.key === 'ArrowDown' ||
                    e.key === 'ArrowUp' ||
                    e.key === 'ArrowLeft' ||
                    e.key === 'ArrowRight'){
    
    
                    this.keys.splice(this.keys.indexOf(e.key), 1)
                }
                console.log(e.key,this.keys);
            });
        }
    }

    class Player{
    
    
        constructor(gameWidth,gameHeight){
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.width = 200;
            this.height = 200;
            this.x = 0;
            this.y = this.gameHeight - this.height;
            this.image  = playerImage;
            this.frameX = 0;
            this.frameY = 0;
            
            // 速度
            // x轴
            this.speedX = 0;
            // y轴
            this.speedY = 0;

            // 重量
            this.weight = 1;
        }
        draw(context){
    
    
            context.fillStyle = 'white';
            context.fillRect(this.x,this.y,this.width,this.height);
            context.drawImage(this.image,this.frameX*this.width,this.frameY*this.height,this.width,this.height,this.x,this.y,this.width,this.height);
        }

        update(input){
    
    
            // 检测X轴按键
            if(input.keys.indexOf('ArrowRight') > -1){
    
    
                this.speedX = 5;
            }
            else if(input.keys.indexOf('ArrowLeft') > -1){
    
    
                this.speedX = -5;
            }
            else{
    
    
                this.speedX = 0;
            }

            // 检测Y轴按键,且只能从地面上起跳
            if(input.keys.indexOf('ArrowUp') > -1 && this.onGround()){
    
    
                this.speedY = -32;
            }

        
            this.x = this.x + this.speedX;
            this.y = this.y + this.speedY;

            // 避免出界
            if(this.x < 0){
    
    
                this.x = 0
            }
            else if(this.x > this.gameWidth - this.width){
    
    
                this.x = this.gameWidth - this.width;
            }

            
            // 跳跃限制
            if(!this.onGround()){
    
    
                this.speedY += this.weight;
                this.frameY = 1;
            }
            else{
    
    
                this.speedY = 0;
                this.frameY = 0;
            }

            // 避免陷入地面
            if(this.y > this.gameHeight - this.height){
    
    
                this.y = this.gameHeight - this.height;
            }
        }
        onGround(){
    
    
            return this.y >= this.gameHeight - this.height;
        }
    }

    class Background{
    
    

    }

    class Enemy{
    
    

    }


    function handleEnemies(){
    
    

    }


    function displayStatusText(){
    
    

    }


    const input = new InputHandler();
    const player = new Player(canvas.width,canvas.height);

    function animate(){
    
    
        ctx.clearRect(0,0,canvas.width,canvas.height);
        player.draw(ctx);
        player.update(input);
        requestAnimationFrame(animate);
    }

    animate();

});

As follows, we have completed moving the character through the arrow

insert image description here

7.2 Background

	class Background{
    
    
        constructor(gameWidth, gameHeight) {
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.image = backgroundImage;
            this.x = 0;
            this.y = 0;
            this.width = 2400;
            this.height = 720;
            this.speed = 7;
        }
        draw(context) {
    
    
            context.drawImage(this.image, this.x, this.y, this.width, this.height);
            context.drawImage(this.image, this.x + this.width, this.y, this.width, this.height);
        }

        update() {
    
    
            this.x -= this.speed
            if (this.x < 0 - this.width){
    
    
                this.x = 0;
            } 
        }
    }

	function animate(){
    
    
        ctx.clearRect(0,0,canvas.width,canvas.height);
        background.draw(ctx);
        background.update();
        player.draw(ctx);
        player.update(input);
        requestAnimationFrame(animate);
    }

7.3 Adding enemies and frame rate control

The author modified some codes of the video, and modified some codes in the player

window.addEventListener('DOMContentLoaded',function(){
    
    
    const canvas = this.document.getElementById('canvas1');
    const ctx = canvas.getContext('2d');
    canvas.width = 800;
    canvas.height = 720;

    let enemies = [];

    // 输入处理
    class InputHandler{
    
    
        constructor(){
    
    
            this.keys = [];
            // 加入上、下、左、右按键,此处使用 indexof保证键唯一,就无视本次输入
            window.addEventListener('keydown',e=>{
    
    
                if ((e.key === 'ArrowDown' ||
                     e.key === 'ArrowUp' ||
                     e.key === 'ArrowLeft' ||
                     e.key === 'ArrowRight') &&
                    this.keys.indexOf(e.key) === -1) {
    
    
                    this.keys.push(e.key)
                }
            });

            // 移除按键
            window.addEventListener('keyup',e=>{
    
    
                if( e.key === 'ArrowDown' ||
                    e.key === 'ArrowUp' ||
                    e.key === 'ArrowLeft' ||
                    e.key === 'ArrowRight'){
    
    
                    this.keys.splice(this.keys.indexOf(e.key), 1)
                }
            });
        }
    }

    class Player{
    
    
        constructor(gameWidth,gameHeight){
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.width = 200;
            this.height = 200;
            this.x = 0;
            this.y = this.gameHeight - this.height;
            this.image  = playerImage;
            this.frameX = 0;
            this.frameY = 0;
            this.maxFrame = 8;
            // 速度
            // x轴
            this.speedX = 0;
            // y轴
            this.speedY = 0;

            // 重量
            this.weight = 1;

            //动画20帧
            this.fps = 20;
            this.frameTimer = 0;
            this.frameInterval = 1000/this.fps;
        }
        draw(context){
    
    
            context.drawImage(this.image,this.frameX*this.width,this.frameY*this.height,this.width,this.height,this.x,this.y,this.width,this.height);
        }

        update(input,deltaTime){
    
    
            // 检测X轴按键
            if(input.keys.indexOf('ArrowRight') > -1){
    
    
                this.speedX = 5;
            }
            else if(input.keys.indexOf('ArrowLeft') > -1){
    
    
                this.speedX = -5;
            }
            else{
    
    
                this.speedX = 0;
            }

            // 检测Y轴按键,且只能从地面上起跳
            if(input.keys.indexOf('ArrowUp') > -1 && this.onGround()){
    
    
                this.speedY = -32;
                this.frameY = 1;
                this.frameX = 0;
                this.maxFrame = 5;
                this.y = this.y + this.speedY;
            }

            if(this.frameTimer > this.frameInterval){
    
    
                if(this.frameX >= this.maxFrame){
    
    
                    this.frameX = 0;
                }
                else{
    
    
                    this.frameX++;
                }
                this.frameTimer = 0;
            }
            else{
    
    
                this.frameTimer += deltaTime; 
            }
        
            this.x = this.x + this.speedX;

            // 避免出界
            if(this.x < 0){
    
    
                this.x = 0
            }
            else if(this.x > this.gameWidth - this.width){
    
    
                this.x = this.gameWidth - this.width;
            }

            
            // 跳跃限制
            if(!this.onGround()){
    
    
                this.speedY += this.weight;
                this.y = this.y + this.speedY;
                if(this.onGround()){
    
    
                    this.y = this.gameHeight - this.height;
                    this.speedY = 0;
                    this.frameY = 0;
                    this.maxFrame = 8;
                }
            }

        }

        // 是否在地面
        onGround(){
    
    
            return this.y >= this.gameHeight - this.height;
        }
    }

    class Background{
    
    
        constructor(gameWidth, gameHeight) {
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.image = backgroundImage;
            this.x = 0;
            this.y = 0;
            this.width = 2400;
            this.height = 720;
            this.speed = 7;
        }
        draw(context) {
    
    
            context.drawImage(this.image, this.x, this.y, this.width, this.height);
            context.drawImage(this.image, this.x + this.width, this.y, this.width, this.height);
        }

        update() {
    
    
            this.x -= this.speed
            if (this.x < 0 - this.width){
    
    
                this.x = 0;
            } 
        }
    }

    class Enemy{
    
    
        constructor(gameWidth, gameHeight) {
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.width = 160;
            this.height = 119;


            this.image = enemyImage;

            this.x = this.gameWidth;
            this.y = this.gameHeight - this.height;

            this.frameX = 0;
            this.maxFrame = 5;

            this.speed = 8;

            // 敌人动画20帧
            this.fps = 20;
            this.frameTimer = 0;
            this.frameInterval = 1000/this.fps;

            this.markedForDeletion = false;
        }
        draw(context) {
    
    
            context.drawImage(this.image, this.frameX * this.width, 0, this.width, this.height, this.x, this.y, this.width, this.height)
        }
        update(deltaTime) {
    
    
            if(this.frameTimer > this.frameInterval){
    
    
                if(this.frameX >= this.maxFrame){
    
    
                    this.frameX = 0;
                }
                else{
    
    
                    this.frameX++;
                }
                this.frameTimer = 0;
            }
            else{
    
    
                this.frameTimer += deltaTime; 
            }

            if(this.x < 0 - this.width){
    
    
                this.markedForDeletion = true;
            }

            this.x -= this.speed;
        }
    }


    function handleEnemies(deltaTime){
    
    
        if(enemyTimer > enemyInterval + randomEnemyInterval){
    
    
            enemies.push(new Enemy(canvas.width,canvas.height));
            randomEnemyInterval = Math.random()*1000 + 500;
            enemyTimer = 0;
        }
        else{
    
    
            enemyTimer += deltaTime;
        }
        let flag = false;
        enemies.forEach(e => {
    
    
            e.draw(ctx);
            e.update(deltaTime);
            if(!flag && e.markedForDeletion){
    
    
                flag = true;
            }
        })
        if(flag){
    
    
            enemies = enemies.filter(e=>!e.markedForDeletion);
        }
    }


    function displayStatusText(){
    
    
        
    }


    const input = new InputHandler();
    const player = new Player(canvas.width,canvas.height);
    const background = new Background(canvas.weight,canvas.height);

    let lastTime = 0;
    let enemyTimer = 0;
    let enemyInterval = 2000;
    // 让敌人刷出时间不可预测
    let randomEnemyInterval = Math.random()*1000 + 500;

    // 60帧,游戏画面的更新帧
    let frameTimer = 0;
    let frameInterval = 1000/60;


    function animate(timeStamp){
    
    
        const deltaTime = timeStamp - lastTime;
        lastTime = timeStamp; 
        frameTimer += deltaTime; 
        if(frameTimer > frameInterval){
    
    
            ctx.clearRect(0,0,canvas.width,canvas.height);

            background.draw(ctx);
            // background.update();
    
            handleEnemies(deltaTime);
            player.draw(ctx);
            player.update(input,deltaTime);
            frameTimer = 0;
        }
        requestAnimationFrame(animate);
    }

    animate(0);

});

insert image description here

7.4 Collision, Scoring, Restart

Our collision box uses a circle for simple collision detection

window.addEventListener('DOMContentLoaded',function(){
    
    
    const canvas = this.document.getElementById('canvas1');
    const ctx = canvas.getContext('2d');
    canvas.width = 800;
    canvas.height = 720;

    let enemies = [];

    // 输入处理
    class InputHandler{
    
    
        constructor(){
    
    
            this.keys = [];
            // 加入上、下、左、右按键,此处使用 indexof保证键唯一,就无视本次输入
            window.addEventListener('keydown',e=>{
    
    
                if ((e.key === 'ArrowDown' ||
                     e.key === 'ArrowUp' ||
                     e.key === 'ArrowLeft' ||
                     e.key === 'ArrowRight') &&
                    this.keys.indexOf(e.key) === -1) {
    
    
                    this.keys.push(e.key)
                }
                else if(e.key === 'Enter' && gameOver){
    
    
                    gameReStart();
                }
            });

            // 移除按键
            window.addEventListener('keyup',e=>{
    
    
                if( e.key === 'ArrowDown' ||
                    e.key === 'ArrowUp' ||
                    e.key === 'ArrowLeft' ||
                    e.key === 'ArrowRight'){
    
    
                    this.keys.splice(this.keys.indexOf(e.key), 1)
                }
            });
        }
    }

    class Player{
    
    
        constructor(gameWidth,gameHeight){
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.width = 200;
            this.height = 200;
            this.x = 0;
            this.y = this.gameHeight - this.height;
            this.image  = playerImage;
            this.frameX = 0;
            this.frameY = 0;
            this.maxFrame = 8;
            // 速度
            // x轴
            this.speedX = 0;
            // y轴
            this.speedY = 0;

            // 重量
            this.weight = 1;

            //动画20帧
            this.fps = 20;
            this.frameTimer = 0;
            this.frameInterval = 1000/this.fps;
        }
        draw(context){
    
    
            context.strokeStyle = 'white';
            context.strokeRect(this.x,this.y,this.width,this.height);
            context.beginPath();
            context.arc(this.x + this.width/2,this.y+this.height/2,this.width/2,0,Math.PI*2);
            context.stroke();

            context.drawImage(this.image,this.frameX*this.width,this.frameY*this.height,this.width,this.height,this.x,this.y,this.width,this.height);
        }

        update(input,deltaTime){
    
    
            // 碰撞检测
            enemies.forEach(e=>{
    
    
                const dx = (e.x + e.width/2) - (this.x + this.width/2);
                const dy = (e.y + e.height/2) - (this.y + this.height/2);
                const distance = Math.sqrt(dx*dx + dy*dy);
                if(distance < e.width/2 + this.width/2){
    
    
                    gameOver = true;
                }
            });


            // 检测X轴按键
            if(input.keys.indexOf('ArrowRight') > -1){
    
    
                this.speedX = 5;
            }
            else if(input.keys.indexOf('ArrowLeft') > -1){
    
    
                this.speedX = -5;
            }
            else{
    
    
                this.speedX = 0;
            }

            // 检测Y轴按键,且只能从地面上起跳
            if(input.keys.indexOf('ArrowUp') > -1 && this.onGround()){
    
    
                this.speedY = -32;
                this.frameY = 1;
                this.frameX = 0;
                this.maxFrame = 5;
                this.y = this.y + this.speedY;
            }

            if(this.frameTimer > this.frameInterval){
    
    
                if(this.frameX >= this.maxFrame){
    
    
                    this.frameX = 0;
                }
                else{
    
    
                    this.frameX++;
                }
                this.frameTimer = 0;
            }
            else{
    
    
                this.frameTimer += deltaTime; 
            }
        
            this.x = this.x + this.speedX;

            // 避免出界
            if(this.x < 0){
    
    
                this.x = 0
            }
            else if(this.x > this.gameWidth - this.width){
    
    
                this.x = this.gameWidth - this.width;
            }

            
            // 跳跃限制
            if(!this.onGround()){
    
    
                this.speedY += this.weight;
                this.y = this.y + this.speedY;
                if(this.onGround()){
    
    
                    this.y = this.gameHeight - this.height;
                    this.speedY = 0;
                    this.frameY = 0;
                    this.maxFrame = 8;
                }
            }

        }

        // 是否在地面
        onGround(){
    
    
            return this.y >= this.gameHeight - this.height;
        }

        restart(){
    
    
            this.x = 0;
            this.y = this.gameHeight - this.height;
            this.frameInterval = 0;
            this.maxFrame = 8;
            this.frameY = 0;
        }
    }

    class Background{
    
    
        constructor(gameWidth, gameHeight) {
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.image = backgroundImage;
            this.x = 0;
            this.y = 0;
            this.width = 2400;
            this.height = 720;
            this.speed = 5;
        }
        draw(context) {
    
    
            context.drawImage(this.image, this.x, this.y, this.width, this.height);
            context.drawImage(this.image, this.x + this.width, this.y, this.width, this.height);
        }

        update() {
    
    
            this.x -= this.speed
            if (this.x < 0 - this.width){
    
    
                this.x = 0;
            } 
        }

        restart(){
    
    
            this.x = 0;
        }
    }

    class Enemy{
    
    
        constructor(gameWidth, gameHeight) {
    
    
            this.gameWidth = gameWidth;
            this.gameHeight = gameHeight;
            this.width = 160;
            this.height = 119;


            this.image = enemyImage;

            this.x = this.gameWidth;
            this.y = this.gameHeight - this.height;

            this.frameX = 0;
            this.maxFrame = 5;

            this.speed = 8;

            // 敌人动画20帧
            this.fps = 20;
            this.frameTimer = 0;
            this.frameInterval = 1000/this.fps;

            this.markedForDeletion = false;
        }
        draw(context) {
    
    
            context.strokeStyle = 'white';
            context.strokeRect(this.x,this.y,this.width,this.height);
            context.beginPath();
            context.arc(this.x + this.width/2,this.y+this.height/2,this.width/2,0,Math.PI*2);
            context.stroke();
            
            context.drawImage(this.image, this.frameX * this.width, 0, this.width, this.height, this.x, this.y, this.width, this.height)
        }
        update(deltaTime) {
    
    
            if(this.frameTimer > this.frameInterval){
    
    
                if(this.frameX >= this.maxFrame){
    
    
                    this.frameX = 0;
                }
                else{
    
    
                    this.frameX++;
                }
                this.frameTimer = 0;
            }
            else{
    
    
                this.frameTimer += deltaTime; 
            }

            if(this.x < 0 - this.width){
    
    
                this.markedForDeletion = true;
                score++;
            }

            this.x -= this.speed;
        }

    }


    function handleEnemies(deltaTime){
    
    
        if(enemyTimer > enemyInterval + randomEnemyInterval){
    
    
            enemies.push(new Enemy(canvas.width,canvas.height));
            randomEnemyInterval = Math.random()*1000 + 500;
            enemyTimer = 0;
        }
        else{
    
    
            enemyTimer += deltaTime;
        }
        let flag = false;
        enemies.forEach(e => {
    
    
            e.draw(ctx);
            e.update(deltaTime);
            if(!flag && e.markedForDeletion){
    
    
                flag = true;
            }
        })
        if(flag){
    
    
            enemies = enemies.filter(e=>!e.markedForDeletion);
        }
    }


    const input = new InputHandler();
    const player = new Player(canvas.width,canvas.height);
    const background = new Background(canvas.weight,canvas.height);

    let lastTime = 0;
    let enemyTimer = 0;
    let enemyInterval = 2000;
    // 让敌人刷出时间不可预测
    let randomEnemyInterval = Math.random()*1000 + 500;

    // 60帧,游戏画面的更新帧
    let frameTimer = 0;
    let frameInterval = 1000/60;

    let score = 0;
    let gameOver = false;


    function displayStatusText(context){
    
    
        context.textAlign = 'left';
        context.fillStyle = 'black';
        context.font = '40px Helvetica';
        context.fillText('score:'+score,20,50);
        context.fillStyle = 'white';
        context.font = '40px Helvetica';
        context.fillText('score:'+score,22,52);
        if(gameOver){
    
    
            context.textAlign = 'center';
            context.fillStyle = 'black';
            context.fillText('Game Over,press "Enter" to restart!',canvas.width/2,200);
            context.fillStyle = 'white';
            context.fillText('Game Over,press "Enter" to restart!',canvas.width/2,200);
        }
    }



    function animate(timeStamp){
    
    
        const deltaTime = timeStamp - lastTime;
        lastTime = timeStamp; 
        frameTimer += deltaTime; 
        if(frameTimer > frameInterval){
    
    
            ctx.clearRect(0,0,canvas.width,canvas.height);

            background.draw(ctx);
            background.update();
    
            handleEnemies(deltaTime);
            player.draw(ctx);
            player.update(input,deltaTime);
            displayStatusText(ctx);
            frameTimer = 0;
        }
        if(!gameOver){
    
    
            requestAnimationFrame(animate);
        }
    }

    animate(0);

    function gameReStart(){
    
    
        player.restart();
        background.restart();

        score = 0;
        enemies = [];
        gameOver = false;

        frameTimer = 0;
        enemyTimer = 0;
        lastTime = 0;

        randomEnemyInterval = Math.random()*1000 + 500;
        animate(0);
    }
});



insert image description here

7.5 Mobile phone format

We enter the developer mode of the browser and set the browser to the mobile phone.

*{
    
    
    margin: 0;
    padding:0;
    box-sizing: border-box;
}
body{
    
    
    background: black;
}

#canvas1{
    
    
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%,-50%);
    border: 5px solid white;
    max-width: 100%;
    max-height: 100%;
}

#playerImage,#backgroundImage,#enemyImage{
    
    
    display: none;
}

insert image description here
The command entered is as follows


			this.touchY = ''; // Y 轴滑动
            this.touchThreshold = 30 ;// 超过30认为滑动
            window.addEventListener('keydown', e => {
    
    
                if ((e.key === 'ArrowDown' ||
                        e.key === 'ArrowUp' ||
                        e.key === 'ArrowLeft' ||
                        e.key === 'ArrowRight') &&
                    this.keys.indexOf(e.key) === -1) {
    
    
                    this.keys.push(e.key);
                }else if(e.key==='Enter'&&gameOver) restartGame()
            })
            // 手指、指针起始位置
            window.addEventListener('touchstart',e=>{
    
    
                this.touchY=e.changedTouches[0].pageY;
            })
            // 手指、指针移动中
            window.addEventListener('touchmove',e=>{
    
    
                const swipeDistance=e.changedTouches[0].pageY-this.touchY;
                if(swipeDistance<-this.touchThreshold && this.keys.indexOf('swipe up')===-1) {
    
    
                	this.keys.push('swipe up');
                }
                else if(swipeDistance>this.touchThreshold && this.keys.indexOf('swipe down')===-1) {
    
    
                    this.keys.push('swipe down');
                    if(gameOver) restartGame();
                }
            }) 
            // 手指、指针移动结束
            window.addEventListener('touchend',e=>{
    
    
                console.log(this.keys);
                this.keys.splice(this.keys.indexOf('swipe up'),1);
                this.keys.splice(this.keys.indexOf('swipe down'),1);
            }) 

When judging, you only need to add the corresponding flag at the execution point.

In the same way, we can add a horizontal sliding operation, and if the finger moves along the X-axis, we can think that the character moves in the X-axis direction. Add if the X-axis displacement is not 0, and stop if it is 0.

If you enter the mobile phone mode, when you slide, the window will also slide, you can try to add the following code

       function stopScroll() {
    
    
        var html = document.getElementsByTagName('html')[0];
        var body = document.getElementsByTagName('body')[0];
        var o = {
    
    };
        o.can = function () {
    
    
            html.style.overflow = "visible";
            html.style.height = "auto";
            body.style.overflow = "visible";
            body.style.height = "auto";
        },
            o.stop = function () {
    
    
                html.style.overflow = "hidden";
                html.style.height = "100%";
                body.style.overflow = "hidden";
                body.style.height = "100%";
            }
        return o;
    }
    const scroll = stopScroll();
    scroll.stop();  

7.6 Full screen mode

#fullScreenButton{
    
    
    position: absolute;
    font-size: 20px;
    padding: 10px;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
}
<!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">
    <title>JavaScript 2D Game</title>
    <link rel="stylesheet" href="./stylte.css">
</head>

<body>
    <canvas id="canvas1"></canvas>
    <img src="./player.png" id="playerImage" alt="playerImage">
    <img src="./backgroundImage.png" id="backgroundImage" alt="backgroundImage">
    <img src="./worm.png" id="enemyImage" alt="enemyImage">
    <button id="fullScreenButton">Toggle Fullscreen</button>

    <script src="./script.js"></script>
</body>

</html>
function toggleFullScreen(){
    
    
        if(!document.fullscreenElement){
    
    
            canvas.requestFullscreen().then().catch(err=>{
    
    
                alert(`错误,切换全屏模式失败:${
      
      err.message}`)
            })
        }else{
    
    
            document.exitFullscreen()
        }
    }
    fullScreenButton.addEventListener('click',toggleFullScreen)

insert image description here

7.7 Existing problems

  1. The collision box is too big, we may need to move and shrink it to make the judgment more accurate, or make it easier to play
  2. The screen is not well filled, and the corresponding js algorithm is needed to help

Unresolved issues by other authors:

  1. In the above way, after restarting, the game character moves "faster" (the time interval is still the same).
  2. In addition, after we restart, we must immediately spawn a monster
  3. After switching the pages of some browsers, we will return after a while to spawn more monsters

Consider whether you can solve part of the problem if you count through the loop yourself.

appendix

[1] Source - material address
[2] Source - video address
[3] Handling video address (JavaScript game development)
[4] github - video material and source code

Guess you like

Origin blog.csdn.net/weixin_46949627/article/details/127832514