贪吃蛇游戏-javascript

贪吃蛇游戏-javascript

介绍

使用javascript的面向对象实现简单的贪吃蛇小游戏

分析

1.  蛇和食物都在一个容器中
2.  蛇碰到容器时游戏结束
3.  食物随机生成
4.  蛇吃食物后, 食物消失, 重新生成食物, 自身长度+1
5.  其中包含对象:  蛇, 食物, 游戏

对象分析

食物

  • 属性
    宽, 高, 位置, 颜色
  • 方法
    1. 渲染食物(随即生成)
    2. 被吃掉时删除该食物

  • 属性
    高, 宽, 位置, 颜色, 运动方向, 身体
  • 方法
    1. 渲染蛇
    2. 移动方法 - 蛇在移动时,包含吃的方法(当蛇头碰到食物, 删除食物, 蛇身长度+1, 重新生成食物)

游戏

  • 属性
    食物, 蛇, 容器
  • 方法
    1. 蛇运动 (当蛇头碰到边界时, 游戏结束)
    2. 通过键盘控制移动

代码实现

  1. index.html页面
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>贪吃蛇游戏</title>
		<link rel="stylesheet" type="text/css" href="css/index.css"/>
	</head>
	<body>
		<div id="map"></div>
	</body>
</html>
<script type="text/javascript" src="js/index.js" ></script>
  1. index.css页面样式
