Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
game-stydy
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
谌继荃
game-stydy
Commits
38d1a0d6
Commit
38d1a0d6
authored
Mar 10, 2021
by
邱旭
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
10.FlppyBird-创建障碍
parent
07fbd997
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
356 additions
and
0 deletions
+356
-0
11.FlppyBird-对象池.html
11.FlppyBird-对象池/11.FlppyBird-对象池.html
+265
-0
11.FlppyBird-对象池.md
11.FlppyBird-对象池/11.FlppyBird-对象池.md
+91
-0
No files found.
11.FlppyBird-对象池/11.FlppyBird-对象池.html
0 → 100644
View file @
38d1a0d6
<!DOCTYPE html>
<html
lang=
"zh"
>
<head>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
<title>
11.FlppyBird-对象池
</title>
<style>
html
,
body
{
margin
:
0
;
padding
:
0
;
width
:
100%
;
height
:
100%
;
overflow
:
hidden
;
}
</style>
<script
src=
"../lib/flppyBirdLib.js"
></script>
</head>
<body>
</body>
<script>
/**
* 屏幕宽高
* @type {{width: number, height: number}}
*/
const
winSize
=
{
width
:
document
.
body
.
clientWidth
,
height
:
document
.
body
.
clientHeight
,
}
</script>
<script>
/**
* Bird
*/
class
Bird
extends
Sprite
{
speed
;
// bird的速度 每次移动多少距离
gravity
;
// 重力加速度
constructor
(
gravity
=
0.2
,
speed
=
0
)
{
super
(
"../images/bird/bird_01.png"
);
this
.
speed
=
speed
;
// 保存speed
this
.
gravity
=
gravity
;
// 保存gravity
}
ready
()
{
super
.
ready
();
// 放到合适的位置
const
{
width
,
height
}
=
this
.
size
;
this
.
top
=
(
winSize
.
height
-
height
)
/
2
-
100
;
this
.
left
=
(
winSize
.
width
-
width
)
/
2
;
}
update
()
{
super
.
update
();
// v = v0 + a * t²
this
.
speed
+=
this
.
gravity
;
// 速度 = 速度 + 加速度 * 时间²
this
.
top
+=
this
.
speed
;
// 更新位置
}
}
/**
* 滚动器
*/
class
ScrollMgr
extends
GameObject
{
speed
;
// 滚动速度
bg1
;
// bg1
bg2
;
// bg2
constructor
(
bg1
,
bg2
,
speed
=
5
)
{
super
();
this
.
bg1
=
bg1
;
this
.
bg2
=
bg2
;
this
.
speed
=
speed
;
this
.
addChild
(
this
.
bg1
);
this
.
addChild
(
this
.
bg2
);
}
ready
()
{
super
.
ready
();
this
.
bg1
.
top
=
winSize
.
height
-
this
.
bg1
.
size
.
height
;
// 放在底部
this
.
bg2
.
top
=
winSize
.
height
-
this
.
bg2
.
size
.
height
;
// 放在底部
}
update
()
{
super
.
update
();
// 获取一些参数
let
bg1Left
=
this
.
bg1
.
left
;
const
bg1Width
=
this
.
bg1
.
size
.
width
;
// 计算位置
bg1Left
-=
this
.
speed
;
// 计算位置
this
.
bg1
.
left
=
bg1Left
;
// 设置bg1的位置
this
.
bg2
.
left
=
bg1Left
+
this
.
bg1
.
size
.
width
;
// bg2跟在bg1后面
// 如果超出屏幕则交换bg1和bg2,为了做到循环滚动
if
(
bg1Left
<=
-
bg1Width
)
{
const
temp
=
this
.
bg1
;
this
.
bg1
=
this
.
bg2
;
this
.
bg2
=
temp
;
}
}
}
</script>
<script>
/**
* Pie
*/
class
Pie
extends
GameObject
{
up
;
// 钢管上部分
down
;
// 钢管下部分
constructor
()
{
super
();
this
.
up
=
this
.
addChild
(
new
Sprite
(
"../images/bird/pie.png"
));
this
.
down
=
this
.
addChild
(
new
Sprite
(
"../images/bird/pie.png"
));
}
/**
* 注意此函数非真正的ready函数,在被addChild的时候都会执行一次
*/
ready
()
{
super
.
ready
();
// 随机中间的距离
const
dis
=
Math
.
random
()
*
80
+
100
;
this
.
down
.
top
=
this
.
up
.
size
.
height
+
dis
;
}
// 这里重写一下size,因为子节点使用绝对定位的不计算入包围盒内,真尴尬
get
size
()
{
return
{
width
:
this
.
up
.
size
.
width
,
height
:
this
.
down
.
top
+
this
.
down
.
size
.
height
}
}
}
/**
* PieMgr
*/
class
PieMgr
extends
GameObject
{
pieArr
=
[];
// 所有的Pie
speed
;
// Pie移动的速度
delay
;
// 添加Pie的延时
constructor
(
speed
,
delay
)
{
super
();
this
.
speed
=
speed
;
this
.
delay
=
delay
;
}
ready
()
{
super
.
ready
();
// 创建计时器来固定时间创建Pie
setInterval
(()
=>
this
.
createPie
(),
this
.
delay
);
}
/**
* 创建Pie
*/
createPie
()
{
// 使用对象池 如果对象池中取不到,说明对象池空了,需要新创建
const
pie
=
ObjectPool
.
get
(
"pie"
)
||
new
Pie
();
this
.
addChild
(
pie
);
this
.
pieArr
.
push
(
pie
);
// 加入列表统一管理
pie
.
top
=
Math
.
random
()
*
-
150
;
// 高度随机
pie
.
left
=
winSize
.
width
;
// 从屏幕左边出现
}
update
()
{
super
.
update
();
// 所有的Pie同时向左移动
const
{
speed
,
pieArr
}
=
this
;
pieArr
.
forEach
((
pie
)
=>
{
pie
.
left
-=
speed
;
if
(
pie
.
left
<=
-
pie
.
size
.
width
)
{
// 如果移出屏幕
this
.
pieArr
.
splice
(
this
.
pieArr
.
indexOf
(
pie
),
1
);
// 从托管列表里移除
this
.
removeChild
(
pie
);
// 从子节点移除
ObjectPool
.
put
(
"pie"
,
pie
);
// 加入对象池
}
});
}
}
</script>
<script>
/**
* FlppyBird
*/
class
FlppyBird
extends
GameStage
{
bird
;
async
reloadRes
()
{
const
path
=
"../images/bird/"
;
const
promises
=
[
"bird_01.png"
,
"bird_02.png"
,
"bird_03.png"
,
"pie.png"
,
"land.png"
,
"background.png"
,
"start_button.png"
].
map
((
v
)
=>
{
return
loadImgAsync
(
`
${
path
}${
v
}
`
);
});
return
Promise
.
all
(
promises
);
}
async
ready
()
{
// 创建鸟
const
bird
=
this
.
bird
=
new
Bird
();
// 创建背景
const
bg1
=
new
Sprite
(
"../images/bird/background.png"
);
const
bg2
=
new
Sprite
(
"../images/bird/background.png"
);
const
bgMgr
=
new
ScrollMgr
(
bg1
,
bg2
,
2
);
// 创建地面
const
land1
=
new
Sprite
(
"../images/bird/land.png"
);
const
land2
=
new
Sprite
(
"../images/bird/land.png"
);
const
landMgr
=
new
ScrollMgr
(
land1
,
land2
,
4
);
const
pieMgr
=
new
PieMgr
(
4
,
1000
);
// 创建PieMgr
this
.
addChild
(
bgMgr
);
this
.
addChild
(
pieMgr
);
// 加在背景和地面的中间
this
.
addChild
(
landMgr
);
this
.
addChild
(
bird
);
// 将背景放在地面的上面,因为默认top是0,子节点在内部定位在底部,所以只需要把背景定位在负的land的高度就可以了
bgMgr
.
top
=
-
land1
.
size
.
height
;
// 使用mousedown监听鼠标按下,并获得鼠标点击的位置
document
.
addEventListener
(
'mousedown'
,
this
.
mouseDown
);
}
mouseDown
=
()
=>
{
this
.
bird
.
speed
=
-
8
;
}
destroy
()
{
super
.
destroy
();
document
.
removeEventListener
(
'mousedown'
,
this
.
mouseDown
);
}
}
// 创建游戏实例
new
FlppyBird
();
</script>
</html>
11.FlppyBird-对象池/11.FlppyBird-对象池.md
0 → 100644
View file @
38d1a0d6
# FlppyBird-对象池
引入概念:
`对象池`
上节我们完成了障碍的动态创建
但是运行一段时间发现,dom节点树上有n个障碍,卡得一批
这些移出屏幕的障碍,不仅占了大量内存,而且完全不需要更新和渲染
![
11_1.png
](
../images/11_1.png
)
## 对象池
使用对象池,回收对象,保存在池中,需要的时候不必再重新创建,只需要从池中获取就可以
对象移除显示列表的时候,放回池中就可以了
-
创建
`ObjectPool`
类
-
用一个静态变量来保存对象
-
实现静态方法
`put`
接口,传入
`name`
来区分保存对象的类型,这样可以保存不同的类型的对象
-
实现静态方法
`get`
接口,传入
`name`
来获取相应的类型的对象
```
javascript
/**
* 一个简单的通用对象池
*/
class
ObjectPool
{
static
objs
=
{};
static
put
(
name
,
obj
)
{
const
pool
=
ObjectPool
.
objs
[
name
]
||
(
ObjectPool
.
objs
[
name
]
=
[]);
pool
.
push
(
obj
);
}
static
get
(
name
)
{
const
pool
=
ObjectPool
.
objs
[
name
]
||
(
ObjectPool
.
objs
[
name
]
=
[]);
if
(
pool
.
length
<=
0
)
{
return
null
;
}
return
pool
.
shift
();
}
}
```
## 改造`PieMgr`
-
创建
`Pie`
时先从对象池中获取,如果没有,则新创建
-
当
`Pie`
移出屏幕后,从托管列表中移除,从子节点移除,并且放回对象池
```
javascript
class
PieMgr
extends
GameObject
{
/* ... */
/**
* 创建Pie
*/
createPie
()
{
// 使用对象池 如果对象池中取不到,说明对象池空了,需要新创建
const
pie
=
ObjectPool
.
get
(
"pie"
)
||
new
Pie
();
this
.
addChild
(
pie
);
this
.
pieArr
.
push
(
pie
);
// 加入列表统一管理
pie
.
top
=
Math
.
random
()
*
-
150
;
// 高度随机
pie
.
left
=
winSize
.
width
;
// 从屏幕左边出现
}
update
()
{
super
.
update
();
// 所有的Pie同时向左移动
const
{
speed
,
pieArr
}
=
this
;
pieArr
.
forEach
((
pie
)
=>
{
pie
.
left
-=
speed
;
if
(
pie
.
left
<=
-
pie
.
size
.
width
)
{
// 如果移出屏幕
this
.
pieArr
.
splice
(
this
.
pieArr
.
indexOf
(
pie
),
1
);
// 从托管列表里移除
this
.
removeChild
(
pie
);
// 从子节点移除
ObjectPool
.
put
(
"pie"
,
pie
);
// 加入对象池
}
});
}
}
```
运行案例,挂机10分钟,一点也不卡,显示列表最多也只有两个
`Pie`
同时存在
# 挂机一天也不卡,牛逼
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment