-
Notifications
You must be signed in to change notification settings - Fork 0
/
BubbleCollisions - 3rd step.html
237 lines (197 loc) · 6.87 KB
/
BubbleCollisions - 3rd step.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<!DOCTYPE html>
<html lang="en">
<!------分------割------线------>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="Author" content="Bruce Zhu">
<title>Bubble Collisions - 泡泡碰撞</title>
</head>
<style>
html,body {
margin: 0;
padding: 0;
}
canvas {
box-shadow: 0 0 40px black;
margin: 50px auto;
}
div {
width: 800px;
height: 600px;
margin: 0 auto;
}
</style>
<!------分------割------线------>
<body>
<div>
<canvas id="bubble" width="800px" height="600px">对不起!您的浏览器不支持Canvas</canvas>
</div>
</body>
<script type="text/javascript">
// 获取画布对象
var canvas = document.getElementById('bubble');
var ctx = canvas.getContext('2d');
// 蓝色泡泡的图片
var blueBubbleImg = new Image();
blueBubbleImg.src = "蓝泡.png";
// 红色泡泡的图片
var redBubbleImg = new Image();
redBubbleImg.src = "红泡.png";
// 创建泡泡对象
var bubble = function(x, y, bubbleWidth, bubbleHeight, whichBubble) {
this.x = x;
this.y = y;
this.r = bubbleHeight/2;
this.bubbleWidth = bubbleWidth;
this.bubbleHeight = bubbleHeight;
this.whichBubble = whichBubble;
this.draw = function () {
// 保存当前环境状态
ctx.save();
ctx.drawImage(this.whichBubble, this.x, this.y, this.bubbleWidth, this.bubbleHeight);
}
}
// 自定义蓝色泡泡的随机函数
function blueRandom(min,max) {
return parseInt(Math.random()*(max - min) + min);
}
// 初始化红球的大小
var redWidth = redHeight = 50;
// 初始化红色泡泡出现的位置
var centerX = (canvas.width - redWidth)/2;
var centerY = (canvas.height - redHeight)/2;
// 实例化红色泡泡对象
var redBubble = new bubble(centerX, centerY, redWidth, redHeight, redBubbleImg);
// 在画布上绘制初始状态的泡泡
redBubbleImg.onload = function () {
redBubble.draw();
}
// 实例化多个蓝色泡泡对象
var blueBubbles = [];
// 将红色泡泡放入对象数组中判断是否会被覆盖
blueBubbles[0] = redBubble;
// 设置生成蓝色泡泡的数量
var blueBubblesNum = 20
for (let i = 1; i <= blueBubblesNum; i++) {
// 设置蓝色泡泡的宽高
let blueBubbleHeight = blueBubbleWidth = blueRandom(30, 70);
// 初始化蓝色泡泡出现的位置
let randomX = blueRandom(0, canvas.width - blueBubbleWidth);
let randomY = blueRandom(0, canvas.height - blueBubbleHeight);
// 如果将会碰壁,舍弃掉
if(blueBubbleCover(randomX, randomY, blueBubbleWidth, blueBubbleHeight)){
i--;
continue;
}
blueBubbles[i] = new bubble(randomX, randomY, blueBubbleWidth, blueBubbleHeight, blueBubbleImg);
}
// 在画布上绘制初始状态的泡泡
blueBubbleImg.onload = function () {
blueBubbleDraw();
}
// 循环绘制蓝色泡泡
function blueBubbleDraw() {
for (let i = 1; i <= blueBubblesNum; i++) {
if (blueBubbles.hasOwnProperty(i)) {
blueBubbles[i].draw();
}
}
}
// 判断绘制的蓝色泡泡是否重叠 PS:详细介绍请看图解
function blueBubbleCover(randomX, randomY, blueBubbleWidth, blueBubbleHeight) {
for (index in blueBubbles) {
if (blueBubbles.hasOwnProperty(index)) {
if(blueBubbles[index].x <= randomX
&& blueBubbles[index].x + blueBubbles[index].bubbleWidth >= randomX
&& blueBubbles[index].y <= randomY
&& blueBubbles[index].y + blueBubbles[index].bubbleHeight >= randomY){
return true
} else if(blueBubbles[index].x <= randomX
&& blueBubbles[index].x + blueBubbles[index].bubbleWidth >= randomX
&& blueBubbles[index].y >= randomY
&& blueBubbles[index].y <= randomY + blueBubbleHeight){
return true
} else if(blueBubbles[index].x >= randomX
&& blueBubbles[index].x <= randomX + blueBubbleWidth
&& blueBubbles[index].y <= randomY
&& blueBubbles[index].y + blueBubbles[index].bubbleHeight >= randomY){
return true
} else if(blueBubbles[index].x >= randomX
&& blueBubbles[index].x <= randomX + blueBubbleWidth
&& blueBubbles[index].y >= randomY
&& blueBubbles[index].y <= randomY + blueBubbleHeight){
return true
}
}
}
}
// 给画布设置监听事件,触发阶段默认为false冒泡阶段
canvas.addEventListener("mousemove", onMouseMove, false);
// 记录鼠标移动到的位置,初始化的值为正中心
var mouseX = centerX;
var mouseY = centerY;
// 保存碰壁瞬间状态的泡泡坐标,如果当泡泡触碰到了墙壁,则redBubble.x/y的值取这一状态的
var mouseTouchBorderX, mouseTouchBorderY;
function onMouseMove(evt){
// offset获取到canvas层中鼠标的位置,然后减去红色泡泡自身高度
mouseX = evt.offsetX - redBubble.bubbleWidth/2;
mouseY = evt.offsetY - redBubble.bubbleHeight/2;
}
// 刷新泡泡
function drawBubble() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 如果红泡泡没有碰壁的话,则执行以下条件语句
if(!redBubbleTouchBorder()){
// 更新泡泡的坐标
redBubble.x = mouseX;
redBubble.y = mouseY;
// 暂时保存这一状态的泡泡坐标,如果碰壁的话,此处不执行
mouseTouchBorderX = mouseX;
mouseTouchBorderY = mouseY;
}
// 重新绘制
redBubble.draw();
blueBubbleDraw();
}
// 判断红泡泡是否触壁,判断触壁要用mouseX/Y而不能用redBubble.x/y,因为mouseX/Y是变化的。
function redBubbleTouchBorder() {
// 碰壁分为两种情况:
// 第一种是横轴左右碰壁,第二种是纵轴上下碰壁
if(mouseX + redBubble.bubbleWidth > canvas.width || mouseX < 0){
// 小球即使碰壁,那么横轴方向上就不能越界了
redBubble.x = mouseTouchBorderX;
// 这两个条件句是为了解决红色泡泡碰壁后不能拖动小球的情况
// 如果既碰到了横轴方向的壁,又碰到了纵轴方向的壁,那么Y轴是不可以再继续移动的
if(mouseY + redBubble.bubbleHeight > canvas.height || mouseY < 0){
// 红色泡泡Y坐标等于碰壁时的Y坐标
redBubble.y = mouseTouchBorderY;
// 记录
mouseTouchBorderX = redBubble.x;
mouseTouchBorderY = redBubble.y;
} else {
// 如果只是碰到了横轴方向的壁,那么Y轴是可以继续移动的
redBubble.y = mouseY;
// 记录
mouseTouchBorderX = redBubble.x;
mouseTouchBorderY = mouseY;
}
return true;
} else if(mouseY + redBubble.bubbleHeight > canvas.height || mouseY < 0){
redBubble.x = mouseX;
redBubble.y = mouseTouchBorderY;
// Y轴碰壁,不能变化,但X轴依然可以随鼠标变化
mouseTouchBorderX = mouseX;
mouseTouchBorderY = redBubble.y;
return true;
} else {
return false;
}
}
// 设置刷新时间,60帧/s的帧率是比较细腻的,所以用1s/60
setInterval(drawBubble, 1000/60);
</script>
<!------分------割------线------>
</html>