JS开发打气球游戏

观视频《月薪4万的程序员有多强?半小时原生JS开发打气球游戏,征服现场数万人!》

清晨,日常打开B站,被首页此视频的标题所吸引,虽一看就是标题党,但还是没能抑制住好奇心。
视频共计60*3分钟,学习到了很多东西。其中后半部分有许多正三观的见解也非常认同。
视频地址:https://www.bilibili.com/video/av15152538/
在线试玩:http://sandbox.runjs.cn/show/luderhbq
参考视频写的demo:https://coding.net/u/yimocoding/p/WeDemo/git/tree/气球大战

看了视频,自己来实现试试

花了半天的时间,人生中的第二个游戏终于完成了,想起第一次做拼图游戏也已经是3年前了~
来吧,试玩一下,看能消灭多少个气球【笑哭】:http://sandbox.runjs.cn/show/luderhbq
然后,一起来一步步构建自己的【气球大战】(文中代码为核心代码,后续有优化,故非完整代码),可以在runjs中去查看

1.用css3画一个气球

看视频的时候觉得自己这个会那个也会,写代码的时候才发现没有智能提示啥都不会,打错单词的次数不是一次两次~

气球效果预览

css代码

//html→→_→→<div class="balloon"></div>

body{margin:0;padding:0}
.balloon{width:150px;height:150px;position:absolute;left:0;top:0;background-color:pink;border-radius:50% 50% 10% 50%;transform:rotate(45deg);box-shadow:1px 1px 20px 20px red inset}
.balloon:after{width:20px;height:20px;content:"";display:block;background:0 0;position:absolute;right:-15px;bottom:-15px;border-left:5px solid red;border-top:5px solid red}
.balloon:before{width:2px;height:50px;content:"";display:block;background:pink;position:absolute;right:-10px;top:100%;margin-top:-16px;transform:rotate(-45deg)}

2.随机创建气球

首先定义了一些变量

    var bnElements=[];//存放所有气球
var random=Math.random;//随机函数
var wW=window.innerWidth;//窗口宽度
var wH=window.innerHeight;//窗口高度
var ballW=160;//气球的宽度
var ballH=300;//气球的宽度
var minSpeed=3;//最小速度,每次向上移动至少3px
var speedNum=8;//速度的定量
var defBnNumber=10;//初始化气球

首先编写并调用初始化方法生成气球

生成气球代码

    init(defBnNumber);
//初始化气球
function init(num){
//创建一个虚拟文档节点
var docFragment=document.createDocumentFragment();
for(var i=0;i<num;i++){
var bnElement=document.createElement('div');
bnElement.className='balloon';
//速度随机,限定最小值
var speed=Math.max(minSpeed,~~(random()*speedNum));
bnElement.setAttribute('speed',speed);//~~取整 移动速度
bnElement.setAttribute('id','ball-'+(bnElements.length+i+1));
//分散排列
var x=(~~(random()*wW))-ballW;
x=Math.max(0,x);
bnElement.style.left=x+'px';
bnElement.style.top=wH+'px';//露一点出来 //1.先将创建的气球放入创建的虚拟文档节点
docFragment.appendChild(bnElement);
bnElements.push(bnElement);
}
//2.将虚拟文档节点添加到body中
document.body.appendChild(docFragment);
}

效果预览

3.气球向上移动

创建一个move方法并在初始化后调用

气球移动代码

    move();//移动气球 只需要调用一次即可
function move(){
var bl=bnElements.length
for(var i=0;i<bl;i++){
var currentElement=bnElements[i]
if(currentElement==null){
continue;
}
var offsetTop=currentElement.offsetTop;
if(offsetTop>-ballH){//窗口中
var speed=currentElement.getAttribute('speed');
currentElement.style.top=offsetTop-speed+'px'
}
else{
//移除dom节点
document.body.removeChild(currentElement);
//移除数组中
bnElements.splice(i,1);
init(1);
}
}
setTimeout(move,1000/30);
}

效果预览

4.点击气球,气球消失

