【前端】利用JavaScript做打砖块小游戏

【写在前面:本篇文章介绍的是博主在学习前端的JavaScript时跟着教程,稍作改良的一个打砖块的小游戏,这个可能与大家见到的简易版打砖块不大一样,会稍微复杂一点点。写这篇文章有两个目的,一是作为学习记录,二是希望对大家有点帮助,对于不足之处,也希望各路大佬可以不吝赐教。本文为作者原创文章,文中所示的图片、代码皆来自网络或博主自制,仅做学习、记录使用,如果某些东西涉及侵权,请作者大大告知博主,可以对此进行补充说明。如有人私自引入商业使用构成侵权或违法犯罪,则博主概不负责。】

这里写目录标题

  • 一、完成情况
  • 二、简介
    • - 板子移动
    • - 碰撞模块
    • - 砖块的生成
  • 三、总结
  • 四、完整代码

一、完成情况

二、简介

这个项目主要是为了练习JavaScript中的一些操作方法而设定的练习,但本身用Chrome写这种程序就是在折磨cup,懂得都懂。当时运行久了(敲代码+开Chrome看完成情况),电脑都差点卡死。所以也不敢继续完成下去了。

大体上的思路其实并不复杂,大家在很多地方都可以看到类似的代码。整个游戏是通过div块完成的,中间一个大的div作为中心方框,下面一个div作为打砖块的板子,然后一个div将角消掉作为小球,最后在游戏开始前随机那么60个白色div作为砖块,就可以开始打了。

其中需要实现的基本功能有三个。一是这个板子的移动,他应该可以有两种方式实现控制,键盘和鼠标,在这里我选择了用鼠标点击拖动的方式实现这一功能。第二个就是碰撞,其中包括了板子和小球的碰撞和小球和砖块的碰撞两种。第三是砖块的生成和消除。

由于一开始我是想直接仿照打砖块的小游戏做的(类似下图这种有奖励的,然后满屏都是球的这种,图片截自某信小程序),所以,在这个项目中未能完成的功能有:1)奖励方框的生成和掉落 2)小球分裂 3)胜负手判断(这个只是单纯没做完2333)
【前端】利用JavaScript做打砖块小游戏_第1张图片

对于已完成的几个功能来讲:

- 板子移动

这里用到了一个简单的div移动的方法,由于用的是鼠标拖动的方法,所以这里只需要检测mouseup、mousedown、mousemove三个事件,这样一来,通过监测鼠标按下和鼠标抬起的事件来判断是否需要移动滑块,在读出鼠标移动的距离用于对板子移动距离进行计算。而对于板子的移动,则只需要在鼠标点下时计算其左上角的坐标,然后再通过鼠标移动时得到的移动数据,对板子的距左距离进行加减运算即可完成。

- 碰撞模块

这个模块相对来说就比较复杂了,倒不是代码有多难,而是由于在这个项目是在div块的基础上完成的,对于碰撞和反弹的判定可能会出现几个问题:

  1. 碰撞判定:碰撞判定其实还不算特别复杂,首先我们先来看看目标碰撞体和小球的示意图【前端】利用JavaScript做打砖块小游戏_第2张图片从图中我们可以看到目标div和小球的div实际上都是一个方块,虽然我们用圆角的方式将小球做成了一个圆形,但其实际碰撞体积还是按方块来计算的,所以我们只需要按方块的体积来计算碰撞,就可以简单实现目标。首先我们得知道,在碰撞计算时,我们实际上是用的offsetLeftoffsetTop两种方法去获取div距离左侧和顶部的距离,然后利用数学的方式判断是否碰撞,大致上如下图所示【前端】利用JavaScript做打砖块小游戏_第3张图片由于在本次设计中小球和所以我们单看关键点,就可以吧整个想象成一个二维坐标系和一堆坐标点,然后就会发现是这样的情况,当小球的关键点坐标落在绿色这个区域时,可以说小球与目标块之间产生了碰撞。这样,碰撞的问题就解决了

  2. 反弹问题:解决了碰撞的问题之后,反弹的问题相对来说就简单一点了,由于砖块是正方形,那么我们就可以画出一下几个区域【前端】利用JavaScript做打砖块小游戏_第4张图片其中当“坐标”落在紫色区域时,我们可以认为小球在砖块的上面或者下面,此时我们反转小球纵向速度的正负值,就可以完成反弹。同理,当小球落在黄色区域时,可以认为小球在砖块的左侧或右侧,此时我们反转小球横向速度的正负值,就可以完成反弹。

