貪吃蛇js

那誰呀撒發表於2020-10-26

在這裡插入圖片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>簡易的貪吃蛇遊戲</title>

		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
			}
			.m{width:400px;
				margin-top: 50px;
    margin-left: auto;
    margin-right: auto;
}
		</style>
	</head>
	<body>
		<div class="m">
			<canvas id='view' width="400" height="400" style="border:1px solid #111;"></canvas>
			<button id='start'>開始</button>
			<button id='parse'>暫停</button>
			<button id='restart'>重新開始</button>
			<h4>最高分: <span id='scoreMax' style='color:red;'>0</span></h4>
			<h4>分數: <span id='score' style='color:skyblue;'>0</span></h4>
		</div>
		<script src="js/config.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/score.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/area.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/food.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/snake.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/move.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript">
			var start = document.getElementById('start');
			var parse = document.getElementById('parse');
			var restart = document.getElementById('restart');
			start.onclick = function() {
				parse = false;
			}
			parse.onclick = function() {
				parse = true;
			}
			restart.onclick = function() {
				snake && snake.restart();
				parse = false;
			}
		</script>
	</body>
</html>

config.js

var exit = [];
// 代表蛇佔的空間
var parse = true;
// 拿元素、建立畫布
var view = document.getElementById('view');
var ctx = view.getContext('2d');
var width = 400,
    height = 400;
var w = 20,
    h = 20;
var maxX = (width / w) - 1,
    maxY = (height / h) - 1;
var speed = 500;
var scoreMax = 0;

var imgsrcs = [
    './img/snakeheadup.png',
    './img/snakeheaddown.png',
    './img/snakeheadleft.png',
    './img/snakeheadright.png'
];
var imgs = [];
var length = 4;
for (var i = 0, len = imgsrcs.length; i < len; i++) {
    var img = new Image(20, 20);
    img.src = imgsrcs[i];
    imgs[i] = img;
}
// 拿到各種需要的變數
var food, snake, move, score;

score.js

var scoreDom = document.getElementById('score');
var scoreMaxDom = document.getElementById('scoreMax');
// 成績類的構造器
function Score() {
    this.score = 0;
}
// 成績類的原型
Score.prototype = {
    scoreAdd: function() {
        this.score += 1;
        scoreDom.innerHTML = this.score;
    },
    scoreClear: function() {
        this.score = 0;
        scoreDom.innerHTML = 0;
    },
    highScore: function() {
        scoreMax = scoreMax > this.score ? scoreMax : this.score;
        scoreMaxDom.innerHTML = scoreMax;
    }
}

area.js

// 畫一幀的頁面
function render(x, y, color, img) {
    ctx.beginPath();
    // 起筆
    ctx.fillStyle = color || 'red';
    // 設定筆
    if (img) {
        ctx.drawImage(img, x * w, y * h, img.width, img.height);
        // drawImage(img,x,y,w,h),canvas用來畫圖片的api
    } else {
        ctx.fillRect(x * w, y * h, w, h);
        // 畫方框的api
    }
    ctx.closePath();
    ctx.fill();
}
// 清理畫布
function clear(x, y) {
    ctx.clearRect(x * w, y * h, w, h);
}

food.js

function Food() {
    this.init();
    // 這裡this指向的是自己的原型
}

