author_engine 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 240a86f7ca8210f55b1000684999a28d178bb8aee05816924c09987279930acb
4
- data.tar.gz: b020c530b4e217ff3b2c6fa8f956eae3a7faef8c3e07de8226fdbd239a0adec9
3
+ metadata.gz: cdf3e00f6f0e8840311bc2fb5c77c7dfe56c0bf9de8efa7cb310468b649d4ff4
4
+ data.tar.gz: b32cfb362b8bdfe3c408ac8e113082c94c68faaa2475afbc91b8e97ffdee2ffe
5
5
  SHA512:
6
- metadata.gz: 979bd0fc59a1767dede59ca38f1ac63965beb8c538c95c25fd824d7d5c0b4449508d83f4dec6bc2e4b0d8c046f37f35c1995da4f2460e4d9562534d59b4e41fd
7
- data.tar.gz: d105fe0793a73d82bb36c69623a031ad0a45ffd0dfbae4027a55e4a77e05bcd75be360fc9fa8427080a2ab1dc4f993f87065a63b0fdbb7e1ec89c99dbc2649d6
6
+ metadata.gz: 0ddf727d607cd61cf2aa34551c8489cc8af8af44c26c263eed9faac1f0ac7ff0563ccbe8ea400a4762d050f08f6a76e40d874484770ee833d28340de3bdb66fd
7
+ data.tar.gz: 91335c5c61622bb198535bb62bd15b5ad3db5eb10f2aa290dfc3b7ff7bc05e96b5ed270834eca6ee25721d1ace97bd30c9587746eabaa3f4217cfd236a8d7560
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- author_engine (0.5.0)
4
+ author_engine (0.6.0)
5
5
  coderay (~> 1.1.2)
6
6
  gosu (~> 0.14.4)
7
7
  opal (~> 0.11.4)
@@ -2,8 +2,17 @@ class AuthorEngine
2
2
  class Loader < Container
3
3
  Project = Struct.new(:name, :block)
4
4
  def setup
5
- @root_directory = Dir.pwd#"#{Dir.home}/AuthorEngineProjects"
6
- Dir.mkdir(@root_directory) unless File.exists?(@root_directory)
5
+ if ARGV[0] && File.exists?(ARGV[0]) && Gosu.milliseconds < 1500
6
+ if ARGV[0].end_with?(".authorengine")
7
+ load(ARGV[0])
8
+ return
9
+ elsif File.directory?(ARGV[0])
10
+ @root_directory = ARGV[0]
11
+ else
12
+ puts "AuthorEngine: #{ARGV[0]} is not a compatible file."
13
+ end
14
+ end
15
+ @root_directory ||= Dir.pwd #"#{Dir.home}/AuthorEngineProjects"
7
16
 
8
17
  @list = []
9
18
  @files = Dir.glob(@root_directory+"/*.authorengine")
@@ -27,13 +36,9 @@ class AuthorEngine
27
36
  end
28
37
  @new_button.x = window.width - @new_button.width
29
38
 
30
- if ARGV[0] && File.exists?(ARGV[0])
31
- if ARGV[0].end_with?(".authorengine")
32
- load(ARGV[0])
33
- else
34
- puts "AuthorEngine: #{ARGV[0]} is not a compatible file."
35
- end
36
- end
39
+ @draw_caret = true
40
+ @last_caret_update = Gosu.milliseconds
41
+ @caret_interval = 500
37
42
  end
38
43
 
39
44
  def load(filename)
@@ -53,8 +58,23 @@ class AuthorEngine
53
58
  end
54
59
 
55
60
  def draw_inputter
61
+ caret_x = @font.text_width(window.text_input.text[0..window.text_input.caret_pos-1])
62
+ caret_x = 0 if window.text_input.caret_pos == 0
63
+ if Gosu.milliseconds > @last_caret_update + @caret_interval
64
+ @draw_caret = !@draw_caret
65
+ @last_caret_update = Gosu.milliseconds
66
+ end
67
+
56
68
  x = window.width/2 - @font.text_width(window.text_input.text+".authorengine")/2
69
+ error_x = window.width/2 - @font.text_width(window.text_input.text.strip+".authorengine already exists!")/2
57
70
  y = window.height/2 - @font.height/2
