• 【笔记】直播编程写游戏


    饮水思源:https://www.bilibili.com/video/av12168808

    添加砖块(先写一个砖块 再弄成n个)&通过暂停与减速来debug:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
            <style type="text/css">
                canvas {
                    border: 1px black solid;
                }
            </style>
        </head>
        <body>
            <canvas id="id-canvas" width="400" height="300"></canvas>
            <script>    
                let makeGuaGame = function(fps) {
                    let g = {
                        actions: {},
                        keydowns: {},
                    };
                    g.canvas = document.querySelector("#id-canvas");
                    g.context = g.canvas.getContext('2d');
                    
                    g.registerAction = function(key, callback) {
                        g.actions[key] = callback;
                    };
                    
                    g.drawImage = function(guaImage) {
                        this.context.drawImage(guaImage.img, guaImage.x, guaImage.y);    
                    }
                    
                    window.addEventListener("keydown", event => {
                        g.keydowns[event.key] = true;
                    });
        
                    window.addEventListener("keyup", event => {
                        g.keydowns[event.key] = false;
                    });                
     
                    setInterval(function() {
                        // events
                        let keys = Object.keys(g.keydowns);
                        for (let i = 0; i != keys.length; ++i) {
                            let k = keys[i];
                            if (g.keydowns[k]) {
                                g.actions[k]();
                            }
                        }
                        // update 
                        g.update();
                        // clear
                        g.context.clearRect(0, 0, g.canvas.width, g.canvas.height);
                        // draw
                        g.draw();            
                    }, 1000/fps); 
                    
                    return g;
                };
    
                let imgFromPath = function(path) {
                    let img = new Image(path);
                    img.src = path;
                    return img;
                };
                
                let makePaddle = function() {
                    let img = imgFromPath('img/paddle.png');
                    let o = {
                        img: img,
                        x: 200,
                        y: 250,
                        speed: 5,
                    };
                    o.moveLeft = function() {
                        this.x -= this.speed;
                        if (this.x < 0) {
                            this.x = 0;
                        }
                    };
                    o.moveRight = function() {
                        this.x += this.speed;
                        if (this.x > 400 - this.img.naturalWidth) {
                            this.x = 400 - this.img.naturalWidth;
                        }
                    };
                    o.collide = function(guaImg) {
                        if (Math.abs(o.x - guaImg.x) < o.img.naturalWidth/2 + guaImg.img.naturalWidth/2 
                          && Math.abs(o.y - guaImg.y) < o.img.naturalHeight/2 + guaImg.img.naturalHeight/2 
                        ) {
                          return true;
                        }
                        return false;
                    };
                    
                    return o;
                };
                
                let makeBall = function() {
                    let img = imgFromPath('img/ball.png');
                    let o = {
                        img: img,
                        x: 200, 
                        y: 250,
                        speedX: 7,
                        speedY: -7,
                        fired: false,
                    };
                    o.fire = function() {
                        this.fired = true;
                    }
                    
                    o.move = function() {
                        if (this.fired) {    
                            if (this.x > 400 || this.x < 0) {
                                this.speedX *= -1;
                            } else if (this.y > 300 || this.y < 0) {
                                this.speedY *= -1;
                            }    
                            this.x += this.speedX;
                            this.y += this.speedY;                        
                        }
                    };
                    o.反弹 = function() {
                        this.speedY *= -1;
                    }
                    
                    return o;                
                };
                
                let makeBrick = function() {
                    let img = imgFromPath('img/brick.png');
                    let o = {
                        img: img,
                        x: 50, 
                        y: 50,
                        alive: true,
                    };        
                    o.kill = function() {
                        this.alive = false;
                    }
                    o.collide = function(guaImg) {
                        if (!this.alive) return false;
                        if (Math.abs(o.x - guaImg.x) < o.img.naturalWidth/2 + guaImg.img.naturalWidth/2 
                          && Math.abs(o.y - guaImg.y) < o.img.naturalHeight/2 + guaImg.img.naturalHeight/2 
                        ) {
                          return true;
                        }
                        return false;
                    };
                    
                    return o;
                };
                
                let __main = function() {
                    let game = makeGuaGame(fps=30);
                    
                    let paddle = makePaddle();
                    
                    let ball = makeBall();
                    
                    let bricks = [];
                    for (let i = 0; i != 3; ++i) {
                        let b = makeBrick();
                        b.x = i * 150;
                        bricks.push(b);
                    }
                    
                    game.registerAction('a', function() {
                        paddle.moveLeft();
                    });
                    
                    game.registerAction('d', function() {
                        paddle.moveRight();    
                    });
    
                    game.registerAction('f', function() {
                        ball.fire();    
                    });
                    
                    let pause = false;
                    window.addEventListener("keydown", event => {
                        if (event.key == 'p') {
                            pause = !pause;
                        }
                    });
                    game.update = function() {    
                        if (pause) { // 暂停的移动
                            return;
                        }
                        
                        ball.move();
                        if (paddle.collide(ball)) {
                            ball.反弹();
                        }
                        for (let i = 0; i != bricks.length; ++i) {
                            if (bricks[i].collide(ball)) {
                                bricks[i].kill();
                                ball.反弹();
                            }
                        }
                    };
                    
                    game.draw = function() {
                        game.drawImage(paddle);    
                        game.drawImage(ball);    
                        for (let i = 0; i != bricks.length; ++i) {
                            if (bricks[i].alive) {
                                game.drawImage(bricks[i]);    
                            }    
                        }
                    };            
                };            
                
                __main();
            </script>
        </body>
    </html>
    View Code

    将各部分代码拆分为独立文件 &添加关卡以及debug模式:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
            <style type="text/css">
                canvas {
                    border: 1px black solid;
                }
            </style>
            <script src="js/utils.js"></script>
            <script src="js/guagame.js"></script>
            <script src="js/paddle.js"></script>
            <script src="js/ball.js"></script>
            <script src="js/brick.js"></script>
            <script src="js/levels.js"></script>
        </head>
        
        <body>
            <canvas id="id-canvas" width="400" height="300"></canvas>
            <script>    
                
                let pause = false;                    
                let enableDebugMode = function(enable) {
                    if (!enable) {
                        return;
                    }
                    window.addEventListener("keydown", event => {
                        if (event.key == 'p') {
                            pause = !pause;
                        }
                    });                    
                };
                
                let __main = function() {
                    enableDebugMode(false);
                    
                    let game = makeGuaGame(fps=40);                
                    let paddle = makePaddle();                
                    let ball = makeBall();                
                    let bricks = loadLevel(0);
                    
                    game.registerAction('a', function() {
                        paddle.moveLeft();
                    });            
                    game.registerAction('d', function() {
                        paddle.moveRight();    
                    });
                    game.registerAction('f', function() {
                        ball.fire();    
                    });
                            
                    game.update = function() {    
                        if (pause) { // 暂停球的移动
                            return;
                        }                    
                        ball.move();
                        if (paddle.collide(ball)) {
                            ball.反弹();
                        }
                        for (let i = 0; i != bricks.length; ++i) {
                            if (bricks[i].collide(ball)) {
                                bricks[i].kill();
                                ball.反弹();
                            }
                        }
                    };
                    
                    game.draw = function() {
                        game.drawImage(paddle);    
                        game.drawImage(ball);    
                        for (let i = 0; i != bricks.length; ++i) {
                            if (bricks[i].alive) {
                                game.drawImage(bricks[i]);    
                            }    
                        }
                    };            
                };            
                
                __main();
            </script>
        </body>
    </html>
    View Code

    砖块生命值 &动态调fps :

    let makeBrick = function(x, y, HP=1) {
        // x, y 是砖块的坐标
        let img = imgFromPath('img/brick.png');
        let o = {
            img: img,
            x: x,
            y: y,
            HP: HP,
            alive: true,
        };
        o.kill = function() {
            this.alive = false;
            // 根据生命值改变图片?先初始化一个img数组
        };
        o.hit = function() {
            console.log(this.HP);
            this.HP--;
            if (this.HP == 0) {
                this.kill();
            }
        };
        o.collide = function(guaImg) {
            if(!this.alive) return false;
            if(Math.abs(o.x - guaImg.x) < o.img.naturalWidth / 2 + guaImg.img.naturalWidth / 2 &&
                Math.abs(o.y - guaImg.y) < o.img.naturalHeight / 2 + guaImg.img.naturalHeight / 2
            ) {
                return true;
            }
            return false;
        };
    
        return o;
    };
    brick.js
    let levels = [
        [
            [100, 50],
        ],
        [
            [0, 50],
            [150, 50, 50],
            [300, 50],
        ],
    ];
    
    
    let loadLevel = function(n) {
        // n表示第几关,该函数返回一个砖块数组
        let level = levels[n];
        
        let bricks = [];
        for (let i = 0; i != level.length; ++i) {
            let param = level[i];
            let b = makeBrick(param[0], param[1], param[2] || 1);
            bricks.push(b);
        }    
        
        return bricks;
    };
    levels.js
    let makeGuaGame = function() {
        let g = {
            actions: {},
            keydowns: {},
            fps: 40,
        };
        g.canvas = document.querySelector("#id-canvas");
        g.context = g.canvas.getContext('2d');
    
        g.registerAction = function(key, callback) {
            g.actions[key] = callback;
        };
    
        g.drawImage = function(guaImage) {
            this.context.drawImage(guaImage.img, guaImage.x, guaImage.y);
        };
    
        window.addEventListener("keydown", event => {
            g.keydowns[event.key] = true;
        });
    
        window.addEventListener("keyup", event => {
            g.keydowns[event.key] = false;
        });
    
        let repaintInfinitely = function() { 
            // events
            let keys = Object.keys(g.keydowns);
            for(let i = 0; i != keys.length; ++i) {
                let k = keys[i];
                if(g.keydowns[k] && g.actions[k] != null) {
                    g.actions[k]();
                }
            }
            // update 
            g.update();
            // clear
            g.context.clearRect(0, 0, g.canvas.width, g.canvas.height);
            // draw
            g.draw();
            setTimeout(function() {
                repaintInfinitely(); // 递归调用setTimeout
            }, 1000 / g.fps);    
        };
        
        g.begin = function() { // 在一切就绪的时候调用(update和draw定义后)
            repaintInfinitely();    
        };
    
        return g;
    };
    guagame.js
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
            <style type="text/css">
                canvas {
                    border: 1px black solid;
                }
            </style>
            <script src="js/utils.js"></script>
            <script src="js/guagame.js"></script>
            <script src="js/paddle.js"></script>
            <script src="js/ball.js"></script>
            <script src="js/brick.js"></script>
            <script src="js/levels.js"></script>
        </head>
        
        <body>
            <canvas id="id-canvas" width="400" height="300"></canvas>
            <p>fps:<input id="id-input-speed" type="range" /></p>
            <script>    
                let pause = false;
                let enableDebugMode = function(game, enable) {
                    if (!enable) {
                        return;
                    }
                    window.addEventListener("keydown", event => {
                        if (event.key == 'p') {
                            pause = !pause;
                        }
                    });
                    document.querySelector("#id-input-speed").addEventListener("input", event => {
                        let newFps = Number(event.target.value);
                        game.fps = newFps;
                    });
                };
                
                let __main = function() {                
                    let game = makeGuaGame();
                    enableDebugMode(game, true);
                    
                    let paddle = makePaddle();                
                    let ball = makeBall();                
                    let bricks = loadLevel(1);
                    
                    game.registerAction('a', function() {
                        paddle.moveLeft();
                    });            
                    game.registerAction('d', function() {
                        paddle.moveRight();    
                    });
                    game.registerAction('f', function() {
                        ball.fire();    
                    });
                            
                    game.update = function() {    
                        if (pause) { // 暂停球的移动
                            return;
                        }    
                        
                        ball.move();
                        if (paddle.collide(ball)) {
                            ball.反弹();
                        }
                        for (let i = 0; i != bricks.length; ++i) {
                            if (bricks[i].collide(ball)) {
                                bricks[i].hit();
                                ball.反弹();
                            }
                        }
                    };
                    
                    game.draw = function() {
                        game.drawImage(paddle);    
                        game.drawImage(ball);    
                        for (let i = 0; i != bricks.length; ++i) {
                            if (bricks[i].alive) {
                                game.drawImage(bricks[i]);    
                            }    
                        }
                    };        
                    
                    game.begin();
                };            
                
                __main();
            </script>
        </body>
    </html>
    index.html

     

     截屏留念,这是一个血很厚的砖块。。

  • 相关阅读:
    计算一个整数的二进制中1的个数
    Java 操作 EXCEL
    WIN7 64位配置Oracle SQL Developer工具
    phpstrom+xdebug调试PHP代码
    Zend Server安装后首次运行就出现Internal Server Error的解决
    在C语言中使用scanf语句时遇到的问题总结
    ElementUI中scrollbar的使用解析
    前端模拟手机屏幕图片渐隐渐现效果实现
    谈谈怎么学习编程?
    underScore学习1:匿名函数中call(this)的作用
  • 原文地址:https://www.cnblogs.com/xkxf/p/9832699.html
Copyright © 2020-2023  润新知