or2d 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|