vamp 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +20 -3
- data/lib/vamp/art.rb +189 -0
- data/lib/vamp/graphic/context.rb +142 -0
- data/lib/vamp/graphic/dotter.rb +53 -0
- data/lib/vamp/graphic/text_dotter.rb +35 -0
- data/lib/vamp/graphic/transfer.rb +170 -0
- data/lib/vamp/graphic/transfer5.rb +217 -0
- data/lib/vamp/graphic.rb +17 -0
- data/lib/vamp/version.rb +1 -1
- data/lib/vamp.rb +5 -12
- data/sample/gui.rb +98 -0
- data/spec/art_spec.rb +56 -0
- data/spec/graphic/context_spec.rb +364 -0
- data/spec/graphic/transfer5_spec.rb +179 -0
- data/spec/graphic/transfer_spec.rb +221 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/vamp_spec.rb +1 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c4315d0432b085681e7afa71522bfc0fe3e04f3
|
4
|
+
data.tar.gz: 591b310d5939ddfa3070a867b54f8c603092e72f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16383a97ea438b01e28dc035290fc1d5ed58952f516a70df23a702088a2d323c138b475e5dd91a5e7653ba57b6d57d241e49ceac634e794f9f651a2df48868b2
|
7
|
+
data.tar.gz: f831bae4c7f817ac9fc073fdefd45ff0f8a5dd48bc868709c0cb4a634d4ee91e37ce0b141ba1ab3dc10ba8f1ada633aca1f6e173db5ced106dfcbabaa51f3614
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# Vamp - necessities for the elegant vampire
|
2
2
|
|
3
3
|
Want to pimp up your command line interface?
|
4
|
-
Just require this gem insert some code and your CLI makes witty vampire quotes.
|
4
|
+
Just require this gem, insert some code and your CLI makes witty vampire quotes.
|
5
|
+
You can even play animated ascii art in a console window.
|
5
6
|
|
6
7
|
## Installation
|
7
8
|
|
@@ -19,10 +20,9 @@ Or install it yourself as:
|
|
19
20
|
|
20
21
|
$ gem install vamp
|
21
22
|
|
22
|
-
## Usage
|
23
|
+
## Usage with thor
|
23
24
|
|
24
25
|
```ruby
|
25
|
-
|
26
26
|
require "thor"
|
27
27
|
require "vamp"
|
28
28
|
|
@@ -53,6 +53,23 @@ end
|
|
53
53
|
CLI.start(ARGV)
|
54
54
|
```
|
55
55
|
|
56
|
+
## Animation Usage
|
57
|
+
|
58
|
+
You can play an ascii art animation within a terminal window by using vamp.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
require "vamp"
|
62
|
+
|
63
|
+
animator = Vamp::Animator.new(File.join(Gem.loaded_specs["vamp"].gem_dir, "files", "vampire.txt"), 31, 0, 24,
|
64
|
+
"No man knows till he has suffered from the night how sweet and how dear to his heart and eye the morning can be.")
|
65
|
+
animator.play
|
66
|
+
```
|
67
|
+
|
68
|
+
To see the animation in higher resolution just click on the following image.
|
69
|
+
|
70
|
+
[![Animation Demo](https://raw.githubusercontent.com/m-31/vamp/data/pic/demo_001.gif)](https://raw.githubusercontent.com/m-31/vamp/data/pic/demo_001.mp4)
|
71
|
+
|
72
|
+
|
56
73
|
## Development
|
57
74
|
|
58
75
|
After checking out the repo, run `bundle install` to install dependencies.
|
data/lib/vamp/art.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
module Vamp
|
2
|
+
module Art
|
3
|
+
|
4
|
+
def self.remove_ansi(text)
|
5
|
+
text.gsub(/[\[\d;]+m/, '')
|
6
|
+
end
|
7
|
+
|
8
|
+
# ascii art by the queen of ascii art: Joan Stark (jgs)
|
9
|
+
# https://en.wikipedia.org/wiki/Joan_Stark
|
10
|
+
VAMPIRE = <<-'END'
|
11
|
+
=/\ /\=
|
12
|
+
/ \'._ (\_/) _.'/ \
|
13
|
+
/ .''._'--(o.o)--'_.''. \
|
14
|
+
/.' _/ |`'=/ " \='`| \_ `.\
|
15
|
+
/` .' `\;-,'\___/',-;/` '. '\
|
16
|
+
/.-' jgs `\(-V-)/` `-.\
|
17
|
+
` " " `
|
18
|
+
END
|
19
|
+
HOBGOBLIN_COLOR = <<-'END'
|
20
|
+
[1;33;48m , _.._ ,
|
21
|
+
(`._."` `"._.')
|
22
|
+
'._ _.' /\
|
23
|
+
| /`-. .-'\ | __ .'.'
|
24
|
+
|(_[1;32;48m()[1;33;48m_\/_[1;32;48m()[1;33;48m_)|' `\ ( (
|
25
|
+
; ,____, ; \ ) )
|
26
|
+
\ /[1;37;48mVvvV[1;33;48m\ / \ \.__ / /
|
27
|
+
/`'._`""`_.' \ \ `\/ /
|
28
|
+
/ . `--' \ \ /
|
29
|
+
/ / `-, _.----' \ ;
|
30
|
+
/ / ) / .--------` \
|
31
|
+
/ /.----' / / ___. \
|
32
|
+
/ /| _ _,| (---' \ |
|
33
|
+
/ / | \`""` \\\\ \ |
|
34
|
+
/ /` | | \\\` \ \
|
35
|
+
/ / [1;34;48m;[1;33;48m [1;34;48m|[1;33;48m / /
|
36
|
+
/ / [1;34;48m_[1;33;48m [1;34;48m\[1;33;48m [1;34;48m/[1;33;48m [1;34;48m/`[1;33;48m [1;34;48m/`[1;33;48m
|
37
|
+
/ _\[1;34;48m/([1;33;48m [1;34;48m|[1;33;48m [1;34;48m|[1;33;48m [1;34;48m/[1;33;48m [1;34;48m.'_[1;33;48m
|
38
|
+
| ( \ [1;34;48m'--'[1;33;48m [1;34;48m\[1;33;48m [1;34;48m.'[1;33;48m [1;34;48m(__)`\[1;33;48m
|
39
|
+
\\\\ [1;34;48m`-------'[1;33;48m [1;30;48mjgs[1;33;48m [1;34;48m/________.'[1;33;48m
|
40
|
+
`\\\
|
41
|
+
[0m
|
42
|
+
END
|
43
|
+
HOBGOBLIN = remove_ansi(HOBGOBLIN_COLOR)
|
44
|
+
SHARK_COLOR = <<-'END'
|
45
|
+
[1;36;48m [1;32;48mo[0;37;48m
|
46
|
+
[1;36;48m ___.. ,[0;37;48m
|
47
|
+
[1;36;48m __..--''__ ( .';[0;37;48m
|
48
|
+
[1;36;48m [1;32;48mo[1;36;48m __.-------.-' `--..__ .' ;[0;37;48m
|
49
|
+
[1;36;48m _.--' [1;35;48m0[1;36;48m) .--._ ``--...____.' .'[0;37;48m
|
50
|
+
[1;36;48m ( _. )). .__.-'' <[0;37;48m
|
51
|
+
[1;36;48m ```[0;37;48m``[1;36;48m---....._____.....- -..___ _____...--'-.'.[0;37;48m
|
52
|
+
[1;36;48m [1;30;48mjgs[1;36;48m `-.___.' ``````` `.;[0;37;48m
|
53
|
+
[0m
|
54
|
+
END
|
55
|
+
SHARK = remove_ansi(SHARK_COLOR)
|
56
|
+
DRAGON_COLOR = <<-'END'
|
57
|
+
[0;37;48m [1;32;48m ___ ___[0;37;48m
|
58
|
+
[1;32;48m ,_;-'-._\__/_.-'[0;37;48m
|
59
|
+
[1;32;48m ,_\ [1;31;48ma[1;32;48m\/[1;31;48ma[0;37;48m
|
60
|
+
[1;32;48m ,_\ ,-( _'-._
|
61
|
+
,_\ ([0;37;48m==[1;32;48m/\ |'-._\[0;37;48m
|
62
|
+
[1;32;48m ,_\ -. /\ \/ | |\ `[0;37;48m
|
63
|
+
[1;32;48m ,_\ \/[0;37;48m==[1;32;48m\ '._\7 '._
|
64
|
+
[0;32;48mjgs[1;32;48m '. '._ \[0;37;48m=[1;32;48m/\'-}}} '-}}}[0;37;48m
|
65
|
+
[1;32;48m / /> /` )
|
66
|
+
|\_.' .'( <_ <_
|
67
|
+
\____.-' '--}}}-}}}[0;37;48m
|
68
|
+
[0m
|
69
|
+
END
|
70
|
+
DRAGON = remove_ansi(DRAGON_COLOR)
|
71
|
+
|
72
|
+
# ascii art by Daniel Au (dcau)
|
73
|
+
# http://www.oocities.org/SoHo/7373/dcau.htm
|
74
|
+
SKULL_COLOR = <<-'END'
|
75
|
+
[1;31;48m _,.-------.,_
|
76
|
+
,;~' '~;,
|
77
|
+
,; ;,
|
78
|
+
; ;
|
79
|
+
,' ',
|
80
|
+
,; ;,
|
81
|
+
; ; . . ; ;
|
82
|
+
| ; ______ ______ ; |
|
83
|
+
| `/~" ~" . "~ "~\' |
|
84
|
+
| ~ ,-~~~^~, | ,~^~~~-, ~ |
|
85
|
+
| | }:{ | |
|
86
|
+
| l / | \ ! |
|
87
|
+
.~ (__,.--" .^. "--.,__) ~.
|
88
|
+
| ---;' / | \ `;--- |
|
89
|
+
\__. \/^\/ .__/
|
90
|
+
V| \ / |V
|
91
|
+
| |T~\___!___!___/~T| |
|
92
|
+
| |`[1;37;48mIIII_I_I_I_IIII'[1;31;48m| |
|
93
|
+
| \,[1;37;48mIII I I I III[1;31;48m,/ |
|
94
|
+
\ `~~~~~~~~~~' /
|
95
|
+
\ . . / [1;30;48m-dcau[1;31;48m
|
96
|
+
\. ^ ./
|
97
|
+
^~~~^~~~^
|
98
|
+
[0m
|
99
|
+
END
|
100
|
+
SKULL = remove_ansi(SKULL_COLOR)
|
101
|
+
|
102
|
+
# acii art by Andreas Freise (a:f)
|
103
|
+
# http://www.ascii-art.de/
|
104
|
+
LIZARD_COLOR = <<-'END'
|
105
|
+
[0;37;48m [1;32;48m)/_[0;37;48m
|
106
|
+
[1;32;48m_.--..---"-,--[1;34;48mc[1;32;48m_[0;37;48m
|
107
|
+
[1;32;48m\L..'[0;37;48m [1;32;48m._[1;34;48mO[1;32;48m__)[1;31;48m_[0;37;48m
|
108
|
+
[1;32;48m,-.[0;37;48m [1;32;48m_.+[0;37;48m [1;32;48m_[0;37;48m [1;32;48m\..--( /[0;37;48m [0;35;48ma:f[0;37;48m
|
109
|
+
[1;32;48m`\.-''__.-'[0;37;48m [1;32;48m\ ([0;37;48m [1;32;48m\_[0;37;48m
|
110
|
+
[1;32;48m`'''[0;37;48m [1;32;48m`\__[0;37;48m [1;32;48m/\[0;37;48m
|
111
|
+
[1;32;48m')[0;37;48m
|
112
|
+
[0m
|
113
|
+
END
|
114
|
+
LIZARD = remove_ansi(LIZARD_COLOR)
|
115
|
+
|
116
|
+
# ascii art by Nico Okha (mOm)
|
117
|
+
RUNNING = <<-'END'
|
118
|
+
_
|
119
|
+
_( }
|
120
|
+
/_ )
|
121
|
+
/ "/
|
122
|
+
/ -;\
|
123
|
+
;--' ´ /'
|
124
|
+
<_
|
125
|
+
END
|
126
|
+
DECLARING = <<-'END'
|
127
|
+
,
|
128
|
+
(}_/
|
129
|
+
/,;
|
130
|
+
"^/ \
|
131
|
+
\|/
|
132
|
+
//
|
133
|
+
""`
|
134
|
+
END
|
135
|
+
|
136
|
+
DECLARING2 = <<-'END'
|
137
|
+
!
|
138
|
+
||
|
139
|
+
!|
|
140
|
+
| \ _
|
141
|
+
| \ /~ ~\
|
142
|
+
\ \_ /<- ->\
|
143
|
+
\ \_\.O.|\\
|
144
|
+
\ ' /__"
|
145
|
+
| \
|
146
|
+
\ ' . \ \
|
147
|
+
\ /) >
|
148
|
+
\ , | /
|
149
|
+
| \__/ <
|
150
|
+
> /o |)
|
151
|
+
/ T /
|
152
|
+
/ | /
|
153
|
+
/ | . /
|
154
|
+
\/ \/ \
|
155
|
+
\ \ \
|
156
|
+
\ \ \
|
157
|
+
\ > \
|
158
|
+
/^ / ^\
|
159
|
+
^^^~ ~~~mOm
|
160
|
+
END
|
161
|
+
GREEK = <<-'END'
|
162
|
+
___
|
163
|
+
/. `\
|
164
|
+
/ , ` |
|
165
|
+
/^\__/'
|
166
|
+
_,--~, /_
|
167
|
+
/' ~~~ -__ ~-,
|
168
|
+
,/ , _ \
|
169
|
+
/ |`-_ _ '_/%\ `\
|
170
|
+
/ |_, ~~ __/`\ \
|
171
|
+
,--~~"' / \ `--/ |, >
|
172
|
+
//^|~~---' ; , , | '
|
173
|
+
,'` , ( | /
|
174
|
+
,' `;;;,' \ ,' |
|
175
|
+
/ 77); `./||`
|
176
|
+
/ ,"^ \, ,
|
177
|
+
/ / \ ,
|
178
|
+
( ,' \ |
|
179
|
+
\ `. \_- \
|
180
|
+
\ ; \ `,
|
181
|
+
` ' \ |
|
182
|
+
\ ` \ `
|
183
|
+
| ) `, `.
|
184
|
+
/ ' ,' )
|
185
|
+
mooO' Ooom' mOm
|
186
|
+
|
187
|
+
END
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require_relative "dotter"
|
3
|
+
require_relative "text_dotter"
|
4
|
+
require_relative "transfer"
|
5
|
+
require_relative "transfer5"
|
6
|
+
|
7
|
+
module Vamp
|
8
|
+
module Graphic
|
9
|
+
# Graphic Context
|
10
|
+
class Context
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def_delegators :@dotter, :dot, :dot?, :undot, :in?, :clear, :screen, :width, :height
|
14
|
+
|
15
|
+
attr_reader :dotter # can set a dot within [0, width] [0, height[]]
|
16
|
+
|
17
|
+
def initialize(dotter)
|
18
|
+
@dotter = dotter
|
19
|
+
end
|
20
|
+
|
21
|
+
# Cohen–Sutherland clipping algorithm clips a line from
|
22
|
+
# P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with
|
23
|
+
# diagonal from (xmin, ymin) to (xmax, ymax).
|
24
|
+
def line(x0, y0, x1, y1)
|
25
|
+
xmin = 0.0
|
26
|
+
ymin = 0.0
|
27
|
+
xmax = width - 1.0
|
28
|
+
ymax = height - 1.0
|
29
|
+
|
30
|
+
# compute outcodes for P0, P1, and whatever point lies outside the clip rectangle
|
31
|
+
outcode0 = compute_out_code(x0, y0)
|
32
|
+
outcode1 = compute_out_code(x1, y1)
|
33
|
+
|
34
|
+
accept = false
|
35
|
+
|
36
|
+
while true
|
37
|
+
if 0 == (outcode0 | outcode1) # Bitwise OR is 0. Trivially accept and get out of loop
|
38
|
+
accept = true
|
39
|
+
break
|
40
|
+
elsif 0 != (outcode0 & outcode1) # Bitwise AND is not 0. Trivially reject and get out of loop
|
41
|
+
break
|
42
|
+
else
|
43
|
+
# failed both tests, so calculate the line segment to clip
|
44
|
+
# from an outside point to an intersection with clip edge
|
45
|
+
|
46
|
+
# At least one endpoint is outside the clip rectangle; pick it.
|
47
|
+
outcodeOut = outcode0 != 0 ? outcode0 : outcode1
|
48
|
+
|
49
|
+
|
50
|
+
# Now find the intersection point;
|
51
|
+
# use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
|
52
|
+
if 0 != (outcodeOut & TOP) # point is above the clip rectangle
|
53
|
+
x = x0.to_f + (x1 - x0) * (ymax - y0) / (y1 - y0)
|
54
|
+
y = ymax
|
55
|
+
elsif (0 != outcodeOut & BOTTOM) # point is below the clip rectangle
|
56
|
+
x = x0.to_f + (x1 - x0) * (ymin - y0) / (y1 - y0)
|
57
|
+
y = ymin
|
58
|
+
elsif (0 != outcodeOut & RIGHT) # point is to the right of clip rectangle
|
59
|
+
y = y0.to_f + (y1 - y0) * (xmax - x0) / (x1 - x0)
|
60
|
+
x = xmax
|
61
|
+
elsif (0 != outcodeOut & LEFT) # point is to the left of clip rectangle
|
62
|
+
y = y0.to_f + (y1 - y0) * (xmin - x0) / (x1 - x0)
|
63
|
+
x = xmin
|
64
|
+
end
|
65
|
+
|
66
|
+
# Now we move outside point to intersection point to clip
|
67
|
+
# and get ready for next pass.
|
68
|
+
if outcodeOut == outcode0
|
69
|
+
x0 = x
|
70
|
+
y0 = y
|
71
|
+
outcode0 = compute_out_code(x0, y0)
|
72
|
+
else
|
73
|
+
x1 = x
|
74
|
+
y1 = y
|
75
|
+
outcode1 = compute_out_code(x1, y1)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if accept
|
80
|
+
draw_line_direct (x0 + 0.5).to_i, (y0 + 0.5).to_i, (x1 + 0.5).to_i, (y1 + 0.5).to_i
|
81
|
+
end
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
# protected
|
86
|
+
|
87
|
+
# Bresenham's line algorithm
|
88
|
+
def draw_line_direct(x0, y0, x1, y1)
|
89
|
+
dx = (x1 - x0).abs
|
90
|
+
sx = x0 < x1 ? 1 : -1
|
91
|
+
dy = -(y1 - y0).abs
|
92
|
+
sy = y0 < y1 ? 1 : -1
|
93
|
+
err = dx + dy
|
94
|
+
while true
|
95
|
+
dot(x0, y0)
|
96
|
+
break if x0 == x1 && y0 == y1
|
97
|
+
e2 = 2 * err
|
98
|
+
if e2 > dy
|
99
|
+
err += dy
|
100
|
+
x0 += sx
|
101
|
+
end
|
102
|
+
if e2 < dx
|
103
|
+
err += dx
|
104
|
+
y0 += sy
|
105
|
+
end
|
106
|
+
end
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# clipping area constants
|
113
|
+
INSIDE = 0; # 0000
|
114
|
+
LEFT = 1; # 0001
|
115
|
+
RIGHT = 2; # 0010
|
116
|
+
BOTTOM = 4; # 0100
|
117
|
+
TOP = 8; # 1000
|
118
|
+
|
119
|
+
# Compute the bit code for a point (x, y) using the clip rectangle
|
120
|
+
# bounded diagonally by (xmin, ymin), and (xmax, ymax)
|
121
|
+
def compute_out_code(x, y)
|
122
|
+
xmin = 0
|
123
|
+
ymin = 0
|
124
|
+
xmax = width - 1
|
125
|
+
ymax = height - 1
|
126
|
+
code = INSIDE # initialised as being inside of clip window
|
127
|
+
|
128
|
+
if x < xmin # to the left of clip window
|
129
|
+
code |= LEFT
|
130
|
+
elsif x > xmax # to the right of clip window
|
131
|
+
code |= RIGHT
|
132
|
+
end
|
133
|
+
if y < ymin # below the clip window
|
134
|
+
code |= BOTTOM
|
135
|
+
elsif y > ymax # above the clip window
|
136
|
+
code |= TOP
|
137
|
+
end
|
138
|
+
code
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Vamp
|
2
|
+
module Graphic
|
3
|
+
# basis class for graphic implementations
|
4
|
+
# you have to implement :dot, :undot, :clear and :screen
|
5
|
+
class Dotter
|
6
|
+
attr_reader :width # number of dots in x direction
|
7
|
+
attr_reader :height # number of dots in y direction
|
8
|
+
|
9
|
+
def initialize(width, height)
|
10
|
+
@width = width
|
11
|
+
@height = height
|
12
|
+
clear
|
13
|
+
end
|
14
|
+
|
15
|
+
# put dot at x, ys
|
16
|
+
def dot(x, y)
|
17
|
+
check(x, y)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
# is there a dot at x, y
|
22
|
+
def dot?(x, y)
|
23
|
+
check(x, y)
|
24
|
+
end
|
25
|
+
|
26
|
+
# remove dot at x, y
|
27
|
+
def undot(x, y)
|
28
|
+
check(x, y)
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
# clear screen of all dots
|
33
|
+
def clear
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
# return complete screen as string representation
|
38
|
+
def screen
|
39
|
+
end
|
40
|
+
|
41
|
+
# check if (x, y) is on the screen
|
42
|
+
def in?(x, y)
|
43
|
+
(0...width) === x && (0...height) === y
|
44
|
+
end
|
45
|
+
|
46
|
+
# check if (x, y) is on the screen, fails if not
|
47
|
+
def check(x, y)
|
48
|
+
fail "for (#{x}, #{y}}: x not in [0, #{width}[" unless (0...width) === x
|
49
|
+
fail "for (#{x}, #{y}}: y not in [0, #{height}[" unless (0...height) === y
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "dotter"
|
2
|
+
|
3
|
+
module Vamp
|
4
|
+
module Graphic
|
5
|
+
# simple sample implementation for a graphic basic implementation
|
6
|
+
class TextDotter < Dotter
|
7
|
+
def dot(x, y)
|
8
|
+
super
|
9
|
+
@data[y][x] = "X"
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def dot?(x, y)
|
14
|
+
super
|
15
|
+
@data[y][x] == "X"
|
16
|
+
end
|
17
|
+
|
18
|
+
def undot(x, y)
|
19
|
+
super
|
20
|
+
@data[y][x] = " "
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear
|
25
|
+
@data = Array.new(height) { Array.new(width, " ") }
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def screen
|
30
|
+
line = "+" + "-" * width + "+\n"
|
31
|
+
line + @data.map { |x| "|#{x.join('')}|" }.join("\n").to_s + "\n" + line
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module Vamp
|
2
|
+
module Graphic
|
3
|
+
# Transfer dotter data into ASCII
|
4
|
+
class Transfer
|
5
|
+
|
6
|
+
attr_reader :char_width
|
7
|
+
attr_reader :char_height
|
8
|
+
attr_reader :context
|
9
|
+
attr_reader :mapping
|
10
|
+
|
11
|
+
SPACE = <<-'END'
|
12
|
+
___
|
13
|
+
___
|
14
|
+
___
|
15
|
+
END
|
16
|
+
|
17
|
+
SLASH = <<-'END'
|
18
|
+
__X
|
19
|
+
_X_
|
20
|
+
X__
|
21
|
+
END
|
22
|
+
|
23
|
+
BACKSLASH = <<-'END'
|
24
|
+
X__
|
25
|
+
_X_
|
26
|
+
__X
|
27
|
+
END
|
28
|
+
|
29
|
+
BACKTICK = <<-'END'
|
30
|
+
X__
|
31
|
+
___
|
32
|
+
___
|
33
|
+
END
|
34
|
+
|
35
|
+
PIPE = <<-'END'
|
36
|
+
_X_
|
37
|
+
_X_
|
38
|
+
_X_
|
39
|
+
END
|
40
|
+
|
41
|
+
MINUS = <<-'END'
|
42
|
+
___
|
43
|
+
XXX
|
44
|
+
___
|
45
|
+
END
|
46
|
+
|
47
|
+
UNDERSCORE = <<-'END'
|
48
|
+
___
|
49
|
+
___
|
50
|
+
XXX
|
51
|
+
END
|
52
|
+
|
53
|
+
FULLSTOP = <<-'END'
|
54
|
+
___
|
55
|
+
___
|
56
|
+
_X_
|
57
|
+
END
|
58
|
+
|
59
|
+
DOUBLEQUOTES = <<-'END'
|
60
|
+
X_X
|
61
|
+
___
|
62
|
+
___
|
63
|
+
END
|
64
|
+
|
65
|
+
SINGLEQUOTE = <<-'END'
|
66
|
+
_X_
|
67
|
+
___
|
68
|
+
___
|
69
|
+
END
|
70
|
+
|
71
|
+
STAR = <<-'END'
|
72
|
+
_X_
|
73
|
+
XXX
|
74
|
+
_X_
|
75
|
+
END
|
76
|
+
|
77
|
+
HASH = <<-'END'
|
78
|
+
XXX
|
79
|
+
XXX
|
80
|
+
XXX
|
81
|
+
END
|
82
|
+
|
83
|
+
def initialize(context)
|
84
|
+
@context = context
|
85
|
+
@char_width = 3
|
86
|
+
@char_height = 3
|
87
|
+
@mapping = {
|
88
|
+
" " => create_pattern(SPACE),
|
89
|
+
"/" => create_pattern(SLASH),
|
90
|
+
"\\" => create_pattern(BACKSLASH),
|
91
|
+
"`" => create_pattern(BACKTICK),
|
92
|
+
"|" => create_pattern(PIPE),
|
93
|
+
"-" => create_pattern(MINUS),
|
94
|
+
"_" => create_pattern(UNDERSCORE),
|
95
|
+
"." => create_pattern(FULLSTOP),
|
96
|
+
"\"" => create_pattern(DOUBLEQUOTES),
|
97
|
+
"'" => create_pattern(SINGLEQUOTE),
|
98
|
+
"*" => create_pattern(STAR),
|
99
|
+
"\#" => create_pattern(HASH),
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_data(pattern)
|
104
|
+
a = pattern.split("\n")
|
105
|
+
fail "pattern has wrong height" if a.size != char_height
|
106
|
+
char_height.times do |dy|
|
107
|
+
fail "pattern has wrong width" if a[dy].size != char_width
|
108
|
+
end
|
109
|
+
a
|
110
|
+
end
|
111
|
+
|
112
|
+
def create_pattern(pattern)
|
113
|
+
char = TextDotter.new(char_width, char_height)
|
114
|
+
a = create_data(pattern)
|
115
|
+
char_height.times do |y|
|
116
|
+
char_width.times do |x|
|
117
|
+
char.dot(x, y) if a[y][x] == "X"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
char
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_pattern(x, y)
|
124
|
+
pattern = ""
|
125
|
+
char_height.times do |dy|
|
126
|
+
char_width.times do |dx|
|
127
|
+
if context.in?(x + dx, y + dy)
|
128
|
+
pattern += (context.dot?(x + dx, y + dy) ? "X" : "_")
|
129
|
+
else
|
130
|
+
pattern += "_"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
pattern += "\n"
|
134
|
+
end
|
135
|
+
create_pattern(pattern.strip)
|
136
|
+
end
|
137
|
+
|
138
|
+
def difference(pattern1, pattern2)
|
139
|
+
m = 0
|
140
|
+
char_width.times do |dx|
|
141
|
+
char_height.times do |dy|
|
142
|
+
m += 1 if pattern1.dot?(dx, dy) != pattern2.dot?(dx, dy)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
m
|
146
|
+
end
|
147
|
+
|
148
|
+
def get_matching(pattern)
|
149
|
+
ranking = {}
|
150
|
+
mapping.each do |k, v|
|
151
|
+
r = difference(pattern, v)
|
152
|
+
ranking[k] = r
|
153
|
+
end
|
154
|
+
ranking.min_by{|k, v| v}[0]
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def ascii
|
159
|
+
a = ""
|
160
|
+
(context.height / char_height).times do |y|
|
161
|
+
(context.width / char_width).times do |x|
|
162
|
+
a += get_matching(get_pattern(x * char_width, y * char_height))
|
163
|
+
end
|
164
|
+
a += "\n"
|
165
|
+
end
|
166
|
+
a.chomp
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|