Jeu de serpent réalisé avec canvas+javascript

Il s'agit d'un petit jeu de serpent réalisé avec html5 canvas (canvas) combiné à du javascript. Il complète les fonctions de base du jeu, mais il y a certains domaines qui ne sont pas encore parfaits. Les ressources et codes javascript utilisés sont téléchargeables en cliquant sur le lien suivant : Snake game code resources made with canvas .

idée générale

Bien que Snake soit un jeu simple, il faut encore considérer beaucoup de choses à réaliser sur la toile. J'ai divisé tout le jeu en plusieurs parties pour les résoudre séparément, et j'ai finalement terminé le jeu. Les modules fonctionnels spécifiques sont les suivants.

fonction requise

(1) Concernant les serpents :

  1. Le dessin du serpent gourmand : j'ai dessiné la couleur du serpent gourmand en bleu (#0000ff), et j'ai dessiné un œil de serpent en noir (#000000) à la tête du serpent, puis j'ai créé un objet serpent, et mis dans le serpent Données relatives aux serpents gourmands, telles que les coordonnées de la tête du serpent, les coordonnées de la queue du serpent, le point tournant du corps du serpent (le serpent générera un point tournant en tournant), la direction de déplacement actuelle de la tête du serpent /queue de serpent, et la direction du cadre précédent de la tête de serpent.
  2. Mouvement du serpent : Utiliser la toile pour créer un petit jeu de serpent ne laisse naturellement pas vraiment le serpent avancer, mais redessine chaque image. Selon l'attribut snake.fangxiang1 (direction de déplacement de la tête du serpent) de l'objet, les coordonnées de la tête du serpent sont modifiées à chaque image. De même, les coordonnées de la queue du serpent sont modifiées selon l'attribut snake.fangxiang2.
  3. Quand le serpent se mange : Après chaque mouvement du serpent, il explorera les couleurs des pixels devant la tête du serpent et aux positions gauche et droite. Si le pixel dans une certaine direction est prédit être bleu, cela signifie que le la prochaine image ira dans cette direction Aller dans la direction vous dévorera, c'est-à-dire que le jeu échoue. J'ai donc créé un tableau aa pour stocker la direction dans laquelle le serpent sera mangé. Lors de l'entrée dans l'image suivante, la direction actuelle sera comparée au tableau aa. Si la direction actuelle est stockée dans le tableau aa, il sera déterminé que vous vous êtes mangé, le jeu est terminé, une boîte de confirmation apparaîtra, et la page sera actualisée.
  4. Le serpent gourmand mange de la nourriture : c'est en fait similaire à se manger, juste une couleur différente (la nourriture est rouge), mais se manger est un échec du jeu, et manger de la nourriture nettoie la nourriture, et dans un Le nouvel emplacement engendre de la nourriture, et le serpent s'allonge.
  5. Comment le serpent gourmand s'allonge : ici je mets une variable gogo, si gogo==false, cela signifie qu'aucune nourriture n'est mangée, et le serpent avance comme d'habitude, quand gogo=false, la tête de serpent avance, la queue de serpent n'avance pas, alors le serpent global La longueur est allongée.
  6. La fonction du point tournant: lorsque l'utilisateur appuie sur les touches fléchées du clavier, les coordonnées actuelles de la tête de serpent seront stockées dans le tableau des points tournants, la tête de serpent continuera d'avancer selon snake.fangxiang1, et le la queue du serpent sera basée sur la différence entre la queue du serpent et le premier point tournant Pour calculer la direction à déplacer, lorsque la queue du serpent atteint la position du premier point tournant, supprimez le point tournant, à ce moment le deuxième tournant représente le "premier" tournant.
    (2) À propos du canevas :
    le canevas est l'interface globale du jeu, principalement composé d'un fond vert (herbe), d'un cercle rouge (nourriture) et d'une polyligne bleue (serpent). La taille est de 300 x 300, et il y a un bouton au centre de la toile pour le bouton de démarrage du jeu, le bouton disparaît après avoir cliqué sur le bouton et le jeu démarre.
    (3) À propos de la nourriture :
    la nourriture disparaîtra après avoir été touchée par la tête de serpent. La méthode spécifique consiste à dessiner un cercle vert aux coordonnées de la nourriture actuelle avec le même rayon que la nourriture, afin que la nourriture puisse être couverte, puis deux entiers aléatoires (multiple de 5), comme nouvelles coordonnées de l'aliment, l'aliment sera redessiné dans le cadre suivant.

tous les codes

L'idée a été expliquée, et ce qui suit est la version complète du code. Les commentaires sont déjà complets, donc je ne vais pas décomposer le code et en parler partie par partie. Bien sûr, copier et coller directement ne fonctionnera certainement pas, car il manque un fichier modernizr.js, et ce fichier et le fichier de code doivent être placés dans le même dossier pour s'exécuter. Le lien au début de l'article permet de télécharger le fichier de code et le fichier modernizr.js.

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>画布练习</title>
<script src="modernizr.js"></script>
<script type="text/javascript">
	window.addEventListener("load", eventWindowLoaded, false);	
	function eventWindowLoaded() {
    
    
		canvasApp();
	}
	function canvasSupport () {
    
    
		return Modernizr.canvas;
	}
	function canvasApp(){
    
    
		if (!canvasSupport()) {
    
    
			return;
		}	
		var theCanvas=document.getElementById("canvas1");	
		var cxt=theCanvas.getContext("2d");
		var food={
    
    
			foodx:100,		//食物的x坐标
			foody:100,		//食物的y坐标
		};
		var snake={
    
    
			headx:150,		//蛇头x坐标
			heady:50,		//蛇头y坐标
			woundx:[],		//转折点x坐标
			woundy:[],		//转折点y坐标
			endx:100,		//蛇尾x坐标
			endy:50,		//蛇尾y坐标
			fangxiang1:"right",	//蛇头方向
			fangxiang2:"right",	//蛇尾方向
		};
		var gameover=false;			//游戏结束的标志
		var aa=[];		//记录下一帧会吃到自己的方向
		var bb;		//记录下一帧会吃到食物的方向
		var gogo=false;		//若gogo=false,则代表没吃到食物,蛇尾需要前进。若gogo=true,则代表吃到食物,蛇尾不需要前进
		drawScreen();
		function drawScreen(){
    
    
			//背景绘制
			cxt.fillStyle="#00ff00";		//设置背景颜色为绿色
			cxt.fillRect(0,0,300,300);		//绘制背景,一个左上角在(0,0),右下角在(600,600)的矩形
			
			//绘制食物
			cxt.beginPath();			//开始绘制
			cxt.fillStyle="#ff0000";		//设置食物颜色为红色
			cxt.arc(food.foodx,food.foody,9,(Math.PI/180)*0,(Math.PI/180)*360,false);		//在(100,100)的位置画一个半径为5的圆
			cxt.fill();			//立即以填充颜色的方式绘制
			cxt.closePath();	//结束绘制
			
			//绘制贪食蛇
			cxt.beginPath();	//开始绘制
			cxt.strokeStyle="#0000ff";		//设置贪食蛇颜色为蓝色
			cxt.lineCap="round";		//设置线段两端为圆角
			cxt.lineWidth=10;		//设置线段宽度为10
			cxt.moveTo(snake.endx,snake.endy);		//设置线段的开始点为蛇尾(snake.endx,snake.endy)
			for(var i=0;i<snake.woundx.length;i++){
    
    
				cxt.lineTo(snake.woundx[i],snake.woundy[i]);		//根据蛇的转折点数量,来连接蛇身和蛇尾
			}
			cxt.lineTo(snake.headx,snake.heady);			//再将蛇头连接
			cxt.stroke();			//立即以描边的方式绘制
			cxt.closePath();		//结束绘制
			
			//绘制贪食蛇的眼睛
			cxt.beginPath();		//开始绘制
			cxt.fillStyle="#000000";		//设置蛇眼为黑色
			cxt.arc(snake.headx,snake.heady,3,(Math.PI/180)*0,(Math.PI/180)*360,false);		//在(snake.headx,snake.heady)的位置画一个半径为3的圆
			cxt.fill();			//以填充颜色的方式立即绘制
			cxt.closePath();		//结束绘制	
			
			//判断游戏是否结束
			if(snake.headx>297||snake.headx<0||snake.heady>297||snake.heady<0){
    
    
				gameover=true;
			}
			for(var i=0;i<aa.length;i++){
    
    
				if(aa[i]==snake.fangxiang1){
    
    
					gameover=true;
					break;
				}
			}
			if(gameover==true){
    
    
				var t=confirm("你输了");		//弹出确认框,并返回一个值t,t代表用户点了确认键/取消键
				if(t==true){
    
    
					clearInterval(tt);	//清除动画
					location = location;		//刷新页面
				}else{
    
    
					clearInterval(tt);
					location = location;
				}
			}
			aa.length=0;		//清空数组
			//判断是否吃到了食物
			if(bb==snake.fangxiang1){
    
    
				cxt.beginPath();
				fillStyle="#00ff00";		//设置颜色为背景色
				cxt.arc(food.foodx,food.foody,9,(Math.PI/180)*0,(Math.PI/180)*360,false);		//清除该食物
				cxt.fill();
				cxt.closePath();
				food.foodx=Math.floor(Math.random()*56)*5+10;		//重新设置食物x坐标
				food.foody=Math.floor(Math.random()*56)*5+10;		//重新设置食物y坐标
				gogo=true;			//表示吃到了食物
			}
			bb="";		//清除bb
			
			//根据snake.fangxiang1来判断蛇头的前进方向,同时根据前进后的蛇头位置,来预判下一步是否会吃到自己或者吃到食物
			switch(snake.fangxiang1){
    
    
				case "right":
					snake.headx+=5;
					var cc=cxt.getImageData(snake.headx+5,snake.heady,1,1);
					setAB(cc,"right");
					cc=cxt.getImageData(snake.headx,snake.heady-5,1,1);
					setAB(cc,"top");
					cc=cxt.getImageData(snake.headx,snake.heady+5,1,1);
					setAB(cc,"bottom");
					break;
				case "left":
					snake.headx-=5;
					var cc=cxt.getImageData(snake.headx-5,snake.heady,1,1);
					setAB(cc,"left");
					cc=cxt.getImageData(snake.headx,snake.heady-5,1,1);
					setAB(cc,"top");
					cc=cxt.getImageData(snake.headx,snake.heady+5,1,1);
					setAB(cc,"bottom");
					break;
				case "top":
					snake.heady-=5;
					var cc=cxt.getImageData(snake.headx+5,snake.heady,1,1);
					setAB(cc,"right");
					cc=cxt.getImageData(snake.headx-5,snake.heady,1,1);
					setAB(cc,"left");
					cc=cxt.getImageData(snake.headx,snake.heady-5,1,1);
					setAB(cc,"top");
					break;
				case "bottom":
					snake.heady+=5;
					var cc=cxt.getImageData(snake.headx+5,snake.heady,1,1);
					setAB(cc,"right");
					cc=cxt.getImageData(snake.headx-5,snake.heady,1,1);
					setAB(cc,"left");
					cc=cxt.getImageData(snake.headx,snake.heady+5,1,1);
					setAB(cc,"bottom");
					break;
			}
			function setAB(e,f){
    
    
				if(e.data[2]==255){
    
    
					aa.push(f);
				}
				if(e.data[0]==255){
    
    
					bb=f;
				}
			}
			
			//根据gogo的值判断蛇尾是否需要前进,用来实现蛇身变长
			if(gogo==false){
    
    
				//以下是蛇尾前进的方法
				if(snake.woundx.length!=0){
    
    
					//若转折点数组不为空,则根据蛇尾坐标和转折点数组中的第一个坐标的差值,判断蛇尾的前进方向
					if(snake.woundx[0]-snake.endx>0){
    
    
						snake.fangxiang2="right";
					}
					if(snake.woundx[0]-snake.endx<0){
    
    
						snake.fangxiang2="left";
					}
					if(snake.woundy[0]-snake.endy>0){
    
    
						snake.fangxiang2="bottom";
					}
					if(snake.woundy[0]-snake.endy<0){
    
    
						snake.fangxiang2="top";
					}
				}else{
    
    
					//若转折点数组为空,则蛇尾与蛇头进行比较
					if(snake.headx-snake.endx>0){
    
    
						snake.fangxiang2="right";
					}
					if(snake.headx-snake.endx<0){
    
    
						snake.fangxiang2="left";
					}
					if(snake.heady-snake.endy>0){
    
    
						snake.fangxiang2="bottom";
					}
					if(snake.heady-snake.endy<0){
    
    
						snake.fangxiang2="top";
					}
				}
			
				//根据蛇尾的前进方向(snake.fanxgiang2)来决定蛇尾的坐标值变化
				switch(snake.fangxiang2){
    
    
					case "right":
						snake.endx+=5;
						break;
					case "left":
						snake.endx-=5;
						break;
					case "top":
						snake.endy-=5;
						break;
					case "bottom":
						snake.endy+=5;
						break;
				}
			}else{
    
    
				gogo=false;
			}
			//当蛇尾到达第一个转折点时,移除该转折点
			if(snake.endx==snake.woundx[0]&&snake.endy==snake.woundy[0]){
    
    
				snake.woundx.shift();		//shift()函数时移除数组中第一个值,并将数组中剩余的值重新设置下标
				snake.woundy.shift();
			}
		}
		
		//键盘监听事件
		function eventKeyDown(event){
    
    
			switch(event.keyCode){
    
    
				case 37:		//37代表了键盘的向左键,同理38为上,39为右,40为下。
					if(snake.fangxiang1!="right"){
    
    
						snake.fangxiang1="left";
						snake.woundx.push(snake.headx);		//将蛇头x坐标存入转折点x坐标数组里
						snake.woundy.push(snake.heady);		//将蛇头y坐标存入转折点y坐标数组里
						break;
					}else{
    
    
						break;
					}
				case 38:
					if(snake.fangxiang1!="bottom"){
    
    
						snake.fangxiang1="top";
						snake.woundx.push(snake.headx);
						snake.woundy.push(snake.heady);
						break;
					}else{
    
    
						break;
					}
				case 39:
					if(snake.fangxiang1!="left"){
    
    
						snake.fangxiang1="right";
						snake.woundx.push(snake.headx);
						snake.woundy.push(snake.heady);
						break;
					}else{
    
    
						break;
					}
				case 40:
					if(snake.fangxiang1!="top"){
    
    
						snake.fangxiang1="bottom";
						snake.woundx.push(snake.headx);
						snake.woundy.push(snake.heady);
						break;
					}else{
    
    
						break;
					}
			}
		}
		
		//开始游戏按钮点击事件
		var button=document.getElementById("start");		//将参数button与id="start"的按钮绑定
		button.addEventListener("click",startgame);			//按钮点击事件
		
		//开始游戏
		var tt;				//用于保存播放动画函数,在游戏结束时需要删除动画(即clearInterval(tt)),才能刷新页面
		function startgame(){
    
    
			button.style.visibility="hidden";		//将开始游戏按钮隐藏
			window.addEventListener("keyup",eventKeyDown,true);	//添加键盘监听事件
			tt=setInterval(drawScreen,70);			//每40毫秒运行一次drawScreen()函数
		}
	}
</script>
</head>
<body>
	<div>
		<canvas id="canvas1" width="300" height="300"></canvas>
		<button id="start" style="position:absolute;left:80px;top:150px;width:150px;height:40px;">开始游戏</button>
		<br>
		<span>使用键盘的上下左右键来控制蛇的移动方向</span>
	</div>
</body>
</html>

Je suppose que tu aimes

Origine blog.csdn.net/zhulong16/article/details/102727334
conseillé
Classement