canvas黑白块游戏

标签: canvas

 

今天手把手教大家写canvas黑白块小游戏

其实canvas基本代码都是在js中写的,我写这个是如果带入到网页中 最好用手机版查看。

首先是css和html

css:

html,body{
    		width: 100%;
    		height: 100%;
    		margin: 0;
    		padding: 0;
    		text-align: center;
    		overflow: hidden;
}

html:

<canvas id="mycan" width="" height=""></canvas>

然后开始写js

//获取宽高
var h = document.documentElement.clientHeight;
var w = document.documentElement.clientWidth;

//canvas对象
var canvas = document.getElementById("mycan");

//获取绘制的环境
var ctx = canvas.getContext("2d");

//设置画布宽高
canvas.width = w;
canvas.height = h;

这时候在浏览器中查看,也是一片空白,然后我们在画布中加点自己想要的东西,

比如先画三条线

/*
	 			mw mh 和mx my是一样的 为什么要写2次,
				 主要是w,h 是宽高
				xy 是坐标 所以写2个 做个区分
				其实也没啥区别,只写一个也没关系,
				至于为什么加1,主要是为了让边框显示出来不至于0,0坐标的方块left和top 没有框
			 * */
			var mw = parseInt(w/4)+1;
			var mh = parseInt(h/5)+1;
			var mx = parseInt(w/4)+1;
			var my = parseInt(h/5)+1;
			
			function drawline(x,y){
				//beginPath主要是为了重新绘制的时候不至于被上一个所影响或者,不被下一个所消除
				ctx.beginPath();
				//设置颜色
				ctx.strokeStyle = 'black';
				//开始划线
				ctx.moveTo(x,y);
				ctx.lineTo(x,h-1);
				ctx.stroke();
			}
					
			function setline(){
				for(var i = 1;i <= 3; i++){
					drawline(mw*i,1);
				}
			}
			
			setline();

然后看看效果:

线画好了,然后开始画框

//new一个数组
var list = new Array();
for(var i = 0; i < 6; i++) {
    //内部添加数组长度为2   1个是用于存储 x 值 另一个用于存储 颜色的true和flase 
    var arr = new Array(2);
    //应该随机一个值  0-3
    var n = Math.floor(Math.random() * 4);
    console.log("n",n);
    arr[0] = n;
    arr[1] = true;
    //刚开始的时候 如果y值 大于屏幕的高度,就将y值放到最上面去至于为什么是6 
    //因为高度是分成5分的  所以必须加1 才能保证方块沾满屏幕
    if(my*i > h){
	    list[i] = new kuang(my*i -  my*6, arr);
    }else{
	    list[i] = new kuang(my*i, arr);
    }
}
					
function drawmian(){
	/*
	 没什么用这个canvas.width = canvas.width;
	其实每次画布都是清空重画,每次设置画布的宽高的时候画布自动清空,所以先清空画布,在从新绘制 
	 * */
	canvas.width = canvas.width;
	//当然如果全是白色也太单调了,我选择加上一张背景图片
			
	//创建 img对象
	var Img=document.createElement('img');
	//设置img的路径
				                        Img.src='http://images.17173.com/2010/newgame/2010/07/08/allan07081500_11s.jpg';
//将图片绘制到画布上去
	ctx.drawImage(Img,0,0,w,h);
				
	//因为画布清空了一次,所以需要将划线写到内部
	setline();
	for(var i = 0; i < list.length ;i++){
	    ctx.beginPath();
		//设置颜色
		if(list[i].arr[1]){
			//绿色	不要吐槽我的审美,我毫无审美观,随便写的颜色
			ctx.fillStyle = "rgba(155, 187, 89, 1)"; 
		}else{
			//灰色
			ctx.fillStyle = "rgba(192,192,192, 1)"; 
		}
		//画方块然后填充自己设置的颜色
	ctx.fillRect(mw*list[i].arr[0] , list[i].y, mw, mh);
	ctx.strokeStyle = "white";
	//话边框,边框颜色自己设置
	ctx.strokeRect(mw*list[i].arr[0] , list[i].y, mw, mh);
	ctx.stroke();
	ctx.closePath();
	}
				
}
			
			
drawmian();

然后再看看效果:

解析一下ctx.fillRect(mw*list[i].arr[0] , list[i].y, mw, mh);

这个函数就是相当于设置 一个方块参数分别的 坐标x,y 和宽高w,h

然后设置x的坐标是 mw*先前在数组里面存的n值

y坐标就是这个当前的高度

