​​

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


【笔记】直播编程写游戏 - 2_paddle【笔记】直播编程写游戏 - 2_html_02


<!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模式:


【笔记】直播编程写游戏 - 2_paddle【笔记】直播编程写游戏 - 2_html_02


<!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 :


【笔记】直播编程写游戏 - 2_paddle【笔记】直播编程写游戏 - 2_html_02


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

【笔记】直播编程写游戏 - 2_paddle【笔记】直播编程写游戏 - 2_html_02


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

【笔记】直播编程写游戏 - 2_paddle【笔记】直播编程写游戏 - 2_html_02


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

【笔记】直播编程写游戏 - 2_paddle【笔记】直播编程写游戏 - 2_html_02


<!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

 

 【笔记】直播编程写游戏 - 2_ide_13

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