71
+
72
+ Gosu.draw_rect(x+caret_x, y, 2, @font.height, Gosu::Color::WHITE) if @draw_caret
73
+ if window.text_input.text.strip+".authorengine" == @name_exists
74
+ @font.draw_text(window.text_input.text.strip+".authorengine already exists!", error_x, y - 32, 0, 1,1, red) if @name_exists
75
+ else
76
+ @name_exists = false
77
+ end
58
78
  @font.draw_text(window.text_input.text+".authorengine", x, y, 0)
59
79
  end
60
80
 
@@ -100,12 +120,22 @@ class AuthorEngine
100
120
  @index = 0 if @list.size == 0
101
121
  @index = @index % @list.size-1 if @list.size != 0
102
122
  when Gosu::KbEnter, Gosu::KbReturn
123
+ filename = window.text_input.text.strip if window.text_input
124
+
103
125
  if @entering_name
104
- SaveFile.create(window.text_input.text.strip+".authorengine")
105
- load(window.text_input.text.strip+".authorengine")
126
+ if File.exists?(filename)
127
+ @name_exists = filename
128
+ else
129
+ window.text_input = nil
130
+ savefile = SaveFile.create(filename+".authorengine")
131
+ load(filename+".authorengine")
132
+ end
106
133
  else
107
134
  @list[@index].block.call if @list[@index]&.block
108
135
  end
136
+ when Gosu::KbEscape
137
+ @entering_name = false
138
+ window.text_input = nil
109
139
  end
110
140
  end
111
141
  end
@@ -1,14 +1,17 @@
1
1
  class AuthorEngine
2
2
  class Part
3
3
  module Common
4
+ # returns display width
4
5
  def width
5
6
  128
6
7
  end
7
8
 
9
+ # returns display height
8
10
  def height
9
11
  128
10
12
  end
11
13
 
14
+ # returns frames per seconds
12
15
  def fps
13
16
  if RUBY_ENGINE == "opal"
14
17
  AuthorEngine::GameRunner.instance.fps
@@ -17,6 +20,14 @@ class AuthorEngine
17
20
  end
18
21
  end
19
22
 
23
+ def distance(x1, y1, x2, y2)
24
+ dx = x2 - x1
25
+ dy = y2 - y1
26
+
27
+ Math.sqrt(dx * dx + dy * dy)
28
+ end
29
+
30
+ # returns number of milliseconds since game started
20
31
  def milliseconds
21
32
  if RUBY_ENGINE == "opal"
22
33
  @__initial_milliseconds ||= `performance.now()`
@@ -44,38 +44,18 @@ class AuthorEngine
44
44
  @game.init
45
45
 
46
46
  @show_touch_controls = false
47
+ @touch_joystick = TouchJoystick.new(x: 100, radius: 50, side: :left)
47
48
  @touch_buttons = []
48
- buttons = AuthorEngine::Part::OpalInput::BUTTONS
49
- key_states = AuthorEngine::Part::OpalInput::KEY_STATES
50
49
  @touch_buttons.push(
51
50
  TouchButton.new(
52
- label: "Up", color: @game.dark_gray, x: 137, y: `window.innerHeight/2 - #{125}`, width: 50, height: 50, side: :left,
53
- contact_proc: proc { key_states[buttons["up"]] = true}, no_contact_proc: proc { key_states[buttons["up"]] = false}
54
- ),
51
+ label: "X", color: @game.red, x: 50, width: 50, height: 50, side: :right, for_key: "x"
52
+ ),
55
53
  TouchButton.new(
56
- label: "Down", color: @game.dark_gray, x: 137, y: `window.innerHeight/2 + 25`, width: 50, height: 50, side: :left,
57
- contact_proc: proc { key_states[buttons["down"]] = true}, no_contact_proc: proc { key_states[buttons["down"]] = false}
58
- ),
59
-
60
- TouchButton.new(
61
- label: "Left", color: @game.black, x: 175, width: 50, height: 50, side: :left,
62
- contact_proc: proc { key_states[buttons["left"]] = true}, no_contact_proc: proc { key_states[buttons["left"]] = false}
63
- ),
64
- TouchButton.new(
65
- label: "Right", color: @game.black, x: 100, width: 50, height: 50, side: :left,
66
- contact_proc: proc { key_states[buttons["right"]] = true}, no_contact_proc: proc { key_states[buttons["right"]] = false}
67
- ),
68
-
69
-
70
- TouchButton.new(
71
- label: "X", color: @game.red, x: 50, width: 50, height: 50, side: :right,
72
- contact_proc: proc { key_states[buttons["x"]] = true}, no_contact_proc: proc { key_states[buttons["x"]] = false}
73
- ),
74
- TouchButton.new(
75
- label: "Y", color: @game.yellow, x: 125, width: 50, height: 50, side: :right,
76
- contact_proc: proc { key_states[buttons["y"]] = true}, no_contact_proc: proc { key_states[buttons["y"]] = false}
54
+ label: "Y", color: @game.yellow, x: 125, width: 50, height: 50, side: :right, for_key: "y"
77
55
  )