然后设置方块的大小宽高,现在也就好理解为什么我要设置两次 mw,mh,mx和my了吧

 

然后是在让这个canvas动起来

//这个就是设置每次移动的大小,数字越大移动的越快
var add = 2;
function ksgame() {
	//先画出来
	drawmian();
	//然后开始循环判断
	for(var i = 0; i < list.length; i++) {
		list[i].y+=add;
		//每当方块过了屏幕的高度
		if(list[i].y > h) {
			var n = Math.floor(Math.random() * 4);
    		list[i].arr[0] = n;
			list[i].arr[1] = true;
			//放到最上面去
			list[i].y -= mh * 6;
		}
	}
		
	//这个函数相当于setInterval ,而且比setInterval平滑很多,
	//不至于看起来像卡了一样,需要了解可以去百度一下
	time  = requestAnimationFrame(goGame);
}
		
//drawmian();
ksgame();

这个只有自己看去看效果了,只要画布动起来了 我们只需要加上一点逻辑判断就可以,修改一部分代码,这个游戏就算完成了

首先在上层添加3个参数

var score = 0;				//分数
var time = null;			//用于停止动画
var start = false;			//开始按钮

修改一下 drawmian 主要是下面添加一个分数和 开始的文本

function drawmian() {
				/*
				 没什么用这个canvas.width = canvas.width;
				其实每次画布都是清空重画,每次设置画布的宽高的时候画布自动清空,所以先清空画布,在从新绘制 
				 * */
				canvas.width = canvas.width;
				//当然如果全是白色也太单调了,我选择加上一张背景图片

				//创建 img对象
				var Img = document.createElement('img');
				//设置img的路径
				Img.src = 'http://images.17173.com/2010/newgame/2010/07/08/allan07081500_11s.jpg';
				//将图片绘制到画布上去
				ctx.drawImage(Img, 0, 0, w, h);

				//因为画布清空了一次,所以需要将划线写到内部
				setline();
				
				var tadd = parseInt(w/2);
				
				
				for(var i = 0; i < list.length; i++) {
					ctx.beginPath();
					//设置颜色
					if(list[i].arr[1]) {
						//绿色	不要吐槽我的审美,我毫无审美观,随便写的颜色
						ctx.fillStyle = "rgba(155, 187, 89, 1)";
					} else {
						//灰色
						ctx.fillStyle = "rgba(192,192,192, 1)";
					}
					//画方块然后填充自己设置的颜色
					ctx.fillRect(mw * list[i].arr[0], list[i].y, mw, mh);
					ctx.strokeStyle = "white";
					//话边框,边框颜色自己设置
					ctx.strokeRect(mw * list[i].arr[0], list[i].y, mw, mh);
					ctx.stroke();
					ctx.closePath();
				}
				//显示分数
				kais(tadd,50,score,"50","red");
				//如果没有开始,设置开始(只是设置文字)
				if(!start){
					var x1 = (mw*list[4].arr[0] + mw/2);
					var y1 = (list[4].y + mh/2);
					kais(x1,y1,"开始");
				}

			}

然后再修改一下  ksgeme,添加了一个 没有点击的判断

function ksgame() {
				//先画出来
				drawmian();
				//然后开始循环判断
				for(var i = 0; i < list.length; i++) {
					list[i].y += add;
					//每当方块过了屏幕的高度
					if(list[i].y > h) {
						//添加一个判断,如果没有点击超过了 高度,停止动画,并显示
						if(list[i].arr[1] == true){
							list[i].y -= 20;
							drawmian();
							window.cancelAnimationFrame(time);
							return;
						}
						var n = Math.floor(Math.random() * 4);
						list[i].arr[0] = n;
						list[i].arr[1] = true;
						//放到最上面去
						list[i].y -= mh * 6;
					}
				}

				//这个函数相当于setInterval ,而且比setInterval平滑很多,
				//不至于看起来像卡了一样,需要了解可以去百度一下
				time = requestAnimationFrame(ksgame);
			}
