前一阵子用纯php+session写了个贪吃蛇纯php实现贪吃蛇游戏(不使用JavaScript),这次再来个正常点儿的,JavaScript贪吃蛇,算法从上一版php贪吃蛇移植过来的,把部分php函数改成了JavaScript的方法,php版本是用table标签画蛇,JavaScript是用canvas画蛇,实现方法不一样,但算法都是一样的,下面还是先上效果图,再上代码。
界面没仔细雕琢,很简陋,下面还是先上代码。
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>贪吃蛇</title>
<style>
body{
overflow:hidden;
background:#000;
}
canvas{
position:absolute;
top:10px;
left:6px;
background:#000;
border:1px solid green;
}
.ctrl{
position:absolute;
top:430px;
left:6px;
width: 400px;
background:#000;
border:1px solid green;
}
button{
background: green;
color: #fff;
font-size: 30px;
border:none;
width:50px;
height: 40px;
text-align:center;
}
span{
color:green;
font-size:20px;
}
</style>
</head>
<!-- 引入vConsole的JS庫
<script src="./frameWork/vConsole/dist/vconsole.min.js"></script>
<script>
// 初始化vConsole
window.vConsole = new window.VConsole({
defaultPlugins: ['system', 'network', 'element', 'storage'], // 可以在此設定要默認加載的面板
maxLogNumber: 1000,
// disableLogScrolling: true,
onReady: () => {
},
onClearLog: () => {
console.log('on clearLog');
}
});
</script>
-->
<body>
<canvas width="400" height="400"></canvas>
<div class="ctrl">
<p> <button onclick="snake.direction='up'">↑</button> <span>得分:0</span></p>
<p> <button onclick="snake.direction='left'">←</button> <button onclick="snake.direction='right'">→</button> <button onclick="snake.startPause()">▶</button></p>
<p> <button onclick="snake.direction='down'">↓</button></p>
</div>
</body>
<script>
class Snake{
constructor(){
this.snake=[[19,19]];
this.rate=200;
this.getFood();
this.direction="left";
this.score=0;
this.print("🐍");
}
print(str){
let sc=document.querySelector("canvas").getContext("2d");
sc.clearRect(0,0,400,400);
sc.fillStyle="green";
if(str!=undefined){
sc.textAlign='center';
sc.font='bold 60px Arial';
sc.fillStyle="green";
sc.fillText(str,190,190);
return;
}
sc.fillRect(this.food[0]*20,this.food[1]*20,20,20);//画食物
for(var i in this.snake){
sc.fillRect(this.snake[i][0]*20,this.snake[i][1]*20,20,20);
}//画蛇
document.querySelector("span").innerText="得分:"+this.score;
}
cpu(){
let snakeHead=[];
//计算蛇头坐标
switch(this.direction){
case "up":{
snakeHead=[
this.snake[0][0],
this.snake[0][1]-1
];
break;
}
case "down":{
snakeHead=[
this.snake[0][0],
this.snake[0][1]+1
];
break;
}
case "left":{
snakeHead=[
this.snake[0][0]-1,
this.snake[0][1]
];
break;
}
case "right":{
snakeHead=[
this.snake[0][0]+1,
this.snake[0][1]
];
break;
}
}
//咬到自己,游戏结束
if(this.inArray(snakeHead,this.snake)){
this.gameOver();
return;
}
//添加蛇头坐标
this.snake.unshift(snakeHead);
//撞墙,游戏结束
if(this.snake[0][0]<0||this.snake[0][1]<0||this.snake[0][0]>19||this.snake[0][1]>19){
this.gameOver();
return;
}
//咬到食物得一分
if(this.inArray(this.food,this.snake)){
this.getFood();
this.score+=1;
}else{
this.snake.splice(this.snake.length-1,1);
}
}
getFood(){
this.food=[Math.round(Math.random()*19),Math.round(Math.random()*19)];
if(this.inArray(this.food,this.snake)){
this.getFood();
}
}
inArray(arr1,arr2){
let ina=false;
for(var i in arr2){
if(arr2[i][0]==arr1[0]&&arr2[i][1]==arr1[1]){
ina=true;
break;
}
}
return ina;
}
startPause(){
if(this.run==null){
document.querySelectorAll("button")[3].innerText="■";
this.run=setInterval(function(){
snake.cpu();
snake.print();
},this.rate);
}else{
document.querySelectorAll("button")[3].innerText="▶";
clearInterval(this.run);
this.run=null;
}
}
gameOver(){
this.startPause();
this.snake=[[19,19]];
this.getFood();
this.direction="left";
setTimeout(`snake.print("game over ")`,snake.rate+1);
this.score=0;
}
}
this.snake=new Snake();
</script>
</body>
</html>
贪吃蛇无非就是添头去尾,撞墙判断和吃自己判断,通过二维数组就能实现,JavaScript不像php那样没有常驻内存,没有定时器,但是处理数组的方法还是php好用一些,比如in_array()函数,JavaScript就得自己实现一个inArray方法。
$this.cpu()方法负责计算蛇体位置数组和食物以及方向控制和得分情况
this.print()方法负责通过页面自动刷新把数据显示在屏幕上
大体流程就是这样,代码注释比较详细了。
要是在电脑端玩最好加上键盘监听,通过键盘控制蛇体方向,这里不再赘述,很简单。
好了,今天就分享这些。