个人分析javascript 小游戏 --飞机大战 (单体单例)

转载一篇-------javascript 小游戏 –飞机大战 (单体单例)

原文博客地址:https://blog.csdn.net/weixin_42955598/article/details/81812171

最近跟着教学视频一边学习一边做了一个javascript的实战小游戏

话不多说 直接附上码源

<!DOCTYPE HTML>
<html>
    <head>
        <title>please enter your title</title>
        <meta charset="utf-8">
        <meta name="Author" content="潭州学院-阿飞老师">
        <style type='text/css'>
            *{ margin:0; padding:0;font-family:"Microsoft yahei";}
            body{ overflow:hidden;}
        </style>
    </head>
    <body>
        <script type="text/javascript">
        /*单例模式*/

            window.onload = function(){
                //通过加载对象的方式开启
                Game.exe();
            };

            var Game = {

                //启动程序
                exe : function(){
                    //设置整个页面为黑色
                    document.body.style.background = '#000';
                    //创建div盒子节点
                    var oDiv = document.createElement('div');
//给盒子添加id属性 GameBox
                        oDiv.id = 'GameBox';
//设置盒子样式
                        oDiv.style.cssText = 'width:300px;height:500px;border:10px solid #fff;margin:50px auto;text-align:center;position:relative;overflow:hidden;';
//将div节点添加到body中  添加节点和删除节点可以参考手册
                    document.body.appendChild( oDiv );
//调用init初始化游戏方法
                    this.init();
                },
//定义分数
                score : 0,
//判断是否结束
                ifEnd : false,

                //初始化
                init : function(){
//将game对象this存储起来,方便之后用的时候出现this代指不一样
                    var This = this;
//找id  --GameBox  也就是前面定义div盒子时添加的
                    var oDiv = document.getElementById('GameBox');
//清楚内容,,,,
//介绍一下:innerHTML可以清空里面的标签,也可以添加标签,innerTEXT不能添加标签(纯文本信息)
                    oDiv.innerHTML = '';
                    Game.score = 0;
                    Game.ifEnd = false;
//创建标题    飞机大战v1.0  h1标签及样式
                    var oH = document.createElement('h1');
                        oH.innerHTML = '飞机大战v1.0';
                        oH.style.cssText = 'color:#fff;font-size:26px;font-weight:normal;padding-top:50px;';
//添加到游戏盒子中  id=GameBox
                        oDiv.appendChild( oH );
//通过for循环创建一个选项,,,简单模式,,一般模式,,困难模式,,开挂模式
                    for (var i=0;i<4;i++ )
                    {
//创建p标签及样式来当按钮
                        var oP = document.createElement('p');
                            oP.index = i;
                            oP.style.cssText = 'font-size:14px;color:#000;width:150px;height:40px;margin:50px auto;text-align:center;line-height:40px;background:#fff;cursor:pointer;';
                        var html = '';
//onmouseover、onmouseout和下面两个用法其实一样,
//就是一对作用下面所有标签,包括自己,一对只是作用于自己,其他标签不管
//p的鼠标监听  onmouseenter 移入鼠标回调的函数  和onmouseleave 一起使用
                        oP.onmouseenter = function(){
                            this.style.background = '#f60';
                            this.style.color = '#fff';
                        };
//p的鼠标监听  onmouseleave 移出鼠标回调的函数  和onmouseenter 一起使用
                        oP.onmouseleave = function(){
                            this.style.background = '#fff';
                            this.style.color = '#000';
                        };
//设置点击事件  点击即可开始游戏,这里This这就是上面所说需要game对象调用start,
//不然这里用的this就相当于oP这个按钮对象,,可以通过console查看
                        oP.onclick = function(e){
//e参数也就是点击事件自带一个even,可以获取当前位置 x y对应宽高
                            e = e||window.event;
                            This.start( this.index , oDiv , e );
                        };
//设置按钮文字   和特殊样式
                        switch ( i )
                        {
                            case 0:
                                html = '简单难度';
                                break;
                            case 1:
                                html = '中等难度';
                                break;
                            case 2:
                                html = '困难难度';
                                break;
                            case 3:
                                html = '飞哥附体';
                                oP.style.color = '#f00';
                                oP.style.fontWeight = 'bold';
                                oP.onmouseenter = function(){
                                    this.style.background = '#f60';
                                };
                                oP.onmouseleave = function(){
                                    this.style.background = '#fff';
                                };
                                break;
                        }
//将文字添加到按钮p上
                        oP.innerHTML = html;
//将按钮p添加到div中  也就是盒子中
                        oDiv.appendChild(oP);
                    };
                },


                //游戏开始
                start : function( index , oGameBox , e ){
//开始游戏 innerHTML清除里面所有东西  
                    oGameBox.innerHTML = '';
//创建span节点
                    var oS = document.createElement('span');
//添加分数,左上角,left:15px,,top10px,,设置分数
                        oS.innerHTML = this.score;
                        oS.style.cssText = 'position:absolute;left:15px;top:10px;font-size:14px;color:#fff';
//添加到盒子中
                    oGameBox.appendChild( oS );
//获取飞机 自身  的属性和方法
                    this.plane( oGameBox , e , index);
//获取飞机 敌人  的属性和方法
                    this.enemy( oGameBox , oS , index );
                },

                //关于飞机
                plane : function( oGameBox , e , index ){
//获取点击按钮触发的位置  x坐标和y坐标相对于浏览器
                    var x = e.pageX,
                        y = e.pageY;
//js提供了一个Image对象,等同于document.createElement('img');
                    var oPlane = new Image(); // document.createElement('img');
//设置小飞机图片及属性  本身
                        oPlane.src = 'img/plane.png';
                        oPlane.width = 60;
                        oPlane.height = 36;
                        oPlane.id = 'plane';
//飞机需要设置的y 和 x
                    var tY = oGameBox.offsetTop+parseInt(oGameBox.style.borderWidth)+oPlane.height/2;
                    var lX = oGameBox.offsetLeft+parseInt(oGameBox.style.borderWidth)+oPlane.width/2;
//50 10 18= 78
//523  10 30= 563    
//这里用了一个回调方法onresize,这个是window的方法,当浏览器尺寸发送变化调用  
//用来监听x变化(宽度)号设置 x值
                    window.onresize = function(){
                        lX = oGameBox.offsetLeft+parseInt(oGameBox.style.borderWidth)+oPlane.width/2;
                    };
//开始游戏时使用觉对定位将飞机定位在选择模式的位置上的地图上
                    var top = y-tY;
                    var left = x-lX;
                        oPlane.style.cssText = 'display:block;position:absolute;top:'+top+'px;left:'+left+'px;';
//添加到盒子中
                    oGameBox.appendChild( oPlane );
//计算飞机能在页面上的最小值和最大值等 也是通过定位来显示
                    var leftMin = - oPlane.width/2;
                    var leftMax = oGameBox.clientWidth - oPlane.width/2;
                    var topMin = 0;
                    var topMax = oGameBox.clientHeight - oPlane.height;
//鼠标在元素上移动时回调的方法监听
                    document.onmousemove = function(e){
//先判断是否结束(或死亡)了
                        if ( !Game.ifEnd )
                        {
                            e = e || window.event;
                            var top = e.pageY - tY;
                            var left = e.pageX - lX;
//这几句就是判断  鼠标在盒子区域内,不能大于最大值,如果大于就取最大,如果小于最小值就取最小,
                            top = Math.min( top , topMax );
                            top = Math.max( top , topMin );
                            left = Math.min( left , leftMax );
                            left = Math.max( left , leftMin );
//设置定位的位置,,也就是飞机跟着鼠标移动,鼠标移出去了,飞机就在边上,不能出去
                            oPlane.style.left = left + 'px';
                            oPlane.style.top = top + 'px';
                        }

                    };
//调用飞机子弹  谁调用  在那里显示  index就是游戏难度的下标
                    this.biubiubiu( oPlane , oGameBox , index );
                },

                //飞机子弹
                biubiubiu : function( oPlane , oGameBox , index ){
//子弹速度
                    var speed;
                    switch ( index )
                    {
                        case 0:
                            speed = 200;
                            break;
                        case 1:
                            speed = 300;
                            break;
                        case 2:
                            speed = 400;
                            break;
                        case 3:
                            speed = 10;
                            break;
                    }
//this.BiuTimer等同于为biubiubiu函数创建了一个对象,用来找到定时器
//开启一个定时器,,定时器有两种,,一种是setInterval(a(),time毫秒)每隔多少时间执行一次函数a()
//另一种setTimeout(a(),1000)则是只调用一次,意思就是 一秒过后调用一次a()
                    this.BiuTimer = setInterval( function(){
//创建image对象,来显示子弹及属性特征
                        var oBiu = new Image();
                            oBiu.src = 'img/bullet.png';
                            oBiu.width = 6;
                            oBiu.height = 22;
                            oBiu.className = 'biubiubiu';
//第一个子弹位置,,
//top就是飞机的top位置,减去子弹自身高度,再减去3,能实现子弹在飞机上面3px效果
                        var top = oPlane.offsetTop - oBiu.height + 3;
//获取子弹left大小,
//飞机的left加上飞机的一般宽度,减去子弹一般的宽度,这样就能实现,子弹中线和飞机对齐
                        var left = oPlane.offsetLeft + oPlane.width/2 - oBiu.width/2;
                            oBiu.style.cssText = 'position:absolute;top:'+top+'px;left:'+left+'px';
//子弹添加到盒子中
                        oGameBox.appendChild( oBiu );
//为每一颗子弹设置一个定时器  oBiu.timer  不然的话子弹就会一直在原地
                        oBiu.timer = setInterval( function(){
                            if ( !oBiu.parentNode )
                            {
                                clearInterval( oBiu.timer );
                            }
//通过修改top定位值  每次减10px  就能达到类似子弹在往上走的样子
                            oBiu.style.top = oBiu.offsetTop - 10 + 'px';
//如果子弹到达最上面,则清楚定时器,,不然很浪费内存资源
                            if ( oBiu.offsetTop < - oBiu.height )
                            {
                                clearInterval( oBiu.timer );
//移除节点(其中一个子弹)
                                oBiu.parentNode.removeChild( oBiu );
                            }
                        } , 13 );//13则为子弹飞行速度了,,用定时器完成的
//speed 是之前有一个index判断速度  难度不同速度不同,,值越大,速度越慢,
//可以在页面测试,f12修改属性
                    } , speed); //  ******************  子弹速度
                },
                //敌军
                enemy : function(oGameBox , oS , index){
//判断游戏难度 给定速度
                    var a , x;
                    switch ( index )
                    {
                        case 0:
                            a = 1;
                            x = 500;
                            break;
                        case 1:
                            a = 3;
                            x = 300;
                            break;
                        case 2:
                            a = 5;
                            x = 200;
                            break;
                        case 3:
                            a = 5;
                            x = 100;
                            break;
                    }
//创建敌人定时器 this.EnemyTimer,之所以先创建定时器,因为,每次执行,就需要一个敌人,不能就一个

                    this.EnemyTimer = setInterval( function(){
//创建敌人  同创建飞机 自身 一样
                        var oEnemy = new Image();
                            oEnemy.src = 'img/enemy.png';
                            oEnemy.width = 23;
                            oEnemy.height = 30;

                        var lMin = 0;
                        var lMax = oGameBox.clientWidth - oEnemy.width;
//这里的随机,是为了在a的范围内创建敌人,不然敌人一直从一个地方出来
                        var left = Math.random() * (lMax-lMin) + lMin;
                        oEnemy.style.cssText = 'position:absolute;top:'+(-oEnemy.height)+'px;left:'+left+'px;'
                        oGameBox.appendChild( oEnemy );
//这里的随机,是为了随机一个速度出来
                        var b = Math.random() * a + 1;
//开启敌人运动的定时器oEnemy.timer
                        oEnemy.timer = setInterval(function(){
//敌人往下运动,每次运动 bpx距离
                            oEnemy.style.top = oEnemy.offsetTop + b + 'px'; // ***********敌军下落速度 
                            if ( oEnemy.offsetTop >= oGameBox.clientHeight )
                            {
                                clearInterval( oEnemy.timer );
//判断敌人是否到达最下面,是的话就删除这个敌人
                                oEnemy.parentNode.removeChild( oEnemy );
                            };
                        },13);

                        //getClass是和子弹的碰撞检测 返回一个子弹集合
                        var allBiu = Game.getClass('biubiubiu');
//定时器oEnemy.pzBiu 用来检测子弹和飞机碰撞没? 
                        oEnemy.pzBiu = setInterval(function(){
//变量子弹集合
                            for (var i=0;i<allBiu.length;i++ )
                            {
//Game.boom判断子弹和是否敌人碰撞
                                if ( Game.boom( oEnemy , allBiu[i] ) )
                                {
//分数加1
                                    Game.score ++;
                                    oS.innerHTML = Game.score;
//替换为敌人被炸毁的图片
                                    oEnemy.src = 'img/boom.png';
//清楚当前子弹击中的敌人和子弹的定时器
                                    clearInterval( oEnemy.pzBiu );
                                    clearInterval( oEnemy.pzPlane );
//移除子弹所在数组节点
                                    allBiu[i].parentNode.removeChild( allBiu[i] );
                                    setTimeout(function(){
                                        if ( oEnemy.parentNode )
                                        {
//移除敌人节点
                                            oEnemy.parentNode.removeChild( oEnemy );
                                        }
                                    },300);
                                    break;
                                }
                            }
                        },50);

                        //和战机的碰撞检测
//和上面子弹差不多,也就是自身飞机 和敌人飞机的检测
                        var oPlane = document.getElementById('plane');
                        oEnemy.pzPlane = setInterval(function(){
//先判断是否游戏结束
                            if ( Game.ifEnd )
                            {
                                clearInterval( oEnemy.pzPlane );
                            }
//判断是否碰撞
                            if ( Game.boom( oEnemy , oPlane ) )
                            {
                                Game.ifEnd = true;
                                clearInterval( oEnemy.pzPlane );
                                clearInterval( Game.BiuTimer );
                                clearInterval( Game.EnemyTimer );
//两个飞机碰撞,,游戏结束,并且两个飞机图片都替换成撞毁的图片
                                oEnemy.src = 'img/boom.png';
                                oPlane.src = 'img/boom2.png';
//开启一次性定时器setTimeout,前面说过这个  一秒后执行Game的over函数
                                setTimeout(function(){
                                    Game.over( oGameBox );
                                },1000);
                            }
                        },50);
                    } , x );  // *********** 敌军生成速度
                },

                //碰撞检测
                boom : function( obj1 , obj2 ){
//假设obj1是敌人飞机  obj2是自己飞机  这里的y 和 x就是 整个页面top顶端和left侧端到目标的距离
//T1  可以这么理解,敌人飞机为一个正方形,ti则是上面线的y的距离
//B1  可以理解为,敌人飞机下面线的y距离
//L1  可以理解为,敌人飞机左侧到浏览器left边的距离
//。。。。。。。。。。
                    var T1 = obj1.offsetTop;
                    var B1 = T1 + obj1.clientHeight;
                    var L1 = obj1.offsetLeft;
                    var R1 = L1 + obj1.clientWidth;

                    var T2 = obj2.offsetTop;
                    var B2 = T2 + obj2.clientHeight;
                    var L2 = obj2.offsetLeft;
                    var R2 = L2 + obj2.clientWidth;
//R2 < L1 飞机的右边距离比敌人飞机左边小,肯定撞不到
//L2 > R1 飞机的左边距离比敌人飞机右边远,肯定撞不到
//B2 < T1 飞机的下边距离比敌人飞机上边远,肯定撞不到
//T2 > B1 飞机的上边距离比敌人飞机下边远,肯定撞不到
                    if ( R2 < L1 || L2 > R1 || B2 < T1 || T2 > B1 )
                    {
                        return false; // 没撞上
                    }
                    else
                    {
                        return true; // 撞上了
                    }
                },

                //游戏结束  没什么可将的了,,就是清楚页面,然后新建结束页面 ,
                //其中重新开始,也就是再调用一次Game的init初始化方法
                over : function(oGameBox){
                    oGameBox.innerHTML = '';
                    var oDiv = document.createElement('div');
                        oDiv.style.cssText = 'width:200px;height:400px;margin:50px;background:#fff;';
                    var oT = document.createElement('h3');
                        oT.innerHTML = 'Game Over';
                        oT.style.cssText = 'padding-top:50px;;'
                    var oP1 = document.createElement('p');
                        oP1.innerHTML = '您的得分是:' + '<span style="color:#f00;font-weight:bold;">' + this.score + '</span>';
                        oP1.style.cssText = 'font-size:16px;color:#000';

                    var oRestart = document.createElement('div');
                        oRestart.style.cssText = 'width:100px;height:40px;font-size:14px;text-align:center;line-height:40px;color:#000;background:#990;margin:20px auto;cursor:pointer;';
                        oRestart.innerHTML = '重新开始';
                    oRestart.onclick = function(){
                        Game.init();
                    };

                    oDiv.appendChild( oT );
                    oDiv.appendChild( oP1 );
                    oDiv.appendChild( oRestart );
                    oGameBox.appendChild( oDiv );
                },

//getClass方法  这个方法写得很好,是我觉得的,遍历所有的节点,并返回所需要的节点数组
//getClass方法  虽然外面调用的时候只有一个参数,但是这里面还是补上了
                getClass : function( cName , parent ){
                    parent = parent || document;
                    if ( document.getElementsByClassName )
                    {
                        return parent.getElementsByClassName(cName);
                    }
                    else
                    {
//这个 我是这么理解的。。获取当前游戏的时候所有节点,,返回一个数组   
//通过后面if判断( if ( arrClass[j] == cName ))是否是自己需要(cName)的元素,添加到数组中
                        var all = parent.getElementsByTagName('*');
                        var arr = [];
                        for ( var i=0;i<all.length;i++ )
                        {
                            var arrClass = all.className.split(' ');
                            for ( var j=0;j<arrClass.length;j++ )
                            {
//判断是否是自己需要的name,,,这里所运用到的就是判断是否是子弹节点
                                if ( arrClass[j] == cName )
                                {
//push方法就是放数组中添加一个节点
                                    arr.push( all[i] );
                                    break;
                                }
                            }
                        }
//最后返回获取到的  例如 获取到的子弹数组
                        return arr;
                    }
                },

            };

        </script>
    </body>