//用于给添加一个文字,
			/*
			 x  x坐标
			 y  y坐标
			 text 文本内容
			 px 大小
			 color 颜色
			 至于其他的位置,我注释掉的可以自己去试下
			 * */
			function kais(x,y,text,px,color){
				ctx.beginPath();
				if(px){
					ctx.font = px + "px Georgia";
				}else{
					ctx.font = "30px Georgia";
				}
		        ctx.fillStyle = color ? color : "black";
		        //ctx.textAlign="start";
		        //ctx.textAlign="end";
		        //ctx.textAlign="left";
				ctx.textAlign="center";
				//ctx.textAlign="right";
				
		//		ctx.textBaseline ="top";//顶部对齐
		//		ctx.textBaseline ="hanging";//悬挂
		//		ctx.textBaseline ="middle";//中间对齐
		//		ctx.textBaseline ="bottom";//底部对齐
				ctx.textBaseline ="alphabetic";//默认
				ctx.fillText(text,x,y);
				ctx.stroke();
				ctx.closePath();
			}

然后添加一个点击事件,是鼠标按下事件


			//添加一个点击事件,至于移动端的  触屏事件我懒得写了
			canvas.addEventListener("mousedown", function(event) {
				event = event || window.event;
				//这是当前点击的位置
				var x = event.clientX;
				var y = event.clientY;
				if(!start){
					if(list[4].y < y && list[4].arr[0]*mw < x ){
						ksgame();
						start = !start;
					}
				}
				//循环判断点击的是那个方块
				for(var i = 0; i < list.length; i++) {
					//先判断点击的是那一排,也就是高度的坐标
					if(list[i].y < y && list[i].y + mh > y) {
						//然后再查看点击的是那一列,也就是宽度的坐标
						var j = parseInt(x/mw);
						//j 就是点击的是哪一列
						//然后再讲这个排的 随机数n 于j对比,如果相同,那么点击的就是对的
						//否则就是点的空白区
						if(list[i].arr[0] == j) {
							//点击后将true变为false 设置颜色,而且不让多次点击得分
							if(list[i].arr[1] == true) {
								list[i].arr[1] = false;
								//这里是分数每次超过20,就让速度变快一点
								if(score % 20 == 0){
									add++;
								}
								//分数
								score++;
							}
						} else {
							console.log("进入取消");
							window.cancelAnimationFrame(time);
							drawmian();
							return;
						}

					}
				}
			})

这样一个 游戏基本没啥问题了,如果想要完善一点,自己写个重新开始之类的,如果读懂了我写的代码(应该是比较好理解了,已经解析的这么细致了),在继续开发应该是很容易的,好了,谢谢大家!,不懂可以留言!

 

 

最后整个页面的代码加上:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title></title>
    <style type="text/css">
    	html,body{
    		width: 100%;
    		height: 100%;
    		margin: 0;
    		padding: 0;
    		text-align: center;
    		overflow: hidden;
    	}
    	
    </style>
    <script type="text/javascript">
    	
   		document.addEventListener('plusready', function(){
   			//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。"
   			
   		});
   		
    </script>
