溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么用h5實(shí)現(xiàn)打火箭小游戲

發(fā)布時(shí)間:2021-07-28 17:21:08 來(lái)源:億速云 閱讀:127 作者:chen 欄目:云計(jì)算

本篇內(nèi)容介紹了“怎么用h5實(shí)現(xiàn)打火箭小游戲”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

一.游戲介紹

游戲介紹:
不斷有攜帶字母炸彈的火箭撞向地面,請(qǐng)根據(jù)火箭身上的字母敲擊鍵盤(pán),每一次對(duì)應(yīng)的敲擊會(huì)擊落攜帶該字母的火箭并使得分加一,每一架火箭撞到地面會(huì)使生命值減一,每擊落十架火箭,火箭數(shù)會(huì)加一,并獎(jiǎng)勵(lì)一點(diǎn)額外生命值,生命值上限為八。

二.HTML內(nèi)容

index.html里包含canvas畫(huà)布和一個(gè) 介紹游戲規(guī)則的div,

當(dāng)鼠標(biāo)點(diǎn)擊頁(yè)面任何一個(gè)地方的時(shí)候,進(jìn)入游戲界面:


index

瀏覽器不支持canvas

1.Click space to pause or begin game.
2.Enter the letter on the rockets to hit them.
3.Number of the hearts will add one together with the rockets after ten rockets hit.
4.Failed when the number of hearts equals zero.
5.Click anywhere to start game!

二.JS內(nèi)容

1.動(dòng)畫(huà)實(shí)現(xiàn)

common.js中并未使用setTimeOut()或者setInterval()作為動(dòng)畫(huà)定時(shí)器,而是使用window.requestAnimationFrame,一種更為優(yōu)化的方式實(shí)現(xiàn)動(dòng)畫(huà)效果。

requestAnimFrame的用法,先設(shè)置瀏覽器的兼容,并設(shè)置動(dòng)畫(huà)的幀率,這里設(shè)置為每1000/60ms執(zhí)行一次回調(diào)函數(shù)

window.requestAnimFrame = (function() {
        return  window.requestAnimationFrame        ||
        window.webkitRequestAnimationFrame          ||
        window.mozRequestAnimationFrame             ||
        window.oRequestAnimationFrame               ||
        window.msRequestAnimationFrame              ||
        function(callback) {
            window.setTimeout(callback, 1000 / 60);
        };
    })();

 requestAnimFrame中的兩個(gè)參數(shù),callback為下次重畫(huà)執(zhí)行的函數(shù),element為要重畫(huà)的節(jié)點(diǎn),即

requestAnimFrame(callback, element);

2.代碼塊及對(duì)象分析

(1) 在Game代碼塊控制游戲的開(kāi)始、結(jié)束和重新開(kāi)始以及動(dòng)畫(huà)的運(yùn)行和鼠標(biāo)、鍵盤(pán)點(diǎn)擊事件的判定

Game.begin(),游戲開(kāi)始界面,點(diǎn)擊任意位置,調(diào)用Game.run()函數(shù)進(jìn)入游戲運(yùn)行界面

Game.run(),游戲運(yùn)行界面,這里使用自定義兼容函數(shù)requestAnimFrame不斷回調(diào)Game.transform()函數(shù)對(duì)畫(huà)布重繪,并調(diào)用鍵盤(pán)點(diǎn)擊監(jiān)聽(tīng)函數(shù)Game.hit(event),判斷按鍵是否擊中火箭

Game.over(),游戲結(jié)束界面,顯示游戲得分、游戲中獎(jiǎng)勵(lì)的生命值和最終火箭數(shù),點(diǎn)擊任意位置會(huì)調(diào)用Game.restart()函數(shù)初始化游戲參數(shù)并調(diào)用Game.begin()進(jìn)入游戲開(kāi)始界面

(2) Background代碼塊用于繪制背景,默認(rèn)樣式為垂直方向灰度加深的漸變色

(3) Hearts代碼塊,根據(jù)全局變量heartsNum設(shè)置生命值的數(shù)量,初始為5,通過(guò)迭代和設(shè)置水平偏移量offSetX創(chuàng)建hearts數(shù)組中對(duì)象的位置屬性,而Heart對(duì)象則要保存位置和半徑屬性。另外,Heart對(duì)象中設(shè)置draw()函數(shù)進(jìn)行自繪,而Hearts代碼塊中設(shè)置draw()函數(shù)控制hearts數(shù)組中所有對(duì)象的自繪 ,以此實(shí)現(xiàn)動(dòng)畫(huà)運(yùn)行時(shí)生命值的狀態(tài)管理 。