</html


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

需要用到的图片,可以自己设计一下

1.自己的飞机

2.敌人飞机

3.boom两种图片都可以用这一张

本文只是转载之后

原文博客地址:https://blog.csdn.net/weixin_42955598/article/details/81812171

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 JavaScript 实现飞机大战游戏的示例,希望能帮到你: HTML 代码: ``` <html> <head> <title>飞机大战游戏</title> <style> #game-board { width: 400px; height: 600px; margin: 0 auto; border: 1px solid #ccc; position: relative; } #player { width: 50px; height: 50px; position: absolute; bottom: 0; left: 50%; margin-left: -25px; background-color: red; } .bullet { width: 5px; height: 10px; position: absolute; bottom: 50px; left: 50%; margin-left: -2px; background-color: blue; } .enemy { width: 50px; height: 50px; position: absolute; top: -50px; left: 50%; margin-left: -25px; background-color: green; } </style> </head> <body> <div id="game-board"> <div id="player"></div> </div> <script src="game.js"></script> </body> </html> ``` JavaScript 代码: ``` var player = document.getElementById('player'); var gameBoard = document.getElementById('game-board'); var enemies = []; var bullets = []; function movePlayer(event) { if (event.keyCode === 37) { player.style.left = Math.max(0, player.offsetLeft - 10) + 'px'; } else if (event.keyCode === 39) { player.style.left = Math.min(gameBoard.offsetWidth - player.offsetWidth, player.offsetLeft + 10) + 'px'; } } function createEnemy() { var enemy = document.createElement('div'); enemy.className = 'enemy'; enemy.style.left = Math.floor(Math.random() * (gameBoard.offsetWidth - enemy.offsetWidth)) + 'px'; gameBoard.appendChild(enemy); enemies.push(enemy); } function moveEnemies() { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; enemy.style.top = enemy.offsetTop + 10 + 'px'; if (enemy.offsetTop >= gameBoard.offsetHeight) { gameBoard.removeChild(enemy); enemies.splice(i, 1); i--; } } } function createBullet() { var bullet = document.createElement('div'); bullet.className = 'bullet'; bullet.style.left = (player.offsetLeft + player.offsetWidth / 2) + 'px'; gameBoard.appendChild(bullet); bullets.push(bullet); } function moveBullets() { for (var i = 0; i < bullets.length; i++) { var bullet = bullets[i]; bullet.style.top = bullet.offsetTop - 10 + 'px'; if (bullet.offsetTop <= 0) { gameBoard.removeChild(bullet); bullets.splice(i, 1); i--; } else { for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; if (isCollide(bullet, enemy)) { gameBoard.removeChild(bullet); bullets.splice(i, 1); i--; gameBoard.removeChild(enemy); enemies.splice(j, 1); break; } } } } } function isCollide(a, b) { var aRect = a.getBoundingClientRect(); var bRect = b.getBoundingClientRect(); return !( (aRect.bottom < bRect.top) || (aRect.top > bRect.bottom) || (aRect.right < bRect.left) || (aRect.left > bRect.right) ); } document.addEventListener('keydown', movePlayer); setInterval(function() { createEnemy(); }, 1000); setInterval(function() { moveEnemies(); moveBullets(); }, 50); setInterval(function() { createBullet(); }, 200); ``` 这个示例中,我们创建了一个飞机大战游戏的简单版本。玩家通过左右方向键来移动飞机,按空格键发射子弹,敌人会从顶部出现并向下移动,玩家需要尽可能地消灭敌人。 希望这个示例对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值