</head>
<body>
	<canvas id="mycan" width="" height=""></canvas>
	
	<script src="js/jquery-1.11.2.min.js" type="text/javascript" charset="utf-8"></script>
	<script type="text/javascript">
	var h = document.documentElement.clientHeight;
	var w = document.documentElement.clientWidth;
	var canvas = document.getElementById("mycan");
	var ctx = canvas.getContext("2d");
	canvas.width = w;
	canvas.height = h;
	
	
	var tadd = parseInt(w/2);
	var add = 2;
	function drawline(x,y){
		ctx.beginPath();
		ctx.strokeStyle = 'black';
		ctx.moveTo(x,y);
		ctx.lineTo(x,h);
		ctx.stroke();
		ctx.closePath();
	}
	function drawtext(text){
		ctx.beginPath();
        ctx.font="50px Georgia";
        ctx.fillStyle = "red";
        //ctx.textAlign="start";
        //ctx.textAlign="end";
        //ctx.textAlign="left";
		ctx.textAlign="center";
		//ctx.textAlign="right";
		
//		ctx.textBaseline ="top";//顶部对齐
//		ctx.textBaseline ="hanging";//悬挂
//		ctx.textBaseline ="middle";//中间对齐
//		ctx.textBaseline ="bottom";//底部对齐
		ctx.textBaseline ="alphabetic";//默认
		ctx.fillText(text,tadd,50);
		ctx.stroke();
		ctx.closePath();
	}
	
	/*
	 mw mh 和mx my是一样的 为什么要写2次,
	 主要是w,h 是宽高
	 xy 是坐标 所以写2个 做个区分
	 * */
	
	var mw = parseInt(w/4)+1;
	var mh = parseInt(h/5)+1;
	var mx = parseInt(w/4)+1;
	var my = parseInt(h/5)+1;
	var score = 0;				//分数
	var time = null;			//用于停止动画
	var start = false;			//开始按钮

	function Rect(y, arr) {
				this.y = y;
				this.arr = arr;
			}
	var list = new Array();
	for(var i = 0; i < 6; i++) {
		var arr = new Array(2);
		//应该随机一个让它是黑色
		var n = Math.floor(Math.random() * 4);
		arr[0] = n;
		arr[1] = true;
		if(my*i > h){
			list[i] = new Rect(my*i -  my*6, arr);
		}else{
			list[i] = new Rect(my*i, arr);
		}
		
	}
	canvas.addEventListener("mousedown",function(event){
		event = event || window.event;
		var x = event.clientX;
		var y = event.clientY;
		//var x = event.pageX - canvas.getBoundingClientRect().left;
        //var y = event.pageY - canvas.getBoundingClientRect().top;
		if(!start){
			if(list[4].y < y && list[4].arr[0]*mw < x ){
				console.log("进入开始2")
				//time  = window.requestAnimationFrame(goGame);
				goGame();
				start = !start;
			}
			
		}
		
        for(var i = 0; i < list.length; i++) {
			if(list[i].y < y && list[i].y + mh > y) {
				//点击在了第i行
				var j = Math.floor(x / mw);
				//将上面取整的数加1
				console.log("j",j);
				console.log(list[i].arr[0]);
				if(list[i].arr[0] == j) {
					if(list[i].arr[1] == true){
						list[i].arr[1] = false;
						
						if(score%10 == 0)
							add++;
						score++;
					}
				}else{
					console.log("进入取消");
					window.cancelAnimationFrame(time);
					drawmian();
					return;
				}

			} 
			/**/

		}
       
	})

	function drawmian(){
		canvas.width = canvas.width;
		var Img=document.createElement('img');
		Img.src='http://images.17173.com/2010/newgame/2010/07/08/allan07081500_11s.jpg';
		ctx.drawImage(Img,0,0,w,h);
		setline();
		for(var i = 0; i < list.length ;i++){
				ctx.beginPath();
				if(list[i].arr[1]){
					ctx.fillStyle = 'rgba(155, 187, 89, 1)'; 
				}else{
					ctx.fillStyle = 'rgba(192,192,192, 1)'; 
				}
				ctx.fillRect(mw*list[i].arr[0] , list[i].y, mw, mh);
				ctx.strokeStyle = "white";
				ctx.strokeRect(mw*list[i].arr[0] , list[i].y, mw, mh);
				ctx.stroke();
				ctx.closePath();
		}
		drawtext(score);
		//kais(tadd,50,score,"30","red");
		if(!start){
			var x1 = (mw*list[4].arr[0] + mw/2);
			var y1 = (list[4].y + mh/2);
			kais(x1,y1,"开始");
		}
	}
	function kais(x,y,text,px,color){
		ctx.beginPath();
		if(px){
			ctx.font = px + "px Georgia";
		}else{
			ctx.font = "30px Georgia";
		}
        ctx.fillStyle = color ? color : "black";
        //ctx.textAlign="start";
        //ctx.textAlign="end";
        //ctx.textAlign="left";
		ctx.textAlign="center";
		//ctx.textAlign="right";
		
//		ctx.textBaseline ="top";//顶部对齐
//		ctx.textBaseline ="hanging";//悬挂
//		ctx.textBaseline ="middle";//中间对齐
//		ctx.textBaseline ="bottom";//底部对齐
		ctx.textBaseline ="alphabetic";//默认
		ctx.fillText(text,x,y);
		ctx.stroke();
		ctx.closePath();
	}
	
	
	//能动的方法
	function goGame() {
		drawmian();
		for(var i = 0; i < list.length; i++) {
			list[i].y+=add;
			
			if(list[i].y > h) {
				console.log(list[i].arr[1]);
				if(list[i].arr[1] == true){
					list[i].y -= 20;
					drawmian();
					window.cancelAnimationFrame(time);
					return;
				}
				var n = Math.floor(Math.random() * 4);
				list[i].arr[0] = n;
				list[i].arr[1] = true;
				//放到最上面去
				list[i].y -= mh * 6;
			}
		}
		time  = requestAnimationFrame(goGame);
		
	}
	
	
	function setline(){
		for(var i = 1;i <= 3; i++){
			drawline(mw*i,1);
		}
	}
	
	
	
	
	drawmian();
	//goGame();
	
	
	//time = setInterval("goGame();",.1); 
	
	
	</script>
</body>

</html>

 

版权声明:本文为qq_38026437原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38026437/article/details/81215990