- 砖块的生成

这里可以有两种方法生成砖块的div,第一种是笨办法,也是简单的方法,直接在html中一个个写上去就好了,但是这样做那么程序就失去意义了,工作量太大。所以我们采用第二种方法,先用createElement依序创建出足够多的砖块,然后再将生成的div变成浮动的形式,最后固定div的“坐标”。这样我们就可以轻松完成对砖块的创建。

三、总结

对这个小练习来说,有以下几个问题:

  1. 最大的问题还是这样做游戏真不推荐,如果把它做完,相当于直接点开了个@echo off ; start cmd;0%;的bat文件,大概能把cpu都给烧了吧。
  2. 在砖块的碰撞端上还是有一定的问题,问题主要出在小球的速度上,由于程序中是判断小球关键点“坐标”与我们目标位置的关系,一旦进入目标位置,则相应速度方向反向。那么就会出现两个问题:一是板子与小球碰撞的问题,由于板子并不是正方形的块,没办法写对角线的判别式(由于是像素点判定,所以如果强行写判别式,可能出现被遗漏的像素,从而造成bug),所以板子的碰撞反弹只能反转纵向速度。二是如果小球随机到的速度过快,会出现在第一次检测时,“坐标”在判定区内,速度反向,但是第二次检测时,小球来不及飞出来,还在判定区内,于是在同一方向上继续反向,造成在边界上鬼畜的情况。如果说第一个问题还无伤大雅的话,第二个问题我们除了能控制小球速度之外,我想不出更好的办法去解决这个bug,可能是我才疏学浅了,如果有好的办法,请各位大神不吝赐教。

总的来说,虽然有点耗cpu,代码也有点小问题,但是能在没用框架的情况下亲手做出这样的游戏,还是蛮有成就感的,知足了。

四、完整代码