Food.prototype = {
    init: function() {
        this.update();
    },
    update: function() {
        var food = this.makeCoordinate();
        this.food = food;
        var foodX = food[0];
        var foodY = food[1];
        this.render(foodX, foodY);
    },
    render: function(x, y) {
        render(x, y, 'blue');
    },
    makeCoordinate: function() {
        var x = this.random(0, maxX);
        var y = this.random(0, maxY);
        for (var i = 0; i < exit.length; i++) {
            if (exit[i].toString() == [x, y].toString()) {
                return this.makeCoordinate();
            }
        }
        return [x, y];
    },
    random: function(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
}

snake.js

function Snake() {
    this.head = [0, 5, imgs[1]]; // x,y座標,頭
    this.body = []; // 二維陣列,身體
    this.snake = []; //完整的蛇
    this.init(6);
    this.direction = 'down'; // 預設向下運動
}

Snake.prototype = {
    init: function(len) {
        len = len ? len > 10 ? 10 : len : 5;
        var head = this.head = [0, len, imgs[1]];
        var body = this.body;
        for (var i = 0; i < len; i++) {
            body.push([0, i]);
        }
        this.getSnake();
    },
    restart: function() {
        ctx.clearRect(0, 0, width, height);
        this.head = [0, 5, imgs[1]]; // x,y座標,頭
        this.body = []; // 二維陣列,身體
        this.snake = []; //完整的蛇
        exit = [];
        this.direction = 'down'; // 預設向下運動
        this.init(6);
        food.update();
        score.scoreClear();
    },
    eat: function() {
        var head = [this.head[0], this.head[1]];
        var body = this.body;
        if (food.food.toString() == head.toString()) {
            food.update();
            score.scoreAdd();
            return true;
        }
        return false;
    },
    update: function(direction) {
        var oldDirection = this.direction;
        this.direction = direction || this.direction;
        if ((this.direction == 'down' && oldDirection == 'up') ||
            (this.direction == 'up' && oldDirection == 'down') ||
            (this.direction == 'left' && oldDirection == 'right') ||
            (this.direction == 'right' && oldDirection == 'left')) {
            this.direction = oldDirection;
        }
        if (this.direction == 'left' && oldDirection != 'right') {
            this.head[0] -= 1;
            this.head[2] = imgs[2];
        } else if (this.direction == 'right' && oldDirection != 'left') {
            this.head[0] += 1;
            this.head[2] = imgs[3];
        } else if (this.direction == 'up' && oldDirection != 'down') {
            this.head[1] -= 1;
            this.head[2] = imgs[0];
        } else if (this.direction == 'down' && oldDirection != 'up') {
            this.head[1] += 1;
            this.head[2] = imgs[1];
        }
        this.die();
    },
    gameOver: function() {
        alert('game over!')
        console.log('game over!');
        parse = true;
        score.highScore();
    },
    die: function() {
        var head = this.head;
        var x = head[0],
            y = head[1];
        if (x < 0 || x > maxX || y < 0 || y > maxY) {
            this.gameOver();
        }
        var body = this.body;
        for (var i = 0; i < body.length; i++) {
            if (body[i].toString() == [x, y].toString()) {
                this.gameOver();
            }
        }
    },
    render: function() {
        var snake = this.snake;
        for (var i = 0, len = snake.length; i < len; i++) {
            var item = snake[i];
            render(item[0], item[1], 'green', item[2]);
            // 印證了前面的if判斷是否有這個引數
        }
    },
    move: function(direction) {
        var head = this.head;
        var headCopy = head.slice(); //之前的頭
        var body = this.body;
        body.push([headCopy[0], headCopy[1]]);
        this.update(direction);
        var eat = this.eat();
        if (!eat) {
            var del = body.shift();
            clear(del[0], del[1]);
        }
        this.getSnake();
    },
    getSnake: function() {
        var head = this.head;
        var body = this.body;
        var snake = this.snake = [];
        for (var i = 0, l = body.length; i < l; i++) {
            snake.push(body[i]);
        }
        snake.push(head);
        exit = [];
        // 印證了這就是存在的全部空間位置
        for (var i = 0; i < snake.length; i++) {
            exit.push(snake[i]);
        }
        this.render();
    }
}

move.js

function Move() {

}

Move.prototype = {
	up: function(s) {
		snake.move('up');
	},
	down: function(s) {
		snake.move('down');
	},
	left: function(s) {
		snake.move('left');
	},
	right: function(s) {
		snake.move('right');
	}
}


document.onkeydown = function(e) {
	var key = e.keyCode;
	if(!parse){
		switch (key) {
			case 37:
			case 65:
				move.left(snake);
				break;
			case 38:
			case 87:
				move.up(snake);
				break;
			case 39:
			case 68:
				move.right(snake);
				break;
			case 40:
			case 83:
				move.down(snake);
				break;
			default:
				break;
		}
	}
};

move.js

function Move() {

}

Move.prototype = {
	up: function(s) {
		snake.move('up');
	},
	down: function(s) {
		snake.move('down');
	},
	left: function(s) {
		snake.move('left');
	},
	right: function(s) {
		snake.move('right');
	}
}


document.onkeydown = function(e) {
	var key = e.keyCode;
	if(!parse){
		switch (key) {
			case 37:
			case 65:
				move.left(snake);
				break;
			case 38:
			case 87:
				move.up(snake);
				break;
			case 39:
			case 68:
				move.right(snake);
				break;
			case 40:
			case 83:
				move.down(snake);
				break;
			default:
				break;
		}
	}
};

init.js

function init() {
	food = new Food();
	snake = new Snake();
	move = new Move();
	score = new Score();
	var timer = setInterval(function() {
		if (!parse) {
			snake.move();
		}
	}, speed);
}

for (var j = 0; j < imgs.length; j++) {
	imgs[j].onload = function() {
		length--;
		if (length == 0) {
			init();
		}
	}
}

相關文章