gosling 2.3.0 → 2.3.2
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 +5 -5
- data/lib/gosling.rb +4 -4
- data/lib/gosling/actor.rb +328 -328
- data/lib/gosling/circle.rb +65 -65
- data/lib/gosling/collision.rb +499 -499
- data/lib/gosling/image_library.rb +24 -24
- data/lib/gosling/inheritance_error.rb +4 -4
- data/lib/gosling/matrix_cache.rb +23 -21
- data/lib/gosling/object_cache.rb +48 -48
- data/lib/gosling/patches.rb +42 -42
- data/lib/gosling/polygon.rb +122 -122
- data/lib/gosling/rect.rb +41 -41
- data/lib/gosling/sprite.rb +50 -50
- data/lib/gosling/transformable.rb +413 -413
- data/lib/gosling/utils.rb +20 -20
- data/lib/gosling/vector_cache.rb +21 -21
- data/lib/gosling/version.rb +7 -7
- data/spec/actor_spec.rb +627 -627
- data/spec/circle_spec.rb +46 -46
- data/spec/collision_spec.rb +1755 -1755
- data/spec/image_library_spec.rb +19 -19
- data/spec/matrix_cache_spec.rb +25 -25
- data/spec/object_cache_spec.rb +22 -22
- data/spec/polygon_spec.rb +284 -284
- data/spec/rect_spec.rb +86 -86
- data/spec/spec_helper.rb +3 -3
- data/spec/sprite_spec.rb +45 -45
- data/spec/transformable_spec.rb +479 -479
- data/spec/vector_cache_spec.rb +80 -80
- metadata +3 -4
@@ -1,24 +1,24 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
|
3
|
-
module Gosling
|
4
|
-
##
|
5
|
-
# A cached Gosu::Image repository.
|
6
|
-
#
|
7
|
-
class ImageLibrary
|
8
|
-
@@cache = {}
|
9
|
-
|
10
|
-
include Singleton
|
11
|
-
|
12
|
-
##
|
13
|
-
# When passed the path to an image, it first checks to see if that image is in the cache. If so, it returns the cached
|
14
|
-
# Gosu::Image. Otherwise, it loads the image, stores it in the cache, and returns it.
|
15
|
-
#
|
16
|
-
def self.get(filename)
|
17
|
-
unless @@cache.has_key?(filename)
|
18
|
-
raise ArgumentError.new("File not found: '#{filename}' in '#{Dir.pwd}'") unless File.exists?(filename)
|
19
|
-
@@cache[filename] = Gosu::Image.new(filename, tileable: true)
|
20
|
-
end
|
21
|
-
@@cache[filename]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Gosling
|
4
|
+
##
|
5
|
+
# A cached Gosu::Image repository.
|
6
|
+
#
|
7
|
+
class ImageLibrary
|
8
|
+
@@cache = {}
|
9
|
+
|
10
|
+
include Singleton
|
11
|
+
|
12
|
+
##
|
13
|
+
# When passed the path to an image, it first checks to see if that image is in the cache. If so, it returns the cached
|
14
|
+
# Gosu::Image. Otherwise, it loads the image, stores it in the cache, and returns it.
|
15
|
+
#
|
16
|
+
def self.get(filename)
|
17
|
+
unless @@cache.has_key?(filename)
|
18
|
+
raise ArgumentError.new("File not found: '#{filename}' in '#{Dir.pwd}'") unless File.exists?(filename)
|
19
|
+
@@cache[filename] = Gosu::Image.new(filename, tileable: true)
|
20
|
+
end
|
21
|
+
@@cache[filename]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Gosling
|
2
|
-
class InheritanceError < StandardError
|
3
|
-
end
|
4
|
-
end
|
1
|
+
module Gosling
|
2
|
+
class InheritanceError < StandardError
|
3
|
+
end
|
4
|
+
end
|
data/lib/gosling/matrix_cache.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
require_relative 'object_cache.rb'
|
4
|
+
|
5
|
+
class MatrixCache
|
6
|
+
include Singleton
|
7
|
+
include ObjectCache
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@cache = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def create
|
16
|
+
Snow::Mat3.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset(matrix)
|
20
|
+
type_check(matrix, Snow::Mat3)
|
21
|
+
matrix.load_identity
|
22
|
+
end
|
23
|
+
end
|
data/lib/gosling/object_cache.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
|
-
require 'fiddle'
|
2
|
-
|
3
|
-
class Object
|
4
|
-
FIDDLE_FREEZE_BIT = ~(1 << 3)
|
5
|
-
|
6
|
-
def unfreeze
|
7
|
-
ptr = @fiddle_pointer || Fiddle::Pointer.new(object_id * 2)
|
8
|
-
ptr[1] &= FIDDLE_FREEZE_BIT
|
9
|
-
@fiddle_pointer = ptr
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
module ObjectCache
|
14
|
-
def clear
|
15
|
-
@cache.clear
|
16
|
-
end
|
17
|
-
|
18
|
-
def recycle(obj)
|
19
|
-
return if @cache.key?(obj.object_id)
|
20
|
-
self.reset(obj)
|
21
|
-
obj.freeze
|
22
|
-
@cache[obj.object_id] = obj
|
23
|
-
end
|
24
|
-
|
25
|
-
def get
|
26
|
-
if @cache.empty?
|
27
|
-
self.create
|
28
|
-
else
|
29
|
-
obj = @cache.delete(@cache.keys.first)
|
30
|
-
obj.unfreeze
|
31
|
-
obj
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def size
|
36
|
-
@cache.size
|
37
|
-
end
|
38
|
-
|
39
|
-
protected
|
40
|
-
|
41
|
-
def create
|
42
|
-
raise "Derived classes must implement create()."
|
43
|
-
end
|
44
|
-
|
45
|
-
def reset(obj)
|
46
|
-
raise "Derived classes must implement reset()."
|
47
|
-
end
|
48
|
-
end
|
1
|
+
require 'fiddle'
|
2
|
+
|
3
|
+
class Object
|
4
|
+
FIDDLE_FREEZE_BIT = ~(1 << 3)
|
5
|
+
|
6
|
+
def unfreeze
|
7
|
+
ptr = @fiddle_pointer || Fiddle::Pointer.new(object_id * 2)
|
8
|
+
ptr[1] &= FIDDLE_FREEZE_BIT
|
9
|
+
@fiddle_pointer = ptr
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ObjectCache
|
14
|
+
def clear
|
15
|
+
@cache.clear
|
16
|
+
end
|
17
|
+
|
18
|
+
def recycle(obj)
|
19
|
+
return if @cache.key?(obj.object_id)
|
20
|
+
self.reset(obj)
|
21
|
+
obj.freeze
|
22
|
+
@cache[obj.object_id] = obj
|
23
|
+
end
|
24
|
+
|
25
|
+
def get
|
26
|
+
if @cache.empty?
|
27
|
+
self.create
|
28
|
+
else
|
29
|
+
obj = @cache.delete(@cache.keys.first)
|
30
|
+
obj.unfreeze
|
31
|
+
obj
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def size
|
36
|
+
@cache.size
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def create
|
42
|
+
raise "Derived classes must implement create()."
|
43
|
+
end
|
44
|
+
|
45
|
+
def reset(obj)
|
46
|
+
raise "Derived classes must implement reset()."
|
47
|
+
end
|
48
|
+
end
|
data/lib/gosling/patches.rb
CHANGED
@@ -1,42 +1,42 @@
|
|
1
|
-
require 'snow-math'
|
2
|
-
|
3
|
-
module Snow
|
4
|
-
class Mat3
|
5
|
-
##
|
6
|
-
# Monkey-patch fix for Mat3 * Vec3
|
7
|
-
#
|
8
|
-
def multiply(rhs, out = nil)
|
9
|
-
case rhs
|
10
|
-
when ::Snow::Mat3
|
11
|
-
multiply_mat3(rhs, out)
|
12
|
-
when ::Snow::Vec3
|
13
|
-
values = (0..2).map { |i| get_row3(i) ** rhs }
|
14
|
-
out ||= Snow::Vec3.new
|
15
|
-
out.set(values)
|
16
|
-
when Numeric
|
17
|
-
scale(rhs, rhs, rhs, out)
|
18
|
-
else
|
19
|
-
raise TypeError, "Invalid type for RHS"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
alias_method :*, :multiply
|
23
|
-
|
24
|
-
##
|
25
|
-
# Monkey-patch fix for #multiply! type-switching
|
26
|
-
#
|
27
|
-
def multiply!(rhs)
|
28
|
-
multiply rhs, case rhs
|
29
|
-
when ::Snow::Mat3, Numeric then self
|
30
|
-
when ::Snow::Vec3 then rhs
|
31
|
-
else raise TypeError, "Invalid type for RHS"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
##
|
36
|
-
# Returns true if this Mat3 is an identity matrix.
|
37
|
-
#
|
38
|
-
def identity?
|
39
|
-
[1, 2, 3, 5, 6, 7].all? { |i| self[i] == 0 } && [0, 4, 8].all? { |i| self[i] == 1 }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
1
|
+
require 'snow-math'
|
2
|
+
|
3
|
+
module Snow
|
4
|
+
class Mat3
|
5
|
+
##
|
6
|
+
# Monkey-patch fix for Mat3 * Vec3
|
7
|
+
#
|
8
|
+
def multiply(rhs, out = nil)
|
9
|
+
case rhs
|
10
|
+
when ::Snow::Mat3
|
11
|
+
multiply_mat3(rhs, out)
|
12
|
+
when ::Snow::Vec3
|
13
|
+
values = (0..2).map { |i| get_row3(i) ** rhs }
|
14
|
+
out ||= Snow::Vec3.new
|
15
|
+
out.set(values)
|
16
|
+
when Numeric
|
17
|
+
scale(rhs, rhs, rhs, out)
|
18
|
+
else
|
19
|
+
raise TypeError, "Invalid type for RHS"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
alias_method :*, :multiply
|
23
|
+
|
24
|
+
##
|
25
|
+
# Monkey-patch fix for #multiply! type-switching
|
26
|
+
#
|
27
|
+
def multiply!(rhs)
|
28
|
+
multiply rhs, case rhs
|
29
|
+
when ::Snow::Mat3, Numeric then self
|
30
|
+
when ::Snow::Vec3 then rhs
|
31
|
+
else raise TypeError, "Invalid type for RHS"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Returns true if this Mat3 is an identity matrix.
|
37
|
+
#
|
38
|
+
def identity?
|
39
|
+
[1, 2, 3, 5, 6, 7].all? { |i| self[i] == 0 } && [0, 4, 8].all? { |i| self[i] == 1 }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/gosling/polygon.rb
CHANGED
@@ -1,122 +1,122 @@
|
|
1
|
-
require_relative 'actor.rb'
|
2
|
-
require_relative 'collision.rb'
|
3
|
-
require_relative 'utils.rb'
|
4
|
-
|
5
|
-
module Gosling
|
6
|
-
##
|
7
|
-
# A Polygon is an Actor with a shape defined by three or more vertices. Can be used to make triangles, hexagons, or
|
8
|
-
# any other unusual geometry not covered by the other Actors. For circles, you should use Circle. For squares or
|
9
|
-
# rectangles, see Rect.
|
10
|
-
#
|
11
|
-
class Polygon < Actor
|
12
|
-
##
|
13
|
-
# Creates a new, square Polygon with a width and height of 1.
|
14
|
-
#
|
15
|
-
def initialize(window)
|
16
|
-
type_check(window, Gosu::Window)
|
17
|
-
super(window)
|
18
|
-
@vertices = [
|
19
|
-
Snow::Vec3[0, 0, 0],
|
20
|
-
Snow::Vec3[1, 0, 0],
|
21
|
-
Snow::Vec3[1, 1, 0],
|
22
|
-
Snow::Vec3[0, 1, 0]
|
23
|
-
]
|
24
|
-
end
|
25
|
-
|
26
|
-
##
|
27
|
-
# Returns a copy of this Polygon's vertices (@vertices is read-only).
|
28
|
-
#
|
29
|
-
def get_vertices
|
30
|
-
@vertices.dup
|
31
|
-
end
|
32
|
-
|
33
|
-
##
|
34
|
-
# Sets this polygon's vertices. Requires three or more Snow::Vec2, Vec3, Vec4, or Arrays containing 2 or more
|
35
|
-
# numbers.
|
36
|
-
#
|
37
|
-
# Usage:
|
38
|
-
# - polygon.set_vertices([Snow::Vec3[-1, 0, 0], Snow::Vec3[0, -1, 0], Snow::Vec3[1, 1, 0]])
|
39
|
-
#
|
40
|
-
def set_vertices(vertices)
|
41
|
-
type_check(vertices, Array)
|
42
|
-
raise ArgumentError.new("set_vertices() expects an array of at least three 2D vectors") unless vertices.length >= 3
|
43
|
-
vertices.each do |v|
|
44
|
-
types_check(v, Snow::Vec2, Snow::Vec3, Snow::Vec4, Array)
|
45
|
-
if v.is_a?(Array)
|
46
|
-
raise ArgumentError.new("set_vertices() expects an array of at least three 2D vectors") unless v.length >= 2
|
47
|
-
v.each { |n| type_check(n, Numeric) }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
if @vertices.length < vertices.length
|
52
|
-
@vertices.concat(Array.new(vertices.length - @vertices.length) { Snow::Vec3.new })
|
53
|
-
elsif @vertices.length > vertices.length
|
54
|
-
@vertices.pop(@vertices.length - vertices.length)
|
55
|
-
end
|
56
|
-
|
57
|
-
vertices.each_index { |i| @vertices[i].set(vertices[i][0], vertices[i][1], 0) }
|
58
|
-
end
|
59
|
-
|
60
|
-
##
|
61
|
-
# Sets this polygon to a rectangular shape with the given width and height, with its upper left at local [0, 0].
|
62
|
-
#
|
63
|
-
def set_vertices_rect(width, height)
|
64
|
-
raise ArgumentError.new("Expected positive non-zero integer, but received #{width.inspect}!") unless width > 0
|
65
|
-
raise ArgumentError.new("Expected positive non-zero integer, but received #{height.inspect}!") unless height > 0
|
66
|
-
|
67
|
-
if @vertices.length < 4
|
68
|
-
@vertices.concat(Array.new(4 - @vertices.length) { Snow::Vec3.new })
|
69
|
-
elsif @vertices.length > 4
|
70
|
-
@vertices.pop(@vertices.length - 4)
|
71
|
-
end
|
72
|
-
|
73
|
-
@vertices[0].set( 0, 0, 0)
|
74
|
-
@vertices[1].set(width, 0, 0)
|
75
|
-
@vertices[2].set(width, height, 0)
|
76
|
-
@vertices[3].set( 0, height, 0)
|
77
|
-
end
|
78
|
-
|
79
|
-
##
|
80
|
-
# Returns an array containing all of our local vertices transformed to global-space. (See Actor#get_global_transform.)
|
81
|
-
#
|
82
|
-
def get_global_vertices(out = nil)
|
83
|
-
type_check(out, Array) unless out.nil?
|
84
|
-
|
85
|
-
tf = MatrixCache.instance.get
|
86
|
-
get_global_transform(tf)
|
87
|
-
|
88
|
-
if out.nil?
|
89
|
-
return @vertices.map { |v| Transformable.transform_point(tf, v, Snow::Vec3.new) }
|
90
|
-
end
|
91
|
-
|
92
|
-
@vertices.each_index do |i|
|
93
|
-
v = @vertices[i]
|
94
|
-
if out[i]
|
95
|
-
Transformable.transform_point(tf, v, out[i])
|
96
|
-
else
|
97
|
-
out[i] = Transformable.transform_point(tf, v)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
out
|
101
|
-
ensure
|
102
|
-
MatrixCache.instance.recycle(tf) if tf
|
103
|
-
end
|
104
|
-
|
105
|
-
##
|
106
|
-
# Returns true if the point is inside of this Polygon, false otherwise.
|
107
|
-
#
|
108
|
-
def is_point_in_bounds(point)
|
109
|
-
Collision.is_point_in_shape?(point, self)
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def render(matrix)
|
115
|
-
# TODO: write transformed vertices to a reserved list of vertices retained in memory each time
|
116
|
-
type_check(matrix, Snow::Mat3)
|
117
|
-
global_vertices = @vertices.map { |v| Transformable.transform_point(matrix, v) }
|
118
|
-
|
119
|
-
fill_polygon(global_vertices)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
1
|
+
require_relative 'actor.rb'
|
2
|
+
require_relative 'collision.rb'
|
3
|
+
require_relative 'utils.rb'
|
4
|
+
|
5
|
+
module Gosling
|
6
|
+
##
|
7
|
+
# A Polygon is an Actor with a shape defined by three or more vertices. Can be used to make triangles, hexagons, or
|
8
|
+
# any other unusual geometry not covered by the other Actors. For circles, you should use Circle. For squares or
|
9
|
+
# rectangles, see Rect.
|
10
|
+
#
|
11
|
+
class Polygon < Actor
|
12
|
+
##
|
13
|
+
# Creates a new, square Polygon with a width and height of 1.
|
14
|
+
#
|
15
|
+
def initialize(window)
|
16
|
+
type_check(window, Gosu::Window)
|
17
|
+
super(window)
|
18
|
+
@vertices = [
|
19
|
+
Snow::Vec3[0, 0, 0],
|
20
|
+
Snow::Vec3[1, 0, 0],
|
21
|
+
Snow::Vec3[1, 1, 0],
|
22
|
+
Snow::Vec3[0, 1, 0]
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Returns a copy of this Polygon's vertices (@vertices is read-only).
|
28
|
+
#
|
29
|
+
def get_vertices
|
30
|
+
@vertices.dup
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Sets this polygon's vertices. Requires three or more Snow::Vec2, Vec3, Vec4, or Arrays containing 2 or more
|
35
|
+
# numbers.
|
36
|
+
#
|
37
|
+
# Usage:
|
38
|
+
# - polygon.set_vertices([Snow::Vec3[-1, 0, 0], Snow::Vec3[0, -1, 0], Snow::Vec3[1, 1, 0]])
|
39
|
+
#
|
40
|
+
def set_vertices(vertices)
|
41
|
+
type_check(vertices, Array)
|
42
|
+
raise ArgumentError.new("set_vertices() expects an array of at least three 2D vectors") unless vertices.length >= 3
|
43
|
+
vertices.each do |v|
|
44
|
+
types_check(v, Snow::Vec2, Snow::Vec3, Snow::Vec4, Array)
|
45
|
+
if v.is_a?(Array)
|
46
|
+
raise ArgumentError.new("set_vertices() expects an array of at least three 2D vectors") unless v.length >= 2
|
47
|
+
v.each { |n| type_check(n, Numeric) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if @vertices.length < vertices.length
|
52
|
+
@vertices.concat(Array.new(vertices.length - @vertices.length) { Snow::Vec3.new })
|
53
|
+
elsif @vertices.length > vertices.length
|
54
|
+
@vertices.pop(@vertices.length - vertices.length)
|
55
|
+
end
|
56
|
+
|
57
|
+
vertices.each_index { |i| @vertices[i].set(vertices[i][0], vertices[i][1], 0) }
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Sets this polygon to a rectangular shape with the given width and height, with its upper left at local [0, 0].
|
62
|
+
#
|
63
|
+
def set_vertices_rect(width, height)
|
64
|
+
raise ArgumentError.new("Expected positive non-zero integer, but received #{width.inspect}!") unless width > 0
|
65
|
+
raise ArgumentError.new("Expected positive non-zero integer, but received #{height.inspect}!") unless height > 0
|
66
|
+
|
67
|
+
if @vertices.length < 4
|
68
|
+
@vertices.concat(Array.new(4 - @vertices.length) { Snow::Vec3.new })
|
69
|
+
elsif @vertices.length > 4
|
70
|
+
@vertices.pop(@vertices.length - 4)
|
71
|
+
end
|
72
|
+
|
73
|
+
@vertices[0].set( 0, 0, 0)
|
74
|
+
@vertices[1].set(width, 0, 0)
|
75
|
+
@vertices[2].set(width, height, 0)
|
76
|
+
@vertices[3].set( 0, height, 0)
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Returns an array containing all of our local vertices transformed to global-space. (See Actor#get_global_transform.)
|
81
|
+
#
|
82
|
+
def get_global_vertices(out = nil)
|
83
|
+
type_check(out, Array) unless out.nil?
|
84
|
+
|
85
|
+
tf = MatrixCache.instance.get
|
86
|
+
get_global_transform(tf)
|
87
|
+
|
88
|
+
if out.nil?
|
89
|
+
return @vertices.map { |v| Transformable.transform_point(tf, v, Snow::Vec3.new) }
|
90
|
+
end
|
91
|
+
|
92
|
+
@vertices.each_index do |i|
|
93
|
+
v = @vertices[i]
|
94
|
+
if out[i]
|
95
|
+
Transformable.transform_point(tf, v, out[i])
|
96
|
+
else
|
97
|
+
out[i] = Transformable.transform_point(tf, v)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
out
|
101
|
+
ensure
|
102
|
+
MatrixCache.instance.recycle(tf) if tf
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Returns true if the point is inside of this Polygon, false otherwise.
|
107
|
+
#
|
108
|
+
def is_point_in_bounds(point)
|
109
|
+
Collision.is_point_in_shape?(point, self)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def render(matrix)
|
115
|
+
# TODO: write transformed vertices to a reserved list of vertices retained in memory each time
|
116
|
+
type_check(matrix, Snow::Mat3)
|
117
|
+
global_vertices = @vertices.map { |v| Transformable.transform_point(matrix, v) }
|
118
|
+
|
119
|
+
fill_polygon(global_vertices)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|