发现颜色有点丑~~遂改。

气球消失代码

bindClick();
//绑定点击气球事件
function bindClick(){
document.body.addEventListener('click',function(e){
if(e.target.className=='balloon'){
boom.call(e.target,function(){
e.target.parentNode.removeChild(e.target);
bnElements.splice(bnElements.lastIndexOf(e.target),1);
init(1);
});
}
});
}
function boom(callback){
//var that=this; //替换了上下文,但是没有使用this的意义.
var speed=this.getAttribute('speed');
this.timer=setInterval(function(){
this.style.opacity=0.1*(speed--)
console.log(this.offsetWidth);
if(speed<1){
callback&&callback();
clearInterval(this.timer);
}
}.bind(this),1000/30);
}

效果预览

核心代码终于写完,在我的纯静态工具站点生成二维码扫一扫,在我的小米手机上玩了玩,ok正常,然后再新入手的ipad中试了试。。。擦。坑爹呢,点了咋没反应啊。
好吧,为了ipad能玩,强忍着泪水(饿的)解决了iOS的safari兼容问题~

5.解决遇到的safari浏览器兼容问题

  • 问题一:Safari中单击事件不能绑定到document.body上~~,因为无效~
    解决方法:给元素加了个父级~,若click事件有问题则还需要将click换成touchend~

  • 问题二:transform变换z-index层级渲染异常
    解决方法:未变换的元素上添加样式:transform: translateZ(120px);
    参考文章:http://www.zhangxinxu.com/wordpress/2016/08/safari-3d-transform-z-index/

总结

get了几个以前不知道没用过的新技能

  • 文档片段
    当需要将一堆节点添加到dom中可以使用document.createDocumentFragment();创建虚拟文档节点,让后将节点先添加到此虚拟节点中,再将此节点追加到指定元素,能够降低dom渲染次数
  • 使用位运算符取整
    取0-9的随机数 ~~(Math.random()*10) //Math.random()大于等于 0.0 且小于 1.0
  • Math.max() Math.min() 可以用来限定边界值
  • setInterval问题:
    • 可能会丢帧(浏览器的刷新频率为60FPS,一秒最大可以重绘60次),故理论上setinterval()间隔时间大于1000/60就不会参数丢帧的情况
    • 时间线偏移(甚至重叠没执行完就执行下一次任务了),若需要每次都执行完才执行下次任务则使用setTimeout+递归
    • this的传递(可以使用bind()去绑定this,不能使用call,会提示没有权限)
      传递this到setInterval中:setInterval(function(){}.bind(this),1000/30)
  • 值的相等判断使用===会比==性能好一点,大部分情况应当使用===
  • 判断回调函数并执行回调函数
    以前我是这样写的:if(typeof(callback)==='function')callback();
    视频中有用短路运算符实现即:callback&&callback()

  • 踩了踩safari的坑
  • 最可怕的事情,不是别人比你强,而是比你强的人比你还努力!!!

作者:易墨 
个人小站:http://www.yimo.link

JS开发打气球游戏的更多相关文章

  1. 【转】利用 three.js 开发微信小游戏的尝试

    前言 这是一次利用 three.js 开发微信小游戏的尝试,并不能算作是教程,只能算是一篇笔记吧. 微信 WeChat 6.6.1 开始引入了微信小游戏,初期上线了一批质量相当不错的小游戏.我在查阅各 ...

  2. 尝试用Vue.js开发网页小游戏的过程

    准备 首先去官方下载并安装VSCODE,下载地址 https://code.visualstudio.com/.安装后打开会发现是英文版的,需要去安装插件来汉化.具体是在扩展插件搜索chinese,选 ...

  3. JS开发HTML5游戏《神奇的六边形》(一)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  4. JS开发HTML5游戏《神奇的六边形》(二)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  5. JS开发HTML5游戏《神奇的六边形》(四)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  6. JS开发HTML5游戏《神奇的六边形》(三)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  7. 使用Html5+C#+微信 开发移动端游戏详细教程 :(三)使用html5引擎搭建游戏框架

    教程里的案例我们是通过H5游戏引擎开发,目前H5的游戏引擎比较好用的是白鹭,不过对于新手来说白鹭的开发环境和工具使用过于复杂,这里推荐一个国内大神编写的游戏引擎:lufylegend. 直接在页面引入 ...

  8. heX——基于 HTML5 和 Node.JS 开发桌面应用

    heX 是网易有道团队的一个开源项目,允许你采用前端技术(HTML,CSS,JavaScript)开发桌面应用软件的跨平台解决方案.heX 是你开发桌面应用的一种新的选择,意在解决传统桌面应用开发中繁 ...

  9. pygame开发滑雪者游戏

    pygame开发滑雪者游戏 一.实验说明 下述介绍为实验楼默认环境,如果您使用的是定制环境,请修改成您自己的环境介绍. 1. 环境登录 无需密码自动登录,系统用户名 shiyanlou,该用户具备 s ...