(4) Rockets代碼塊負(fù)責(zé)繪制小火箭們,火箭數(shù)量由全局變量rocketsNum控制,初始為5,火箭的具體繪制由Rocket對(duì)象完成,在這里Rocket對(duì)象的狀態(tài)是隨機(jī)產(chǎn)生的,Rockets代碼塊中的rockets數(shù)組負(fù)責(zé)保存所有Rocket對(duì)象的狀態(tài)。Rockets代碼塊控制所有Rocket對(duì)象的自繪,并在鍵盤(pán)敲擊時(shí),循環(huán)遍歷數(shù)組中的對(duì)象以判斷火箭是否被擊中。

(5) TextNodes代碼塊負(fù)責(zé)繪制文本,TextNodes.setup()函數(shù)負(fù)責(zé)設(shè)置文本的內(nèi)容、位置、字體、樣式和字符的偏移量,當(dāng)然也可以不進(jìn)行設(shè)置,這時(shí)會(huì)采用默認(rèn)值。TextNode對(duì)象保存單個(gè)字符的內(nèi)容和位置信息并負(fù)責(zé)文本的自繪,TextNodes代碼塊會(huì)負(fù)責(zé)所有nodes數(shù)組中的對(duì)象的自繪。

(6) start函數(shù)負(fù)責(zé)從介紹游戲規(guī)則的界面轉(zhuǎn)到游戲開(kāi)始界面。

下面就不多說(shuō)了,貼代碼common.js:

window.onload=function(){
	var canvas=document.getElementById("canvas");
	var ctx=canvas.getContext("2d");
	canvas_width=canvas.width;
	canvas_height=canvas.height;

	var heartsNum=5;//生命值數(shù)
	var extraHearts=0;//額外增加的生命值數(shù)
	var rocketsNum=5;//火箭數(shù)
	var score=0;//得分?jǐn)?shù)

	window.requestAnimFrame = (function() {
        return  window.requestAnimationFrame        ||
        window.webkitRequestAnimationFrame          ||
        window.mozRequestAnimationFrame             ||
        window.oRequestAnimationFrame               ||
        window.msRequestAnimationFrame              ||
        function(callback) {
            window.setTimeout(callback, 1000 / 60);
        };
	})();

	var Game={
		animationID:0,//animationID,flag控制暫停和開(kāi)始
		flag:true,

		begin:function(){
			ctx.clearRect(0,0,canvas_width,canvas_height);

			Background.draw("yellow");

			TextNodes.setup("HitRocket",100,240,"96px 楷體,arial","#000");
			TextNodes.draw();
			TextNodes.setup("Click anywhere to start",150,360,"42px 楷體,arial","#000");
			TextNodes.draw();

			Rockets.init();
			Hearts.init();

			window.addEventListener("click",Game.run);
		},

		//緩沖,移除監(jiān)聽(tīng)器
		run:function(){
			window.removeEventListener("click",Game.run);
			Game.transform();

			window.addEventListener("keyup",Game.hit);
		},

		transform:function(){
			if(heartsNum>0){
				Game.animationID=requestAnimationFrame(Game.transform);

				//清空畫(huà)布
				ctx.clearRect(0,0,canvas_width,canvas_height);

				//背景
				Background.draw();

				//計(jì)分
				TextNodes.setup("Score:"+score,640,50,"42px 楷體,arial","#f00",20);
				TextNodes.draw();

				//火箭
				Rockets.transform();
				Rockets.modify();
				Rockets.draw();

				//生命值
				Hearts.modify();
				Hearts.draw();

			}else Game.over();
		},

		hit:function(event){
			event = (event)?event:window.event;

			if(event.keyCode==32)
				//暫停開(kāi)始
				if(Game.flag){
					Game.flag=false;
					window.cancelAnimationFrame(Game.animationID);
				}else{
					Game.flag=true;
					requestAnimationFrame(Game.transform);
				}
			else if(event.keyCode>=65&&event.keyCode<=90)
				//打擊火箭
				Rockets.loopHit(String.fromCharCode(event.keyCode));
		},

		over:function(){
			window.removeEventListener("keyup",Game.hit);

			Background.draw("#000");

			TextNodes.setup("Game Over!",100,120,"96px 楷體,arial","#f00");
			TextNodes.draw();
			TextNodes.setup("Click anywhere to retry!",120,200,"48px 楷體,arial","#f00");
			TextNodes.draw();
			TextNodes.setup("Score:"+score,240,320,"90px 楷體,arial","#f00");
			TextNodes.draw();
			TextNodes.setup("Extra hearts:"+extraHearts,120,420,"42px 楷體,arial","#f00",25);
			TextNodes.draw();
			TextNodes.setup("Total rockets:"+rocketsNum,120,500,"42px 楷體,arial","#f00",25);
			TextNodes.draw();

			window.addEventListener("click",Game.restart);
		},

		restart:function(){
			window.removeEventListener("click",Game.restart);

			//init
			heartsNum=5;
			extraHearts=0;
			rocketsNum=5;
			score=0;

			Game.begin();
		}
	}

	//繪制背景
	//有傳入繪制樣式,則使用該樣式,否則使用默認(rèn)樣式,垂直加深灰色漸變
	var Background={
		draw:function(fillStyle){
			if(fillStyle)
				ctx.fillStyle=fillStyle;
			else{
				var grd=ctx.createLinearGradient(0,0,0,canvas_height);
				grd.addColorStop(0,"#ccc");
				grd.addColorStop(1,"#777");
				ctx.fillStyle=grd;
			}
			ctx.fillRect(0,0,canvas_width,canvas_height);
		}
	}

	//繪制生命值
	var Heart=function(x,y){
		//不能初始化
		var x,y,radius;

		this.x=x;
		this.y=y;
		this.radius=20;

		this.draw=function(){
			ctx.beginPath();
			ctx.arc(this.x,this.y,this.radius,0,2*Math.PI);
			ctx.closePath();

			var grd=ctx.createRadialGradient(this.x,this.y,0,this.x,this.y,this.radius);
			grd.addColorStop(1,"#f00");
			grd.addColorStop(0,"#fff");
			ctx.fillStyle=grd;

			ctx.fill();
		}
	}

	//管理生命值的初始化和數(shù)量變化
	var Hearts={
		hearts:null,
		x:50,
		y:40,
		offSetX:50,
		init:function(){
			this.hearts=new Array();
			for(var i=0;i<heartsNum;i++)//按水平偏移排列生命值
				this.hearts[i]=new Heart(this.x+i*this.offSetX,this.y);
		},
		modify:function(){
			//修改生命值數(shù)量
			if(heartsNum<this.hearts.length)
				for(var i=heartsNum;i<this.hearts.length;i++)
					this.hearts[i]=null;
			else 
				for(var i=this.hearts.length;i<heartsNum;i++)
					this.hearts[i]=new Heart(this.x+i*this.offSetX,this.y);
		},
		draw:function(){
			for(var i=0;i<this.hearts.length;i++)
				this.hearts[i].draw();
		}
	}

	var Rocket=function(scale){
		var str="ABCDEFGHIJKLMNOPQRSTUVWSYZ";
		var x,y,scale,letter,speed,fontColor;

		this.init=function(scale){
			this.x=Math.random()*(canvas_width-20)+10;
			this.y=Math.random()*canvas_height/5*2;
			this.scale=scale;
			//隨機(jī)生成火箭體上的字母
			this.letter=str[Math.floor(Math.random()*26)];
			this.speed=Math.random()*2+1;
			this.fontColor="#000";
		}

		this.init(scale);

		this.draw=function(){

			ctx.save();
			ctx.translate(this.x,this.y);
			ctx.scale(this.scale,this.scale);

			//火箭火焰
			ctx.beginPath();
			ctx.moveTo(0,-80);
			ctx.lineTo(-25,0);
			ctx.lineTo(-10,30);
			ctx.lineTo(10,30);
			ctx.lineTo(25,0);
			ctx.closePath();
			var fire=ctx.createLinearGradient(-25,0,25,0);
			fire.addColorStop(0.2,"#f00");
			fire.addColorStop(0.5,"#f80");
			fire.addColorStop(0.8,"#f00");
			ctx.fillStyle=fire;
			ctx.fill();

			//火箭身體
			ctx.beginPath();
			ctx.moveTo(-10,30);
			ctx.lineTo(-30,160);
			ctx.lineTo(0,200);
			ctx.lineTo(30,160);
			ctx.lineTo(10,30);
			ctx.closePath();
			var body=ctx.createLinearGradient(-30,0,30,0);
			body.addColorStop(0.01,"#fff");
			body.addColorStop(0.5,"#00f");
			body.addColorStop(0.99,"#fff");
			ctx.fillStyle=body;
			ctx.fill();

			//火箭窗戶
			ctx.fillStyle="#ade";
			ctx.fillRect(-10,150,12,20);

			//火箭文字
			ctx.fillStyle=this.fontColor;
			ctx.font="42px bold 楷體,arial";

			ctx.fillText(this.letter,-12,120);

			ctx.restore();

		}

		this.hit=function(key){
			//判斷是否擊中火箭
			//若擊中,分?jǐn)?shù)+1,重置火箭
			if(this.letter==key){
				score++;
				
				//每擊中10個(gè)火箭,生命值+1,上限為8,火箭數(shù)+1,無(wú)上限
				if(score%10==0&&heartsNum<8){
					heartsNum++;
					extraHearts++;
					rocketsNum++;
				}

				//擊中時(shí)重置火箭屬性
				this.init(this.scale);
				return true;
			}
			return false;
		}

		this.move=function(){
			//火箭沒(méi)有被擊落,重置火箭屬性,生命值-1
			if(this.y>=canvas_height){
				this.init(this.scale);
				heartsNum--;
			}//即將超出屏幕范圍的時(shí)候,進(jìn)行預(yù)警,火箭體上的字母變?yōu)榧t色
			else if(this.y>canvas_height/7*5)
				this.fontColor="#f00";
			this.y+=this.speed;
		}
	}

	//管理火箭的初始化,數(shù)量變化,運(yùn)動(dòng)
	var Rockets={
		rockets:null,
		scale:0.4,//控制火箭的大小
		init:function(){
			this.rockets=new Array();
			for(var i=0;i<rocketsNum;i++)
				this.rockets[i]=new Rocket(this.scale);
		},
		draw:function(){
			for(var i=0;i<this.rockets.length;i++)
				this.rockets[i].draw();
		},
		transform:function(){
			for(var i=0;i<this.rockets.length;i++)
				this.rockets[i].move();
		},
		modify:function(){
			//修改火箭數(shù)量
			for(var i=this.rockets.length;i<rocketsNum;i++)
				this.rockets[i]=new Rocket(this.scale);
		},
		loopHit:function(key){
			for(var i=0;i<this.rockets.length;i++)
				if(this.rockets[i].hit(key))
					//如果擊中火箭,退出循環(huán)
					break;
		}
	}

	//繪制文本的單個(gè)字符
	var TextNode=function(txt,x,y){
		var txt,x,y;

		this.txt=txt;
		this.x=x;
		this.y=y;

		this.setup=function(txt,x,y){
			this.txt=txt;
			this.x=x;
			this.y=y;
		}

		this.draw=function(){
			ctx.fillText(this.txt,this.x,this.y);
		}
	}

	//管理字符串屬性的變化和繪制
	var TextNodes={
		nodes:null,
		x:100,
		y:200,
		offSetX:60,
		font:"96px 楷體,arial",
		fillStyle:"#000",
		setup:function(txt,x,y,font,fillStyle,offSetX){
			this.x=x;
			this.y=y;
			this.font=font;
			this.fillStyle=fillStyle;
			//可選參數(shù),字符的偏移
			this.offSetX=offSetX?offSetX:(canvas_width-2*x)/txt.length;

			this.nodes=new Array();
			for(var i=0;i<txt.length;i++)
				this.nodes[i]=new TextNode(txt[i],this.x+i*this.offSetX,this.y);
		},
		draw:function(){
			ctx.font=this.font;
			ctx.fillStyle=this.fillStyle;

			for(var i=0;i<this.nodes.length;i++)
				this.nodes[i].draw();
		}
	}

	var start=function(){
		document.getElementById("ins").style.display="none";
		Game.begin();
		window.removeEventListener("click",start);
	}

	//點(diǎn)擊介紹,開(kāi)始游戲
	window.addEventListener("click",start);
};

“怎么用h5實(shí)現(xiàn)打火箭小游戲”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

h5
AI