日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript制作简易的《飞机大战》

發(fā)布時(shí)間:2023/12/9 javascript 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript制作简易的《飞机大战》 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

老規(guī)矩,我們先上最終效果圖:

飛機(jī)大戰(zhàn) - Google Chrome 2022-05-09 18-27-36

接下來我們開始這個(gè)項(xiàng)目案例的書寫;
1.項(xiàng)目準(zhǔn)備
項(xiàng)目分析,
基本準(zhǔn)備。
我們首先分析這個(gè) 項(xiàng)目分析,
我們需要 背景。飛機(jī)。子彈。敵機(jī) 這四個(gè)元素
然后所有的元素都是動(dòng)態(tài)的出現(xiàn)的,其中飛機(jī)是被用戶可以操作的。

有撞擊事件彈出失敗彈窗

基本準(zhǔn)備
首先創(chuàng)立一個(gè)html文件,及其需要的img文件和js文件。

并且在html文件中調(diào)用js文件(當(dāng)然各位也可以邊寫邊調(diào)用)

我們所有的操作都在計(jì)時(shí)器里觸發(fā)function start() {timer = setInterval(function() {},30)}start();

圖片的查詢可以參考 作者的 JavaScript 利用內(nèi)置對象Mach的一個(gè)方法制作滿天星 (點(diǎn)擊這個(gè)標(biāo)題跳轉(zhuǎn)到這篇文章)
如何利用 阿里的 iconfont 矢量圖庫來獲取我們所需要的資源,這里直接下載png文件就可以了。
接下來我們開始正式項(xiàng)目的書寫:
2.背景圖的運(yùn)動(dòng)
添加一個(gè)div標(biāo)簽作為項(xiàng)目界面:

<div id="container"></div>

對界面進(jìn)行一些簡單的樣式設(shè)置

#container {width: 320px;height: 560px;background-image: url(img/bg.jpg);background-size: 100% 100%;position: relative;margin: 0 auto;}

進(jìn)行js操作:

我們先獲取元素var dContainer = document.getElementById("container"); 分別設(shè)置界面的寬和高var sw = 320;var sh = 560;

我們用背景圖的方式插入圖片,這里注意一點(diǎn)要進(jìn)行position定位,因?yàn)橹笃渌麕讉€(gè)元素的運(yùn)動(dòng)都要根據(jù)背景圖來進(jìn)行絕對定位。
然后開始書寫背景圖的js部分:
js/bg.js部分

var dis = 0; 背景圖的移動(dòng) var speed = 5; 移動(dòng)速度 function bgMove() {dis += 5; 每次移動(dòng)5dis = dis>sh ? 0 : dis; 三目運(yùn)算符 當(dāng)背景圖移動(dòng)的距離大于界面高度的時(shí)候就為0否則就為原來的高度將寬和高傳給背景標(biāo)簽的css樣式 寬為0 因?yàn)椴恍枰笥乙苿?dòng),高度需要向下移動(dòng):dContainer.style.backgroundPosition = `0 ${dis}px`; }

我們在這里再寫一個(gè)公用方法,用于存放我們需要調(diào)用的方法
這里寫一個(gè)隨機(jī)函數(shù),(想了解的可以看這個(gè) JavaScript 利用內(nèi)置對象Mach的一個(gè)方法制作滿天星):
js/public.js部分

公用方法 function rand(min,max) {return Math.round(Math.random() * (max-min) +min); }

在這個(gè)js文件里在寫一個(gè)判斷函數(shù)用于媒體查詢

判斷是否是移動(dòng)端 function isPhone() {var arr = ["iPhone","iPad","Android"];var is = false;for(var i=0; i<arr.length; i++){if (navigator.userAgent.includes(arr[i])){is = true;break;}} return is; }

相對應(yīng)的js操作再添加移動(dòng)端的部分:

var dContainer = document.getElementById("container");var sw = 320;var sh = 560;添加的移動(dòng)端判斷if(isPhone()){sw = window.innerWidth;sh = window.innerHeight;}

2.飛機(jī)的移動(dòng)及其操作控制
我們先添加一個(gè)div,用于飛機(jī)的添加

<div id="container"><div id="hero"></div></div>

如法炮制css:

#hero {width: 66px;height: 82px;background-image: url(img/hero.png);background-size: 100% 100%;position: absolute; 這里注意絕對定位,相對于父級定位,接下來的兩行操作才得以執(zhí)行left: 127px;top: 476px;}