78
56
  )
57
+
58
+ @fullscreen_button = TouchButton.new(label: "Fullscreen", color: @game.black, x: 50, y: 10, width: 100, height: 50, side: :right)
79
59
  touch_handler_setup
80
60
 
81
61
  return self
@@ -95,6 +75,8 @@ class AuthorEngine
95
75
  def run_game
96
76
  `window.requestAnimationFrame(function() {#{run_game}})` # placed here to ensure next frame is called even if draw or update throw an error
97
77
  `#{@game.canvas_context}.clearRect(0,0, window.innerWidth, window.innerHeight)`
78
+ `#{@game.canvas_context}.fillStyle = "#222"`
79
+ `#{@game.canvas_context}.fillRect(0,0, window.innerWidth, window.innerHeight)`
98
80
 
99
81
  @counted_frames+=1
100
82
 
@@ -139,22 +121,17 @@ class AuthorEngine
139
121
  end
140
122
 
141
123
  def draw_touch_controls
124
+ @fullscreen_button.draw
142
125
  @touch_buttons.each(&:draw)
126
+ @touch_joystick.draw
143
127
  end
144
128
 
145
129
  def update_touch_controls
146
- active_buttons = []
147
-
148
- @touch_buttons.each do |button|
149
- @current_touches.each do |id, touch|
150
- if touch.x.between?(button.x, button.x+button.width) && touch.y.between?(button.y, button.y+button.height)
151
- active_buttons << button
152
- button.active
153
- end
154
- end
155
- end
130
+ @touch_buttons.each { |button| button.trigger?(@current_touches) }
131
+ @touch_joystick.update(@current_touches)
132
+ end
156
133
 
157
- (@touch_buttons - active_buttons).each(&:inactive)
134
+ def reposition_touch_controls
158
135
  end
159
136
 
160
137
  def resize_canvas
@@ -173,6 +150,8 @@ class AuthorEngine
173
150
  `#{@game.canvas}.style.height = #{height}`
174
151
 
175
152
  `#{@game.canvas_context}.imageSmoothingEnabled = false`
153
+
154
+ reposition_touch_controls
176
155
  return nil
177
156
  end
178
157
 
@@ -221,19 +200,26 @@ class AuthorEngine
221
200
  return nil
222
201
  end
223
202
 
203
+ def fullscreen_changed
204
+ resize_canvas
205
+ end
206
+
224
207
  def show(update_interval = (1000.0 / 60))
225
208
  return unless RUBY_ENGINE == "opal"
226
209
 
227
210
  `window.addEventListener('resize', () => { #{resize_canvas} })`
228
- `document.addEventListener('keydown', (event) => { #{AuthorEngine::Part::OpalInput::KEY_STATES[`event.key`] = true} })`
211
+ `document.addEventListener('keydown', (event) => { #{@show_touch_controls = false; AuthorEngine::Part::OpalInput::KEY_STATES[`event.key`] = true} })`
229
212
  `document.addEventListener('keyup', (event) => { #{AuthorEngine::Part::OpalInput::KEY_STATES[`event.key`] = false} })`
230
213
 
