-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathball.js
120 lines (106 loc) · 3.31 KB
/
ball.js
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
// properties and initial velocity
const defaultProps = {
radius: 30,
hue: 0
}
class Ball {
constructor(x = 0, y = 0, sceneProps, props) {
this.props = {
...defaultProps,
startVelX: (Math.random() + 1) * (Math.floor(Math.random() * 2) || -1),
startVelY: (Math.random() + 1) * (Math.floor(Math.random() * 2) || -1),
...props
}
this.sceneProps = sceneProps
this.x = x
this.y = y
this.velX = this.props.startVelX
this.velY = this.props.startVelY
}
draw(ctx) {
const { x, y, props } = this
ctx.save()
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.props.hue + ',100%,50%)'
ctx.strokeStyle = "#000000";
ctx.arc(
x, y,
props.radius,
0, Math.PI * 2
)
ctx.fill()
ctx.stroke()
ctx.restore()
}
bounce(other) {
console.log(this,other,this.velX*2)
var dx = other.x - this.x
var dy = other.y - this.y
const radii = this.props.radius + other.props.radius
var m = Math.sqrt(dx * dx + dy * dy)
var ux = dx / m
var uy = dy / m
var ax = (ux * radii) - dx
var ay = (uy * radii) - dy
//other.x += ax / 2
//other.y += ay / 2
this.x -= ax
this.y -= ay
dx = other.x - this.x
dy = other.y - this.y
m = Math.sqrt(dx * dx + dy * dy)
ux = dx / m
uy = dy / m
const tx = -uy
const ty = ux
var v1u = ux * this.velX + uy * this.velY
var v2u = ux * other.velX + uy * other.velY
var v1t = tx * this.velX + ty * this.velY
var v2t = tx * other.velX + ty * other.velY
this.velX = v2u * ux + v1t * tx
this.velY = v2u * uy + v1t * ty
other.velX = v1u * ux + v2t * tx
other.velY = v1u * uy + v2t * ty
console.log(this,other,this.velX*2)
}
collide(others) {
others.forEach(other => {
if (other == this || (this.velX == 0 && this.velY == 0)) { return }
var dx = other.x - this.x
var dy = other.y - this.y
var radii = this.props.radius + other.props.radius
if ((dx * dx) + (dy * dy) < radii * radii) {
this.props.hue += 1
//console.log(this.props.hue)
this.bounce(other)
}
})
}
update(others) {
const { props, sceneProps } = this
// bottom bound
if (this.y + props.radius >= sceneProps.height) {
this.velY *= -1
this.y = Math.min(sceneProps.height*2 - this.y,sceneProps.height-props.radius)
}
// top bound
if (this.y - props.radius <= 0) {
this.velY *= -1
this.y = Math.max(-this.y,props.radius)
}
// left bound
if (this.x - props.radius <= 0) {
this.velX *= -1
this.x = Math.max(-this.x,props.radius)
}
// right bound
if (this.x + props.radius >= sceneProps.width) {
this.velX *= -1
this.x = Math.min(sceneProps.width*2 - this.x,sceneProps.width-props.radius)
}
this.collide(others)
// update position
this.x += this.velX
this.y += this.velY
}
}