github代碼地址:https://github.com/McRayFE/snake
涉及到的知識點:
- 鍵盤事件
- setInterval()定時器
- javascript中數(shù)組的使用
- 碰撞的檢測
- offsetLeft,offsetWidth,offsetTop,offsetHeight
實現(xiàn)的思路
- 讓小蛇動起來
- 讓食物隨機生成
- 檢測碰撞
- 讓身體跟隨
HTML主體代碼
<div class="container">
<!--小蛇移動的操場-->
<div id="playground">
<!--小蛇-->
<div id="snake"></div>
<!--食物-->
<div id="food"></div>
</div>
<!--記錄得分-->
<div id="menu">
<div>得分<span id="score"></span></div>
</div>
</div>
一個小蛇移動的操場playground
嫁蛇,里面包含了小蛇snake
和食物food
,還有一個記錄得分的menu
CSS代碼
*{
padding:0;
margin:0;
}
.container{
width:600px;
height:500px;
margin:0 auto;
}
#playground{
width:450px;
height:100%;
background-color:pink;
float:left;
position:relative;
}
#menu{
width:150px;
height:100%;
background-color:blue;
float:left;
}
#snake{
width:20px;
height:20px;
background-color:red;
position:absolute;
left:0;
top:0;
}
#food{
width:20px;
height:20px;
background-color:yellow;
position:absolute;
}
.body{
width:20px;
height:20px;
background-color:green;
position:absolute;;
top:0;
left:0;
}
#score{
font-size:30px;
font-weight:bold;
color:black;
}
#menu div{
font-size:20px;
font-weight:bold;
margin-left:20px;
}
此時界面的效果如下:
獲取元素和定義全局變量
var snake = document.getElementById("snake");
var food = document.getElementById("food");
var playground = document.getElementById("playground");
var score = document.getElementById('score');
/*設(shè)置全局變量*/
var timer;
var srr = [];//存放蛇的位置的數(shù)組
var num = 0;//數(shù)組的長度
var snakeBody;//每次吃調(diào)一個食物,增加的身體
var timer1 = setInterval(eat,10);//設(shè)置一個碰撞的時間器
讓小蛇動起來
監(jiān)聽鍵盤事件,判斷上下左右鍵的ASCII碼值來執(zhí)行不同方向的移動函數(shù)首量,其中每移動1px氓栈,就要將小蛇的位置存入到arr[]
數(shù)組中,因為后面實現(xiàn)身體跟隨的時候厉膀,是根據(jù)數(shù)組里面的位置來動態(tài)變化的颤殴。
document.onkeydown = function(e){
var evt = window.evnet || e;
switch(evt.keyCode){
case 37://左
clearInterval(timer);
timer = window.setInterval(runLeft,10);//向左移動的時間器
function runLeft(){
if(snake.offsetLeft > 0){
snake.style.left = snake.offsetLeft - 1 + 'px';
snake.style.top = snake.offsetTop + 'px';
srr.push([snake.offsetLeft,snake.offsetTop]);//每移動1px觅廓,就將位置存進(jìn)數(shù)組中
num++;//相應(yīng)的數(shù)組長度加1
}else{
clearInterval(timer);
console.log("failed!");
}
}
break;
case 38://上
clearInterval(timer);
timer = window.setInterval(runTop,10);
function runTop(){
if(snake.offsetTop > 0){
snake.style.top = snake.offsetTop - 1 + 'px';
snake.style.left = snake.offsetLeft + 'px';
srr.push([snake.offsetLeft,snake.offsetTop]);
num++;
} else{
clearInterval(timer);
console.log("failed!");
}
}
break;
case 39://右
clearInterval(timer);
timer = window.setInterval(runRight,10);
function runRight(){
if(snake.offsetLeft < 430){
snake.style.left = snake.offsetLeft + 1 + 'px';
snake.style.top = snake.offsetTop + 'px';
srr.push([snake.offsetLeft,snake.offsetTop]);
num++;
} else{
clearInterval(timer);
console.log("falied!");
}
}
break;
case 40://下
clearInterval(timer);
timer = window.setInterval(runBottom,10);
function runBottom(){
if(snake.offsetTop < 480) {
snake.style.top = snake.offsetTop + 1 + 'px';
snake.style.left = snake.offsetLeft + 'px';
srr.push([snake.offsetLeft,snake.offsetTop]);
num++;
}else{
clearInterval(timer);
console.log("falied!");
}
}
break;
}
}
讓食物隨機產(chǎn)生
運用了Math類里面的random
方法實現(xiàn)食物的隨機產(chǎn)生,代碼如下涵但,配合碰撞檢測使用
function pos(){
food.style.left = parseInt(Math.random()*430) + 'px';
food.style.top = parseInt(Math.random()*480) + 'px';
}
碰撞檢測
小蛇和食物不碰撞有四種可能杈绸,圖中黃色是食物,紅色是小蛇:
第一種情況:
第二種情況:
第三種情況:
第三種情況
除了以上四種情況以外的都是碰撞的情況矮瘟,所以代碼如下
/*檢測碰撞函數(shù)*/
function eat(){
snakeCrashFood(snake,food);
function snakeCrashFood(obj1,obj2){
var obj1Left = obj1.offsetLeft;
var obj1Width = obj1.offsetWidth + obj1.offsetLeft;
var obj1Top = obj1.offsetTop;
var obj1Height = obj1.offsetHeight + obj1.offsetTop;
var obj2Left = obj2.offsetLeft;
var obj2Width = obj2.offsetWidth + obj2.offsetLeft;
var obj2Top = obj2.offsetTop;
var obj2Height = obj2.offsetHeight + obj2.offsetTop;
if(!((obj1Width<obj2Left)||(obj2Width<obj1Left)||(obj1Height<obj2Top)||(obj2Height<obj1Top))){
snakeBody = document.createElement("div");
snakeBody.setAttribute("class","body");
playground.appendChild(snakeBody);//添加一節(jié)新的身體
pos();//讓食物重新隨機出現(xiàn)
setInterval(follow,10);//動態(tài)地改變新的身體的位置
}
}
}
讓身體跟隨
在講讓小蛇動起來的那一節(jié)的時候瞳脓,已經(jīng)提到過了,小蛇每移動1px澈侠,都會將此時的位置存入到位置數(shù)組中劫侧,這個位置數(shù)組就是在這一節(jié)里面起作用的,能讓身體動態(tài)地跟隨哨啃,看下面的圖片
紅色的頭節(jié)點移動了40px烧栋,此時arr[]
數(shù)組的長度就為40,那么第二節(jié)身體的位置剛好就是arr[20]
的位置拳球,第三節(jié)的位置就是arr[40]
的位置审姓,依次加等20。醇坝。邑跪。實現(xiàn)的代碼如下
/*身體跟隨函數(shù)*/
function follow(){
/*獲得增加的身體的數(shù)組*/
var bodyNum = document.getElementsByClassName("body");
score.innerHTML = bodyNum.length;
var place = 0;
/*數(shù)組每移動1px,新的身體的位置就是相對于前一個身體的第20個數(shù)組的位置,后面依次加等*/
for(var i=0;i<bodyNum.length;i++){
place += 20;
bodyNum[i].style.left = srr[num-place][0] + 'px';
bodyNum[i].style.top = srr[num-place][1] + 'px';
}
}