编译器:vs code
浏览器:Chrome

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>闲的蛋疼</title>
        <style>
        	//做一些简单的css样式,美化网页
            #div1{width: 600px; height: 600px; border: 1px solid black; border-bottom: dashed 1px black; position: relative ; margin: 100px auto;}
            #ball1{width: 6px; height: 6px; background-color: red; border-radius: 50%; position:absolute; bottom: 30px; left: 300px;}
            #bat{width: 100px; height: 20px; background-color:grey; opacity: 1; position:absolute; bottom: -15px; left: 250px;}
            #brick div{width: 19px; height: 19px; border: 0.5px solid black ; float: left; }
            body{height: 100%; width: 100%; background-image: url('E:/vs code/源代码/html/img_2323.jpg'); background-attachment: fixed; position: relative;font-family: Arial; background-position: center 0;}
            #rewardBrick {position: absolute;}
            #rewardBrick div{width: 14px; height: 14px; background-color: orange; opacity: 1; position:absolute; left: 3px; top: 3px;}
        </style>
        
        //
        <script>
            window.onload = function(){
                var oDiv = document.getElementById('div1');
                var oBall = document.getElementById('ball1');
                var oBat = document.getElementById('bat');
                var oBrick = document.getElementById('brick');
                var aBricks = oBrick.getElementsByTagName('div');
                var rBrick = document.getElementById('rewardBrick');
                var rBrick1 = rBrick.getElementsByTagName('div');
                var rBrick2 = document.getElementsByClassName('nb');

                dragX(oBat);
                creatBrick(360);

                //随机生成一个的速度
                var speedX = 1 + Math.random()*3;/* parseInt(Math.random()*3) +10; */ 
                var speedY = -1 - Math.random()*3;

                //触壁反弹函数
                setInterval(function(){
                    oBall.style.left = oBall.offsetLeft + speedX + 'px';
                    oBall.style.top = oBall.offsetTop + speedY + 'px';

                    if(oBall.offsetLeft >= 594 || oBall.offsetLeft <= 0){
                        speedX *= -1;
                    }

                    if(oBall.offsetTop >= 594 || oBall.offsetTop <= 0){
                        speedY *= -1;
                    }

                    //砖块反弹和板子反弹
                    if(knock(oBall,oBat)){
                        speedY *= -1;
                    }

                    for(var i = 0; i < aBricks.length; i++){
                        if(knock(oBall,aBricks[i])){
                            
                            if(knockPositionJudge_Brick(oBall,aBricks[i]) == 'surface'){
                                speedY *= -1;
                            }else if(knockPositionJudge_Brick(oBall,aBricks[i]) == 'side'){
                                speedX *= -1;
                            }
                        
                            var left2 = aBricks[i].offsetLeft;
                            var top2 = aBricks[i].offsetTop;
                            oBrick.removeChild(aBricks[i]);
                            // reward(aBricks[i],left2,top2);
                            return top2;
                            break;
                        }
                    }

                    //奖励模块移动
                    // var bricks_1 = $(".nb");
                    // bricks_1.style.backgroundColor = 'blue';
                    // if(rBrick1.length > 0){
                    //     document.getElementsByClassName('nb');
                    // }

                   
                },10);  //10ms检测一次

            }

            //拍子拖拽函数
            function dragX(node){
                node.onmousedown = function(ev){
                    var e = ev ||window.event;
                    var offsetX = e.clientX - node.offsetLeft;

                    document.onmousemove = function(ev){
                        var e = ev ||window.event;
                        var l = e.clientX - offsetX;
                        if(l <= 0){
                            l = 0;
                        }
                        if(l >= 500){
                            l = 500;
                        }
                        node.style.left = l +'px';
                    }
                }

                document.onmouseup = function(){
                    document.onmousemove = null;
                }
            }

            //创建砖块的函数
            function creatBrick(n){
                var oBrick = document.getElementById('brick');
                for(var i = 0; i < n; i++){
                    var node = document.createElement('div');
                    node.style.backgroundColor = 'rgba(255,255,255,0.7)';
                    oBrick.appendChild(node);
                }

                //文档流转换
                var aBricks = oBrick.getElementsByTagName('div');
                for(var i = 0; i < aBricks.length; i++){
                    aBricks[i].style.left = aBricks[i].offsetLeft +'px';
                    aBricks[i].style.top = aBricks[i].offsetTop +'px';
                }

                for(var i = 0; i < aBricks.length; i++){
                    aBricks[i].style.position = 'absolute';
                }
            }

            //碰撞处理的函数
            function knock(node1,node2){
                var l1 = node1.offsetLeft;
                var r1 = node1.offsetLeft + node1.offsetWidth;
                var t1 = node1.offsetTop;
                var b1 = node1.offsetTop + node1.offsetHeight;

                var l2 = node2.offsetLeft;
                var r2 = node2.offsetLeft + node2.offsetWidth;
                var t2 = node2.offsetTop ;
                var b2 = node2.offsetTop + node2.offsetHeight;

                if(t2 >= b1 || b2 <= t1 || l2 >= r1 || r2 <= l1){
                    return false;
                }else{
                    return true;
                }
            }

            function knockPositionJudge_Brick(node1,node2){
                var x1 = node1.offsetLeft - node2.offsetLeft;
                var y1 = node1.offsetTop - node2.offsetTop;
               
                if(y1 >= -6 && y1 - x1 <= 0 && x1 >= -6 && x1 <= 7|| y1 >= -6 && y1 + x1 <= 14 && x1 >= 7 && x1 <= 20|| y1 + x1 >= 14 && y1 <= 20 && x1 >= -6 && x1 <= 7 || y1 - x1 >= 0 && y1 <= 20 && x1 >= 7 && x1 <= 20 ){
                    return 'surface';
                }else {
                    return 'side';
                }
            }

            //随机掉落奖励箱子的创建
            // function reward(aBricks,leftPoint,topPoint){

            //     if(Math.random() <= 1){
            //     var rBrick = document.getElementById('rewardBrick');
            //     var newBrick = document.createElement('div');
                
            //     newBrick.className = 'nb';
            //     newBrick.style.left = leftPoint + 3 + 'px';
            //     newBrick.style.top = topPoint +3 + 'px';

            //     rBrick.appendChild(newBrick);
            //     newBrick.style.position = 'absulute';
            //     newBrick.style.display = 'inline-block';
                
            //     topPosition = topPoint + 3;
            //     return topPosition;

            //     }
            // }

            //小球分裂函数
            function divideBall(){

            }

            //小球消失函数
            function removeBall(){

            }

            //胜负手判断函数
            function result(){

            }

        </script>
    </head>
    <body>
        <div id="div1">
            <div id="ball1"></div>
            <div id="bat"></div>
            <div id="brick"></div>
            <div id="rewardBrick"></div>
        </div>
        
    </body>
</html>

你可能感兴趣的:(前端,js,javascript,html,css)