接下來是飛機(jī)的移動(dòng)操作部分js/hero.js:

先獲取元素 var dHero = document.getElementById("hero"); 添加狀態(tài),用于移動(dòng)的判斷 var isLeft = false; var isTop = false; var isRight = false; var isBottom = false; 按下事件 window.onkeydown = function(e) {// console.log(e.keyCode); 這里可以獲取我們鍵盤按鍵的值,在操作臺可以看到if(e.keyCode === 37){isLeft = true;}else if(e.keyCode === 38){isTop = true;}else if(e.keyCode === 39){isRight = true;}else if(e.keyCode === 40){isBottom = true;} } 抬起事件 window.onkeyup = function(e) {if(e.keyCode === 37){isLeft = false;}else if(e.keyCode === 38){isTop = false;}else if(e.keyCode === 39){isRight = false;}else if(e.keyCode === 40){isBottom = false;} }

我們通過布爾值來進(jìn)行狀態(tài)判斷,在移動(dòng)的操作中只需要看是flase還是true就可以進(jìn)行移動(dòng)

function heroMove() { 先獲取飛機(jī)元素的偏移量var left = dHero.offsetLeft;var top = dHero.offsetTop; 這里就直接進(jìn)行判斷 因?yàn)槭峭瑫r(shí)進(jìn)行的所以我們使用四個(gè)同級的if語句if (isLeft) {left -= 8; 每次移動(dòng)的距離left= left<-10 ? -10 : left; 三目運(yùn)算符 當(dāng)移動(dòng)的距離大于界面的時(shí)候就為0否則就為原來的}if (isTop) {top -= 8;top = top<0 ? 0 : top;}if (isRight) {left += 8;left= left>sw-56 ? sw-56 : left;}if (isBottom) {top += 8;top = top>sh-82 ? sh-82 : top;}最后將得到的值賦給飛機(jī)的樣式dHero.style.left = left + 'px';dHero.style.top = top + 'px'; }

接下來我們再寫一個(gè)移動(dòng)端的移動(dòng)操作

觸屏事件 dHero.ontouchstart = function(e) {e.preventDefault(); 消除默認(rèn)的操作if (e.touches.length > 1){return ;}var touch = e.touches[0];var x = touch.pageX;var y = touch.pageY;var l = dHero.offsetLeft;var t = dHero.offsetTop;window.ontouchmove = function(e) {var touch2 = e.touches[0];dHero.style.left = touch2.pageX - x + l +'px';dHero.style.top = touch2.pageY - y + t +'px';} }

3.敵機(jī)的創(chuàng)建與移動(dòng)
在html中添加div標(biāo)簽

這個(gè)標(biāo)簽只有存儲權(quán)限,沒有操作權(quán)限(請細(xì)細(xì)品味這句話)<div id="enemy">這里我們將敵機(jī)注釋,我們在js中動(dòng)態(tài)創(chuàng)建敵機(jī)<!-- <div class="enemy"></div> --> </div>

添加相應(yīng)的css

.enemy {width: 38px;height: 34px;background-image: url(img/enemy.png);position: absolute;background-size: 100% 100%;}

接下來是js/enemy.js部分:

獲取元素 var dEnemy = document.getElementById("enemy"); 創(chuàng)建敵機(jī) function creatEnemy() {dom操作創(chuàng)建div標(biāo)簽var enemy = document.createElement('div');enemy.className = 'enemy';enemy.style.left = rand(0,sw-38) +'px'; 調(diào)用隨機(jī)函數(shù)(我們之前在公用方法里面寫過,這里直接調(diào)用)enemy.speed = rand(3,8);dEnemy.appendChild(enemy);將創(chuàng)建的敵機(jī)存儲在父級里 } 這里是一個(gè)拓展的操作,由于之前創(chuàng)建會使每次出現(xiàn)的敵機(jī)數(shù)量一致(且計(jì)時(shí)器的速度是30毫秒 使敵機(jī)數(shù)量過于龐大) 我們這里使用一個(gè)操作 概率 var diff = 200; 定義一個(gè)變量并且使隨機(jī)數(shù)在 0~diff 中這樣使它小于 10,這樣只要改變diff的值就可以使小于10的數(shù)有一個(gè)范圍, diff越大 小于10出現(xiàn)的數(shù)的可能性就更小,反之更大 function enemyMove() {if (rand(0,diff) <= 10){ //概率creatEnemy();}var es = dEnemy.children; 所有敵機(jī)for(var i=0; i<es.length; i++) { 遍歷所有敵機(jī)var e = es[i]; 每一個(gè)敵機(jī)if(e.offsetTop > sh-40){ 當(dāng)敵機(jī)的位置大于界面高度使它消失dEnemy.removeChild(e); 刪除敵機(jī) 使其消失i--; //防止漏元素continue; 退出此次循環(huán)進(jìn)入下次循環(huán)}e.style.top = e.offsetTop + e.speed + 'px'; 更新每個(gè)敵機(jī)的位置} }

4.子彈的創(chuàng)建及其移動(dòng)
在html中添加div標(biāo)簽

<div id="container"><div id="hero"></div><div id="enemy"><!-- <div class="enemy"></div> --></div>同敵機(jī)的創(chuàng)建,只有存儲權(quán)限 沒有管理權(quán)限<div id="bullet"><!-- <div class="bullet"></div> --></div></div>

子彈的移動(dòng)js/bullet.js部分:

獲取元素 var dBullet = document.getElementById("bullet"); 創(chuàng)建子彈 function creatBullet() {var bullet = document.createElement('div');bullet.className = 'bullet'; 子彈的出現(xiàn)是從飛機(jī)的頭部出現(xiàn) 所以位置應(yīng)該從獲取飛機(jī)的距離bullet.style.left = dHero.offsetLeft + 33 - 8 + 'px'; bullet.style.top = dHero.offsetTop + 'px';dBullet.appendChild(bullet); } 子彈的移動(dòng) function bulletMove() {creatBullet();var bs = dBullet.children;遍歷每個(gè)子彈for(var i=0; i<bs.length; i++){var top = bs[i].offsetTop;if(top <= -14){dBullet.removeChild(bs[i]);i--;continue;}bs[i].style.top = top - 20 + 'px';} }

其實(shí) 寫到這里我們會發(fā)現(xiàn)子彈和敵機(jī)的操作幾乎是相同的,只不過,子彈是從一個(gè)地方出現(xiàn),敵機(jī)的多個(gè)地方出現(xiàn)
再補(bǔ)上css部分

.bullet {width: 16px;height: 20px;background-image: url(img/bullet.png);position: absolute;background-size: 100% 100%;top: 476px;;}

5。碰撞檢測
這就是最重要的部分了,我們將飛機(jī),子彈 分別與敵機(jī)的碰撞 觸發(fā)不同的事件
關(guān)于碰撞檢測 我們有下面這張圖

當(dāng)r2<l1 , b2<t1 ,r1<l2,b1<t2 時(shí)便不會發(fā)生碰撞

function isCrash(a,b) {var l1 = a.offsetLeft;var t1 = a.offsetTop;var r1 = l1 + a.offsetWidth;var b1 = t1 + a.offsetHeight;var l2 = b.offsetLeft;var t2 = b.offsetTop;var r2 = l2 + b.offsetWidth;var b2 = t2 + b.offsetHeight;碰撞檢測if(r2<l1 || b2<t1 || r1<l2 || b1<t2) {return false;} else{return true;} }

接下來我們把碰撞檢測函數(shù)在調(diào)用一下 并且觸發(fā)相應(yīng)的事件

function check() {var bs = dBullet.children; 所有的子彈var es = dEnemy.children; 所有的敵機(jī)for(var i=0; i<es.length; i++){ 遍歷所有敵機(jī)var e = es[i]; 每一個(gè)敵機(jī)if(isCrash(dHero,e)){ 進(jìn)行判斷alert("失敗"); 彈窗}//子彈和敵機(jī)的碰撞檢測for(var j=0; j<bs.length; j++){var b = bs[j];if(isCrash(e,b)){dBullet.removeChild(b); 刪除該子彈dEnemy.removeChild(e); 刪除該敵機(jī)}}} }

6,最后,我們將所有函數(shù)在計(jì)時(shí)器里調(diào)用

function start() {timer = setInterval(function() {bgMove();heroMove();enemyMove();bulletMove();check();},30)}start();

以上就是利用js制作的一個(gè)簡易的飛機(jī)大戰(zhàn),喜歡的小伙伴可以一件三連哦🤑🤑🤑

總結(jié)

以上是生活随笔為你收集整理的JavaScript制作简易的《飞机大战》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。