or2d 0.0.0
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/or2d/animation.rb +60 -0
- data/lib/or2d/animations/composite_animations.rb +160 -0
- data/lib/or2d/animations/entity_animations.rb +221 -0
- data/lib/or2d/composite.rb +73 -0
- data/lib/or2d/composites/projectile.rb +97 -0
- data/lib/or2d/composites/sprite.rb +245 -0
- data/lib/or2d/composites/text.rb +167 -0
- data/lib/or2d/console.rb +199 -0
- data/lib/or2d/entity.rb +78 -0
- data/lib/or2d/instance.rb +186 -0
- data/lib/or2d/patches/music.rb +30 -0
- data/lib/or2d/patches/renderable.rb +5 -0
- data/lib/or2d/patches/sound.rb +18 -0
- data/lib/or2d/patches/sprite.rb +20 -0
- data/lib/or2d/patches/window.rb +9 -0
- data/lib/or2d/resource.rb +182 -0
- data/lib/or2d/scene.rb +160 -0
- data/lib/or2d/scenes/placeholder_scene.rb +70 -0
- data/lib/or2d/version.rb +50 -0
- data/lib/or2d.rb +94 -0
- metadata +146 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
module OR2D
|
2
|
+
# The Instance object represents a single running instance of OR2D. It maintains a list of all entities in the
|
3
|
+
# current instance, and a list of all scenes in the current instance. It also maintains a reference to the current
|
4
|
+
# scene. There should only be one instance of OR2D::Instance at any given time.
|
5
|
+
class Instance
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
# @!attribute [r] entities
|
9
|
+
# @return [Hash] a hash of all entities in the game instance
|
10
|
+
attr_reader :entities
|
11
|
+
|
12
|
+
# @!attribute [r] scene
|
13
|
+
# @return [OR2D::Scene] the current scene
|
14
|
+
attr_reader :scene
|
15
|
+
|
16
|
+
# @!attribute [r] window
|
17
|
+
# @return [Ruby2D::Window] the game window
|
18
|
+
attr_reader :window
|
19
|
+
|
20
|
+
# @!attribute [r] modifiers
|
21
|
+
# @return [Array] the currently held modifier keys
|
22
|
+
attr_reader :modifiers
|
23
|
+
|
24
|
+
# @!attribute [r] mouse
|
25
|
+
# @return [OR2D::Mouse] the mouse state
|
26
|
+
attr_reader :mouse
|
27
|
+
|
28
|
+
# Constructs a new OR2D instance.
|
29
|
+
def initialize
|
30
|
+
super()
|
31
|
+
setup
|
32
|
+
end
|
33
|
+
|
34
|
+
# Run the game instance.
|
35
|
+
def run
|
36
|
+
@window.render do
|
37
|
+
@scene.render unless @scene.nil? || @scene.rendered? || @scene.finished?
|
38
|
+
rescue StandardError => e
|
39
|
+
puts "An error occurred while rendering the scene: #{e.message}"
|
40
|
+
puts e.backtrace if OR2D.debug?
|
41
|
+
end
|
42
|
+
|
43
|
+
@window.update do
|
44
|
+
process_animations
|
45
|
+
process_scene
|
46
|
+
rescue StandardError => e
|
47
|
+
puts "An error occurred while updating the scene: #{e.message}"
|
48
|
+
puts e.backtrace if OR2D.debug?
|
49
|
+
end
|
50
|
+
|
51
|
+
@window.show
|
52
|
+
end
|
53
|
+
|
54
|
+
# Schedule an animation for an entity.
|
55
|
+
def animate(entity_id, &_)
|
56
|
+
@animations[entity_id] ||= Set.new
|
57
|
+
@animations[entity_id].add(OR2D::Animation.new(entity_id, &_))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Adds a scene to the game instance.
|
61
|
+
# @param scene [OR2D::Scene] the scene to add
|
62
|
+
def add_scene(scene)
|
63
|
+
@scenes.add(scene)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Adds an entity to the game instance.
|
67
|
+
# @param entity [OR2D::Entity] the entity to add
|
68
|
+
def add_entity(entity)
|
69
|
+
@entities[entity.id] = entity
|
70
|
+
end
|
71
|
+
|
72
|
+
# Removes an entity from the game instance.
|
73
|
+
# @param entity_id [String] the ID of the entity to remove
|
74
|
+
# @return [OR2D::Entity] the removed entity
|
75
|
+
def remove_entity(entity_id)
|
76
|
+
@entities.delete(entity_id)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Is the current frame a key frame?
|
80
|
+
# @param frame [Integer] the key frame interval
|
81
|
+
# @return [Boolean] whether or not the current frame is a key frame
|
82
|
+
def key_frame?(frame = 60)
|
83
|
+
(@window.get(:frames) % frame).zero?
|
84
|
+
end
|
85
|
+
|
86
|
+
# Close the game instance.
|
87
|
+
def quit
|
88
|
+
@window.close
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def setup
|
94
|
+
@window = Ruby2D::Window.new(title: ENV['OR2D_TITLE'] || 'OR2D Game',
|
95
|
+
width: ENV['OR2D_WIDTH']&.to_i || OR2D.lowest_scalable_width,
|
96
|
+
height: ENV['OR2D_HEIGHT']&.to_i || OR2D.lowest_scalable_height,
|
97
|
+
vsync: ENV['OR2D_VSYNC'] || true)
|
98
|
+
|
99
|
+
@projectiles = Set.new
|
100
|
+
@animations = {}
|
101
|
+
@entities = {}
|
102
|
+
@modifiers = { shift: false, control: false, alt: false, meta: false, backspace: false }
|
103
|
+
@mouse = { left: false, right: false, middle: false }
|
104
|
+
@scenes = Set.new
|
105
|
+
|
106
|
+
@window.on(:key_up) do |event|
|
107
|
+
case event.key
|
108
|
+
when /shift/ then @modifiers[:shift] = false
|
109
|
+
when /ctrl|control/ then @modifiers[:control] = false
|
110
|
+
when /alt/ then @modifiers[:alt] = false
|
111
|
+
when /meta/ then @modifiers[:meta] = false
|
112
|
+
when /backspace/ then @modifiers[:backspace] = false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
@window.on(:key_held) do |event|
|
117
|
+
case event.key
|
118
|
+
when /shift/ then @modifiers[:shift] = true
|
119
|
+
when /ctrl|control/ then @modifiers[:control] = true
|
120
|
+
when /alt/ then @modifiers[:alt] = true
|
121
|
+
when /meta/ then @modifiers[:meta] = true
|
122
|
+
when /backspace/ then @modifiers[:backspace] = true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
@window.on(:mouse_down) do |event|
|
127
|
+
case event.button
|
128
|
+
when :left then @mouse[:left] = true
|
129
|
+
when :right then @mouse[:right] = true
|
130
|
+
when :middle then @mouse[:middle] = true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
@window.on(:mouse_up) do |event|
|
135
|
+
case event.button
|
136
|
+
when :left then @mouse[:left] = false
|
137
|
+
when :right then @mouse[:right] = false
|
138
|
+
when :middle then @mouse[:middle] = false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
Signal.trap('INT') do
|
143
|
+
Thread.new do
|
144
|
+
puts 'Caught SIGINT, exiting...'
|
145
|
+
quit
|
146
|
+
end.join
|
147
|
+
end
|
148
|
+
|
149
|
+
Signal.trap('TERM') do
|
150
|
+
Thread.new do
|
151
|
+
puts 'Caught SIGTERM, exiting...'
|
152
|
+
quit
|
153
|
+
end.join
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def process_animations
|
158
|
+
return if @animations.empty?
|
159
|
+
|
160
|
+
@animations.each do |id, bundle|
|
161
|
+
bundle.each(&:resume)
|
162
|
+
bundle.delete_if(&:complete?)
|
163
|
+
@animations.delete(id) if bundle.empty?
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def process_scene
|
168
|
+
if @scene.nil? || @scene.finished?
|
169
|
+
if @scenes.empty?
|
170
|
+
@scene = OR2D::Scenes::PlaceholderScene.new
|
171
|
+
else
|
172
|
+
@scene = @scenes.first
|
173
|
+
@scenes.delete(@scene)
|
174
|
+
end
|
175
|
+
|
176
|
+
@scene.render
|
177
|
+
end
|
178
|
+
|
179
|
+
@scene.update
|
180
|
+
rescue StandardError => e
|
181
|
+
puts "An error occurred while processing the current scene: #{e.message}"
|
182
|
+
puts e.backtrace if OR2D.debug?
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Ruby2D
|
2
|
+
class Music
|
3
|
+
|
4
|
+
attr :playing
|
5
|
+
|
6
|
+
def playing?
|
7
|
+
@playing
|
8
|
+
end
|
9
|
+
|
10
|
+
def play
|
11
|
+
@playing ||= true
|
12
|
+
ext_play
|
13
|
+
end
|
14
|
+
|
15
|
+
def pause
|
16
|
+
@playing = false
|
17
|
+
ext_pause
|
18
|
+
end
|
19
|
+
|
20
|
+
def resume
|
21
|
+
@playing = true
|
22
|
+
ext_resume
|
23
|
+
end
|
24
|
+
|
25
|
+
def stop
|
26
|
+
@playing = false
|
27
|
+
ext_stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ruby2D
|
2
|
+
class Sprite
|
3
|
+
|
4
|
+
attr_reader :animations, :defaults, :playing
|
5
|
+
|
6
|
+
# Explicitly set the frame of the Sprite.
|
7
|
+
# The animation hash is expected to be in either of the following formats:
|
8
|
+
# { animation_name: [frame_1, frame_2, ...] }
|
9
|
+
# { animation_name: frame_range }
|
10
|
+
# This function will grab the explicit frame index of the given animation and set it.
|
11
|
+
def set_explicit_frame(animation, frame = 0)
|
12
|
+
_set_explicit_frame(@animations[animation][frame])
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_frame(animation, frame = 0)
|
16
|
+
@defaults[:animation] = animation
|
17
|
+
@defaults[:frame] = frame
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# The Resource module contains helper methods for creating resources.
|
2
|
+
# @author Patrick W.
|
3
|
+
# @since 2023-04-20
|
4
|
+
module OR2D::Resource
|
5
|
+
|
6
|
+
# Construct a new resource of the given type with the passed options.
|
7
|
+
# @param type [Symbol] the type of resource to create
|
8
|
+
# @param options [Hash] the options to pass to the resource
|
9
|
+
def create(type, options)
|
10
|
+
case type
|
11
|
+
when :image then OR2D::Resource.create_image(options)
|
12
|
+
when :sprite then OR2D::Resource.create_sprite(options)
|
13
|
+
when :text then OR2D::Resource.create_text(options)
|
14
|
+
when :tileset then OR2D::Resource.create_tileset(options)
|
15
|
+
when :triangle then OR2D::Resource.create_triangle(options)
|
16
|
+
when :quad then OR2D::Resource.create_quad(options)
|
17
|
+
when :circle then OR2D::Resource.create_circle(options)
|
18
|
+
when :square then OR2D::Resource.create_square(options)
|
19
|
+
when :line then OR2D::Resource.create_line(options)
|
20
|
+
when :rectangle then OR2D::Resource.create_rectangle(options)
|
21
|
+
else raise "Unknown resource type: #{type}!"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a Ruby2D::Circle object from the given options.
|
26
|
+
# @param options [Hash] the options to pass to the Circle
|
27
|
+
# @return [Ruby2D::Circle] the created Circle
|
28
|
+
def create_circle(options)
|
29
|
+
Ruby2D::Circle.new(x: options[:x] || 0,
|
30
|
+
y: options[:y] || 0,
|
31
|
+
z: options[:z] || 0,
|
32
|
+
radius: options[:radius] || 50,
|
33
|
+
sectors: options[:sectors] || 30,
|
34
|
+
color: options[:color] || 'yellow',
|
35
|
+
opacity: options[:opacity] || 1.0)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Create a Ruby2D::Image object from the given options.
|
39
|
+
# @param options [Hash] the options to pass to the Image
|
40
|
+
# @return [Ruby2D::Image] the created Image
|
41
|
+
def create_image(options)
|
42
|
+
Ruby2D::Image.new(options[:path],
|
43
|
+
atlas: options[:atlas],
|
44
|
+
width: options[:width] * OR2D.scale || 4,
|
45
|
+
height: options[:height] * OR2D.scale || 4,
|
46
|
+
opacity: options[:opacity] || 1.0,
|
47
|
+
rotate: options[:rotate] || 0,
|
48
|
+
x: options[:x] || 0,
|
49
|
+
y: options[:y] || 0,
|
50
|
+
z: options[:z] || 0)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create a Ruby2D::Line object from the given options.
|
54
|
+
# @param options [Hash] the options to pass to the Line
|
55
|
+
# @return [Ruby2D::Line] the created Line
|
56
|
+
def create_line(options)
|
57
|
+
Ruby2D::Line.new(x1: options[:x1],
|
58
|
+
y1: options[:y1],
|
59
|
+
x2: options[:x2],
|
60
|
+
y2: options[:y2],
|
61
|
+
z: options[:z],
|
62
|
+
width: options[:width] * OR2D.scale || 2,
|
63
|
+
color: options[:color] || 'yellow',
|
64
|
+
opacity: options[:opacity] || 1.0)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Create a Ruby2D::Rectangle object from the given options.
|
68
|
+
# @param options [Hash] the options to pass to the Rectangle
|
69
|
+
# @return [Ruby2D::Rectangle] the created Rectangle
|
70
|
+
def create_rectangle(options)
|
71
|
+
Ruby2D::Rectangle.new(x: options[:x] || 0,
|
72
|
+
y: options[:y] || 0,
|
73
|
+
z: options[:z] || 0,
|
74
|
+
width: options[:width] * OR2D.scale,
|
75
|
+
height: options[:height] * OR2D.scale,
|
76
|
+
color: options[:color] || 'yellow',
|
77
|
+
opacity: options[:opacity] || 1.0)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Create a Ruby2D::Sprite object from the given options.
|
81
|
+
# @param options [Hash] the options to pass to the Sprite
|
82
|
+
# @return [Ruby2D::Sprite] the created Sprite
|
83
|
+
def create_sprite(options)
|
84
|
+
Ruby2D::Sprite.new(options[:path],
|
85
|
+
atlas: options[:atlas],
|
86
|
+
width: options[:width] ? options[:width] * OR2D.scale : nil,
|
87
|
+
height: options[:height] ? options[:height] * OR2D.scale : nil,
|
88
|
+
rotate: options[:rotate] || 0,
|
89
|
+
opacity: options[:opacity] || 1.0,
|
90
|
+
loop: options[:loop] || false,
|
91
|
+
time: options[:time] || 100,
|
92
|
+
animations: options[:animations] || {},
|
93
|
+
default: options[:default] || 0,
|
94
|
+
clip_height: options[:clip_height],
|
95
|
+
clip_width: options[:clip_width],
|
96
|
+
clip_x: options[:clip_x] || 0,
|
97
|
+
clip_y: options[:clip_y] || 0,
|
98
|
+
x: options[:x] || 0,
|
99
|
+
y: options[:y] || 0,
|
100
|
+
z: options[:z] || 0)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create a Ruby2D::Square object from the given options.
|
104
|
+
# @param options [Hash] the options to pass to the Square
|
105
|
+
# @return [Ruby2D::Square] the created Square
|
106
|
+
def create_square(options)
|
107
|
+
Ruby2D::Square.new(x: options[:x] || 0,
|
108
|
+
y: options[:y] || 0,
|
109
|
+
z: options[:z] || 0,
|
110
|
+
size: options[:size],
|
111
|
+
color: options[:color] || 'yellow',
|
112
|
+
opacity: options[:opacity] || 1.0)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Create a Ruby2D::Text object from the given options.
|
116
|
+
# @param options [Hash] the options to pass to the Text
|
117
|
+
# @return [Ruby2D::Text] the created Text
|
118
|
+
def create_text(options)
|
119
|
+
Ruby2D::Text.new(options[:text],
|
120
|
+
x: options[:x] || 0,
|
121
|
+
y: options[:y] || 0,
|
122
|
+
z: options[:z] || 0,
|
123
|
+
size: (options[:size] || 16) * OR2D.scale,
|
124
|
+
style: options[:style],
|
125
|
+
font: options[:font] || Ruby2D::Font.default,
|
126
|
+
color: options[:color] || 'yellow',
|
127
|
+
rotate: options[:rotate] || 0,
|
128
|
+
opacity: options[:opacity] || 1.0)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Create a Ruby2D::Tileset object from the given options.
|
132
|
+
# @param options [Hash] the options to pass to the Tileset
|
133
|
+
# @return [Ruby2D::Tileset] the created Tileset
|
134
|
+
def create_tileset(options)
|
135
|
+
Ruby2D::Tileset.new(options[:path],
|
136
|
+
tile_width: options[:tile_width] || 16,
|
137
|
+
tile_height: options[:tile_height] || 16,
|
138
|
+
width: options[:width],
|
139
|
+
height: options[:height],
|
140
|
+
z: options[:z] || 100,
|
141
|
+
padding: options[:padding] || 0,
|
142
|
+
spacing: options[:spacing] || 0,
|
143
|
+
scale: options[:scale] || 1,
|
144
|
+
show: options[:show] || false)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Create a Ruby2D::Triangle object from the given options.
|
148
|
+
# @param options [Hash] the options to pass to the Triangle
|
149
|
+
# @return [Ruby2D::Triangle] the created Triangle
|
150
|
+
def create_triangle(options)
|
151
|
+
Ruby2D::Triangle.new(x1: options[:x1],
|
152
|
+
y1: options[:y1],
|
153
|
+
x2: options[:x2],
|
154
|
+
y2: options[:y2],
|
155
|
+
x3: options[:x3],
|
156
|
+
y3: options[:y3],
|
157
|
+
z: options[:z],
|
158
|
+
color: options[:color] || 'yellow',
|
159
|
+
opacity: options[:opacity] || 1.0)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Create a Ruby2D::Quad object from the given options.
|
163
|
+
# @param options [Hash] the options to pass to the Quad
|
164
|
+
# @return [Ruby2D::Quad] the created Quad
|
165
|
+
def create_quad(options)
|
166
|
+
Ruby2D::Quad.new(x1: options[:x1],
|
167
|
+
y1: options[:y1],
|
168
|
+
x2: options[:x2],
|
169
|
+
y2: options[:y2],
|
170
|
+
x3: options[:x3],
|
171
|
+
y3: options[:y3],
|
172
|
+
x4: options[:x4],
|
173
|
+
y4: options[:y4],
|
174
|
+
z: options[:z],
|
175
|
+
color: options[:color] || 'yellow',
|
176
|
+
opacity: options[:opacity] || 1.0)
|
177
|
+
end
|
178
|
+
|
179
|
+
class << self
|
180
|
+
include OR2D::Resource
|
181
|
+
end
|
182
|
+
end
|
data/lib/or2d/scene.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
module OR2D
|
2
|
+
# A Scene object represents a single scene in an OR2D instance. Each Scene maintains two internal lists to keep
|
3
|
+
# track of the visibility state of Entities in the scene. It provides 3 functions to control how the Scene is updated,
|
4
|
+
# rendered, and whether or not it should be redrawn. It is recommended to use inheritance to create new scenes.
|
5
|
+
# @example Inheritance
|
6
|
+
# class MyScene < OR2D::Scene
|
7
|
+
# def initialize
|
8
|
+
# super('my_scene')
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# private
|
12
|
+
#
|
13
|
+
# def setup_render
|
14
|
+
# super do
|
15
|
+
# # Render code here
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def setup_update
|
20
|
+
# super do
|
21
|
+
# # Update code here
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def setup_redraw
|
26
|
+
# super do
|
27
|
+
# # Redraw code here
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# @author Patrick W.
|
33
|
+
# @since 2023-04-12
|
34
|
+
class Scene
|
35
|
+
|
36
|
+
# @!attribute [r] id
|
37
|
+
# @return [String] the ID of the scene
|
38
|
+
attr_reader :id
|
39
|
+
|
40
|
+
# Constructs a new Scene object.
|
41
|
+
# @param id [String] the ID of the scene
|
42
|
+
# @param procs [Hash] a hash of procs to be used for the scene
|
43
|
+
def initialize(id, procs = {})
|
44
|
+
@id = id
|
45
|
+
@descriptors = {}
|
46
|
+
@workers = {}
|
47
|
+
@visible = Set.new
|
48
|
+
@hidden = Set.new
|
49
|
+
@rendered = false
|
50
|
+
@finish = false
|
51
|
+
|
52
|
+
procs[:redraw?].nil? ? setup_redraw : setup_redraw(&procs[:redraw?])
|
53
|
+
procs[:update].nil? ? setup_update : setup_update(&procs[:update])
|
54
|
+
procs[:render].nil? ? setup_render : setup_render(&procs[:render])
|
55
|
+
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# Updates the scene.
|
60
|
+
def update
|
61
|
+
@workers[:update].resume(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Render the scene.
|
65
|
+
def render
|
66
|
+
@workers[:render].resume
|
67
|
+
end
|
68
|
+
|
69
|
+
# Should the scene be redrawn?
|
70
|
+
# @return [Boolean] true if the scene should be redrawn, false otherwise
|
71
|
+
def redraw?
|
72
|
+
@workers[:redraw?].resume
|
73
|
+
end
|
74
|
+
|
75
|
+
# Finishes the scene.
|
76
|
+
def finish
|
77
|
+
@descriptors.each_value { |descriptor| OR2D.game.window.off(descriptor) }
|
78
|
+
@finish = true
|
79
|
+
end
|
80
|
+
|
81
|
+
# Has the scene finished?
|
82
|
+
# @return [Boolean] true if the scene has finished, false otherwise
|
83
|
+
def finished?
|
84
|
+
@finish
|
85
|
+
end
|
86
|
+
|
87
|
+
# Has the scene been rendered?
|
88
|
+
def rendered?
|
89
|
+
@rendered
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Halts the running fiber, stopping the scene.
|
95
|
+
def halt
|
96
|
+
Fiber.yield
|
97
|
+
end
|
98
|
+
|
99
|
+
# Setup event descriptors.
|
100
|
+
def setup_descriptor(label, event, &block)
|
101
|
+
@descriptors[label] = OR2D.game.window.on(event, &block)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Setup the Scene's render worker.
|
105
|
+
def setup_render(&_)
|
106
|
+
@workers[:render] = Fiber.new do
|
107
|
+
loop do
|
108
|
+
break if finished?
|
109
|
+
|
110
|
+
@visible.each { |entity_id| OR2D::Game.source.add(OR2D::Game.entities[entity_id]) }
|
111
|
+
@hidden.each { |entity_id| OR2D::Game.source.remove(OR2D::Game.entities[entity_id]) }
|
112
|
+
|
113
|
+
yield if block_given?
|
114
|
+
rescue StandardError => e
|
115
|
+
puts e.message
|
116
|
+
puts e.backtrace if OR2D.debug?
|
117
|
+
ensure
|
118
|
+
@rendered = true
|
119
|
+
Fiber.yield unless finished?
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Setup the Scene's update worker.
|
125
|
+
def setup_update(&_)
|
126
|
+
@workers[:update] = Fiber.new do |scene|
|
127
|
+
loop do
|
128
|
+
break if finished?
|
129
|
+
|
130
|
+
yield(scene) if block_given?
|
131
|
+
rescue StandardError => e
|
132
|
+
puts e.message
|
133
|
+
puts e.backtrace if OR2D.debug?
|
134
|
+
ensure
|
135
|
+
Fiber.yield unless finished?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Setup the Scene's redraw? worker.
|
141
|
+
def setup_redraw(&_)
|
142
|
+
@workers[:redraw?] = Fiber.new do
|
143
|
+
loop do
|
144
|
+
break if finished?
|
145
|
+
|
146
|
+
if rendered? && block_given?
|
147
|
+
Fiber.yield(yield)
|
148
|
+
elsif rendered?
|
149
|
+
Fiber.yield(true)
|
150
|
+
else
|
151
|
+
Fiber.yield(false)
|
152
|
+
end
|
153
|
+
rescue StandardError => e
|
154
|
+
puts e.message
|
155
|
+
puts e.backtrace if OR2D.debug?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module OR2D::Scenes
|
2
|
+
# The PlaceholderScene class is a placeholder scene for the OR2D gem. When no other scenes are enqueued or displayed, this scene will be displayed.
|
3
|
+
class PlaceholderScene < OR2D::Scene
|
4
|
+
|
5
|
+
# Construct a new PlaceholderScene object.
|
6
|
+
def initialize
|
7
|
+
super('PLACEHOLDER_SCENE')
|
8
|
+
@cursor_position = OR2D::Entity.new(:text, { color: 'white', x: 0, y: 0, size: 16, height: 16, width: 16 })
|
9
|
+
|
10
|
+
setup_events
|
11
|
+
setup_console
|
12
|
+
end
|
13
|
+
|
14
|
+
# Complete processing of the scene
|
15
|
+
def finish
|
16
|
+
@console.remove
|
17
|
+
@cursor_position.destroy
|
18
|
+
@descriptors.each_value { |descriptor| OR2D.game.window.off(descriptor) }
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def setup_console
|
25
|
+
@console = OR2D::Console.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup_render
|
29
|
+
super do
|
30
|
+
@cursor_position.show
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_update
|
35
|
+
super do
|
36
|
+
@cursor_position.x = OR2D.game.window.get(:mouse_x)
|
37
|
+
@cursor_position.y = OR2D.game.window.get(:mouse_y)
|
38
|
+
@console.update
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup_events
|
43
|
+
setup_descriptor(:mouse_input, :mouse) do |event|
|
44
|
+
@cursor_position.resource.text = "[x: #{event.x}, y: #{event.y}]"
|
45
|
+
@cursor_position.width = @cursor_position.resource.text.length * (6 * OR2D.scale)
|
46
|
+
end
|
47
|
+
|
48
|
+
setup_descriptor(:debug_input, :key_up) do |event|
|
49
|
+
case event.key
|
50
|
+
when 'g' then @cursor_position.grow(factor: 0.2)
|
51
|
+
when 'z' then @cursor_position.shrink(factor: 0.2)
|
52
|
+
when 't' then @cursor_position.fade(speed: 0.01)
|
53
|
+
when 'r'
|
54
|
+
if OR2D.game.modifiers[:control]
|
55
|
+
OR2D.game.entities.each_value(&:rotate) && @cursor_position.rotate
|
56
|
+
elsif OR2D.game.modifiers[:meta]
|
57
|
+
@cursor_position.rotation(speed: 1.0, angle: 360, clockwise: false)
|
58
|
+
else
|
59
|
+
@cursor_position.rotation(speed: 1.0, angle: 360, clockwise: true)
|
60
|
+
end
|
61
|
+
when 'b'
|
62
|
+
if OR2D.game.modifiers[:control]
|
63
|
+
OR2D.game.entities.each_value(&:toggle_boundary) && @cursor_position.toggle_boundary
|
64
|
+
end
|
65
|
+
when 'escape' then finish
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|