h5贪吃蛇
程序员文章站
2022-06-25 11:30:24
h5制作贪吃蛇htmlcssjs游戏效果使用canvas制作的一个贪吃蛇小游戏,写了一写比较简单的算法,望大佬们多多指正!!!多的不说直接看代码吧。html规划一个游戏界面 csshtml, body { padding: 0; margin: 0;...
使用canvas制作的一个贪吃蛇小游戏,写了一写比较简单的算法,望大佬们多多指正!!!多的不说直接看代码吧。
html
规划一个游戏界面
<div class="mian">
<canvas id='huaban'></canvas>
</div>
css
html,
body {
padding: 0;
margin: 0;
}
body {
background: black;
}
.mian {
margin: auto;
width: 800px;
height: 500px;
margin-top: 30px;
background: rgba(255, 251, 251, 0.089);
}
js
var s_X = 0, s_Y = 0;//存储鼠标实时的位置
var c_w = window.innerWidth / 2 - 400, c_h = 30;//初始窗口的大小
var life = true;//蛇的生命
var body_arr = [],//身体继承存储数组
body_jc = [],
food_color = ['#1db0b8', '#de8100', '#3b200c', '#ff534d', '#edd0be'], //食物随机颜色存储的数组
_bg,//背景的对象
sk,//蛇的对象
speed = 1000 / 120,//定时器的速度
food_number = 1,//单位大小内食物的个数
zanti = 1,//暂停
time = 0;//整体的时间线
var food = [
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
];//食物池
var huabu = document.querySelector('#huaban');
var huaban = huabu.getContext('2d');
function daxiao() {
huabu.width = 800;
huabu.height = 500;
}//画板的宽高
daxiao();
window.onresize = function () {
c_w = window.innerWidth / 2 - 400;//当界面窗口发生变化时窗口大小
}
class bg {
x = -800;
y = -500;
hua() {//使用两个循环来制作地图,而不是循环的嵌套,从而减轻计算机的负担
huaban.clearRect(0, 0, 800, 500);
huaban.lineWidth = 1;
huaban.strokeStyle = 'rgba(255, 251, 251, 0.25)';
for (var i = 0; i < 2400 / 145; i++) {
huaban.beginPath();
huaban.moveTo(this.x, this.y + i * 120);
huaban.lineTo(this.x + 800 * 3, this.y + i * 120);
huaban.closePath();
huaban.stroke();
}
for (var j = 0; j < 1500 / 72; j++) {
huaban.beginPath();
huaban.moveTo(this.x + j * 120, this.y);
huaban.lineTo(this.x + j * 120, this.y + 500 * 3 + 420);
huaban.closePath();
huaban.stroke();
}
};
move() {
this.d = Math.sqrt((s_X - (sk.x + c_w)) ** 2 + (s_Y - (sk.y + c_h)) ** 2);//背景的位置与蛇的位置的距离,一切判断基于此条件
if (this.d != 0) {
if (this.x < sk.x - sk.r - 2 && this.x + 800 * 3 > sk.x + sk.r + 2) {//范围判断
this.x -= (s_X - (sk.x + c_w)) / this.d;
sk.relative_x += (s_X - (sk.x + c_w)) / this.d;
} else {
life = false;
// if (s_X > sk.x + c_w && this.x + 800 * 3 > sk.x + sk.r + 2) {
// this.x -= (s_X - (sk.x + c_w)) / this.d;
// }
// if (s_X < sk.x + c_w && this.x < sk.x - sk.r - 2) {
// this.x -= (s_X - (sk.x + c_w)) / this.d;
// }//边界不会超出
}//注释掉的代码为当蛇到达x边界时不会死亡只是不能超游戏界面外运动
if (this.y < sk.y - sk.r - 2 && this.y + 600 * 3 + 120 > sk.y + sk.r + 2) {
this.y -= (s_Y - (sk.y + c_h)) / this.d;
sk.relative_y += (s_Y - (sk.y + c_h)) / this.d;
} else {
life = false;
// if (s_Y > sk.x + c_h && this.y + 600 * 3 + 120 > sk.y + sk.r + 2) {
// this.y -= (s_Y - (sk.y + c_h)) / this.d;
// }
// if (s_Y < sk.y + c_h && this.y < sk.y - sk.r - 2) {
// this.y -= (s_Y - (sk.y + c_h)) / this.d;
// }//边界不会超出
}//注释掉的代码为当蛇到达y边界时不会死亡只是不能超游戏界面外运动
}
sk.body(sk.x - (s_X - (sk.x + c_w)) / this.d * 20, sk.y - (s_Y - (sk.y + c_h)) / this.d * 20);//一直传递蛇身体新的位置
sk.eat();//画食物
this.hua();//背景画
for (var i = 0; i < 20; i++) {
for (var j = 0; j < 16; j++) {
for (var k = 0; k < food[i][j].length; k++) {
food[i][j][k].x -= (s_X - (sk.x + c_w)) / this.d;
food[i][j][k].y -= (s_Y - (sk.y + c_h)) / this.d;
food[i][j][k].creta();
}//食物的遍历更新食物的位置
}
}
// if (body_arr.length >= 9) {
// console.log(body_jc, body_arr)
// body_jc[0].x = body_arr[5].x;
// body_jc[0].y = body_arr[5].y;
// body_jc[0].hua();
// }//对蛇身体开始更新位置
sk.eye_x = 14 * ((s_X - (sk.x + c_w))) / this.d;
sk.eye_y = 14 * (-(s_Y - (sk.y + c_h))) / this.d;//蛇眼睛珠子的位置随着不同方向从而一直变化
sk.head();//画蛇头
time++;
}
run() {
var time = setInterval(() => {
this.move()
if (life == false) {//当蛇死掉时清除定时器
clearInterval(time);
jieshu();
}
}, speed)
}//蛇身体开始运动并且开始一直从新画背景
}
class snake {
x = 800 / 2;
y = 500 / 2;
r = 20;//蛇头位置固定在屏幕中间
color = '#ffa400';
relative_x = 400;
relative_y = 250;
eye_x = 14;
eye_y = 0;//眼睛珠子初始的位置
weight = 0;
head() {
huaban.beginPath();
huaban.fillStyle = 'white';
huaban.arc(this.x, this.y, this.r + 2, 0, Math.PI * 2);
huaban.fill();//蛇头边界
huaban.beginPath();
huaban.fillStyle = this.color;
huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
huaban.fill();//蛇头主体
huaban.beginPath();
huaban.fillStyle = 'white';
huaban.arc(this.x + this.eye_y, this.y + this.eye_x, 10, 0, Math.PI * 2);
huaban.fill();//蛇左眼睛
huaban.beginPath();
huaban.fillStyle = 'black';
huaban.arc(this.x + this.eye_y, this.y + this.eye_x, 5, 0, Math.PI * 2);
huaban.fill();//蛇左眼睛珠子
huaban.beginPath();
huaban.fillStyle = 'white';
huaban.arc(this.x - this.eye_y, this.y - this.eye_x, 10, 0, Math.PI * 2);
huaban.fill();//蛇右眼睛
huaban.beginPath();
huaban.fillStyle = 'black';
huaban.arc(this.x - this.eye_y, this.y - this.eye_x, 5, 0, Math.PI * 2);
huaban.fill();//蛇右眼睛珠子
};//蛇头的函数
body(x, y) {
body_arr.push({ 'x': x, 'y': y });
if (body_arr.length >= 10) {
body_arr.splice(0, 1);
}
};//将蛇头的坐标传递进body_arr数组实现第二节身体继承
eat() {
var i = 19 - Math.abs(parseInt((_bg.x - this.x + 800 * 3) / 120));
var j = 15 - Math.abs(parseInt((_bg.y - this.y + 600 * 3 + 120) / 120));
for (var k = 0; k < food[i][j].length; k++) {
food[i][j][k].d = Math.sqrt((food[i][j][k].x - this.x) ** 2 + (food[i][j][k].y - this.y) ** 2);//计算食物与自己的距离
// console.log('中心点'+sk.relative_x,'食物'+food[i][j][k].x);
// console.log('中心点'+sk.relative_y,'食物'+food[i][j][k].y)
if (food[i][j][k].d < food[i][j][k].r + this.r + 20) {
food[i][j][k].move(i, j, k);
this.weight += food[i][j][k].weight;
}
}
}
}//吃东西的函数
function _body(x, y) {
this.x = x;
this.y = y;
this.r = 15;
this.d = 100;
this.color = '#ffa400';
this.hua = function () {
huaban.beginPath();
huaban.fillStyle = 'white';
huaban.arc(this.x, this.y, this.r + 2, 0, Math.PI * 2);
huaban.fill();//蛇头边界
huaban.beginPath();
huaban.fillStyle = this.color;
huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
huaban.fill();//蛇头主体
}
}//蛇身体的构造函数
function _food(x, y) {
this.x = x;
this.y = y;
this.r = suiji(1, 3);
this.weight = this.r;
this.color = food_color[parseInt(suiji(0, 4))];
this.creta = function () {
huaban.beginPath();
huaban.fillStyle = this.color;
huaban.arc(this.x, this.y, this.r + 2, 0, Math.PI * 2);
huaban.fill();//画食物
};
this.move = function (i, j, k) {
var moveTime = setInterval(() => {
if (this.d < sk.r) {
clearInterval(moveTime);
food[i][j].splice(k, 1);
} else {
this.c = Math.sqrt((this.x - sk.x) ** 2 + (this.y - sk.y) ** 2);
this.x -= (this.x - sk.x) / this.c;
this.y -= (this.y - sk.y) / this.c;//
}
}, 1000 / 60)
}
}//食物的构造函数
function suiji(max, min) {
return Math.random() * (max - min) + min;
}//随机数函数
function add_food() {
for (var i = 0; i < 20; i++) {
for (var j = 0; j < 16; j++) {
for (var k = 0; k < food_number; k++) {
var _food_ = new _food(suiji(-800 + i * 120, -800 + (i + 1) * 120), suiji(-500 + j * 120, -500 + (j + 1) * 120));
food[i][j].push(_food_);
_food_.creta();
}
}
}
}//将食物添加进地图并用food三维数组来存储
function start() {
_bg = new bg();
_bg.hua();
sk = new snake();
sk.head();
_bg.run();
add_food();
body_jc.push[new _body(0, 0)];
}//开始函数
function jieshu() {
// huaban.clearRect(0, 0, 800, 500);//清除屏幕
}//蛇死掉时执行的函数
start();//开始执行的函数
function mouseMove(ev) {
ev = ev || window.event;
var mousePos = mouseCords(ev);
s_X = mousePos.x, s_Y = mousePos.y;
}//传递鼠标实时位置给s_X,s_Y。
function mouseCords(ev) {
if (ev.pageX || ev.pageY) {
return {
x: ev.pageX, y: ev.pageY
};
}
//获取鼠标的实时位置
}
document.onmousemove = mouseMove;//鼠标位置
document.querySelector('.mian').onclick = function () {
zanti++;
zanti % 2 == 0 ? life = false : life = true;
_bg.run();
}
游戏效果
游戏效果图
食物池来来存放的食物,减轻计算机的工作量,更高效的运行这个游戏,对手还没有写,自己的身体也还没有写,涉及到一些继承的算法,还在思考中,请大佬们赐教。
本文地址:https://blog.csdn.net/weixin_52624175/article/details/112752769
上一篇: ps怎么把文字放到倾斜的包装袋上? ps字体斜着放的技巧
下一篇: 十进制转格雷码