01-案例介绍

02-面向对象思维分析

03-构建方块对象



/* 1.方块对象Cube (8行js) */
class Cube {
// 1.1 构造函数
constructor(x = 0, y = 0, bgc = this.randomColor()) {
this.x = x
this.y = y
this.bgc = bgc
this.html = `<div class="cube" style="left:${x * 20}px;top:${y * 20}px;background-color:${bgc}"></div>`
}
// 1.2 原型
randomColor () {
// rgb(0-255,0-255,0-255)
return `rgb( ${parseInt(Math.random() * 256)} , ${parseInt(Math.random() * 256)} , ${parseInt(Math.random() * 256)} )`
}
}
04-构建食物对象

/* 2.食物对象Food (3行js) */
class Food extends Cube {
// 2.1 构造函数
constructor() {
super(parseInt(Math.random() * 40), parseInt(Math.random() * 30))
}
}
05-构建蛇对象
/* 3.蛇对象Snake(18行js) */
class Snake {
// 3.1 构造函数
constructor() {
this.body = [
{ x: 5, y: 1, bgc: 'red' },
{ x: 4, y: 1, bgc: 'orange' },
{ x: 3, y: 1, bgc: 'green' },
{ x: 2, y: 1, bgc: 'purple' },
{ x: 1, y: 1, bgc: 'blue' },
]
this.direction = 'KeyD'
}
// 3.2 渲染
render () {
return this.body.map(item => new Cube(item.x, item.y, item.bgc).html).join('')
}
// 3.3 反方向
revDirection () {
switch (this.direction) {
case 'KeyW': return 'KeyS'
case 'KeyA': return 'KeyD'
case 'KeyS': return 'KeyW'
case 'KeyD': return 'KeyA'
}
}
// 3.3 移动
move (key) {
// (1)记录当前移动方向
this.direction = key
// (2)每一节身体位置前移
for (let i = this.body.length - 1; i > 0; i--) {
this.body[i].x = this.body[i - 1].x
this.body[i].y = this.body[i - 1].y
}
// (3)蛇头位置取决于移动方向
if (key === 'KeyW') this.body[0].y--
else if (key === 'KeyA') this.body[0].x--
else if (key === 'KeyS') this.body[0].y++
else if (key === 'KeyD') this.body[0].x++
// (4)碰撞检测 : 蛇头不能与任意身体位置重合 arr.slice(1)返回1下标之后的所有元素
if (this.body.slice(1).some(item => item.x === this.body[0].x && item.y === this.body[0].y)) {
Game.over()
}
// (5)边界检测
if ([-1, 40].includes(this.body[0].x) || [-1, 30].includes(this.body[0].y)) {
Game.over()
}
}
}
06-构建游戏对象
/* 4.游戏对象(30行js) */
class Game {
// 4.1 构造函数
constructor() {
this.map = document.querySelector('.map')// 地图
this.food = new Food()// 食物
this.snake = new Snake()// 蛇
this.map.innerHTML = this.food.html + this.snake.render()
this.score = 0// 分数
this.timer = null// 定时器
}
// 4.2 开始游戏
start () {
window.addEventListener('keydown', ({ code }) => {
// 按键检测
if (!['KeyW', 'KeyA', 'KeyS', 'KeyD'].includes(code) || this.snake.revDirection() === code) return
/* 自动移动 */
clearInterval(this.timer)
this.timer = setInterval(() => {
// (1)蛇移动
this.snake.move(code)
// (2)吃食物判定
this.eat()
// (3)重新渲染
this.map.innerHTML = this.food.html + this.snake.render()
}, 100)
/* 长按方向键可以加速移动 */
// (1)蛇移动
this.snake.move(code)
// (2)吃食物判定
this.eat()
// (3)重新渲染
this.map.innerHTML = this.food.html + this.snake.render()
})
}
// 4.3 吃食物
eat () {
// 1. 判断食物和蛇头位置是否重叠
if (this.food.x === this.snake.body[0].x && this.food.y === this.snake.body[0].y) {
// (1)把食物放在尾巴位置
this.snake.body.push({
x: this.snake.body[this.snake.body.length - 1].x,
y: this.snake.body[this.snake.body.length - 1].y,
bgc: this.food.bgc
})
// (2)产生新的食物
this.food = new Food()
// (3)分数++
this.score++
document.querySelector('.score').innerHTML = this.score
}
}
// 4.4 暂停游戏
pause () {
clearInterval(this.timer)
}
// 4.5 结束游戏
static over () {
alert('Game Over')
location.reload()
}
}
const game = new Game()
game.start()
document.querySelector('.start').addEventListener('click', function () {
location.reload()
})
document.querySelector('.pause').addEventListener('click', function () {
game.pause()
})
07-完整代码
/* 1.方块对象Cube (8行js) */
class Cube {
// 1.1 构造函数
constructor(x = 0, y = 0, bgc = this.randomColor()) {
this.x = x
this.y = y
this.bgc = bgc
this.html = `<div class="cube" style="left:${x * 20}px;top:${y * 20}px;background-color:${bgc}"></div>`
}
// 1.2 原型
randomColor () {
// rgb(0-255,0-255,0-255)
return `rgb( ${parseInt(Math.random() * 256)} , ${parseInt(Math.random() * 256)} , ${parseInt(Math.random() * 256)} )`
}
}
/* 2.食物对象Food (3行js) */
class Food extends Cube {
// 2.1 构造函数
constructor() {
super(parseInt(Math.random() * 40), parseInt(Math.random() * 30))
}
}
/* 3.蛇对象Snake(18行js) */
class Snake {
// 3.1 构造函数
constructor() {
this.body = [
{ x: 5, y: 1, bgc: 'red' },
{ x: 4, y: 1, bgc: 'orange' },
{ x: 3, y: 1, bgc: 'green' },
{ x: 2, y: 1, bgc: 'purple' },
{ x: 1, y: 1, bgc: 'blue' },
]
this.direction = 'KeyD'
}
// 3.2 渲染
render () {
return this.body.map(item => new Cube(item.x, item.y, item.bgc).html).join('')
}
// 3.3 反方向
revDirection () {
switch (this.direction) {
case 'KeyW': return 'KeyS'
case 'KeyA': return 'KeyD'
case 'KeyS': return 'KeyW'
case 'KeyD': return 'KeyA'
}
}
// 3.3 移动
move (key) {
// (1)记录当前移动方向
this.direction = key
// (2)每一节身体位置前移
for (let i = this.body.length - 1; i > 0; i--) {
this.body[i].x = this.body[i - 1].x
this.body[i].y = this.body[i - 1].y
}
// (3)蛇头位置取决于移动方向
if (key === 'KeyW') this.body[0].y--
else if (key === 'KeyA') this.body[0].x--
else if (key === 'KeyS') this.body[0].y++
else if (key === 'KeyD') this.body[0].x++
// (4)碰撞检测 : 蛇头不能与任意身体位置重合 arr.slice(1)返回1下标之后的所有元素
if (this.body.slice(1).some(item => item.x === this.body[0].x && item.y === this.body[0].y)) {
Game.over()
}
// (5)边界检测
if ([-1, 40].includes(this.body[0].x) || [-1, 30].includes(this.body[0].y)) {
Game.over()
}
}
}
/* 4.游戏对象(30行js) */
class Game {
// 4.1 构造函数
constructor() {
this.map = document.querySelector('.map')// 地图
this.food = new Food()// 食物
this.snake = new Snake()// 蛇
this.map.innerHTML = this.food.html + this.snake.render()
this.score = 0// 分数
this.timer = null// 定时器
}
// 4.2 开始游戏
start () {
window.addEventListener('keydown', ({ code }) => {
// 按键检测
if (!['KeyW', 'KeyA', 'KeyS', 'KeyD'].includes(code) || this.snake.revDirection() === code) return
/* 自动移动 */
clearInterval(this.timer)
this.timer = setInterval(() => {
// (1)蛇移动
this.snake.move(code)
// (2)吃食物判定
this.eat()
// (3)重新渲染
this.map.innerHTML = this.food.html + this.snake.render()
}, 100)
/* 长按方向键可以加速移动 */
// (1)蛇移动
this.snake.move(code)
// (2)吃食物判定
this.eat()
// (3)重新渲染
this.map.innerHTML = this.food.html + this.snake.render()
})
}
// 4.3 吃食物
eat () {
// 1. 判断食物和蛇头位置是否重叠
if (this.food.x === this.snake.body[0].x && this.food.y === this.snake.body[0].y) {
// (1)把食物放在尾巴位置
this.snake.body.push({
x: this.snake.body[this.snake.body.length - 1].x,
y: this.snake.body[this.snake.body.length - 1].y,
bgc: this.food.bgc
})
// (2)产生新的食物
this.food = new Food()
// (3)分数++
this.score++
document.querySelector('.score').innerHTML = this.score
}
}
// 4.4 暂停游戏
pause () {
clearInterval(this.timer)
}
// 4.5 结束游戏
static over () {
alert('Game Over')
location.reload()
}
}
const game = new Game()
game.start()
document.querySelector('.start').addEventListener('click', function () {
location.reload()
})
document.querySelector('.pause').addEventListener('click', function () {
game.pause()
})