演示效果
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body {
margin: 0;
padding: 0;
box-sizing: border-box;
width: 100%;
height: 100%;
background-color: #00ff94;
}
.sky {
width: 100%;
height: 100%;
border: 1px solid black;
position: relative;
background-image: url(./哦哦哦哦哦.png);
}
.bird {
position: absolute;
left: 20px;
top: 35%;
width: 30px;
height: 30px;
background-color: #f40;
}
.up,
.down {
background-color: yellowgreen;
position: absolute;
}
</style>
</head>
<body>
<div class="sky">
<div class="bird"></div>
</div>
<script>
var g = 1;
var arr = [];
var flag = true;
var wuwuwu = document.getElementsByClassName("bird")[0];
var wuli = document.getElementsByClassName("sky")[0];
// 鸟
var bird = {
body: wuwuwu,
width: 30,
height: 30,
x: wuwuwu.offsetLeft,
y: wuwuwu.offsetTop,
speedX: 2,
speedY: 0
}
// 天空
var sky = {
x: 0,
height: wuli.offsetHeight,
body: wuli
}
// 混屏
var timer = setInterval(() => {
if (flag) {
sky.x -= bird.speedX;
sky.body.style.backgroundPositionX = sky.x + "px";
// 背景以小鸟飞的速度往左移动
bird.speedY += g;
// 这是业务逻辑
bird.y += bird.speedY;
bird.body.style.top = bird.y + "px";
if (bird.y < 0 || bird.y > sky.height - bird.height) {
stop();
}
}
}, 40);
// 按键
document.onkeydown = function(e) {
if (e.keyCode === 38) {
bird.speedY = -10;
} else if (e.keyCode === 13) {
location.reload();
}
}
// gg
function stop() {
flag = false;
clearInterval(timer);
for (var i = 0; i < arr.length; i++) {
clearInterval(arr[i].timer);
}
}
class 柱子 {
constructor(x) {
let div = document.createElement("div");
let div2 = document.createElement("div");
let h0 = sky.height;
let h1 = Math.ceil(Math.random() * 150) + 200;
let h2 = h0 - h1 - 200;
this.up = h1;
this.down = h1 + 200;
this.width = 80;
this.x = x;
this.div = div;
this.div2 = div2;
div.style.height = h1 + "px";
div.style.left = x + "px";
div.style.width = this.width + "px";
div.className = "up";
div2.className = "down";
div2.style.width = this.width + "px";
div2.style.height = h2 + "px";
div2.style.top = h1 + 200 + "px";
div2.style.left = x + "px";
sky.body.appendChild(div);
sky.body.appendChild(div2);
this.timer = setInterval(() => {
if (flag) {
if (this.x <= -80) {
this.div.parentNode.removeChild(this.div);
this.div2.parentNode.removeChild(this.div2);
arr.shift();
arr[arr.length] = new 柱子(1100);
}
this.x -= 1;
div.style.left = this.x + "px";
div2.style.left = this.x + "px";
// 判定结束游戏
if (bird.x + bird.width > this.x && bird.x < this.x + this.width) {
// 横坐标进来了
if (bird.y <= this.up || bird.y >= this.down) {
stop();
}
}
}
}, 10);
}
}
for (var i = 0; i < 6; i++) {
arr[i] = new 柱子(i * 200 + 400);
}
</script>
</body>
</html>
解析
解析一下这一坨长长的代码,是一个面向对象编程的超级小游戏
有一个鸟,一个天空,几个管子
鸟有宽度高度,有飞行的速度,还有自己的x、y值,就是定位的left与top
天空有背景图,这玩意一直跑,一直跑
每个柱子都是一个对象,他们生出来就开始往左边跑,直到出屏幕后被回收
当小鸟的坐标(x,y)与一些障碍物的坐标(x,y)冲突时,调用stop结束定时器,游戏结束。
游戏开始后,背景往左边滚,小鸟往下掉,柱子往左滚,按键盘上键,小鸟的向上的速度增加很多,但是定时器里,每次执行都会把小鸟向下的速度增加,所以小鸟迟早会往下掉,就需要适时的按上键来维持。
语法上一个是定时器,对象来存数据,dom操作与内存中数据同步
先说对象,是一种以键值对形式存储数据的方式,然后还是对显示一类事物抽象后又具象的一个有特点的家伙。鸟在这里有宽高有颜色有速度有坐标。天空和树又何尝不是?
再说dom操作,相信现在dom已经拦不住大家了,如果还是不熟练,dom操作案例讲解
再说定时器:
1、setTimeout允许设置一个超时对象,超时后执行这个对象,但是只执行一次,无周期
2、setInternval允许设置一个超时对象,超时后执行这个对象,周期等于超时对象指定的时间,周期为无限循环
定时器是在指定时间, 将任务放入事件队列,等待js引擎空闲后被执行.
就是说,到了时间,我把线程给你放到事件队列,主线程要是很忙,那么它就在队列放着,没法确保它执行。
使用setInterval时,并不能保证两次执行之间间隔具体是多少,因为我只是按时间差放到队列的,一切都要看它怎么执行的,电脑卡写啥代码也不会好使!
定时器还可以拿来渲染页面,有些好看的页面,一下子渲染出来会显得比较卡,慢慢来比较快。
另外记得clearInterval或clearTimeout,不然可能会出奇奇怪怪的事情
下一篇讲
js运行原理与机制
里面详细讲了定时器存在的潜在问题