rgss3 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -14
- data/lib/rgss3.rb +35 -1
- data/lib/rgss3/audio.rb +96 -0
- data/lib/rgss3/bitmap.rb +290 -0
- data/lib/rgss3/color.rb +163 -0
- data/lib/rgss3/container.rb +42 -0
- data/lib/rgss3/font.rb +50 -0
- data/lib/rgss3/game_window.rb +21 -0
- data/lib/rgss3/graphics.rb +137 -0
- data/lib/rgss3/input.rb +159 -0
- data/lib/rgss3/kernel_ext.rb +41 -0
- data/lib/rgss3/plane.rb +9 -0
- data/lib/rgss3/rect.rb +49 -0
- data/lib/rgss3/rgss3a.rb +129 -0
- data/lib/rgss3/rgss_error.rb +2 -0
- data/lib/rgss3/rgss_reset.rb +2 -0
- data/lib/rgss3/rpg.rb +997 -0
- data/lib/rgss3/sprite.rb +57 -0
- data/lib/rgss3/sprite_container.rb +21 -0
- data/lib/rgss3/table.rb +80 -0
- data/lib/rgss3/tilemap.rb +310 -0
- data/lib/rgss3/tone.rb +69 -0
- data/lib/rgss3/version.rb +1 -1
- data/lib/rgss3/viewport.rb +43 -0
- data/lib/rgss3/window.rb +58 -0
- data/rgss3.gemspec +1 -1
- metadata +25 -3
data/lib/rgss3/color.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
class Color
|
2
|
+
|
3
|
+
attr_accessor :gosu_color
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
case args.size
|
7
|
+
when 0
|
8
|
+
empty
|
9
|
+
when 3, 4
|
10
|
+
set(*args)
|
11
|
+
else
|
12
|
+
raise ArgumentError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def set(*args)
|
17
|
+
case args.size
|
18
|
+
when 1
|
19
|
+
if args[0].is_a?(Color)
|
20
|
+
@gosu_color = args[0].to_gosu
|
21
|
+
else
|
22
|
+
raise ArgumentError
|
23
|
+
end
|
24
|
+
when 3
|
25
|
+
@gosu_color = Gosu::Color.rgba(*args.map(&:round), 255)
|
26
|
+
when 4
|
27
|
+
@gosu_color = Gosu::Color.rgba(*args.map(&:round))
|
28
|
+
else
|
29
|
+
raise ArgumentError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def red
|
34
|
+
@gosu_color.red.to_f
|
35
|
+
end
|
36
|
+
|
37
|
+
def blue
|
38
|
+
@gosu_color.blue.to_f
|
39
|
+
end
|
40
|
+
|
41
|
+
def green
|
42
|
+
@gosu_color.green.to_f
|
43
|
+
end
|
44
|
+
|
45
|
+
def alpha
|
46
|
+
@gosu_color.alpha.to_f
|
47
|
+
end
|
48
|
+
|
49
|
+
def red_i
|
50
|
+
@gosu_color.red
|
51
|
+
end
|
52
|
+
|
53
|
+
def blue_i
|
54
|
+
@gosu_color.blue
|
55
|
+
end
|
56
|
+
|
57
|
+
def green_i
|
58
|
+
@gosu_color.green
|
59
|
+
end
|
60
|
+
|
61
|
+
def alpha_i
|
62
|
+
@gosu_color.alpha
|
63
|
+
end
|
64
|
+
|
65
|
+
def empty
|
66
|
+
@gosu_color = Gosu::Color::NONE
|
67
|
+
end
|
68
|
+
|
69
|
+
def red=(value)
|
70
|
+
@gosu_color.red = value
|
71
|
+
end
|
72
|
+
|
73
|
+
def blue=(value)
|
74
|
+
@gosu_color.blue = value
|
75
|
+
end
|
76
|
+
|
77
|
+
def green=(value)
|
78
|
+
@gosu_color.green = value
|
79
|
+
end
|
80
|
+
|
81
|
+
def alpha=(value)
|
82
|
+
@gosu_color.alpha = value
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_a
|
86
|
+
[red_i, green_i, blue_i, alpha_i]
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :rgba, :to_a
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
format '(%.6f, %.6f, %.6f, %.6f)', red, green, blue, alpha
|
93
|
+
end
|
94
|
+
|
95
|
+
alias_method :inspect, :to_s
|
96
|
+
|
97
|
+
def to_fa
|
98
|
+
[red, green, blue, alpha]
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_gosu
|
102
|
+
@gosu_color.dup
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_pixel
|
106
|
+
Magick::Pixel.from_color(to_rmagick_color)
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_rmagick_color
|
110
|
+
"rgba(#{red_i},#{green_i},#{blue_i},#{alpha_i})"
|
111
|
+
end
|
112
|
+
|
113
|
+
def _dump(d = 0)
|
114
|
+
[red, green, blue, alpha].pack('d4')
|
115
|
+
end
|
116
|
+
|
117
|
+
def self._load(s)
|
118
|
+
new(*s.unpack('d4'))
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.try_convert(color)
|
122
|
+
case color
|
123
|
+
when Color
|
124
|
+
color
|
125
|
+
when String
|
126
|
+
from_pixel Magick::Pixel.from_color(color)
|
127
|
+
when Integer
|
128
|
+
from_int(color)
|
129
|
+
when Magick::Pixel
|
130
|
+
from_pixel(color)
|
131
|
+
when Gosu::Color
|
132
|
+
from_gosu(color)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.from_pixel(pixel)
|
137
|
+
new(*rgba_from_pixel(pixel))
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.rgba_from_pixel(pixel)
|
141
|
+
# "#RRGGBBAA"
|
142
|
+
rgba_hex = pixel.to_color(Magick::AllCompliance, true, 8, true)
|
143
|
+
rgba = rgba_hex[1, 8].to_i(16)
|
144
|
+
rgba_from_int(rgba)
|
145
|
+
end
|
146
|
+
|
147
|
+
def from_int(rgba)
|
148
|
+
new(*rgba_from_int(rgba))
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.rgba_from_int(rgba)
|
152
|
+
(0...4).each_with_object(Array.new(4)) do |i, result|
|
153
|
+
result[3 - i] = rgba & 0xff
|
154
|
+
rgba >>= 8
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.from_gosu(gosu_color)
|
159
|
+
color = allocate
|
160
|
+
color.gosu_color = gosu_color
|
161
|
+
color
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module RGSS3
|
3
|
+
# common methods for Plane, Sprite and Window
|
4
|
+
module Container
|
5
|
+
|
6
|
+
attr_reader :opacity
|
7
|
+
attr_accessor :z, :ox, :oy
|
8
|
+
attr_accessor :viewport, :visible
|
9
|
+
attr_accessor :tone
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@visible = true
|
13
|
+
@z = 0
|
14
|
+
@ox = 0
|
15
|
+
@oy = 0
|
16
|
+
@opacity = 255
|
17
|
+
Graphics.add_container(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize_copy
|
21
|
+
copy = super
|
22
|
+
Graphics.add_container(copy)
|
23
|
+
copy
|
24
|
+
end
|
25
|
+
|
26
|
+
def dispose
|
27
|
+
@disposed = true
|
28
|
+
Graphics.remove_container(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def disposed?
|
32
|
+
@disposed
|
33
|
+
end
|
34
|
+
|
35
|
+
def opacity=(int)
|
36
|
+
@opacity = [[int, 255].min, 0].max
|
37
|
+
end
|
38
|
+
|
39
|
+
def draw
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/rgss3/font.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
class Font
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
attr_accessor :default_name, :default_size, :default_bold
|
6
|
+
attr_accessor :default_italic, :default_shadow, :default_outline
|
7
|
+
attr_accessor :default_color, :default_out_color
|
8
|
+
|
9
|
+
def exist?(name)
|
10
|
+
f = (Gosu::Font.new(Graphics.gosu_window, "./Fonts/#{name}.ttf", 8) rescue false)
|
11
|
+
Gosu::Font.new(Graphics.gosu_window, name, 8) unless f
|
12
|
+
return true
|
13
|
+
rescue
|
14
|
+
return false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
self.default_name = ["Verdana", "Arial", "Courier New"]
|
19
|
+
self.default_size = 24
|
20
|
+
self.default_bold = false
|
21
|
+
self.default_italic = false
|
22
|
+
self.default_shadow = false
|
23
|
+
self.default_outline = true
|
24
|
+
self.default_color = Color.new(255, 255, 255, 255)
|
25
|
+
self.default_out_color = Color.new(0, 0, 0, 128)
|
26
|
+
|
27
|
+
attr_accessor :name, :size, :bold, :italic, :shadow, :outline, :color, :out_color
|
28
|
+
|
29
|
+
def initialize(name = Font.default_name, size = Font.default_size)
|
30
|
+
@name = name.dup
|
31
|
+
@size = size
|
32
|
+
@bold = Font.default_bold
|
33
|
+
@italic = Font.default_italic
|
34
|
+
@shadow = Font.default_shadow
|
35
|
+
@outline = Font.default_outline
|
36
|
+
@color = Font.default_color.dup
|
37
|
+
@out_color = Font.default_out_color.dup
|
38
|
+
end
|
39
|
+
|
40
|
+
# NEW
|
41
|
+
|
42
|
+
def first_existant_name
|
43
|
+
if @name.is_a?(Array)
|
44
|
+
@name.each {|a| return a if Font.exist?(a) }
|
45
|
+
else
|
46
|
+
return @name if Font.exist?(@name)
|
47
|
+
end
|
48
|
+
return "Verdana"
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RGSS3
|
2
|
+
class GameWindow < Gosu::Window
|
3
|
+
attr_reader :frame_rate
|
4
|
+
def initialize(width: 544, height: 416, full_screen: false, frame_rate: 60, title: "Game")
|
5
|
+
@frame_rate = frame_rate
|
6
|
+
super(width, height, full_screen, 1000.0 / frame_rate)
|
7
|
+
self.caption = title
|
8
|
+
end
|
9
|
+
|
10
|
+
def update
|
11
|
+
fiber = RGSS3.fiber
|
12
|
+
if fiber
|
13
|
+
fiber.alive? ? fiber.resume : close
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def draw
|
18
|
+
Graphics.draw
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
|
2
|
+
require 'set'
|
3
|
+
module Graphics
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
attr_accessor :frame_count
|
8
|
+
attr_reader :gosu_window
|
9
|
+
attr_reader :brightness, :frame_rate
|
10
|
+
|
11
|
+
def gosu_window
|
12
|
+
RGSS3.window
|
13
|
+
end
|
14
|
+
|
15
|
+
def frame_rate
|
16
|
+
RGSS3.window.frame_rate
|
17
|
+
end
|
18
|
+
|
19
|
+
def brightness=(int)
|
20
|
+
@brightness = [[255, int].min, 0].max
|
21
|
+
@draw_color.alpha = 255 - @brightness
|
22
|
+
end
|
23
|
+
|
24
|
+
def frame_rate=(int)
|
25
|
+
# @frame_rate = [[120, int].min, 10].max
|
26
|
+
#reform_window(width, height, fullscreen?, 1.0 / @frame_rate * 1000)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@brightness = 255
|
31
|
+
@frame_count = 0
|
32
|
+
@frozen = false
|
33
|
+
@draw_color = Gosu::Color.rgba(255, 255, 255, 0)
|
34
|
+
# @draw_color.saturation = 0
|
35
|
+
# @draw_color.alpha = 0
|
36
|
+
@containers = Set.new
|
37
|
+
|
38
|
+
def self.update
|
39
|
+
window = RGSS3.window
|
40
|
+
@current = window.record(window.width, window.height) do
|
41
|
+
@containers.each(&:draw)
|
42
|
+
end
|
43
|
+
@frame_count += 1
|
44
|
+
@latest = @current unless @frozen
|
45
|
+
Fiber.yield
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.wait(duration)
|
49
|
+
duration.times { update }
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.fadeout(duration)
|
53
|
+
# Thread.new {
|
54
|
+
# rate = @brightness / duration.to_f
|
55
|
+
# until @brightness <= 0
|
56
|
+
# self.brightness -= rate
|
57
|
+
# sleep 1.0 / frame_rate
|
58
|
+
# end
|
59
|
+
# self.brightness = 0
|
60
|
+
# }
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.fadein(duration)
|
64
|
+
# Thread.new {
|
65
|
+
# rate = 255 / duration.to_f
|
66
|
+
# until @brightness >= 255
|
67
|
+
# self.brightness += rate
|
68
|
+
# sleep 1.0 / frame_rate
|
69
|
+
# end
|
70
|
+
# self.brightness = 255
|
71
|
+
# }
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.freeze
|
75
|
+
@frozen = true
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.transition(duration = 10, filename = "", vague = 40)
|
79
|
+
@frozen = false
|
80
|
+
# VAGUE ELUDES ME AS TO HOW TO INTEGRATE
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.snap_to_bitmap
|
84
|
+
Bitmap.from_gosu(@current)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.frame_reset
|
88
|
+
# AT A LOSS ON HOW TO INTEGRATE
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.width
|
92
|
+
RGSS3.window.width
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.height
|
96
|
+
RGSS3.window.height
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.resize_screen(w, h)
|
100
|
+
reform_window(w, h, fullscreen?, RGSS3.update_interval)
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.play_movie(filename)
|
104
|
+
# LIKELY TO REMAIN UNINTEGRATED
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.add_container(container)
|
108
|
+
@containers.add(container)
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.remove_container(container)
|
112
|
+
@containers.delete(container)
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.fullscreen?
|
116
|
+
RGSS3.window.fullscreen?
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.draw
|
120
|
+
if @latest
|
121
|
+
@latest.draw(0, 0, 0)
|
122
|
+
c = @draw_color
|
123
|
+
RGSS3.window.draw_quad(0, 0, c, 0, height, c, width, 0, c, width, height, c, 1)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# def self.set_fullscreen(bool)
|
128
|
+
# return if bool == fullscreen?
|
129
|
+
# reform_window(width, height, bool, gosu_window.update_interval)
|
130
|
+
# end
|
131
|
+
|
132
|
+
def self.reform_window(w, h, f, update_interval)
|
133
|
+
# Graphics.gosu_window.close
|
134
|
+
# Graphics.gosu_window = GosuGame.new(w, h, f, update_interval)
|
135
|
+
# Graphics.gosu_window.show
|
136
|
+
end
|
137
|
+
end
|
data/lib/rgss3/input.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
|
2
|
+
# Usage:
|
3
|
+
# Input.trigger?(2)
|
4
|
+
# Input.trigger?(:DOWN)
|
5
|
+
# Input.trigger?(Input::KB_DOWN)
|
6
|
+
# Input.trigger?(Input::Key[Gosu::KB_DOWN])
|
7
|
+
module Input
|
8
|
+
|
9
|
+
include Gosu
|
10
|
+
|
11
|
+
KEY_TO_INT = {
|
12
|
+
DOWN: 2,
|
13
|
+
LEFT: 4,
|
14
|
+
RIGHT: 6,
|
15
|
+
UP: 8,
|
16
|
+
|
17
|
+
A: 11,
|
18
|
+
B: 12,
|
19
|
+
C: 13,
|
20
|
+
X: 14,
|
21
|
+
Y: 15,
|
22
|
+
Z: 16,
|
23
|
+
L: 17,
|
24
|
+
R: 18,
|
25
|
+
|
26
|
+
SHIFT: 21,
|
27
|
+
CTRL: 22,
|
28
|
+
ALT: 23,
|
29
|
+
|
30
|
+
F5: 25,
|
31
|
+
F6: 26,
|
32
|
+
F7: 27,
|
33
|
+
F8: 28,
|
34
|
+
F9: 29
|
35
|
+
}
|
36
|
+
|
37
|
+
KEY_TO_INT_PROC = KEY_TO_INT.to_proc
|
38
|
+
|
39
|
+
KEY_TO_INT.each_key do |sym|
|
40
|
+
const_set sym, sym
|
41
|
+
end
|
42
|
+
|
43
|
+
KEY_MAPPER = {
|
44
|
+
KB_ENTER => C,
|
45
|
+
KB_LEFT_SHIFT => [SHIFT, A],
|
46
|
+
KB_RIGHT_SHIFT => [SHIFT, A],
|
47
|
+
KB_LEFT_CONTROL => CTRL,
|
48
|
+
KB_RIGHT_CONTROL => CTRL,
|
49
|
+
KB_LEFT_ALT => ALT,
|
50
|
+
KB_RIGHT_ALT => ALT,
|
51
|
+
KB_SPACE => C,
|
52
|
+
KB_ESCAPE => B,
|
53
|
+
KB_DOWN => DOWN,
|
54
|
+
KB_LEFT => LEFT,
|
55
|
+
KB_RIGHT => RIGHT,
|
56
|
+
KB_UP => UP,
|
57
|
+
KB_INSERT => B,
|
58
|
+
KB_NUMPAD_0 => B,
|
59
|
+
KB_NUMPAD_2 => DOWN,
|
60
|
+
KB_NUMPAD_4 => LEFT,
|
61
|
+
KB_NUMPAD_6 => RIGHT,
|
62
|
+
KB_NUMPAD_8 => UP,
|
63
|
+
KB_F5 => F5,
|
64
|
+
KB_F6 => F6,
|
65
|
+
KB_F7 => F7,
|
66
|
+
KB_F8 => F8,
|
67
|
+
KB_F9 => F9,
|
68
|
+
KB_Z => C,
|
69
|
+
KB_X => B,
|
70
|
+
KB_A => X,
|
71
|
+
KB_S => Y,
|
72
|
+
KB_D => Z,
|
73
|
+
KB_Q => L,
|
74
|
+
KB_W => R
|
75
|
+
}.freeze
|
76
|
+
|
77
|
+
REVERSE_KEY_MAPPER = {}
|
78
|
+
|
79
|
+
KEY_MAPPER.each do |kb_key, syms|
|
80
|
+
keys = Array(syms).map(&KEY_TO_INT_PROC)
|
81
|
+
keys.each do |key|
|
82
|
+
REVERSE_KEY_MAPPER[key] ||= []
|
83
|
+
REVERSE_KEY_MAPPER[key].push(kb_key)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
REVERSE_KEY_MAPPER.freeze
|
88
|
+
|
89
|
+
# A wrapper for Gosu::KB_****
|
90
|
+
# can be used as argument for methods in Input
|
91
|
+
Key = Struct.new(:kb_key)
|
92
|
+
|
93
|
+
Gosu.constants.each do |sym|
|
94
|
+
if sym[0, 3] == :KB_
|
95
|
+
kb_key = Gosu.const_get(sym)
|
96
|
+
const_set sym, Key[kb_key].freeze
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# stores pressed times of each key
|
101
|
+
@states = Hash.new { |h, k| h[k] = 0 }
|
102
|
+
@dir_4_8 = [5, 5]
|
103
|
+
|
104
|
+
def self.update
|
105
|
+
@states.each_key do |kb_key|
|
106
|
+
@states[kb_key] = RGSS3.window.button_down?(kb_key) ? @states[kb_key] + 1 : 0
|
107
|
+
end
|
108
|
+
@dir_4_8 = calculate_dir_4_8
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.trigger?(key)
|
112
|
+
presstime?(key) { |t| t == 1 }
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.press?(key)
|
116
|
+
presstime?(key, &:positive?)
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.repeat?(key)
|
120
|
+
presstime?(key) { |t| t == 1 || t > 23 && t % 6 == 0 }
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.dir4
|
124
|
+
@dir_4_8[0]
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.dir8
|
128
|
+
@dir_4_8[1]
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def self.presstime?(arg)
|
134
|
+
arg = KEY_TO_INT[arg] if arg.is_a?(Symbol)
|
135
|
+
arg = REVERSE_KEY_MAPPER[arg] if arg.is_a?(Integer)
|
136
|
+
arg = [arg.kb_key] if arg.is_a?(Key)
|
137
|
+
return false unless arg
|
138
|
+
arg.any? { |kb_key| yield @states[kb_key] }
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.calculate_dir_4_8
|
142
|
+
min_presstime = Float::INFINITY
|
143
|
+
dir4 = 5
|
144
|
+
dir8 = [2, 4, 6, 8].inject(5) do |dir, dir_checking|
|
145
|
+
presstime = REVERSE_KEY_MAPPER[dir_checking].map(&@states).select(&:positive?).min
|
146
|
+
if presstime
|
147
|
+
if presstime < min_presstime
|
148
|
+
dir4 = dir_checking
|
149
|
+
presstime = min_presstime
|
150
|
+
end
|
151
|
+
dir + dir_checking - 5
|
152
|
+
else
|
153
|
+
dir
|
154
|
+
end
|
155
|
+
end
|
156
|
+
return dir8, dir8 if [2, 4, 5, 6, 8].include?(dir8)
|
157
|
+
return dir4, dir8
|
158
|
+
end
|
159
|
+
end
|