随机推荐

  1. 牛客网暑期ACM多校训练营(第二场)J farm (二维树状数组)

    题目链接: https://www.nowcoder.com/acm/contest/140/J 思路: 都写在代码注释里了,非常好懂.. for_each函数可以去看一下,遍历起vector数组比较 ...

  2. oracle 创建表空间 与创建用户与分配用户权限

    创建一个表空间名为ABC create tablespace "ABC"     //貌似要大写 datafile 'D:\oracle\TBSPACES\ABC.dbf'   / ...

  3. 【题解】 bzoj4033: [HAOI2015]树上染色* (动态规划)

    bzoj4033,懒得复制,戳我戳我 Solution: 定义状态\(dp[i][j]\)表示\(i\)号节点为根节点的子树里面有\(j\)个黑色节点时最大的贡献值 然后我们要知道的就是子节点到根节点 ...

  4. 学习Spring Boot:(十二)Mybatis 中自定义枚举转换器

    前言 在 Spring Boot 中使用 Mybatis 中遇到了字段为枚举类型,数据库存储的是枚举的值,发现它不能自动装载. 解决 内置枚举转换器 MyBatis内置了两个枚举转换器分别是:org. ...

  5. 【Luogu P4074】[WC2013]糖果公园(树上带修改莫队)

    题目描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩. 糖果公园的结构十分奇特,它由 \(n\) 个游 ...

  6. HGOI20180823 三校联考

    首测:220qwq(算差的好吧) 后来改了一个地方:300qwq(算慢的好吧) std被踩qwq 注意:输入数据第一行忘记输入n,亲脑补 题解: 多项式除法(若最后除出的答案为1那么就是成功),对于f ...

  7. Vitrualbox 桥接网卡界面名称未指定、Filters currently installed on the system have reached the limit、不能为虚拟电脑 打开一个新任务

    1. 桥接网卡界面名称未指定 http://wenku.baidu.com/link?url=VFG0hknsDX3VPXQoX5f-g1wUX_LBl-lOj0ZqD222kM31iVCPJKVu3 ...

  8. Burpsuit分块传输插件绕WAF原理和技巧(转)

      0x00 原理 给服务器发送payload数据包,使得waf无法识别出payload,当apache,tomcat等web容器能正常解析其内容.如图一所示 0x02  实验环境 本机win10+x ...

  9. 【CF771A】Bear and Friendship Condition

    题目大意:给定一张无向图,要求如果 A 与 B 之间有边,B 与 C 之间有边,那么 A 与 C 之间也需要有边.问这张图是否满足要求. 题解:根据以上性质,即:A 与 B 有关系,B 与 C 有关系 ...

  10. 分布式系统登录功能拦截器的实现以及cookie的共享问题(利用cookie实现session在分布式系统的共享)

    当我们的网站采用分布式部署系统时,每个子系统拥有自己独立的session,如果不实现session共享,当用户切换系统访问的时候,会不停的提示登录,这对于用户体验是非常不好的.因此对于多个子系统的的访 ...