h5+js實現單機版貪吃蛇

項目地址-> 已上傳github

項目地址-> 碼雲

項目演示地址


技術細節html

  • 全部的全局變量
var snake_body  // 蛇節數組,存儲每一個蛇節的位置
var direction   // 蛇當前移動的方向
var food_position   // 食物的位置,每次被蛇吃掉時更新
複製代碼
  • 初始化蛇節數組和蛇開始移動的方向、食物的位置
function init_snake() {
    // 數組中每個值都是一個對象,裏面存放了x、y軸的座標位置和color顏色信息,red是蛇頭
    snake_body = [{
    	x: 40,
    	y: 40,
    	color: 'black'
    }, {
    	x: 60,
    	y: 40,
    	color: 'black'
    }, {
    	x: 80,
    	y: 40,
    	color: 'red'
    }]
    // 蛇開始默認向右邊移動
    direction = 'right'
    // 食物開始位置
    food_position = {
    	x: 260,
    	y: 180
    }
}
// 調用蛇的初始化方法
init_snake()
複製代碼
  • 先將遊戲場景畫好,
// init canvas
function init() {
    context.strokeStyle = '#EEEEEE'
    for(var i = 0; i < 500; i += 20) {
        // 畫豎線
    	context.moveTo(i, 0)
    	context.lineTo(i, 500)
    	// 畫橫線
    	context.moveTo(0, i)
    	context.lineTo(500, i)
    }
    context.stroke()
    // 由於遊戲場景中默認會有一個食物,這個食物在隨機位置生成
    context.fillStyle = 'black'
    context.fillRect(food_position.x, food_position.y, 20, 20)
}   
複製代碼
  • 開始畫蛇
// repaint snake fastival
function draw_snake() {
    var new_fastival = []
    for(var i = 0; i < snake_body.length; i++) {
        context.fillStyle = snake_body[i].color
        context.fillRect(snake_body[i].x, snake_body[i].y, 20, 20)
        new_fastival.push({
    	    x: snake_body[i].x,
    	    y: snake_body[i].y
        })
    }
    // 判斷是否和食物發生碰撞
    eat_food()
    // 判斷是否死亡
    dead(new_fastival)
}
複製代碼
  • 監聽鍵盤點擊事件,根據keycode修改direction方向變量
// left 37
// right 39
// top 38
// bottom 40
window.addEventListener('keydown', function(e) {
    if(e.keyCode == 37) {
    	if(direction != 'right') {
            direction = 'left'
    	}
    } else if(e.keyCode == 39) {
    	if(direction != 'left') {
            direction = 'right'
    	}
    } else if(e.keyCode == 38) {
    	if(direction != 'bottom') {
    	    direction = 'top'
    	}
    } else if(e.keyCode == 40) {
    	if(direction != 'top') {
            direction = 'bottom'
    	}
    }
})
複製代碼
  • 蛇的移動方法
    經過將後一位數組的值賦值給前一位,最後將snake_body蛇節數組中最後一個元素的x或y值加上一個蛇節的寬度,若是是left方向,x-=20,right方向x+=20,top方向y-=20,bottom方向y+=20。
function move_snake() {
    var x = 0, y = 0
    // 對方向做判斷
    if(direction == 'right') {
    	x = 20
    } else if(direction == 'left') {
    	x = -20
    } else if(direction == 'top') {
    	y = -20
    } else if(direction == 'bottom') {
    	y = 20
    }
    for(var i = 0; i < snake_body.length - 1; i++) {
    	snake_body[i].x = snake_body[i + 1].x
    	snake_body[i].y = snake_body[i + 1].y
    }
    snake_body[snake_body.length - 1].x += x
    snake_body[snake_body.length - 1].y += y
}
複製代碼
  • 判斷食物是否被吃掉
function eat_food() {
    // 若是蛇節數組中最後一個對象的x、y值等於食物的x、y值,那麼這個食物將會被蛇吃掉
    if(snake_body[snake_body.length - 1].x == food_position.x && snake_body[snake_body.length - 1].y == food_position.y) {
    	// 再次生產食物
    	random_food()
    	// 蛇在吃掉食物以後將會添加一個蛇節
    	add_snake_fastival()
    }
}
複製代碼
  • 食物在被吃掉以後,位置將隨機生產
// 隨機生產食物位置的方法
function random_food() {
    food_position = {
        // ~~ 是位運算取整算法,比Math.floor()這個方法效率高
    	x: ~~(Math.random() * (500 / 20)) * 20,
    	y: ~~(Math.random() * (500 / 20)) * 20
    }
}
複製代碼
  • 爲蛇添加一個蛇節
function add_snake_fastival() {
    // 新蛇節
    new_fastival = {
    	x: snake_body[0].x - 20,
    	y: snake_body[0].y - 20,
    	color: 'black'
    }
    // 在全局數組中的頭部添加
    snake_body.unshift(new_fastival)
}
複製代碼
  • 判斷蛇是否死掉,蛇在撞牆或者撞本身都會死掉
function dead(new_fastival) {
    var last_fastival = snake_body[snake_body.length - 1]
    // 判斷是否撞牆
    if(last_fastival.x == -20 || last_fastival.x == 500 || last_fastival.y == -20 || last_fastival.y == 500) {
    	alert("從新開始遊戲")
    	init_snake()
    }
    // 判斷是否自殘
    for(var i = 0; i < new_fastival.length; i++) {
    	for(var j = i + 1; j < new_fastival.length; j++) {
            if(new_fastival[i].x == new_fastival[j].x && new_fastival[i].y == new_fastival[j].y) {
            	alert("從新開始遊戲")
            	init_snake()
            }
    	}
    }
}
複製代碼
  • 效果圖

在canvas遊戲開發中,咱們會遇到像這樣不少節點須要進行碰撞檢測。

而重複寫這些碰撞檢測代碼會極大的影響咱們的開發效率,我根據我之前用過的遊戲引擎的經驗,如unitycocos creator..。

我本身編寫了一個插件,專門用於碰撞檢測,只須要傳入x、y、width、height等參數,你就能夠很方便的進行遊戲開發了~~

碰撞檢測博客請另參見 本身模擬遊戲引擎,動手寫個js碰撞檢測插件,若是有任何問題,歡迎你們來和我交流!git

相關文章
相關標籤/搜索