class Snake {
constructor() {
// 蛇头位子
this.head = new Vector(0, 0);
// 除了蛇头外蛇身的位子
this.body = [];
// 蛇移动的步伐
this.step = new Vector(1, 0);
// 蛇头加上蛇身长度
this.maxLength = 3;
}
update() {
// push head to body
this.body.push(this.head);
// generate new head
// 整只蛇往前一步,蛇头当然也就往前一步
this.head = this.head.add(this.step);
// shift the tail
// 整只蛇往前一步,蛇尾当然也就往前一步,故删除旧蛇尾位子
while(this.body.length > this.maxLength){
this.body.shift();
}
};
setDirection(direction) {
var newStep;
switch(direction){
case 'Right':
newStep = new Vector(1,0);
break
case 'Left':
newStep = new Vector(-1,0);
break
case 'Up':
newStep = new Vector(0,-1);
break
case 'Down':
newStep = new Vector(0,1);
break
};
// 蛇本来往左走,如果玩家按下向右键,则不理玩家,蛇维持往左步伐
if(!this.step.equal(newStep.mul(-1))){
this.step = newStep;
}
};
// 判断蛇头有没有撞墙
isWithinBoundary(boundary) {
var xWithinBoundary = this.head.x >= 0 && this.head.x < boundary
var yWithinBoundary = this.head.y >= 0 && this.head.y < boundary
return xWithinBoundary && yWithinBoundary;
};
};
class Game{
constructor() {
// 舞台由 20 格,每格 26px 的格子组成,且每个之间的间距为 2px
this.blocks = 20;
this.blockWidth = 26;
this.blockSpace = 2;
// 请蛇上台
this.snake = new Snake();
this.foods = [];
this.generateFoods();
this.start = true;
this.bgm = new BGM();
// init
this.init();
}
init() {
// set canvas
this.canvas = document.getElementById('canvasSnake');
this.canvas.width = this.blockWidth * this.blocks + this.blockSpace * (this.blocks - 1);
this.canvas.height = this.canvas.width;
this.ctx = this.canvas.getContext('2d');
// render canvas view
this.render();
// update game data
this.update();
};
render() {
// bg
this.ctx.fillStyle = '#dbe3c5';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.width);
// 画出舞台格子
for (var bX = 0; bX < this.blocks; bX++) {
for (var bY = 0; bY < this.blocks; bY++) {
this.drawBlock(new Vector(bX, bY), '#ced6b8')
};
};
// snake
this.snake.body.forEach(sbPosition =>
this.drawBlock(sbPosition, `rgb(${144-this.snake.maxLength*3},${150+this.snake.maxLength},${128+this.snake.maxLength*2})`));
this.foods.forEach(fPosition => {
this.drawBlock(fPosition, 'rgb(24,174,198)');
});
// render again
requestAnimationFrame(()=>this.render(),1);
};
// 计算我们画的舞台格子,实际是在 canvas 上多少 px 的位子
getPosition(blockXY) {
return {
x:blockXY.x * (this.blockWidth + this.blockSpace),
y:blockXY.y * (this.blockWidth + this.blockSpace)
}
};
// 画一格(舞台格子的大小)
drawBlock(blockPos, color) {
var pos = this.getPosition(blockPos);
this.ctx.fillStyle = color;
this.ctx.fillRect(pos.x, pos.y, this.blockWidth, this.blockWidth);
};
update() {
if(this.start){
// 更新蛇的状态
this.snake.update();
// 确认食物是不是被蛇吃了
this.foods.forEach((food, i) => {
if(food.equal(this.snake.head)){
this.generateFoods();
this.foods.splice(i, 1);
this.snake.maxLength ++;
}
});
// 确认蛇是不是输了
// 蛇有超出边界吗
if(!this.snake.isWithinBoundary(this.blocks)){
this.endGame();
};
// 蛇有撞到自己吗
this.snake.body.forEach((sbPos) =>{
if(sbPos.equal(this.snake.head)){
this.endGame();
console.log(this.snake.body,sbPos,this.snake.head)
}
})
};
// update again
setTimeout(()=>this.update(),150);
};
generateFoods() {
var x = parseInt(Math.random() * this.blocks);
var y = parseInt(Math.random() * this.blocks);
var newFood = new Vector(x, y);
this.foods.push(newFood);
};
startGame () {
this.snake = new Snake();
this.start = true;
this.bgm.play();
};
endGame () {
this.start = false;
this.bgm.pause();
};
};
如果以上理解有所出入,求求侠客都在麻烦协助提点,感谢!! ε= ᕕ( ᐛ )ᕗ
<<: Day15 - this&Object Prototypes Ch3 Objects - Iteration 开头
大家好~~继昨天提到的自动填满功能,今天将更深入的来探讨这个功能,分别为自动填满等差数列及格式。那在...
老实说我决定要写影像处理这个部分的时候还蛮犹豫的,因为在javascript 做影像处理的这个领域,...
结构体介绍 CAN_FilterTypeDef typedef struct { uint32_t ...
嗨!我是莉莉,目前是个软件工程师。去年因为公司内部任务接触到和资安相关的议题,开始对资讯安全感兴趣、...
今天来分享我在 AIS 的所见所闻! 进入正题 前些天的文章中已经向各位分享 AIS 的报名方式 (...