原生js+canvas實(shí)現(xiàn)貪吃蛇效果
本文實(shí)例為大家分享了canvas實(shí)現(xiàn)貪吃蛇效果的具體代碼,供大家參考,具體內(nèi)容如下
效果展示:

源碼展示:
頁面布局展示:worm.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>貪吃蛇</title>
<style type="text/css">
canvas{
border: 1px solid black;
}
div{
width: 50px; height: 50px;
border: 1px solid black; cursor: pointer;
text-align: center; line-height: 50px;
}
</style>
<script type="text/javascript" src="Node.js" ></script>
<script type="text/javascript" src="Worm.js" ></script>
<script src="Stage.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
function load () {
//創(chuàng)建一個(gè)舞臺(tái) 調(diào)用print方法打印
stage=new Stage();
//獲取ctx
var mCanvas=document.getElementById("mCanvas");
ctx=mCanvas.getContext('2d');
stage.print(ctx);
startPrint();
}
function changeDir(dir){
DIR=dir;
}
var task;
var stage;
var ctx;
function startPrint () {
task=window.setInterval(function () {
stage.worm.step();
stage.print(ctx);
}, SPEED);
}
function endPrint () {
window.clearInterval(task);
}
</script>
</head>
<body onload="load()">
<canvas id="mCanvas" width="500" height="500">
</canvas>
<table>
<tr>
<td></td>
<td>
<div onclick="changeDir(UP)">UP</div>
</td>
<td></td>
</tr>
<tr>
<td>
<div onclick="changeDir(LEFT)">LEFT</div>
</td>
<td></td>
<td>
<div onclick="changeDir(RIGHT)">RIGHT</div>
</td>
</tr>
<tr>
<td></td>
<td>
<div onclick="changeDir(DOWN)">DOWN</div>
</td>
<td></td>
</tr>
</table>
</body>
</html>
節(jié)點(diǎn)類的js :Node.js
/* 節(jié)點(diǎn)類 */
function Node (x, y) {
this.x=x;
this.y=y;
this.equals=function (i, j) {
return this.x==i && this.y==j;
};
}
舞臺(tái)類js:Stage.js
/** 舞臺(tái)類 */
function Stage () {
this.width=50;
this.height=50;
this.worm=new Worm();
/* 在canvas中繪制舞臺(tái)的內(nèi)容 */
this.print=function (ctx) {
for(i=0; i<this.width; i++){
for(j=0; j<this.height; j++){
//如果當(dāng)前節(jié)點(diǎn)是蛇身子的一部分
//那么換一種顏色繪制
if(this.worm.contains(i,j)){
ctx.fillStyle="#ab55ff";
ctx.fillRect(i*10, j*10, 10, 10);
}else if(this.worm.food.equals(i, j)){
ctx.fillStyle="#000000";
ctx.fillRect(i*10, j*10, 10, 10);
}else{
ctx.fillStyle="#dddddd";
ctx.fillRect(i*10, j*10, 10, 10);
}
}
}
//在舞臺(tái)的左上角繪制分?jǐn)?shù)
ctx.font="30px Arial";
ctx.fillStyle="#880000";
ctx.fillText("score:"+SCORE, 10,40);
};
}
蛇類js:Worm.js
/** 蛇類 */
var UP=0;
var DOWN=1;
var LEFT=2;
var RIGHT=3;
var DIR=UP;
var SCORE=0;
var SPEED=300;
//蛇類初始化的形狀
function Worm () {
this.nodes=[];
this.nodes[this.nodes.length]=new Node(20,10);
this.nodes[this.nodes.length]=new Node(20,11);
this.nodes[this.nodes.length]=new Node(20,12);
this.nodes[this.nodes.length]=new Node(20,13);
this.nodes[this.nodes.length]=new Node(20,14);
this.nodes[this.nodes.length]=new Node(20,15);
this.nodes[this.nodes.length]=new Node(21,15);
this.nodes[this.nodes.length]=new Node(22,15);
this.nodes[this.nodes.length]=new Node(23,15);
this.nodes[this.nodes.length]=new Node(24,15);
this.nodes[this.nodes.length]=new Node(24,16);
this.nodes[this.nodes.length]=new Node(24,17);
this.nodes[this.nodes.length]=new Node(24,18);
this.nodes[this.nodes.length]=new Node(24,19);
/* 蛇會(huì)走一步 */
this.step=function () {
//計(jì)算出頭結(jié)點(diǎn) 把頭節(jié)點(diǎn)添加到nodes數(shù)組中
var oldHead=this.nodes[0];
var newHead;
switch (DIR){
case UP:
if(oldHead.y-1<0){
newHead=new Node(oldHead.x, 49);
}else{
newHead=new Node(oldHead.x, oldHead.y-1);
}
break;
case DOWN:
if(oldHead.y+1>49){
newHead=new Node(oldHead.x, 0);
}else{
newHead=new Node(oldHead.x, oldHead.y+1);
}
break;
case LEFT:
if(oldHead.x-1<0){
newHead=new Node(49, oldHead.y);
}else{
newHead=new Node(oldHead.x-1, oldHead.y);
}
break;
case RIGHT:
if(oldHead.x+1>49){
newHead=new Node(0, oldHead.y);
}else{
newHead=new Node(oldHead.x+1, oldHead.y);
}
break;
}
this.nodes.unshift(newHead);
if(!this.food.equals(newHead.x, newHead.y)){
//把尾節(jié)點(diǎn)刪掉 (在沒有吃到食物的時(shí)候)
this.nodes.pop();
}else{
//吃到了食物 重新生成食物
this.food=this.randomFood();
SCORE+=10;
SPEED-=50;
endPrint();
startPrint();
}
};
/* 判斷i,j節(jié)點(diǎn)是否是當(dāng)前蛇身子的一部分 */
this.contains=function (i, j) {
for(k=0; k<this.nodes.length; k++){
var node=this.nodes[k];
if(node.x==i && node.y==j){
return true;
}
}
return false;
};
//聲明生成食物的方法
this.randomFood=function () {
var x;
var y;
do{
x=Math.floor(Math.random()*50);
y=Math.floor(Math.random()*50);
}while(this.contains(x, y));
return new Node(x, y);
};
//聲明食物
this.food=this.randomFood();
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js+for循環(huán)實(shí)現(xiàn)字符串自動(dòng)轉(zhuǎn)義的代碼(把后面的字符替換前面的字符)
這段代碼是從網(wǎng)上看到的一段不錯(cuò)的代碼,用for命令實(shí)現(xiàn)字符串的轉(zhuǎn)移,而且使用的是for循環(huán)直接將后面的字符替換成前面的字符,這個(gè)邏輯以前沒試過2020-12-12
基于JavaScript實(shí)現(xiàn)每日簽到打卡軌跡功能
這篇文章主要為大家詳細(xì)介紹了基于JavaScript實(shí)現(xiàn)每日簽到打卡軌跡功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
JavaScript實(shí)現(xiàn)簡(jiǎn)單音樂播放器
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單音樂播放器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
表單input項(xiàng)使用label同時(shí)引用Bootstrap庫導(dǎo)致input點(diǎn)擊效果區(qū)增大問題
這篇文章主要介紹了表單input項(xiàng)使用label,同時(shí)引用Bootstrap庫,導(dǎo)致input點(diǎn)擊效果區(qū)增大問題的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10
在多個(gè)頁面使用同一個(gè)HTML片段《續(xù)》
上一篇文章中我們使用textarea來模擬AJAX的返回結(jié)果,造成了一些誤解。 這里我們首先用asp.net的Generic Handler做一個(gè)簡(jiǎn)單的后臺(tái)來重現(xiàn)這個(gè)AJAX過程。2011-03-03
javascript實(shí)現(xiàn)圖片跟隨鼠標(biāo)移動(dòng)效果的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)圖片跟隨鼠標(biāo)移動(dòng)效果的方法,涉及javascript鼠標(biāo)事件及頁面元素的相關(guān)操作技巧,需要的朋友可以參考下2015-05-05
詳解用js代碼觸發(fā)dom事件的實(shí)現(xiàn)方案
這篇文章主要介紹了詳解用js代碼觸發(fā)dom事件的實(shí)現(xiàn)方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06

