h5制作貪吃蛇
- html
- css
- js
- 游戲效果
使用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://www.uj5u.com/qita/250129.html
標籤:其他
下一篇:位元幣上的數獨游戲合約