231
- `#{@game.canvas}.addEventListener('touchstart', (event) => { #{@show_touch_controls = true; handle_touch_start(`event`); puts "Touch started..."} })`
232
- `#{@game.canvas}.addEventListener('touchmove', (event) => { #{handle_touch_move(`event`); puts "Touch moved..."} })`
233
- `#{@game.canvas}.addEventListener('touchcancel', (event) => { #{handle_touch_cancel(`event`); puts "Touch canceled."} })`
234
- `#{@game.canvas}.addEventListener('touchend', (event) => { #{handle_touch_end(`event`); puts "Touch Ended."} })`
214
+ `#{@game.canvas}.addEventListener('touchstart', (event) => { #{@show_touch_controls = true; handle_touch_start(`event`)} })`
215
+ `#{@game.canvas}.addEventListener('touchmove', (event) => { #{handle_touch_move(`event`)} })`
216
+ `#{@game.canvas}.addEventListener('touchcancel', (event) => { #{handle_touch_cancel(`event`)} })`
217
+ `#{@game.canvas}.addEventListener('touchend', (event) => { #{handle_touch_end(`event`)} })`
218
+
219
+ `#{@game.canvas}.addEventListener('fullscreenchange', () => { #{fullscreen_changed} })`
235
220
 
236
221
  `document.getElementById('loading').style.display = "none"`
222
+
237
223
  `window.requestAnimationFrame(function() {#{run_game}})`
238
224
  return nil
239
225
  end
@@ -45,7 +45,7 @@ class AuthorEngine
45
45
  _level = AuthorEngine::GameRunner.instance.levels[level]
46
46
  raise "No level at '#{index}'!" unless _level
47
47
  raise "No sprite at '#{current_sprite}'!" unless AuthorEngine::GameRunner.instance.sprites[current_sprite]
48
- raise "No sprite at '#{current_sprite}'!" unless AuthorEngine::GameRunner.instance.sprites[replacement_sprite]
48
+ raise "No sprite at '#{replacement_sprite}'!" unless AuthorEngine::GameRunner.instance.sprites[replacement_sprite]
49
49
 
50
50
  _level.each {|sprite| sprite.sprite = replacement_sprite if sprite.sprite == current_sprite}
51
51
  end
@@ -1,9 +1,13 @@
1
1
  class AuthorEngine
2
2
  class TouchButton
3
3
  attr_reader :x, :y, :width, :height
4
- def initialize(label:, color:, x:, y: nil, width:, height:, side:, contact_proc:, no_contact_proc:)
4
+ def initialize(label:, color:, x:, y: nil, width:, height:, side:, for_key: nil, &block)
5
5
  @label, @color, @x, @y, @width, @height = label, color, x, y, width, height
6
- @side, @contact_proc, @no_contact_proc = side, contact_proc, no_contact_proc
6
+ @side, @for_key = side, for_key
7
+ @block = block
8
+
9
+ @buttons = AuthorEngine::Part::OpalInput::BUTTONS
10
+ @key_states = AuthorEngine::Part::OpalInput::KEY_STATES
7
11
 
8
12
  @game = AuthorEngine::GameRunner.instance.game
9
13
  @game_width = 128 * @game.scale
@@ -17,20 +21,46 @@ class AuthorEngine
17
21
  raise "side must be :left or :right"
18
22
  end
19
23
 
20
- @y = `window.innerHeight/2 - #{height}` unless @y.is_a?(Numeric)
24
+ @y = `window.innerHeight/2 - #{height/2}` unless @y.is_a?(Numeric)
21
25
  end
22
26
 
23
27
  def draw
24
28
  `#{@game.canvas_context}.fillStyle = #{@color}`
25
- `#{@game.canvas_context}.fillRect(#{@x}, #{@y}, #{width}, #{width})`
29
+ `#{@game.canvas_context}.fillRect(#{@x}, #{@y}, #{@width}, #{@height})`
30
+
31
+ font = "#{@height}px Connection, Consolas"
32
+ `#{@game.canvas_context}.font = #{font}`
33
+ `#{@game.canvas_context}.fillStyle = "white"`
34
+ `#{@game.canvas_context}.textBaseline = "top"`
35
+ `#{@game.canvas_context}.fillText(#{@label}, #{@x}, #{@y}, #{@width})`
36
+ end
37
+
38
+ def trigger?(touches)
39
+ triggered = false
40
+
41
+ touches.detect do |id, touch|
42
+ if touch.x.between?(@x, @x+@width) && touch.y.between?(@y, @y+@height)
43
+ triggered = true
44
+ end
45
+ end
46
+
47
+
48
+ if @for_key
49
+ active if triggered
50
+ inactive unless triggered
51
+ else
52
+ @block.call if @block && triggered
53
+ end
54
+
55
+ return triggered
26
56
  end
