rutui 0.4 → 0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/rutui.rb +3 -21
- data/lib/rutui/ansi.rb +46 -0
- data/lib/rutui/axx.rb +66 -66
- data/lib/rutui/figlet.rb +126 -127
- data/lib/rutui/objects.rb +309 -250
- data/lib/rutui/pixel.rb +20 -18
- data/lib/rutui/screen.rb +125 -83
- data/lib/rutui/screenmanager.rb +73 -60
- data/lib/rutui/sprites.rb +50 -49
- data/lib/rutui/table.rb +183 -180
- data/lib/rutui/textfield.rb +122 -99
- data/lib/rutui/theme.rb +53 -52
- metadata +16 -17
- data/lib/rutui/util.rb +0 -78
data/lib/rutui/pixel.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
|
1
|
+
module RuTui
|
2
|
+
## Pixel Class
|
3
|
+
# Each pixel consinsts of foreground, background and
|
4
|
+
# a symbol. What it is, is self explainaring
|
5
|
+
#
|
6
|
+
# Colors can be numbers between 0 and 255
|
7
|
+
# (dunno how windows or OSX handles colors over 16)
|
8
|
+
#
|
9
|
+
# The Symbol may eats every in Ruby working Ascii Symbol
|
10
|
+
#
|
11
|
+
class Pixel
|
12
|
+
attr_accessor :fg, :bg, :symbol
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def initialize foreground = 15, background = nil, symbol = " "
|
15
|
+
@fg = foreground
|
16
|
+
@bg = background
|
17
|
+
@symbol = symbol
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
def self.random sym = "#"
|
21
|
+
Pixel.new(rand(255),rand(255),sym)
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
data/lib/rutui/screen.rb
CHANGED
@@ -1,107 +1,149 @@
|
|
1
1
|
# This File contains the Screen Class
|
2
2
|
|
3
|
-
|
4
|
-
# The Screen is the root element of your app.
|
5
|
-
# Its basicly a map containing you screens pixels
|
6
|
-
#
|
7
|
-
class Screen
|
8
|
-
# Initialize me with a default pixel, if you want
|
9
|
-
def initialize default_pixel = Theme.get(:background)
|
10
|
-
size = Utils.winsize
|
11
|
-
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
12
|
-
@map = @smap.dup
|
13
|
-
@default = default_pixel
|
14
|
-
@objects = []
|
15
|
-
@statics = []
|
16
|
-
# Set as default if first screen
|
17
|
-
ScreenManager.add :default, self if ScreenManager.size == 0
|
18
|
-
end
|
19
|
-
|
20
|
-
# regen screen (size change?)
|
21
|
-
def rescreen
|
22
|
-
size = Utils.winsize
|
23
|
-
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
3
|
+
require 'io/console'
|
24
4
|
|
25
|
-
|
26
|
-
|
5
|
+
module RuTui
|
6
|
+
## Screen Class
|
7
|
+
# The Screen is the root element of your app.
|
8
|
+
# Its basicly a map containing you screens pixels
|
9
|
+
#
|
10
|
+
class Screen
|
11
|
+
# Initialize me with a default pixel, if you want
|
12
|
+
def initialize default_pixel = Theme.get(:background)
|
13
|
+
size = Screen.size
|
14
|
+
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
15
|
+
@map = @smap.dup
|
16
|
+
@default = default_pixel
|
17
|
+
@objects = []
|
18
|
+
@statics = []
|
19
|
+
# Set as default if first screen
|
20
|
+
ScreenManager.add :default, self if ScreenManager.size == 0
|
27
21
|
end
|
28
22
|
|
29
|
-
|
30
|
-
|
23
|
+
# regen screen (size change?)
|
24
|
+
def rescreen
|
25
|
+
size = Screen.size
|
26
|
+
@smap = Array.new(size[0]){ Array.new(size[1]) }
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@default = pixel
|
36
|
-
end
|
28
|
+
@statics.each do |s|
|
29
|
+
self.add_static s
|
30
|
+
end
|
37
31
|
|
38
|
-
|
39
|
-
|
40
|
-
def get_default
|
41
|
-
@default
|
42
|
-
end
|
32
|
+
@map = @smap.dup
|
33
|
+
end
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
object.each do |ri,ci,pixel|
|
49
|
-
@smap[object.y+ri][object.x+ci] = pixel if !pixel.nil? and object.y+ri > 0 and object.y+ci > 0
|
35
|
+
# Set default/background pixel
|
36
|
+
# Ex.: screen.set_default Pixel.new(244,1,";")
|
37
|
+
def set_default pixel
|
38
|
+
@default = pixel
|
50
39
|
end
|
51
|
-
end
|
52
40
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
41
|
+
##
|
42
|
+
# Get default/background pixel
|
43
|
+
def get_default
|
44
|
+
@default
|
45
|
+
end
|
58
46
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
47
|
+
##
|
48
|
+
# add object that doesnt change over time
|
49
|
+
def add_static object
|
50
|
+
@statics << object if !@statics.include? object
|
51
|
+
object.each do |ri,ci,pixel|
|
52
|
+
if !pixel.nil? and object.y+ri >= 0 and object.y+ci >= 0
|
53
|
+
if @smap[object.y+ri][object.x+ci].nil?
|
54
|
+
if pixel.bg == -1
|
55
|
+
pixel.bg = @map[object.y + ri][object.x + ci].bg if !@map[object.y + ri][object.x + ci].nil?
|
56
|
+
pixel.bg = Theme.get(:background).bg if pixel.bg == -1
|
57
|
+
end
|
58
|
+
if pixel.fg == -1
|
59
|
+
pixel.fg = @map[object.y + ri][object.x + ci].fg if !@map[object.y + ri][object.x + ci].nil?
|
60
|
+
pixel.fg = Theme.get(:background).fg if pixel.fg == -1
|
61
|
+
end
|
64
62
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
next if o.x.nil? or o.y.nil?
|
74
|
-
o.each do |ri,ci,pixel|
|
75
|
-
@map[o.y + ri][o.x + ci] = pixel if !pixel.nil? and o.y+ri > 0 and o.x+ci > 0 and o.y+ri < @map.size and o.x+ci < @map[0].size
|
63
|
+
@smap[object.y+ri][object.x+ci] = pixel
|
64
|
+
else
|
65
|
+
@smap[object.y+ri][object.x+ci] = @smap[object.y+ri][object.x+ci].dup
|
66
|
+
@smap[object.y+ri][object.x+ci].fg = pixel.fg if pixel.fg != -1
|
67
|
+
@smap[object.y+ri][object.x+ci].bg = pixel.bg if pixel.bg != -1
|
68
|
+
@smap[object.y+ri][object.x+ci].symbol = pixel.symbol
|
69
|
+
end
|
70
|
+
end
|
76
71
|
end
|
77
72
|
end
|
73
|
+
##
|
78
74
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
75
|
+
# add dynamic object
|
76
|
+
def add object
|
77
|
+
@objects << object
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# remove object
|
82
|
+
def delete object
|
83
|
+
@objects.delete(object)
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# draw the pixel-screen map
|
88
|
+
def draw
|
89
|
+
lastpixel = Pixel.new(rand(255), rand(255), ".")
|
90
|
+
@map = Marshal.load( Marshal.dump( @smap )) # Deep copy
|
91
|
+
|
92
|
+
# get all the objects
|
93
|
+
@objects.each do |o|
|
94
|
+
next if o.x.nil? or o.y.nil?
|
95
|
+
o.each do |ri,ci,pixel|
|
96
|
+
if !pixel.nil? and o.y+ri >= 0 and o.x+ci >= 0 and o.y+ri < @map.size and o.x+ci < @map[0].size
|
97
|
+
# -1 enables a "transparent" effect
|
98
|
+
if pixel.bg == -1
|
99
|
+
pixel.bg = @map[o.y + ri][o.x + ci].bg if !@map[o.y + ri][o.x + ci].nil?
|
100
|
+
pixel.bg = Theme.get(:background).bg if pixel.bg == -1
|
101
|
+
end
|
102
|
+
if pixel.fg == -1
|
103
|
+
pixel.fg = @map[o.y + ri][o.x + ci].fg if !@map[o.y + ri][o.x + ci].nil?
|
104
|
+
pixel.fg = Theme.get(:background).fg if pixel.fg == -1
|
105
|
+
end
|
106
|
+
|
107
|
+
@map[o.y + ri][o.x + ci] = pixel
|
91
108
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
out = "" # Color.go_home
|
113
|
+
# and DRAW!
|
114
|
+
@map.each do |line|
|
115
|
+
line.each do |pixel|
|
116
|
+
if lastpixel != pixel
|
117
|
+
out += RuTui::Ansi.clear_color if lastpixel != 0
|
118
|
+
if pixel.nil?
|
119
|
+
out += "#{RuTui::Ansi.bg(@default.bg)}#{RuTui::Ansi.fg(@default.fg)}#{@default.symbol}"
|
120
|
+
else
|
121
|
+
out += "#{RuTui::Ansi.bg(pixel.bg)}#{RuTui::Ansi.fg(pixel.fg)}#{pixel.symbol}"
|
122
|
+
end
|
123
|
+
lastpixel = pixel
|
95
124
|
else
|
96
|
-
|
125
|
+
if pixel.nil?
|
126
|
+
out += @default.symbol
|
127
|
+
else
|
128
|
+
out += pixel.symbol
|
129
|
+
end
|
97
130
|
end
|
98
131
|
end
|
99
132
|
end
|
133
|
+
|
134
|
+
# draw out
|
135
|
+
print out.chomp
|
136
|
+
$stdout.flush
|
100
137
|
end
|
101
138
|
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
|
139
|
+
# Hides the cursor
|
140
|
+
def self.hide_cursor
|
141
|
+
print RuTui::Ansi.hide_cursor
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.size
|
145
|
+
IO.console.winsize
|
146
|
+
end
|
106
147
|
|
148
|
+
end
|
107
149
|
end
|
data/lib/rutui/screenmanager.rb
CHANGED
@@ -1,76 +1,89 @@
|
|
1
1
|
# This file contains the ScreenManager
|
2
|
+
module RuTui
|
3
|
+
## Screen Manager Class
|
4
|
+
# Static class to handle screens
|
5
|
+
#
|
6
|
+
class ScreenManager
|
7
|
+
@@screens = {}
|
8
|
+
@@current = :default
|
9
|
+
@@blocked = false
|
2
10
|
|
3
|
-
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@@current = :default
|
11
|
+
# Set a screen
|
12
|
+
# Ex.: ScreenManager.set :default, Screen.new
|
13
|
+
def self.add name, screen
|
14
|
+
@@screens[name] = screen
|
15
|
+
end
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
17
|
+
# Get count of existing screens
|
18
|
+
def self.size
|
19
|
+
@@screens.size
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
# Delete screen by name
|
23
|
+
def self.delete name
|
24
|
+
@@screens.delete(name) if !@@screens[name].nil?
|
25
|
+
end
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
# Set current screen
|
28
|
+
def self.set_current name
|
29
|
+
@@current = name
|
30
|
+
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
# Get current screen
|
33
|
+
def self.get_current
|
34
|
+
# Fix size and others of screen here
|
35
|
+
@@current
|
36
|
+
end
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
38
|
+
# Get the complete screen by name
|
39
|
+
def self.get_screen name
|
40
|
+
@@screens[name]
|
41
|
+
end
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
# Refit screen size
|
44
|
+
def self.refit
|
45
|
+
size = Screen.size
|
46
|
+
if @autofit and size != @lastsize
|
47
|
+
@@screens[@@current].rescreen
|
48
|
+
@lastsize = size
|
49
|
+
end
|
50
|
+
end
|
41
51
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@@screens[@@current].rescreen
|
47
|
-
@lastsize = size
|
52
|
+
# draw current screen
|
53
|
+
def self.draw
|
54
|
+
print RuTui::Ansi.go_home
|
55
|
+
@@screens[@@current].draw
|
48
56
|
end
|
49
|
-
end
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
58
|
+
# Raw Game Loop
|
59
|
+
# Ex.: ScreenManager.loop({ :autodraw => true, :autofit => true }){ |key| p key }
|
60
|
+
def self.loop options
|
61
|
+
autodraw = options[:autodraw]
|
62
|
+
@autofit = options[:autofit]
|
63
|
+
@autofit = true if @autofit.nil?
|
64
|
+
@timeout = options[:timeout]
|
65
|
+
@lastsize = nil
|
66
|
+
@lastaction = Time.now.to_f
|
67
|
+
print RuTui::Ansi.clear
|
68
|
+
print RuTui::Ansi.set_start
|
69
|
+
Screen.hide_cursor
|
70
|
+
|
71
|
+
ScreenManager.draw
|
56
72
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
while true
|
74
|
+
if !@@blocked
|
75
|
+
@@blocked = true
|
76
|
+
key = Input.getc
|
77
|
+
yield key
|
78
|
+
if (@timeout.nil? or (@lastaction < Time.now.to_f-@timeout))
|
79
|
+
@lastaction = Time.now.to_f
|
80
|
+
ScreenManager.refit if @autofit
|
81
|
+
ScreenManager.draw if autodraw
|
82
|
+
end
|
83
|
+
@@blocked = false
|
84
|
+
end
|
85
|
+
end
|
68
86
|
|
69
|
-
while true
|
70
|
-
key = Utils.gets
|
71
|
-
yield key
|
72
|
-
ScreenManager.refit if @autofit
|
73
|
-
ScreenManager.draw if autodraw
|
74
87
|
end
|
75
88
|
end
|
76
89
|
end
|
data/lib/rutui/sprites.rb
CHANGED
@@ -1,64 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module RuTui
|
2
|
+
class Sprite < BaseObject
|
3
|
+
attr_accessor :tick, :current, :sprites, :ticks, :object
|
4
|
+
@@spr = []
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def initialize options
|
7
|
+
@x = options[:x]
|
8
|
+
@y = options[:y]
|
9
|
+
@x = 0 if @x.nil?
|
10
|
+
@y = 0 if @y.nil?
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
@tick = 0
|
13
|
+
@object = options[:obj]
|
14
|
+
@file = options[:file]
|
15
|
+
@current = nil
|
15
16
|
|
16
|
-
|
17
|
+
@@spr << self
|
17
18
|
|
18
|
-
|
19
|
+
@sprites = {}
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
create_from_file if !@file.nil?
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
def create_from_file
|
25
|
+
if File.exists? @file
|
26
|
+
data = File.open(@file).read
|
27
|
+
# AXX Format
|
28
|
+
if data.include? '---' and data.include? '| :'
|
29
|
+
out = []
|
30
|
+
data = data.split("---")
|
31
|
+
while data.size > 0
|
32
|
+
while data[0].match(/^#/)
|
33
|
+
data.shift
|
34
|
+
end
|
35
|
+
name = data.shift
|
36
|
+
content = data.shift
|
37
|
+
@sprites[name] = [] if @sprites[name].nil?
|
38
|
+
@sprites[name] << Axx.parse(content)
|
39
|
+
@current = name if @current.nil? # first sprite gets default
|
40
|
+
@obj = @sprites[@current][0]
|
33
41
|
end
|
34
|
-
name = data.shift
|
35
|
-
content = data.shift
|
36
|
-
@sprites[name] = [] if @sprites[name].nil?
|
37
|
-
@sprites[name] << Axx.parse(content)
|
38
|
-
@current = name if @current.nil? # first sprite gets default
|
39
|
-
@obj = @sprites[@current][0]
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
43
|
-
end
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
# set current animation
|
47
|
+
def set_current name
|
48
|
+
@current = name
|
49
|
+
@obj = @sprites[@current][0]
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
# Add sprite
|
53
|
+
def add name, images
|
54
|
+
@current = name if @current.nil? # first sprite gets default
|
55
|
+
@sprites[name] = images
|
56
|
+
end
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
# Update ticker
|
59
|
+
def update
|
60
|
+
@tick += 1
|
61
|
+
@tick = 0 if @tick >= ( @sprites[@current].size )
|
62
|
+
@obj = @sprites[@current][@tick]
|
63
|
+
end
|
62
64
|
end
|
63
|
-
|
64
65
|
end
|