* {
	margin: 0;
	padding: 0;
}
#map {
	width: 800px;
	height: 600px;
	background-color: darkgrey;
	position: relative;
	color: goldenrod
}
  1. index.js.
    3.1 工具
    // 生成固定范围内的随机整数
    (function() {
    function getRandom(min, max) {
    	return Math.round(min + Math.random() * (max - min));
    }
    window.tools = {
    	getRandom
    }
    })();
    
    3.1 食物对象
    // 使用自调用函数形式解决命名冲突问题
    (function(){
    // 容器
    const position = 'absolute'; 
    // 记录创建食物, 删除时使用
    const foods = [];
    // 食物对象
    function Food(options) {
    	//	属性	x, y, width, height, color
    	options = options || {};
    	this.x = options.x || 0;
    	this.y = options.y || 0;
    	this.width = options.width || 20;
    	this.height = options.height || 20;
    	this.color = options.color || 'green';
    }
    // 渲染   删除原食物,创建新食物
    Food.prototype.render = function (map) {
    	removeFood();
    	// 动态创建div, 为一个食物
    	const div = document.createElement('div');
    	// 添加食物到容器中
    	map.appendChild(div);
    	// 添加到食物的缓存数组中
    	foods.push(div);
    	// 设置食物样式
    	div.style.position = position;
    	// 随即生成食物x坐标  
    	this.x = tools.getRandom(0, map.offsetWidth / this.width - 1) * this.width;
    	div.style.left = this.x + 'px';
    	// 随即生成食物Y坐标 
    	this.y = tools.getRandom(0, map.offsetHeight / this.width - 1) * this.height;
    	div.style.top = this.y + 'px';
    	div.style.width = this.width + 'px';
    	div.style.height = this.height + 'px';
    	div.style.backgroundColor = this.color;
    }
    // 删除食物
    function removeFood() {
    	// 删除div (食物)
    	foods.forEach(item => item.parentNode.removeChild(item));
    	// 清空数组
    	foods.splice(0, foods.length);
    }
    // 把food对象绑定到window对象中使用
    window.Food = Food;
    })();
    
    3.2 蛇对象
    //使用局部作用域防止命名冲突
    (function() {
    const position = 'absolute';
    // 记录当前创建的蛇节
    const snakes = [];
    /**
     * 蛇对象
     * @param {Object} options 蛇属性设置
     */
    function Snake(options) {
    	options = options || {};
    	this.width = options.width || 20;
    	this.height = options.height || 20;
    	//蛇移动的方向
    	this.direction = options.direction || 'right';
    	// 蛇的身体(蛇节) 第一个元素存储蛇头
    	this.body = [
    		{x: 3, y:2, color: 'red'},
    		{x: 2, y:2, color: 'goldenrod'},
    		{x: 1, y:2, color: 'goldenrod'}
    	];
    }
    /**
     * 渲染蛇
     * @param {Object} map 渲染容器
     */
    Snake.prototype.render = function(map) {
    	// 删除之前创建的蛇
    	removeSnake();
    	// 把每一个蛇节渲染到页面上
    	this.body.forEach(item => {
    		const div = document.createElement('div');
    		map.appendChild(div);
    		// 记录创建的蛇节  方便删除
    		snakes.push(div);
    		div.style.position = position;
    		div.style.height = this.height + 'px';
    		div.style.width = this.width + 'px';
    		div.style.left = item.x * this.width + 'px';
    		div.style.top = item.y * this.height + 'px';
    		div.style.backgroundColor = item.color;
    	});
    }
    
    /**
     * 蛇移动的方法
     * @param {Object} food 根据食物判断是否是吃的状态
     * @param {Object} map 使用该部分重新渲染食物
     * @param {Object} timerId 定时器用于游戏结束
     */
    Snake.prototype.move = function(food, map, timerId) {
    	
    	// 蛇身 - 蛇节移动到上一节位置
    	for(let i = this.body.length - 1; i > 0; i--) {
    		this.body[i].x = this.body[i - 1].x;
    		this.body[i].y = this.body[i - 1].y;
    	}
    	// 蛇头 - 蛇头根据方向控制移动
    	const snakeHand = this.body[0];
    	switch(this.direction) {
    		case 'right': // 向右走
    			snakeHand.x += 1;
    			break;
    		case 'left':
    			snakeHand.x -= 1;
    			break;
    		case 'up':
    			snakeHand.y -= 1;
    			break;
    		case 'down':
    			snakeHand.y += 1;
    			break;
    	}
    	// 蛇头的坐标
    	const handX = snakeHand.x * this.width;
    	const handY= snakeHand.y * this.height;
    	if (handX < 0 || 
    		handX > map.offsetWidth ||
    		handY < 0 || 
    		handY > map.offsetHeight) {
    			console.log(111)
    			alert('GAME OVER!!!');
    			timerId.clearInterval();
    			return
    		}
    	if (handX === food.x && handY === food.y) {
    		// 蛇身长度+1
    		const last = this.body[this.body.length - 1];
    		this.body.push({
    			x: last.x,
    			y: last.y,
    			color: last.color
    		})
    		// 重新生成食物
    		food.render(map);
    		
    	}
    	
    }
    
    /**
     * 删除之前创建的蛇
     */
    function removeSnake() {
    	snakes.forEach(item => item.parentNode.removeChild(item));
    	snakes.splice(0, snakes.length);
    }
    // 绑定蛇对象到window中
    window.Snake = Snake;
    })();
    
    3.3 游戏对象
    (function() {
    let that; // 记录当前游戏对象 方便使用
    function Game(map) {
    	this.food = new Food();
    	this.snake = new Snake();
    	this.map = map;
    	that = this;
    }
    /**
     * 开始游戏
     */
    Game.prototype.start = function() {
    	// 1. 渲染食物和蛇到容器中
    	this.food.render(this.map);
    	// 2. 游戏逻辑
    	//		2-1. 蛇运动 (当蛇头碰到边界时, 游戏结束)
    	snakeRun();
    	//		2-2. 通过键盘控制移动
    	bindKey();
    }
    
    /**
     * 蛇移动
     */
    function snakeRun() {
    	const timerId = setInterval(function() {
    		// 蛇运动一格(该处this指向window对象, 因此使用that)
    		this.snake.move(that.food, that.map, timerId);
    		// 重新渲染蛇
    		this.snake.render(that.map);
    	}.bind(that), 150);
    }
    /**
     * 注册键盘控制方向
     */
    function bindKey() {
    	document.addEventListener('keydown', function(e) {
    		switch(e.keyCode) {
    			case 38:
    				this.snake.direction = 'up';
    				break;
    			case 40:
    				this.snake.direction = 'down';
    				break;
    			case 37:
    				this.snake.direction = 'left';
    				break;
    			case 39:
    				this.snake.direction = 'right';
    				break;
    		}
    	}.bind(that), false);// false事件冒泡
    }
    // 绑定game对象到windows对象中
    window.Game = Game; 
    })();
    
    3.4 主函入口
    (function() {
    const map = document.getElementById('map');
    const game = new Game(map);
    game.start();
    })();
    

总结

到此为止贪食蛇简单demo就告以段落, 本代码使用javascript面向对象的思想实现, 其中不足之处众多, 欢迎大家指点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值