27
57
 
28
58
  def active
29
- @contact_proc.call
59
+ @key_states[@buttons[@for_key]] = true
30
60
  end
31
61
 
32
62
  def inactive
33
- @no_contact_proc.call
63
+ @key_states[@buttons[@for_key]] = false
34
64
  end
35
65
  end
36
66
  end
@@ -1,12 +1,21 @@
1
1
  class AuthorEngine
2
2
  module TouchHandler
3
- Touch = Struct.new(:x, :y)
3
+ Touch = Struct.new(:origin_x, :origin_y, :x, :y)
4
4
  def touch_handler_setup
5
5
  @current_touches = {}
6
6
  end
7
7
 
8
8
  def copy_touch(touch)
9
- Touch.new(`touch.pageX`, `touch.pageY`)
9
+ Touch.new(`touch.pageX`, `touch.pageY`, `touch.pageX`, `touch.pageY`)
10
+ end
11
+
12
+ def set_touch(touch)
13
+ struct = @current_touches[`#{touch}.identifier`]
14
+
15
+ struct.x = `#{touch}.pageX`
16
+ struct.y = `#{touch}.pageY`
17
+
18
+ return nil
10
19
  end
11
20
 
12
21
  def handle_touch_start(event)
@@ -17,6 +26,14 @@ class AuthorEngine
17
26
  #{@current_touches[`touches[i].identifier`] = copy_touch(`touches[i]`)}
18
27
  }`
19
28
 
29
+ if @fullscreen_button && @fullscreen_button.trigger?(@current_touches)
30
+ `if (document.fullscreenElement == null && #{@game.canvas}.requestFullscreen) {
31
+ #{game.canvas}.requestFullscreen()
32
+ } else if(document.fullscreenElement != null && document.exitFullscreen) {
33
+ document.exitFullscreen()
34
+ } `
35
+ end
36
+
20
37
  return nil
21
38
  end
22
39
 
@@ -25,7 +42,7 @@ class AuthorEngine
25
42
 
26
43
  touches = `#{event}.changedTouches`
27
44
  `for (var i = 0; i < #{touches}.length; i++) {
28
- #{@current_touches[`touches[i].identifier`] = copy_touch(`touches[i]`)}
45
+ #{set_touch(`touches[i]`)}
29
46
  }`
30
47
 
31
48
  return nil
