/
dot.rb
121 lines (99 loc) · 2.73 KB
/
dot.rb
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
class Point
attr_accessor :x, :y
def initialize(x, y)
@x = x
@y = y
end
def to_s
"(#{@x}, #{@y})"
end
end
class Dot
attr_accessor :pos, :size, :mass, :v
def initialize(app, pos, opt = {})
Shoes.debug "HELP MEEEEE"
@app = app
@pos = Point.new(*pos)
@v = opt[:v] ? Point.new(*opt[:v]) : Point.new(0.0, 0.0)
@fv = Point.new(@v.x, @v.y)
@size = opt[:size] || 25
@mass = opt[:mass] || 1
@name = opt[:name] || "unnamed" #for debugging purposes
if (!opt[:hidden]) then
@rect = @app.rect :top => @pos.y, :left => @pos.x, :width => @size
end
end
def die_slowly
@rect.height -= 1
@rect.width -= 1
if @rect.width == 0 then
@rect.remove
end
return @rect.width == 0 ? "dead" : "dying"
end
def pos=(arr)
@pos = Point.new(*arr)
@rect.move @pos.x, @pos.y
end
def velocitize
if DEBUG && (@v.x != @fv.x or @v.y != @fv.y) then
Shoes.debug "#{@name} from #{@v.to_s} to #{@fv.to_s}"
end
@v.x = @fv.x
@v.y = @fv.y
end
def move
velocitize
@pos.x += @v.x * @mass
@pos.y += @v.y * @mass
@rect.move @pos.x, @pos.y
end
def check_collisions(others)
contact = []
others.each do |other|
contact << other if other != self and will_hit?(other)
end
contact.each do |other|
collide(other)
end
if hit_wall? #TODO: refactor, there's some duplicate logic in here
hit_stationary
end
end
def hit_wall?
(@pos.x <= 0 and @fv.x < 0) or
(@pos.x + @size >= @app.width and @fv.x >= 0) or
(@pos.y <= 0 and @fv.y < 0) or
(@pos.y + @size >= @app.height and @fv.y >= 0)
end
def hit_stationary
@fv.x = -@fv.x if (@pos.x <= 0 and @fv.x < 0) or
(@pos.x + @size >= @app.width and @fv.x >= 0)
@fv.y = -@fv.y if (@pos.y <= 0 and @fv.y < 0) or
(@pos.y + @size >= @app.height and @fv.y >= 0)
end
def collide(other)
mco1 = (@mass - other.mass) / (@mass + other.mass)
mco2 = 2*other.mass / (@mass + other.mass)
@fv.x = mco1 * @v.x + mco2 * other.v.x
@fv.y = mco1 * @v.y + mco2 * other.v.y
end
def pos_at(step)
Point.new(@pos.x + step*@v.x, @pos.y + step*@v.y)
end
def overlap?(other, at=0)
fpos = self.pos_at(at)
ofpos = other.pos_at(at)
return (fpos.x + @size >= ofpos.x and
fpos.x <= ofpos.x + other.size and
fpos.y + @size > ofpos.y and
fpos.y <= ofpos.y + other.size)
end
def will_hit?(other)
(0.1..1.0).step(0.3).each do |i|
next if !(self.overlap?(other, i))
return true
end
return false
end
end