首先声明: 这个贪食蛇的小游戏,是我闲来无事写的。没有参考任何范例,纯原创。
对于JS我是一个初学者 ,如有不足的地方,勿喷。
虽然只是一个小小的游戏,但还是有必要声明一下,仅供学习、参考使用,不得用于商业用途(我 是觉得不大可能)。
个人觉得功能还不完善,如果有哪位大神可以完善一下就更好了。
代码大概有五六百行,分为三个文件一个html文件和两个js文件,下面是这三个文件的代码。
如果你觉得下面的代码看起来太麻烦,可以联系我的邮箱 jsennahe@foxmail.com ,我会将整个工程文件发给你。
由于嫌麻烦就没有将html、js、css 分开写,请见谅。
HTML文件 tancishe.html代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>这是:贪食蛇</title>
<link rel="stylesheet" >
<style>
#canvas{
z-index: -1;
}
#Father{
height: 655px;
width: 1220px;
margin: 0 auto;
margin-top: 5px;
/*background-color: #a9a9a9;*/
border:none;
}
body{
background-image:url(back4.jpg);
}
.ziti1{
font-size: 50px;
color: #FFFAFA;
font-family: "楷体";
}
.ziti2{
font-size: 30px;
font-family: "楷体";
color:#696969;
}
.ziti2:hover{
color:#fff;
}
a{
text-decoration: none;
}
.Top1{
margin: 0 auto;
width: 1220px;
height: 30px;
border-bottom: 3px dotted #696969;
line-height: 30px;
display: none;
}
.Top-left{
width: 403px;
height: 40px;
float: left;
line-height: 40px;
z-index: 6;
}
.Top-right{
width: 403px;
height: 40px;
float: right;
line-height: 40px;
z-index: 6
}
.fontstyle{
}
</style>
</head>
<body align="center" id="body">
<!-- 顶部的展示部分 -->
<div class="Top">
<!-- <input type="text" width="100" height="20" /> -->
<!-- <div class="Top-center"> --><!--<a><font class="ziti1">贪食蛇</font></a>--><!-- </div> -->
</div>
<!-- 中部游戏主界面 -->
<div align="center" id="Father" >
<div class="Top1" id="timeandlong">
<!-- <input type="text" width="100" height="20" /> -->
<div class="Top-left" ><font color="#696969" class="fontstyle">时间:</font><font color="#696969" id="Time">00</font></div>
<!-- <div class="Top-center"> --><a href="javascript:window.opener=null;window.open('','_self');window.close();" ><font class="ziti2">关闭</font></a><!-- </div> -->
<div class="Top-right"><font color="#696969"class="fontstyle">长度:</font><font color="#696969" id="Length" >00</font></div>
</div>
<canvas id="canvas" width="1210" height="610" >
</canvas>
<div>
<!-- //背景音乐 -->
<audio id = "sud" loop="loop" autoplay="autoplay" hidden="true" >
<source src="http://12844029.s21d-12.faiusrd.com//55//ABUIABA3GAAgkbWfxQUo7djo9QE" type="audio/mpeg" type="audio/mpeg" />
</audio>
<!-- //吃子音效 -->
<audio id = "sud1" hidden="true">
<source src="http://12844029.s21d-12.faiusrd.com/0/ABUIABAAGAAg6Z2fxQUopdGr9gM" type="audio/mpeg" />
</audio>
<!-- //结束音效 -->
<audio id = "sud2" hidden="true">
<source src="http://12844029.s21d-12.faiusrd.com/55/ABUIABA3GAAgpo6fxQUo4JnL4QE" type="audio/mpeg" />
</audio>
<script src="http://12844029.s21d-12.faiusrd.com//0//ABUIABAAGAAgoP7ZxQUonPGOMg"></script>
<script src="http://12844029.s21d-12.faiusrd.com//0//ABUIABAAGAAgrduRxQUojMbG7wE"></script>
<script>
var audio0 = document.getElementById('sud'); //背景音乐
var audio1 = document.getElementById('sud1'); //吃方块
var audio2 = document.getElementById('sud2'); //结束游戏
window.οnlοad=function(){
//Our code here...
var GTime=document.getElementById('Time');//显示时间元素
var SLength=document.getElementById('Length');
var timelong=document.getElementById("timeandlong");
var father=document.getElementById('Father');
var canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
mouse = utils.captureMouse(canvas);
var arr = []; //数组用于存放身体的方块
var fps = 500; //帧的刷新时间500ms
var a=0; //判断按钮文字颜色 1-开始游戏,2-结束游戏,3-游戏帮助
var timer1; //定时器1 频率是10毫秒
var timer2; //定时器2 频率是400毫秒
head =new HeadFang(); //new 的头方块
//为头方块随机生成一个位置
head.x = Math.floor(Math.random()*22) * 50;//Math.random() * canvas.width;
head.y = Math.floor(Math.random()*10) * 50;//Math.random() * canvas.height;
//初始化速度为零
var vx=0,vy=0;
//初始化三个方块的身体
for(var fang,i = 0 ; i < 3; i++){
fang = new Fang(20);
fang.id = "fang" + i;
fang.x = head.x*(i+1)*10;//Math.random() * canvas.width;
fang.y = head.y*(i+1)*10;//Math.random() * canvas.height;
arr.push(fang);
}
//监听键盘的上下左右键
window.addEventListener('keydown',function(event){
switch(event.keyCode){
case 37:
if(vy!=0){
vy=0;
}
if(vx == 0){
vx = -head.width;
}
break;
case 39:
if(vy!=0){
vy=0;
}
if(vx == 0){
vx = head.width;
}
break;
case 38:
if(vx!=0){
vx=0;
}
if(vy == 0){
vy = -head.width;
}
break;
case 40:
if(vx!=0){
vx=0;
}
if(vy == 0){
vy = head.width;
}
break;
}
},false);
//一个递归方法,将后一个方块放到前一个方块的位置
function draw(arrlang){
if(arrlang>=arr.length-1)return;
else{
draw(arrlang+=1);
if(arrlang!=0){
arr[arrlang].x=arr[arrlang-1].x;
arr[arrlang].y=arr[arrlang-1].y;
}
//console.log(arrlang+" "+arr.length);
arr[arrlang].draw(context);
}
}
function ResetAll(){
//重新计算头的坐标,并将速度置为零
head.x = Math.floor(Math.random()*22) * 50;
head.y = Math.floor(Math.random()*10) * 50;
vx=0;
vy=0;
//保留数组的前三个对象
arr=arr.slice(0,3);
for(var i=0;i<arr.length;i++){
arr[i].x=head.x;
arr[i].y=head.y;
}
}
//游戏结束所绘制的东西
function gameover(Over){
//添加监听事件
canvas.addEventListener('mousedown',function(){
//判断鼠标是否在指定的区域内
if(utils.containsPoint(Over.getBounds(),mouse.x,mouse.y)){
//document.write("in ball : mousedown");
console.log("***mousedown***");
begin=0;
value=0;
Over=null; //销毁结束画面对象
//结束游戏是将游戏时间重置为零
time1=0;
//将画面的刷新时间重置
fps=500;
audio0.play();
timelong.setAttribute('style','display: none;');
}else {
//document.write("canvas:mousedown");
}
},false);
//调用重置方法
ResetAll();
//设置显示的文字
Over.name1="Over";
Over.name2="重新开始";
btnstyle(Over);
Over.draw(context);
}
//游戏开始所绘制的东西
function gamebegin(Begin){
//添加监听事件
canvas.addEventListener('mousedown',function(){
//判断鼠标是否在指定的区域内
if(utils.containsPoint(Begin.getBounds(),mouse.x,mouse.y)){
//document.write("in ball : mousedown");
//console.log("***mousedown***");
//调用全屏的方法,点击开始游戏后就全屏显示
quan();
//window.open(document.location, 'big', 'fullscreen=yes');
Begin=null;
begin=1;
var myDate = new Date();
//var mytime=myDate.getTime();
time=myDate.getTime();
//显示边框和游戏参数
timelong.setAttribute('style','display: block;');
father.setAttribute('style','border:3px dotted #696969;')
}
else{
}
/*else if(utils.containsPoint(Begin.getBounds1(),mouse.x,mouse.y)){
console.log("结束游戏");
window.close();
}
else if(utils.containsPoint(Begin.getBounds2(),mouse.x,mouse.y)){
console.log("游戏帮助");
}*/
},false);
//按钮样式
btnstyle(Begin);
Begin.name1="贪吃蛇";
Begin.name2="开始游戏";
Begin.draw(context);
}
// 按钮样式
function btnstyle(be){
var obj=be;
if(utils.containsPoint(obj.getBounds(),mouse.x,mouse.y)){
obj.color="#fff";
obj.x1=50;
a=1;
canvas.style.cursor="pointer";
}else if(utils.containsPoint(obj.getBounds1(),mouse.x,mouse.y)){
obj.color1="#fff";
obj.x2=50;
a=2;
canvas.style.cursor="pointer";
}else if(utils.containsPoint(obj.getBounds2(),mouse.x,mouse.y)){
obj.color2="#fff";
obj.x3=50;
a=3;
canvas.style.cursor="pointer";
}else{
switch(a){
case 1:
Begin.color="#fff";
Begin.x1=50;
break;
case 2:
Begin.color1="#fff";
Begin.x2=50;
break;
case 3:
Begin.color2="#fff";
Begin.x3=50;
break;
}
canvas.style.cursor="auto";
}
}
//监听其他按钮事件
function Anfun(BO){
canvas.addEventListener('mousedown',function(){
//判断鼠标是否在指定的区域内
if(utils.containsPoint(BO.getBounds1(),mouse.x,mouse.y)){
//console.log("结束游戏");
window.close();
}
else if(utils.containsPoint(BO.getBounds2(),mouse.x,mouse.y)){
//console.log("游戏帮助");
}else {
//console.log("无效的鼠标点击");
}
},false);
}
//判断是否自己撞自己
function Self(){
var value=0;
for(var i=3;i<arr.length-1;i++){
if(arr[i].x==head.x && arr[i].y==head.y){
value++;
break;
}
}
return value;
}
//实现全屏
function requestFullScreen(element) {
var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen;
if (requestMethod) {
requestMethod.call(element);
}
else if (typeof window.ActiveXObject !== "undefined") {
var wscript = new ActiveXObject("WScript.Shell");
if (wscript !== null) {
wscript.SendKeys("{F11}");
}
}
}
//全屏方法
function quan(){
var elem = document.getElementById("body");
requestFullScreen(elem);
};
var value=0; //由于判断新生成的方块是否被吃 没有被吃(1) 被吃(0)
var NewFang; //新生成方块的名称
var begin=0; //判断是否是 开始游戏(0) 进行游戏(1) 结束游戏(2)
//开始和结束游戏所绘制画面的两个对象
var Begin;
var Over;
var time=0; //用来计时的
var time1=0; //游戏所用的秒数
//开始或结束游戏绘制的主方法
function drawFrame1(){
context.clearRect(0,0,canvas.width,canvas.height);
if(begin==0){
Begin=new BOgame();
gamebegin(Begin);
Anfun(Begin);
audio0.play();
SLength.innerHTML=arr.length-1;
}
else if(begin==2){
Over=new BOgame();
gameover(Over);
Anfun(Over);
}
else {
//清除开始或结束游戏的定时器,启用进行游戏的定时器
clearInterval(timer1);
timer2=setInterval(drawFrame,fps);
}
}
//进行游戏绘制主方法
function drawFrame(){
//window.requestAnimationFrame(drawFrame,canvas);
context.clearRect(0,0,canvas.width,canvas.height);
//将时间打印到上
GTime.innerHTML=time1;
//否则判断是否结束游戏
if(head.x >= canvas.width-10 || head.x <= -5 || head.y >= canvas.height-10 || head.y <= -5 || Self()!=0 )
{
Over=new BOgame();
gameover(Over);
// Anfun(Over);
//将游戏状态置为结束
begin=2;
//开始播放结束音乐
audio2.play();
//停止播放背景音乐
audio0.pause();
audio0.currentTime = 0;
//value=2;
timelong.setAttribute('style','display: block;');
father.setAttribute('style','border:none;')
//清除进行游戏的定时器,启用开始或结束游戏的定时器
clearInterval(timer2);
timer1=setInterval(drawFrame1,10);
}
//否则进行游戏
if(begin==1){
canvas.style.cursor="none";
//如果开始的速度等于零,则不进行移动
if(vx!=0||vy!=0){
arr[0].x=head.x;
arr[0].y=head.y;
//调用一个递归方法,形成蛇往前走的效果
draw(0);
head.x += vx;
head.y += vy;
head.draw(context);
//fps+=10;
var myDate = new Date();
var mytime=0;
mytime=myDate.getTime();
if(mytime-time>=1000){
time=myDate.getTime();
time1=time1+1;
}
}
head.draw(context);
//当value=0时表示新生成的方块被吃,再重新生成一个方块
if(value==0){
NewFang =new Fang();
NewFang.x = Math.floor(Math.random()*23) * 50;//Math.random() * canvas.width;
NewFang.y = Math.floor(Math.random()*11) * 50;//Math.random() * canvas.height;
value=1;
}
if(begin!=2){
NewFang.draw(context);
}
//NewFang.draw(context);
//判断是否吃到点,
if(NewFang.x==head.x && NewFang.y==head.y){
SLength.innerHTML=arr.length;
audio1.play();
value=0;
if(fps>=150){
fps-=10;
//没吃到一个,就将画面的刷新的时间减少十毫秒
clearInterval(timer2);
timer2=setInterval(drawFrame,fps);
}
arr.push(NewFang);
}
}
}
//window.setInterval(drawFrame,fps);
timer1=setInterval(drawFrame1,10);
};
</script>
</body>
</html>
JS文件 fang.js 代码:
function Fang() {
this.x = 0;
this.y = 0;
this.width = 50;
this.height = 50;
this.rotation = 0;
this.color = "#7FFFD4";
}
Fang.prototype.draw = function() {
context.save();
context.translate(this.x, this.y);
context.rotate(this.rotation);
context.lineWidth = 1;
context.strokeStyle = "#00ffff";
context.fillStyle = this.color;
context.beginPath();
context.moveTo(10, 10);
context.lineTo(50, 10);
context.lineTo(50, 50);
context.lineTo(10, 50);
context.lineTo(10, 10);
context.closePath();
context.stroke();
context.restore();
};
function HeadFang() {
this.x = 0;
this.y = 0;
this.width = 50;
this.height = 50;
this.rotation = 0;
this.color = "#ff0000";
}
HeadFang.prototype.draw = function() {
context.save();
context.translate(this.x, this.y);
context.rotate(this.rotation);
context.lineWidth = 1;
context.strokeStyle = "#ff0000";
context.fillStyle = this.color;
context.beginPath();
context.moveTo(10, 10);
context.lineTo(50, 10);
//context.lineTo(75,30);
context.lineTo(50, 50);
context.lineTo(10, 50);
// context.lineTo(50,30);
// context.lineTo(10,50);
context.lineTo(10, 10);
context.closePath();
context.stroke();
context.restore();
};
function BOgame() {
this.x = 15; //三个按钮的横坐标
this.x1= 25; //开始游戏按钮上文字的横坐标
this.x2= 25; //结束游戏按钮上文字的横坐标
this.x3= 25; //游戏帮助按钮上文字的横坐标
this.y = 365; //开始游戏按钮‘框’纵坐标
this.y1= 445; //结束游戏按钮‘框’纵坐标
this.y2= 525 //游戏帮助按钮‘框’纵坐标
this.width = 215;
this.height = 65;
//三个按钮的颜色
this.color = "#DF5326";
this.color1 = "#DF5326";
this.color2 = "#DF5326";
this.name = "Game";
this.name1 = "贪吃蛇";
this.name2 = "开始游戏";
this.name3 = "退出游戏";
this.name4 = "游戏指南";
}
BOgame.prototype.draw = function() {
//上部左边文字
context.font = 'bold 144px consolas';
context.textAlign = 'left';
context.textBaseline = 'top';
context.strokeStyle = '#DF5326';
context.strokeText(this.name, 15, 150);
//this.txt(this.name, false, 'bold 144px consolas', '#DF5326', 15, 249);
上部右边文字
context.font = 'bold 90px arial';
context.strokeStyle = '#DF5326';
//context.fillStyle = 'red';
context.strokeText(this.name1, 350,200);
//this.txt(this.name1, false, 'bold 90px consolas', '#DF5326', 350, 249);
按钮文字-开始游戏-
context.font = 'bold 50px 楷体';
context.fillStyle = this.color;
context.fillText(this.name2, this.x1,380);
//this.txt(this.name2, true, 'bold 50px 楷体', this.color, this.x1, 380);
按钮文字-退出游戏-
context.font = 'bold 50px 楷体';
context.fillStyle = this.color1;
context.fillText(this.name3, this.x2,460);
//this.txt(this.name3, true, 'bold 50px 楷体', this.color1, this.x2, 460);
按钮文字-游戏指南-
context.font = 'bold 50px 楷体';
context.fillStyle = this.color2;
context.fillText(this.name4, this.x3,540);
//this.txt(this.name4, true, 'bold 50px 楷体', this.color2, this.x3, 540);
};
//鼠标范围-开始游戏
BOgame.prototype.getBounds = function() {
return {
x: this.x,
y: this.y,
width: this.width,
height: this.height,
};
};
//鼠标范围-退出游戏
BOgame.prototype.getBounds1 = function() {
return {
x: this.x,
y: this.y1,
width: this.width,
height: this.height,
};
};
//鼠标范围-游戏帮助
BOgame.prototype.getBounds2 = function() {
return {
x: this.x,
y: this.y2,
width: this.width,
height: this.height,
};
};
第二个JS文件 utils.js代码:
var utils={};
utils.captureMouse=function(element){
var mouse={x:0,y:0};
element.addEventListener('mousemove',function(event){
var x,y;
if(event.pageX||event.pageY){
x=event.pageX;
y=event.pageY;
}else{
x=event.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;
y=event.clientY+document.body.scrollTop+document.documentElement.scrollTop;
}
x-=element.offsetLeft;
y-=element.offsetTop;
mouse.x=x;
mouse.y=y;
},false);
return mouse;
};
utils.containsPoint = function (rect, x, y){
return !(x < rect.x || x > rect.x + rect.width || y < rect.y || y > rect.y + rect.height);
};
这是一开始的画面
这是游戏进行时的画面
这是游戏结束时的画面