-
Notifications
You must be signed in to change notification settings - Fork 1
/
harlem_bits.rb
144 lines (116 loc) · 2.59 KB
/
harlem_bits.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env ruby
require "os"
class Bit
def initialize(color, on = false)
@color, @on = color, on
end
def switch
@on = !@on
end
def off
@on = false
end
def to_s
@on ? '1'.send(@color) : '0'
end
alias_method :inspect, :to_s
end
module CliRendering
require 'colored'
COLORS = Colored.methods - [:extra, :colors, :colorize, :color] - Object.methods
def draw
puts with_enough_breaks_to_page_down
end
private
def rand_color
COLORS[rand(COLORS.size-1)]
end
def with_enough_breaks_to_page_down
"#{"\n" * 50}#{with_space_below}"
end
def with_space_below
"#{rows_with_newlines}#{"\n" * 5}"
end
def rows_with_newlines
@arena.map { |row| with_leading_space row }.join("\n")
end
def with_leading_space(row)
"#{' '*10}#{row.join(' ')}"
end
end
class Arena
include CliRendering
def initialize(width, height)
@width, @height, @arena = width.to_i, height.to_i, []
@height.times do |h|
@arena << (1..@width).map do |i|
Bit.new rand_color
end
end
end
def center
@arena[@height/2][@width/2]
end
def clear
@arena.each { |row| row.each { |bit| bit.off } }
end
def random!
random.map { |bit| bit.switch }
end
def random
found = []
@arena.each do |row|
row.each do |bit|
found << bit if rand(@width) < @width/3
end
end
found
end
end
class Harlem
DURATION = 30
FRAME_RATE = 30.0
AUDIO_FILE = 'HarlemShake.mp3'
def self.shake(width, height)
if OS.osx?
t = Thread.new { system "afplay #{AUDIO_FILE}" }
elsif OS.linux?
t = Thread.new { system "mpg123 #{AUDIO_FILE}" }
else
#Playing songs from windows command line? Can it be done? Has science gone too far?
t = Thread.new { puts "Pretend that there's music, pal." }
end
s = new width || 50, height || 25
s.start
rescue Interrupt
s.kill
t.kill
ensure
puts 'fin'
exit 0
end
def initialize(width, height)
@arena = Arena.new width, height
@alive = true
end
def kill
@alive = false
end
def start
start_t = Time.now.to_f
last_t = Time.now.to_i
frame = 0
switched = false
while @alive
cur_t = Time.now.to_f
delta = cur_t - start_t
@arena.clear
@arena.center.switch if delta % 2.0 == 0 || (delta % 2.0) / 2.0 > 0.3
@arena.random! if delta >= (DURATION / 2) + 1
@arena.draw
break if delta > DURATION
sleep 1/FRAME_RATE
end
end
end
Harlem.shake ARGV[0], ARGV[1] if $0 == __FILE__