@@ -0,0 +1,122 @@
1
+ class AuthorEngine
2
+ class TouchJoystick
3
+ def initialize(x:, y: nil, radius:, side:, background: nil, color: nil)
4
+ @x, @y, @radius, @side, @background, @color = x, y, radius, side, background, color
5
+
6
+ @buttons = AuthorEngine::Part::OpalInput::BUTTONS
7
+ @key_states = AuthorEngine::Part::OpalInput::KEY_STATES
8
+
9
+ @game = AuthorEngine::GameRunner.instance.game
10
+ @game_width = 128 * @game.scale
11
+ @game_x = `window.innerWidth/2 - #{@game_width/2}`
12
+
13
+ if @side == :left
14
+ @x = @game_x-@x
15
+ elsif @side == :right
16
+ @x = @game_x+@game_width+@x
17
+ else
18
+ raise "side must be :left or :right"
19
+ end
20
+
21
+ @y = `window.innerHeight/2` unless @y.is_a?(Numeric)
22
+ @color = @game.dark_gray unless @color
23
+ @background = @game.light_gray unless @background
24
+
25
+ @joystick_x, @joystick_y, @joystick_radius = @x, @y, @radius/2
26
+ end
27
+
28
+ def draw
29
+ # Background
30
+ `#{@game.canvas_context}.fillStyle = #{@background}`
31
+ `#{@game.canvas_context}.beginPath()`
32
+ `#{@game.canvas_context}.arc(#{@x}, #{@y}, #{@radius}, 0, 2 * Math.PI)`
33
+ `#{@game.canvas_context}.fill()`
34
+
35
+ # Joystick
36
+ `#{@game.canvas_context}.beginPath()`
37
+ `#{@game.canvas_context}.fillStyle = #{@color}`
38
+ `#{@game.canvas_context}.arc(#{@joystick_x}, #{@joystick_y}, #{@joystick_radius}, 0, 2 * Math.PI)`
39
+ `#{@game.canvas_context}.fill()`
40
+
41
+ return nil
42
+ end
43
+
44
+ def circles_collide?(x,y, radius, x2,y2, radius2)
45
+ radii = radius + radius2
46
+
47
+ if @game.distance(x,y, x2,y2) < radii
48
+ return true
49
+ else
50
+ return false
51
+ end
52
+ end
53
+
54
+ def update(touches)
55
+ touch_detected = false
56
+
57
+ touches.detect do |id, touch|
58
+ if circles_collide?(@x, @y, @radius, touch.origin_x, touch.origin_y, 1)
59
+ touch_detected = true
60
+
61
+ _distance = @game.distance(@x,@y, touch.x,touch.y).clamp(0, @radius)
62
+ _direction = Math.atan2(touch.y - @y, touch.x - @x)
63
+
64
+ @joystick_x = @x +(_distance * Math.cos(_direction))
65
+ @joystick_y = @y +(_distance * Math.sin(_direction))
66
+
67
+ return true
68
+ end
69
+ end
70
+
71
+
72
+ unless touch_detected
73
+ @joystick_x = @x
74
+ @joystick_y = @y
75
+ end
76
+
77
+ trigger_input
78
+
79
+ return nil
80
+ end
81
+
82
+ def trigger_input(threshold = 0.35)
83
+ threshold = @radius * threshold
84
+
85
+ if @joystick_x != @x || @joystick_y != @y
86
+ if (@x - @joystick_x) < -threshold
87
+ set("right", true)
88
+ else
89
+ set("right", false)
90
+ end
91
+
92
+ if (@x - @joystick_x) > threshold
93
+ set("left", true)
94
+ else
95
+ set("left", false)
96
+ end
97
+
98
+ if (@y - @joystick_y) < -threshold
99
+ set("down", true)
100
+ else
101
+ set("down", false)
102
+ end
103
+
104
+ if (@y - @joystick_y) > threshold
105
+ set("up", true)
106
+ else
107
+ set("up", false)
108
+ end
109
+
110
+ else
111
+ set("up", false)
112
+ set("down", false)
113
+ set("left", false)
114
+ set("right", false)
115
+ end
116
+ end
117
+
118
+ def set(key, boolean)
119
+ @key_states[@buttons[key]] = boolean
120
+ end
121
+ end
122
+ end
@@ -14,4 +14,5 @@ require_relative "game/game"
14
14
  require_relative "save_file"
15
15
  require_relative "game/opal/touch_handler"
16
16
  require_relative "game/opal/touch_button"
17
+ require_relative "game/opal/touch_joystick"
17
18
  require_relative "game/opal/game_runner"
@@ -1,3 +1,3 @@
1
1
  class AuthorEngine
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -60,7 +60,11 @@ class AuthorEngine
60
60
  end
61
61
  end
62
62
 
63
- import_spritesheet(window.container.savefile.sprites)
63
+ if window.container.savefile.sprites.to_blob.length < 4
64
+ import_spritesheet(spritesheet)
65
+ else
66
+ import_spritesheet(window.container.savefile.sprites)
67
+ end
64
68
  end
65
69
 
66
70
  def focus
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: author_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyberarm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-23 00:00:00.000000000 Z
11
+ date: 2018-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gosu
@@ -148,6 +148,7 @@ files:
148
148
  - lib/author_engine/game/opal/parts/input.rb
149
149
  - lib/author_engine/game/opal/touch_button.rb
150
150
  - lib/author_engine/game/opal/touch_handler.rb
151
+ - lib/author_engine/game/opal/touch_joystick.rb
151
152
  - lib/author_engine/image.rb
152
153
  - lib/author_engine/level_picker.rb
153
154
  - lib/author_engine/opal.rb