D3.js版贪吃蛇(Eating Snake)

简介

三方君用 d3.js 实现贪吃蛇小游戏设计

点这边玩玩看

Source Code

<!DOCTYPE html>
<html>
<head>
    <title>Eating Snake</title>
	<script src="https://d3js.org/d3.v3.min.js"></script>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<body>
<style>
	button {
      padding: 6px 12px;
      font-size: 14px;
      background-color: #fff;
      border: 1px solid #ccc;
      border-radius: 4px;
      margin: 5px;
    }
    .start {
      color: white;
      background-color: red;
      border: 1px solid transparent;
    }	
	.new {
      color: white;
      background-color: #5cb85c;
      border: 1px solid transparent;
    }
	#Grids{
	  border: 1.5px solid #ccc;
	  max-width: 250px;
	  max-height: 250px;
	}
</style>
<p>Eating Snake</p>
<div id="Control"></div>
<div id="Grids"></div>
<script>
$(document).ready(function(){
	var rectW = 25, rectL = 25, cc = 10, delayTime = 100, timerID = 0, stopped = true, 
		nextDir, grids, body, food, head,
		color = ['white','black','green'],
		directionVectors = {
			65: [-1,0], 37: [-1,0],    // 'A' or Left Arrow
			87: [0,-1], 38: [0,-1],    // 'W' or Up Arrow
			68: [1,0],  39: [1,0],     // 'D' or Right Arrow
			83: [0,1],  40: [0,1]      // 'S' or Down Arrow
		};
		
	var xs = d3.scale.linear().domain([0,rectL]).range([0,rectL * cc]),
		ys = d3.scale.linear().domain([0,rectW]).range([0,rectW * cc]);
		
	var rects = d3.select("#Grids")
				.append("svg:svg")    
				.attr("stroke", "rgba(204, 204,204,0.2)")
				.attr("shape-rendering", "optimizeSpeed")
				.attr("width",rectL*cc)
				.attr("height", rectW*cc);
			
	var ctrl = d3.select("#Control")
		
		ctrl.append('button')
			.attr('class', 'new')
			.text('New')
			.on('click', function(){ return setNewGrid() });
		
		ctrl.append('button')
			.attr('class', 'start')
			.text('Start')
			.on('click', startStop);
			
	var initialize = function(){
		
		grids = [];
		d3.range(rectL).forEach(function(x){
			grids[x] = new Array();
			d3.range(rectW).forEach(function(y){	
				grids[x][y] = 0;
			});
		});
		
		body = [[0,0],[0,1],[0,2],[0,3]];
		head = [0,3];
		nextDir = [0,1];
		
		makeFood();
		makeBody();

		rects.selectAll("rect")
			.data(function(){ return setGrid()})
			.enter()
			.append("rect")
			.attr("x", function(d){ return xs(d.x)})
			.attr("y", function(d){ return ys(d.y)})
			.attr("width",cc)
			.attr("height",cc)
			.attr("fill", function(d){ return color[d.state];});
	};

	$(document).keydown(function(event){
		var vector = directionVectors[event.which];
		if (!vector) return;
		// (right <--> left or up <--> down)
		if ((vector[0] !== 0 && vector[0] + nextDir[0] === 0) ||
			(vector[1] !== 0 && vector[1] + nextDir[1] === 0)) {
				return;
			}		
		nextDir = vector;
		event.preventDefault()
	});
	 
	function collide(a, b){
		var k = 0
		b.forEach( function(x){
			if(a[0]==x[0] && a[1]==x[1]){
				k = 1;
			}
		});
		return k;
	} ;
	
	function makeFood(){
		var x, y, k = 1;
		while(k){
			x = Math.floor(Math.random()*rectL); 
			y = Math.floor(Math.random()*rectW);
			if(!collide([x,y],body))
				k = 0;
		}
		food = [x, y];
		grids[x][y] = 2; 
	}
	
	function makeBody(){
		for(var i in body){
			var x = body[i][0],
				y = body[i][1];
			grids[x][y] = 1;
		}
	}
	
	var setGrid = function (){
		var bits = [];
		for(var i= 0; i< rectL; i++){
			for(var j= 0; j< rectW; j++){
				bits.push({ "x": i, "y": j, "state": grids[i][j] });
			}
		}
		return bits;
	};
	
	var setNewGrid = function (){	
		initialize();
		displayGrid();
		nextDir = [0,1];
	}
	
	var move = function(){

		function getNext(i,j){
			var x = i[0] + j[0];
			var y = i[1] + j[1];
			return [x, y];
		}
		
		var nextPos = getNext(head, nextDir);
		
		if(nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] >= rectL ||  nextPos[1] >= rectW ){
			startStop();
			return;
		}
		
		if(collide(nextPos, body)){
			startStop();
			return;
		}
		
		head[0] = nextPos[0];
		head[1] = nextPos[1];
		body.push([head[0], head[1]]);
		
		if(nextPos[0] == food[0] && nextPos[1] == food[1]){
			makeFood(); 
		}
		else{
			grids[body[0][0]][body[0][1]] = 0;
			body.shift();
		}
		
		makeBody()
		
		displayGrid();
	};

	var displayGrid = function(){	
		rects.selectAll("rect")
			.data(function(){ return setGrid()})
			.transition()
			.attr("fill", function(d) { return color[d.state]; })
			.duration(0);
	}
	
	function startStop() {
		stopped = !stopped;
		d3.select('button.start')
			.text(function () { return stopped ? 'Start' : 'Stop';});
	}
	
	var run = function(){		
		clearInterval(timerID);
		timerID = setInterval( function(){ if (!stopped) move();},delayTime);
	}
	
	initialize();
	run();
});
</script>
</body>
</html>

 

 

D3JS相关系列教程

  1. D3.js 实战 - 上色落伍了,来点图样吧!
  2. D3.js 实战 - 地表最快地球仪应用   
  3. 让我的视觉化动起来!D3.js 动画函数入门
  4. D3.js 视觉化教学 -全球即时地震视觉化
  5. 总整理!你不可错过的 d3.js 数据转换技巧
  6. D3.js版贪吃蛇(Eating Snake)
  7. 统计图表制作 – 使用 d3-generator
  8. 用 JavaScript 做数据视觉化 - D3.JS
  9. 高手才知道!七个你所不知道的 D3.js 秘技
  10. D3JS 实战 - 是长条也是圆饼的变形图表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值