JavaScript游戏开发(3)(笔记)

素材可以去一位大佬放在github的源码中直接下,见附录。

七、支持移动设备的横向卷轴游戏

使用前面我们所学习的部分,组合成为一个游戏。

是否玩过《疯狂喷气机》(手游)这类游戏,该部分试着做一个类似与它的简单的横板游戏。

准备

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 角色的简单移动

我们通过如下代码控制角色移动

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();

});

如下,我们完成了通过箭头移动角色

在这里插入图片描述

7.2 背景

	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 加入敌人与帧数控制

笔者修改了视频的一些代码,并修改了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);

});

在这里插入图片描述

7.4 碰撞、计分、重新开始

我们碰撞盒采用圆形,来做简单的碰撞检测

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);
    }
});



在这里插入图片描述

7.5 手机格式

我们进入浏览器的开发者模式,将浏览器设置为手机。

*{
    
    
    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;
}

在这里插入图片描述
输入的指令如下


			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);
            }) 

判断时,只需要在执行处加入相应的标志即可。

同理,我们可以加入横向滑动操作,随着如果手指沿着X轴移动,我们可以认为X轴方向移动角色。X轴位移不为0则加入,为0则停止。

如果进入手机模式,滑动时,窗口也跟着滑动,可以试着加入如下代码

       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 全屏模式

#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)

在这里插入图片描述

7.7 存在的问题

  1. 碰撞盒太大了,我们可能需要移动和缩小,来让判定更准确,或者玩起来更容易
  2. 没有很好的填充满屏幕,需要相应的js算法来帮助

其他笔者未解决问题:

  1. 如上方式,在重新开始后,游戏角色动作”变快“(时间间隔仍旧一样)。
  2. 此外,我们重新开始后,必然立即刷一只怪物
  3. 一些浏览器的页面再切换后,我们隔一段时间再返回,可以刷出更多怪物

考虑如果自己通过循环来计数,是否可以解决部分问题。

附录

[1]源-素材地址
[2]源-视频地址
[3]搬运视频地址(JavaScript 游戏开发)
[4]github-视频的素材以及源码

猜你喜欢

转载自blog.csdn.net/weixin_46949627/article/details/127832514
今日推荐