JS 连锁泡泡 v1.1 源码解析与实现思路

作者:青柠

时间:2026-10-24

浏览:258

本文分享 JS 连锁泡泡 v1.1 的完整源码。作者指出游戏核心逻辑如移动、碰撞和消失已实现,但省略了关卡等游戏性内容。代码重点展示了如何利用面向对象编程和闭包修正 setInterval 的上下文问题,注释详尽,适合学习 JS 游戏基础逻辑。

文章目录

JS 连锁泡泡 v1.1 源码解析

泡泡的移动、碰撞及消除功能均已实现。随着开发深入,作者认为后续涉及游戏性设计(例如关卡数量、消除目标数量等)部分较为繁琐,因此未予编写。有兴趣的读者可以阅读此代码,其中多处使用了闭包来修正 setInterval 函数的作用域问题(该函数在 JS 中较为特殊)。代码采用面向对象风格,并包含完整的注释说明。


JS 连锁泡泡 v1.1 源码解析
JS 连锁泡泡 v1.1 源码解析
<html> <head> <title>原创JS连锁泡泡 v1.1</title> <style>      body{ margin: 0px; padding: 0px; background-color: #000; } #main{ border: solid red 0px; width: 800px; height: 600px; font-size: 48px; position: absolute; background-color: #fff; } .little{ height: 15px; width: 15px; font-size: 1px; border: solid #ccc 0px; position: absolute; left: 100px; top: 100px; background: url(/upload/20090928170442418.gif) no-repeat; filter: alpha(opacity=30); } .big{ height: 61px; width: 61px; font-size: 9pt; border: solid #ccc 0px; position: absolute; left: 0px; top: 0px; background: url(/upload/20090928170442175.gif) no-repeat; /**使显示的分数居中**/ line-height: 61px; color: #fff; filter: alpha(opacity=30); } #info{         position: absolute;         left: 820px;         top 20px;         border: solid #fff 1px;         height: 600px;         width: 300px;         color: #fff;         padding: 5px; } #score{         float: right;         border: solid #ccc 1px;         height: 10px;         width: 80px;         margin: 5px;         font-size: 30px; } </style> </head> <body> <div id="main">         <div id="score">0</div> </div> <div id="info">          原创JS连锁泡泡 v1.1          原创作者 sunxing007          转载请务必注明来自:          http://blog.csdn.net/sunxing007          开发环境:IE8 暂时没有考虑兼容性            </div> </body> </html> <script type="text/javascript">      /*******************************************************      * 原创JS连锁泡泡 v1.1      * 原创作者 sunxing007      * 转载请务必注明来自:http://blog.csdn.net/sunxing007      *******************************************************/ var doc = document; function $(id){return doc.getElementById(id)}; var container = $('main'); var score_ele = $('score'); try{         //针对ie6缓存背景图          document.execCommand("BackgroundImageCache", false, true);         }catch(e){alert(e)}; /*******************************************************/ //系统参数 //小泡泡半径 var little_radius = 7; //爆炸后的泡泡半径 var big_radius = 30; //半径差 var delta_radius = big_radius - little_radius; //容器宽度 var container_width = 800; //容器高度 var container_height = 600; //与定义的泡泡移动的4个方向 //[x,y]代表x方向的增量和y方向的增量,也就确定了移动方向 var direct = [[1,1],[1,-1],[-1,1],[-1,-1]]; //爆炸后的泡泡集合 var chained_bubbles = []; //所有的泡泡 方便管理 var all_bubbles = []; /*****************************************************/ //泡泡模型 function Bubble(left, top, bgPos, score, dirIndex){ var ele = doc.createElement('div'); ele.align = 'center'; ele.className = 'little'; ele.style.left = left + 'px'; ele.style.top = top + 'px'; this.bgPos = bgPos; ele.style.backgroundPositionX = -bgPos*(little_radius*2+1); this.element = ele; ele.bubble = this; this.score = score; this.exploded = false; this.dirIndex = dirIndex; this.container.appendChild(ele); this.container.onclick = function(){         if(window.curBubble){                 //curBubble.distroy.apply(curBubble);                 chained_bubbles.push(curBubble);                 curBubble.explode.apply(curBubble);                 curBubble.container.onclick = null;         } } ele.onmouseover = function(){         this.style.filter = 'alpha(opacity=100)';         window.curBubble = ele.bubble;          } ele.onmouseout = function(){         this.style.filter = 'alpha(opacity=30)'; } } Bubble.prototype = {         //容器的引用      container: $('main'),      //移动泡泡 move: function(){              if(chained_bubbles.length>0){                      for(var i=0; i<chained_bubbles.length; i++){                              if(this.crushed(chained_bubbles[i])){                                      this.explode();                              }                          }                  } var _self = this; //连续移动泡泡的函数,因为要用到setInterval, //所以这个函数作成闭包 var _f = function(){      if(chained_bubbles.length>0){                              for(var i=0; i<chained_bubbles.length; i++){                                      if(this.crushed(chained_bubbles[i])){                                              this.explode();                                              break;                                      }                                  }                          }         var l = parseInt(this.element.style.left) + direct[this.dirIndex][0];         var t = parseInt(this.element.style.top) + direct[this.dirIndex][1];         //status = 'l:' + l + " t:" + t;         if(this.checkBorder(l, t)){          this.element.style.left = l;          this.element.style.top = t;     }     else{             //this.stop();             this.changeDirect();     } } this.timer = setInterval(function(){ _f.apply(_self); //移动速度 }, 10) }, //停止移动 stop: function(){         clearInterval(this.timer); }, //边界检查 看泡泡有没有超出容器 checkBorder: function(l, t){         if(l>(container_width-big_radius-1-little_radius)||l<(big_radius-little_radius)||t>(container_height-big_radius-1-little_radius)||t<(big_radius-little_radius)){                 return false;             }         return true; }, //碰壁后改变泡泡的移动方向 changeDirect: function(){         var _l = parseInt(this.element.style.left);         var _t = parseInt(this.element.style.top);         for(var i=1; i<=4; i++){              if(direct[this.dirIndex][0]==-direct[(i+this.dirIndex)%4][0]&&direct[this.dirIndex][1]==-direct[(i+this.dirIndex)%4][1]){                      continue;              }                 var l = _l + direct[(i+this.dirIndex)%4][0];                 var t = _t + direct[(i+this.dirIndex)%4][1];                 if(this.checkBorder(l, t)){                         this.dirIndex = (i+this.dirIndex)%4;                         break;                 }                 else{                      continue;                     }         } }, //泡泡爆炸 explode: function(){         this.stop();         this.element.style.left = parseInt(this.element.style.left) - delta_radius;         this.element.style.top = parseInt(this.element.style.top) - delta_radius;         this.element.className = 'big';         this.element.style.backgroundPositionX = - this.bgPos*(big_radius*2+1);         this.element.innerText = this.score;         this.exploded = true;         score_ele.innerText = parseInt(score_ele.innerText) + this.score;         chained_bubbles.push(this);         this.fade.apply(this); }, /**是否和另外一个已经爆炸的泡泡碰撞了**/ crushed: function(other){         if(!other.exploded){                 return false;             }         if(!other.element) return false;         var l = parseInt(other.element.style.left);         var t = parseInt(other.element.style.top);         var w = big_radius*2-8;//big_radius*2+1;         var h = w;         var pt = [,,,];         pt[0] = [parseInt(this.element.style.left) - delta_radius, parseInt(this.element.style.top) - delta_radius];         pt[1] = [pt[0][0]+w,pt[0][1]];         pt[2] = [pt[0][0]+w,pt[0][1]+h];         pt[3] = [pt[0][0],pt[0][1]+h];         for(var i=0; i<4; i++){                 if(pt[i][0]>l&&pt[i][1]>t&&pt[i][0]<=(l+w)&&pt[i][1]<=(t+h)){                     return true;                 }         }         return false; }, //爆炸的泡泡逐渐消失 fade: function(){         var _self = this;         var opacity = 28;         var _f = function(){                 this.element.style.filter = 'alpha(opacity=' + (opacity-2) + ')';                 opacity -=2;                 if(opacity==0){                         this.distroy();                 }         };         this.timer = setInterval(function(){                 _f.apply(_self);         }, 200); }, //析构方法 因为对象中很多地方涉及对象相互引用 //需要在析构函数中消除环形引用,以防内存泄露 distroy: function(){         if(this.timer){                 clearInterval(this.timer);         }         for(var j=0; j<chained_bubbles.length; j++){                 //if(chained_bubbles[j]==null) continue;                 if(chained_bubbles[j]===this){                         chained_bubbles.splice(j, 1);                         //chained_bubbles[j] = null;                         status = 'distroyed from chained_bubbles[' + j + ']';                         break;                 }         }         for(var i=0; i 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


转载请务必注明来自:http://blog.csdn.net/sunxing007

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章