<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <title>Document</title>
? ? <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.js"></script>
? ? <style>
? ? ? ? canvas{
? ? ? ? ? ? box-shadow: 0 0? 10px #000;
? ? ? ? ? ? display: block;
? ? ? ? ? ? margin:20px auto;
? ? ? ? }
? ? </style>
</head>
<body>
? ? <canvas width="1200" height="800" id="canvas"></canvas>
</body>
<script>
? ? $(function(){
? ? ? ? // var draw = new Draw($('#canvas')[0]);? //創(chuàng)建一個(gè)繪圖的實(shí)例對(duì)象
? ? ? ? // draw.main();//調(diào)用main繪制圖像
? ? ? ? function Draw(canvas){
? ? ? ? ? ? // 初始化
? ? ? ? ? ? this.canvas = canvas;
? ? ? ? ? ? // 創(chuàng)建check函數(shù)
? ? ? ? ? ? this.check = function(){
? ? ? ? ? ? ? ? // 檢測(cè)瀏覽器是否支持canvas
? ? ? ? ? ? ? ? if (!this.canvas.getContext) {
? ? ? ? ? ? ? ? ? ? //如果符合就輸出false
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? ? ? // 否則輸出true
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? this.main = function(){
? ? ? ? ? ? ? ? // 檢測(cè)兼容
? ? ? ? ? ? ? ? if (!this.check()) {
? ? ? ? ? ? ? ? ? ? // 如果符合就打印顯示瀏覽器不支持canvas輸出false
? ? ? ? ? ? ? ? ? ? console.log('瀏覽器不支持canvas');
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? // 繪畫上下文
? ? ? ? ? ? ? ? Draw.prototype.xt = this.canvas.getContext('2d');
? ? ? ? ? ? ? ? // 創(chuàng)建蛇? 畫出初始的蛇
? ? ? ? ? ? ? ? var snake = new Snake(this);
? ? ? ? ? ? ? ? snake.draw();
? ? ? ? ? ? ? ? // 隨機(jī)產(chǎn)生一個(gè)食物? 畫出初始的食物
? ? ? ? ? ? ? ? var food = randFood(snake);
? ? ? ? ? ? ? ? food.draw();
? ? ? ? ? ? ? ? // 做一個(gè)動(dòng)畫的定時(shí)器
? ? ? ? ? ? ? ? Draw.prototype.timer = setInterval(function(){
? ? ? ? ? ? ? ? ? ? // 清楚舊的圖像
? ? ? ? ? ? ? ? ? ? Draw.prototype.xt.clearRect(0,0,this.canvas.width,this.canvas.height);
? ? ? ? ? ? ? ? ? ? // 改變蛇的位置
? ? ? ? ? ? ? ? ? ? if (!snake.move()) {
? ? ? ? ? ? ? ? ? ? ? ? clearInterval(Draw.prototype.timer);
? ? ? ? ? ? ? ? ? ? ? ? alert('游戲結(jié)束');
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? // 重新繪制圖像
? ? ? ? ? ? ? ? ? ? snake.draw();
? ? ? ? ? ? ? ? ? ? food.draw();
? ? ? ? ? ? ? ? ? ? if (isRectHit(food,snake.head)) {
? ? ? ? ? ? ? ? ? ? ? ? Snake.prototype.isEatFood = true;
? ? ? ? ? ? ? ? ? ? ? ? // 重新產(chǎn)生食物
? ? ? ? ? ? ? ? ? ? ? ? food = randFood(snake);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? },80);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 蛇頭(準(zhǔn)備創(chuàng)建的方塊)的元素
? ? ? ? function Rect(x,y,width,height,color){
? ? ? ? ? ? this.x = x;
? ? ? ? ? ? this.y = y;
? ? ? ? ? ? this.width = width;
? ? ? ? ? ? this.height = height;
? ? ? ? ? ? this.color = color;
? ? ? ? }
? ? ? ? // 完善矩形? 繪制矩形? ?
? ? ? ? Rect.prototype.draw = function(){
? ? ? ? ? ? // 開始繪畫矩形
? ? ? ? ? ? Draw.prototype.xt.beginPath();
? ? ? ? ? ? // 畫筆顏色
? ? ? ? ? ? Draw.prototype.xt.fillStyle = this.color;
? ? ? ? ? ? // 填充矩形
? ? ? ? ? ? Draw.prototype.xt.fillRect(this.x,this.y,this.width,this.height);
? ? ? ? ? ? // 描邊
? ? ? ? ? ? Draw.prototype.xt.strokeRect(this.x,this.y,this.width,this.height);
? ? ? ? }
// 構(gòu)造對(duì)象蛇
? ? ? ? function Snake(obj){
? ? ? ? ? ? // 畫蛇頭? 蛇頭的顏色是紅色的?
? ? ? ? ? ? this.head = new Rect(obj.canvas.width/2-20,obj.canvas.height/2-20,40,40,'red');
? ? ? ? ? ? //定義一個(gè)空數(shù)組存放組成整蛇的方塊對(duì)象?
? ? ? ? ? ? this.body = [];? //表示多個(gè)身體
? ? ? ? ? ? // 蛇身的x比蛇頭移動(dòng)40
? ? ? ? ? ? var x = this.head.x-40;
? ? ? ? ? ? // 距離y不變
? ? ? ? ? ? var y = this.head.y;
? ? ? ? ? ? // 循環(huán)創(chuàng)建身體? 默認(rèn)蛇的長(zhǎng)度是3
? ? ? ? ? ? for (var i = 0; i < 3; i++) {
? ? ? ? ? ? ? ? // 每吃一個(gè)東西蛇身會(huì)加一個(gè)? 蛇身的顏色是灰色的
? ? ? ? ? ? ? ? var rect = new Rect(x,y,40,40,'gray');
? ? ? ? ? ? ? ? this.body.push(rect);
? ? ? ? ? ? ? ? x-=40;
? ? ? ? ? ? }? ? ?
? ? ? ? }
? ? ? ? // 添加蛇默認(rèn)的運(yùn)動(dòng)方向? 向右
? ? ? ? // 公有屬性映跟,任何地方能夠修改方向
? ? ? ? Snake.prototype.direction = 1;
? ? ? ? // 定義一個(gè)是否吃到食物的標(biāo)記
? ? ? ? Snake.prototype.isEatFood = false;
? ? ? ? // 畫蛇方法
? ? ? ? Snake.prototype.draw = function(){
? ? ? ? ? ? // 畫蛇頭
? ? ? ? ? ? this.head.draw();
? ? ? ? ? ? // 循環(huán)創(chuàng)建蛇身
? ? ? ? ? ? for (var i = 0; i < this.body.length; i++) {
? ? ? ? ? ? ? ? this.body[i].draw();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 蛇移動(dòng)的方法
? ? ? ? Snake.prototype.move = function(){
? ? ? ? ? ? // 檢測(cè)碰撞到墻壁
? ? ? ? ? ? if (this.head.x<40 || this.head.y<-40 || this.head.x>$('#canvas')[0].width-40-40 || this.head.y>$('#canvas')[0].height-40-40) {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? // 檢測(cè)蛇頭與蛇身
? ? ? ? ? ? for (var i =0;i<this.body.length;i++) {
? ? ? ? ? ? ? ? console.log(this.body[i])
? ? ? ? ? ? ? ? if (isRectHit(this.head,this.body[i])) {
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? // 加一個(gè)頭
? ? ? ? ? ? var rect = new Rect(this.head.x,this.head.y,40,40,'gray');
? ? ? ? ? ? // 添加身體開始的地方
? ? ? ? ? ? this.body.splice(0,0,rect);
? ? ? ? ? ? // 去掉一個(gè)尾巴,
? ? ? ? ? ? if (Snake.prototype.isEatFood) {
? ? ? ? ? ? ? ? Snake.prototype.isEatFood = false;
? ? ? ? ? ? ? ? // 重新隨機(jī)產(chǎn)生食物
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? this.body.pop();
? ? ? ? ? ? }
? ? ? ? ? ? switch(this.direction){
? ? ? ? ? ? ? ? case 0:
? ? ? ? ? ? ? ? ? ? this.head.y -= 40
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 1:
? ? ? ? ? ? ? ? ? ? this.head.x += 40
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 2:
? ? ? ? ? ? ? ? ? ? this.head.y +=40
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 3:
? ? ? ? ? ? ? ? ? ? this.head.x -= 40
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? //判定吃到食物蓄拣,即蛇頭坐標(biāo)與食物坐標(biāo)重合
? ? ? ? ? ? function isEatFood () {
? ? ? ? ? ? ? ? if (Snake.head.x == food.x && Snake.head.y == food.y){
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
// 添加鍵盤監(jiān)聽
? ? ? ? $(window).keydown(function(e){
? ? ? ? ? ? switch(e.keyCode){
? ? ? ? ? ? ? ? case 37:
? ? ? ? ? ? ? ? ? ? // 如果當(dāng)前的方向是向右的,不能改為向左
? ? ? ? ? ? ? ? ? ? if (Snake.prototype.direction == 1) {
? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? Snake.prototype.direction = 3;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 38:
? ? ? ? ? ? ? ? ? ? // 如果當(dāng)前的方向是向下的努隙,不能改為向上
? ? ? ? ? ? ? ? ? ? if (Snake.prototype.direction == 2) {
? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? Snake.prototype.direction = 0;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 39:
? ? ? ? ? ? ? ? ? ? if (Snake.prototype.direction == 3) {
? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? Snake.prototype.direction = 1;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 40:
? ? ? ? ? ? ? ? ? ? if (Snake.prototype.direction == 0) {
? ? ? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? Snake.prototype.direction = 2;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? })
? ? ? ? // 隨機(jī)產(chǎn)生食物
? ? ? ? function randFood(snake){
? ? ? ? ? ? // 是否在蛇身上
? ? ? ? ? ? isInSnake = true;
? ? ? ? ? ? while(isInSnake){
? ? ? ? ? ? ? ? // 產(chǎn)生兩個(gè)位置 x,y
? ? ? ? ? ? ? ? var x = getRandPosition(0,($('#canvas')[0].width-40)/40)*40;
? ? ? ? ? ? ? ? var y = getRandPosition(0,($('#canvas')[0].height-40)/40)*40;
? ? ? ? ? ? ? ? // 創(chuàng)建食物矩形
? ? ? ? ? ? ? ? var food = new Rect(x-20,y-20,40,40,'green');
? ? ? ? ? ? ? ? isInSnake = false;
? ? ? ? ? ? ? ? // 判斷這個(gè)位置是否在蛇身
? ? ? ? ? ? ? ? // 是否是蛇頭
? ? ? ? ? ? ? ? if (isRectHit(food,snake.head)) {
? ? ? ? ? ? ? ? ? ? isInSnake = true;
? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? // 是否是蛇身
? ? ? ? ? ? ? ? for (var i=0; i < snake.body.length; i++) {
? ? ? ? ? ? ? ? ? ? if (isRectHit(food,snake.body[i])) {
? ? ? ? ? ? ? ? ? ? ? ? isInSnake = true;
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? return food;
? ? ? ? }
? ? ? ? // 產(chǎn)生隨機(jī)數(shù)的函數(shù)
? ? ? ? function getRandPosition(min,max){
? ? ? ? ? ? return Math.round(Math.random()*(max-min)+min);
? ? ? ? }
? ? ? ? // 判斷矩形是否重合
? ? ? ? function isRectHit(rect1,rect2){
? ? ? ? ? ? var R1_min_x = rect1.x;
? ? ? ? ? ? var R1_min_y = rect1.y;
? ? ? ? ? ? var R2_min_x = rect2.x;
? ? ? ? ? ? var R2_min_y = rect2.y;
? ? ? ? ? ? var R1_max_x = rect1.x + 20;
? ? ? ? ? ? var R2_max_x = rect2.x + 20;
? ? ? ? ? ? var R1_max_y = rect1.y + 20;
? ? ? ? ? ? var R2_max_y = rect2.y + 20;
? ? ? ? ? ? // 兩個(gè)圖形的最大邊界和最小邊界
? ? ? ? ? ? var min_x = Math.max(R1_min_x,R2_min_x);
? ? ? ? ? ? var max_x = Math.min(R1_max_x,R2_max_x);
? ? ? ? ? ? var min_y = Math.max(R1_min_y,R2_min_y);
? ? ? ? ? ? var max_y = Math.min(R1_max_y,R2_max_y);
? ? ? ? ? ? if (min_x<max_x&&min_y<max_y) {
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? var draw = new Draw($('#canvas')[0]);? //創(chuàng)建一個(gè)繪圖的實(shí)例對(duì)象
? ? ? ? draw.main();//調(diào)用main繪制圖像
? ? });
</script>
<ml>