【笔记】直播编程写游戏 - 1
饮水思源:https://www.bilibili.com/video/av12138532
原始版本:
<!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 canvas = document.querySelector("#id-canvas"); let context = canvas.getContext('2d'); let img = new Image(); img.src = "img/xx.png"; let x = 200, y = 250; img.onload = function() { context.drawImage(img, x, y); }; window.addEventListener("keydown", event => { let k = event.key; if (k == 'a') { x -= 10; } else if (k == 'd') { x += 10; } context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(img, x, y); }); </script> </body> </html>
改善卡顿(提高按住1秒钟更新的次数):
<!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 __main = function() { let canvas = document.querySelector("#id-canvas"); let context = canvas.getContext('2d'); let img = new Image(); img.src = "img/xx.png"; let x = 200, y = 250, speed = 5; img.onload = function() { context.drawImage(img, x, y); }; let leftDown = false, rightDown = false; window.addEventListener("keydown", event => { let k = event.key; if (k == 'a') { leftDown = true; } else if (k == 'd') { rightDown = true; } }); window.addEventListener("keyup", event => { let k = event.key; if (k == 'a') { leftDown = false; } else if (k == 'd') { rightDown = false; } }); setInterval(function() { // update if (leftDown) { x -= speed; } else if (rightDown) { x += speed; } // draw context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(img, x, y); }, 1000/30); // 1/30秒更新一次也就是1秒钟更新30次 }; __main(); </script> </body> </html>
重构版本1(封装img等):
<!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 imgFromPath = function(path) { let img = new Image(path); img.src = path; return img; }; let makePaddle = function() { let o = { img: imgFromPath('img/xx.png'), x: 100, y: 250, speed: 5, }; o.moveLeft = function() { this.x -= this.speed; }; o.moveRight = function() { this.x += this.speed; }; return o; }; let makeGuaGame = function() { let g = { }; g.canvas = document.querySelector("#id-canvas"); g.context = g.canvas.getContext('2d'); // g.update(); 报错。 setInterval(function() { // update g.update(); // clear g.context.clearRect(0, 0, g.canvas.width, g.canvas.height); // draw g.draw(); }, 1000/30); return g; }; let __main = function() { let game = makeGuaGame(); let paddle = makePaddle(); let leftDown = false, rightDown = false; window.addEventListener("keydown", event => { let k = event.key; if (k == 'a') { leftDown = true; } else if (k == 'd') { rightDown = true; } }); window.addEventListener("keyup", event => { let k = event.key; if (k == 'a') { leftDown = false; } else if (k == 'd') { rightDown = false; } }); game.update = function() { if (leftDown) { paddle.moveLeft(); } else if (rightDown) { paddle.moveRight(); } }; game.draw = function() { this.context.drawImage(paddle.img, paddle.x, paddle.y); }; }; __main(); </script> </body> </html>
重构版本2(封装事件监听):
<!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 imgFromPath = function(path) { let img = new Image(path); img.src = path; return img; }; let makePaddle = function() { let o = { img: imgFromPath('img/xx.png'), x: 100, y: 250, speed: 5, }; o.moveLeft = function() { this.x -= this.speed; }; o.moveRight = function() { this.x += this.speed; }; return o; }; let makeGuaGame = function() { 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; }; 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/30); return g; }; let __main = function() { let game = makeGuaGame(); let paddle = makePaddle(); game.registerAction("a", function() { paddle.moveLeft(); }); game.registerAction("d", function() { paddle.moveRight(); }); game.update = function() { }; game.draw = function() { this.context.drawImage(paddle.img, paddle.x, paddle.y); }; }; __main(); </script> </body> </html>
填加ball:
<!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() { 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/30); 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; }; o.moveRight = function() { this.x += this.speed; }; 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; } }; return o; }; let __main = function() { let game = makeGuaGame(); let paddle = makePaddle(); let ball = makeBall(); game.registerAction("a", function() { paddle.moveLeft(); }); game.registerAction("d", function() { paddle.moveRight(); }); game.registerAction("f", function() { ball.fire(); }); game.update = function() { ball.move(); if (paddle.collide(ball)) { ball.speedY *= -1; } }; game.draw = function() { game.drawImage(paddle); game.drawImage(ball); }; }; __main(); </script> </body> </html>