author_engine 0.4.0 → 0.5.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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/author_engine/game/opal/exporter.rb +82 -20
- data/lib/author_engine/game/opal/game_runner.rb +88 -5
- data/lib/author_engine/game/opal/parts/input.rb +1 -1
- data/lib/author_engine/game/opal/touch_button.rb +36 -0
- data/lib/author_engine/game/opal/touch_handler.rb +49 -0
- data/lib/author_engine/opal.rb +2 -0
- data/lib/author_engine/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 240a86f7ca8210f55b1000684999a28d178bb8aee05816924c09987279930acb
|
4
|
+
data.tar.gz: b020c530b4e217ff3b2c6fa8f956eae3a7faef8c3e07de8226fdbd239a0adec9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 979bd0fc59a1767dede59ca38f1ac63965beb8c538c95c25fd824d7d5c0b4449508d83f4dec6bc2e4b0d8c046f37f35c1995da4f2460e4d9562534d59b4e41fd
|
7
|
+
data.tar.gz: d105fe0793a73d82bb36c69623a031ad0a45ffd0dfbae4027a55e4a77e05bcd75be360fc9fa8427080a2ab1dc4f993f87065a63b0fdbb7e1ec89c99dbc2649d6
|
data/Gemfile.lock
CHANGED
@@ -14,6 +14,21 @@ class AuthorEngine
|
|
14
14
|
return name.split("_").map {|n| n.capitalize}.join(" ")
|
15
15
|
end
|
16
16
|
|
17
|
+
# Rebuild opal runtime of it doesn't exist or if its out of date
|
18
|
+
def build_opal?
|
19
|
+
opal_runtime = "#{export_directory}/js/runtime.js"
|
20
|
+
|
21
|
+
if File.exists?(opal_runtime)
|
22
|
+
file = File.open(opal_runtime)
|
23
|
+
version = file.first.gsub("/", "").strip
|
24
|
+
file.close
|
25
|
+
|
26
|
+
Opal::VERSION != version
|
27
|
+
else
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
17
32
|
def stylesheet
|
18
33
|
%{
|
19
34
|
@font-face { font-family: Connection; src: url('fonts/Connection.otf'); }
|
@@ -27,7 +42,7 @@ body {
|
|
27
42
|
#canvas {
|
28
43
|
display: block;
|
29
44
|
margin: 0 auto;
|
30
|
-
cursor: none;
|
45
|
+
// cursor: none;
|
31
46
|
}
|
32
47
|
#loading {
|
33
48
|
font-family: Connection, sans serif;
|
@@ -54,8 +69,8 @@ var projectString = `#{File.open(@project_file).read}`;
|
|
54
69
|
|
55
70
|
def game_runtime
|
56
71
|
program = %{
|
57
|
-
require "opal"
|
58
|
-
require "opal-parser"
|
72
|
+
# require "opal"
|
73
|
+
# require "opal-parser"
|
59
74
|
require "author_engine/opal"
|
60
75
|
|
61
76
|
`var callback = function(){
|
@@ -72,18 +87,34 @@ if (
|
|
72
87
|
}`
|
73
88
|
}
|
74
89
|
|
75
|
-
|
90
|
+
puts "Transpiling to JavaScript using Opal..."
|
91
|
+
|
92
|
+
opal_builder = nil
|
93
|
+
if build_opal?
|
94
|
+
puts " Building Opal runtime..."
|
95
|
+
|
96
|
+
opal_builder = Opal::Builder.new
|
97
|
+
opal_builder.build("opal")
|
98
|
+
opal_builder.build("opal-parser")
|
99
|
+
else
|
100
|
+
puts " Skipping Opal runtime. Already exists as v#{Opal::VERSION}..."
|
101
|
+
end
|
102
|
+
|
103
|
+
puts " Building AuthorEngine runtime with project..."
|
104
|
+
game_builder = Opal::Builder.new
|
76
105
|
base_path = File.expand_path("../../../..", __FILE__)
|
77
|
-
|
106
|
+
game_builder.append_paths("#{base_path}")
|
78
107
|
|
79
|
-
|
108
|
+
game_builder.build_require("author_engine/opal")
|
80
109
|
|
110
|
+
opal_builder_js = nil
|
111
|
+
if opal_builder
|
112
|
+
opal_runtime_js = opal_builder.build_str("", "(inline)").to_s
|
113
|
+
end
|
81
114
|
|
82
|
-
|
83
|
-
builder.build("opal-parser")
|
84
|
-
builder.build_require("author_engine/opal")
|
115
|
+
author_engine_js = game_builder.build_str(program, "(inline)").to_s
|
85
116
|
|
86
|
-
|
117
|
+
return {opal_runtime: opal_runtime_js, author_engine_runtime: author_engine_js}
|
87
118
|
end
|
88
119
|
|
89
120
|
def template
|
@@ -103,13 +134,23 @@ if (
|
|
103
134
|
<h1>Your Browser Does Not Support HTML5 Canvas!</h1>
|
104
135
|
</canvas>
|
105
136
|
|
137
|
+
<script src="game.js"></script>
|
106
138
|
<script>
|
107
139
|
// Add a small delay before loading application in order to finish loading page and show "Loading..."
|
108
140
|
window.setTimeout(function() {
|
109
|
-
|
110
|
-
|
141
|
+
console.log("Loading Opal runtime...");
|
142
|
+
|
143
|
+
var opal_runtime = document.createElement('script');
|
144
|
+
opal_runtime.onload = function() {
|
145
|
+
console.log("Loading AuthorEngine runtime...");
|
111
146
|
|
112
|
-
|
147
|
+
var author_engine_runtime = document.createElement('script');
|
148
|
+
author_engine_runtime.src = "js/author_engine.js";
|
149
|
+
document.head.appendChild(author_engine_runtime);
|
150
|
+
}
|
151
|
+
opal_runtime.src = "js/runtime.js";
|
152
|
+
|
153
|
+
document.head.appendChild(opal_runtime);
|
113
154
|
}, 500);
|
114
155
|
</script>
|
115
156
|
</body>
|
@@ -121,17 +162,28 @@ if (
|
|
121
162
|
template
|
122
163
|
end
|
123
164
|
|
124
|
-
def
|
165
|
+
def export_directory
|
125
166
|
filename = File.basename(@project_file)
|
126
167
|
directory = File.expand_path(@project_file.sub(filename, ''))
|
127
168
|
name = filename.sub(".authorengine", "")
|
128
169
|
|
170
|
+
return "#{directory}/#{name}"
|
171
|
+
end
|
172
|
+
|
173
|
+
def save(string)
|
174
|
+
filename = File.basename(@project_file)
|
175
|
+
directory = File.expand_path(@project_file.sub(filename, ''))
|
176
|
+
name = filename.sub(".authorengine", "")
|
129
177
|
export_path = "#{directory}/#{name}"
|
178
|
+
|
130
179
|
unless File.exists?(export_path)
|
131
180
|
Dir.mkdir(export_path)
|
132
|
-
|
133
|
-
|
134
|
-
|
181
|
+
end
|
182
|
+
unless File.exists?("#{export_path}/fonts")
|
183
|
+
Dir.mkdir("#{export_path}/fonts")
|
184
|
+
end
|
185
|
+
unless File.exists?("#{export_path}/js")
|
186
|
+
Dir.mkdir("#{export_path}/js")
|
135
187
|
end
|
136
188
|
|
137
189
|
puts "Saving to \"#{export_path}\""
|
@@ -139,10 +191,20 @@ if (
|
|
139
191
|
file.write(string)
|
140
192
|
end
|
141
193
|
|
142
|
-
|
194
|
+
hash = game_runtime
|
195
|
+
if hash[:opal_runtime]
|
196
|
+
File.open("#{export_path}/js/runtime.js", "w") do |file|
|
197
|
+
file.write("// #{Opal::VERSION}\n")
|
198
|
+
file.write(hash[:opal_runtime])
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
File.open("#{export_path}/game.js", "w") do |file|
|
143
203
|
file.write(project)
|
144
|
-
|
145
|
-
|
204
|
+
end
|
205
|
+
|
206
|
+
File.open("#{export_path}/js/author_engine.js", "w") do |file|
|
207
|
+
file.write(hash[:author_engine_runtime])
|
146
208
|
end
|
147
209
|
|
148
210
|
fonts_path = "#{File.expand_path("../../../../../", __FILE__)}/assets/fonts"
|
@@ -7,6 +7,8 @@ class AuthorEngine
|
|
7
7
|
@instance = klass
|
8
8
|
end
|
9
9
|
|
10
|
+
include TouchHandler
|
11
|
+
|
10
12
|
attr_reader :save_file, :spritesheet, :sprites, :levels, :fps
|
11
13
|
attr_reader :game
|
12
14
|
def initialize(project_string)
|
@@ -41,6 +43,41 @@ class AuthorEngine
|
|
41
43
|
|
42
44
|
@game.init
|
43
45
|
|
46
|
+
@show_touch_controls = false
|
47
|
+
@touch_buttons = []
|
48
|
+
buttons = AuthorEngine::Part::OpalInput::BUTTONS
|
49
|
+
key_states = AuthorEngine::Part::OpalInput::KEY_STATES
|
50
|
+
@touch_buttons.push(
|
51
|
+
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
|
+
),
|
55
|
+
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}
|
77
|
+
)
|
78
|
+
)
|
79
|
+
touch_handler_setup
|
80
|
+
|
44
81
|
return self
|
45
82
|
end
|
46
83
|
|
@@ -57,6 +94,7 @@ class AuthorEngine
|
|
57
94
|
|
58
95
|
def run_game
|
59
96
|
`window.requestAnimationFrame(function() {#{run_game}})` # placed here to ensure next frame is called even if draw or update throw an error
|
97
|
+
`#{@game.canvas_context}.clearRect(0,0, window.innerWidth, window.innerHeight)`
|
60
98
|
|
61
99
|
@counted_frames+=1
|
62
100
|
|
@@ -68,8 +106,30 @@ class AuthorEngine
|
|
68
106
|
|
69
107
|
|
70
108
|
if @sprites.size == (@spritesheet_width/@sprite_size)*(@spritesheet_height/@sprite_size)
|
109
|
+
width = 128 * @game.scale
|
110
|
+
|
111
|
+
# `#{@canvas_context}.setTransform(1, 0, 0, 1, 0, 0)`
|
112
|
+
`#{@game.canvas_context}.save()`
|
113
|
+
`#{@game.canvas_context}.translate(window.innerWidth/2 - #{width/2}, 0)`
|
114
|
+
`#{@game.canvas_context}.scale(#{@game.scale}, #{@game.scale})`
|
115
|
+
`#{@game.canvas_context}.save()`
|
116
|
+
|
117
|
+
region = `new Path2D()`
|
118
|
+
`#{region}.rect(0, 0, 128, 128)`
|
119
|
+
`#{@game.canvas_context}.clip(#{region})`
|
120
|
+
`#{@game.canvas_context}.save()`
|
71
121
|
draw
|
122
|
+
|
123
|
+
`#{@game.canvas_context}.restore()`
|
124
|
+
`#{@game.canvas_context}.restore()`
|
125
|
+
`#{@game.canvas_context}.restore()`
|
126
|
+
|
72
127
|
update
|
128
|
+
|
129
|
+
if @show_touch_controls
|
130
|
+
draw_touch_controls
|
131
|
+
update_touch_controls
|
132
|
+
end
|
73
133
|
else
|
74
134
|
@game.draw_background
|
75
135
|
@game.text("Loading sprite #{@sprites.size}/#{(@spritesheet_width/@sprite_size)*(@spritesheet_height/@sprite_size)}.", 0, @game.height/2, 8)
|
@@ -78,6 +138,25 @@ class AuthorEngine
|
|
78
138
|
return nil
|
79
139
|
end
|
80
140
|
|
141
|
+
def draw_touch_controls
|
142
|
+
@touch_buttons.each(&:draw)
|
143
|
+
end
|
144
|
+
|
145
|
+
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
|
156
|
+
|
157
|
+
(@touch_buttons - active_buttons).each(&:inactive)
|
158
|
+
end
|
159
|
+
|
81
160
|
def resize_canvas
|
82
161
|
width = `window.innerWidth`
|
83
162
|
height = `window.innerHeight`
|
@@ -88,12 +167,11 @@ class AuthorEngine
|
|
88
167
|
@game.scale = `window.innerHeight / 128.0`
|
89
168
|
end
|
90
169
|
|
91
|
-
`#{@game.canvas}.width =
|
92
|
-
`#{@game.canvas}.height =
|
93
|
-
`#{@game.canvas}.style.width =
|
94
|
-
`#{@game.canvas}.style.height =
|
170
|
+
`#{@game.canvas}.width = #{width}`
|
171
|
+
`#{@game.canvas}.height = #{height}`
|
172
|
+
`#{@game.canvas}.style.width = #{width}`
|
173
|
+
`#{@game.canvas}.style.height = #{height}`
|
95
174
|
|
96
|
-
`#{@game.canvas_context}.scale(#{@game.scale}, #{@game.scale})`
|
97
175
|
`#{@game.canvas_context}.imageSmoothingEnabled = false`
|
98
176
|
return nil
|
99
177
|
end
|
@@ -150,6 +228,11 @@ class AuthorEngine
|
|
150
228
|
`document.addEventListener('keydown', (event) => { #{AuthorEngine::Part::OpalInput::KEY_STATES[`event.key`] = true} })`
|
151
229
|
`document.addEventListener('keyup', (event) => { #{AuthorEngine::Part::OpalInput::KEY_STATES[`event.key`] = false} })`
|
152
230
|
|
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."} })`
|
235
|
+
|
153
236
|
`document.getElementById('loading').style.display = "none"`
|
154
237
|
`window.requestAnimationFrame(function() {#{run_game}})`
|
155
238
|
return nil
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class TouchButton
|
3
|
+
attr_reader :x, :y, :width, :height
|
4
|
+
def initialize(label:, color:, x:, y: nil, width:, height:, side:, contact_proc:, no_contact_proc:)
|
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
|
7
|
+
|
8
|
+
@game = AuthorEngine::GameRunner.instance.game
|
9
|
+
@game_width = 128 * @game.scale
|
10
|
+
@game_x = `window.innerWidth/2 - #{@game_width/2}`
|
11
|
+
|
12
|
+
if @side == :left
|
13
|
+
@x = @game_x-@x
|
14
|
+
elsif @side == :right
|
15
|
+
@x = @game_x+@game_width+@x
|
16
|
+
else
|
17
|
+
raise "side must be :left or :right"
|
18
|
+
end
|
19
|
+
|
20
|
+
@y = `window.innerHeight/2 - #{height}` unless @y.is_a?(Numeric)
|
21
|
+
end
|
22
|
+
|
23
|
+
def draw
|
24
|
+
`#{@game.canvas_context}.fillStyle = #{@color}`
|
25
|
+
`#{@game.canvas_context}.fillRect(#{@x}, #{@y}, #{width}, #{width})`
|
26
|
+
end
|
27
|
+
|
28
|
+
def active
|
29
|
+
@contact_proc.call
|
30
|
+
end
|
31
|
+
|
32
|
+
def inactive
|
33
|
+
@no_contact_proc.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
module TouchHandler
|
3
|
+
Touch = Struct.new(:x, :y)
|
4
|
+
def touch_handler_setup
|
5
|
+
@current_touches = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def copy_touch(touch)
|
9
|
+
Touch.new(`touch.pageX`, `touch.pageY`)
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle_touch_start(event)
|
13
|
+
`#{event}.preventDefault()`
|
14
|
+
|
15
|
+
touches = `#{event}.changedTouches`
|
16
|
+
`for (var i = 0; i < #{touches}.length; i++) {
|
17
|
+
#{@current_touches[`touches[i].identifier`] = copy_touch(`touches[i]`)}
|
18
|
+
}`
|
19
|
+
|
20
|
+
return nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_touch_move(event)
|
24
|
+
`#{event}.preventDefault()`
|
25
|
+
|
26
|
+
touches = `#{event}.changedTouches`
|
27
|
+
`for (var i = 0; i < #{touches}.length; i++) {
|
28
|
+
#{@current_touches[`touches[i].identifier`] = copy_touch(`touches[i]`)}
|
29
|
+
}`
|
30
|
+
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def handle_touch_cancel(event)
|
35
|
+
handle_touch_end(event)
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_touch_end(event)
|
39
|
+
`#{event}.preventDefault()`
|
40
|
+
|
41
|
+
touches = `#{event}.changedTouches`
|
42
|
+
`for (var i = 0; i < #{touches}.length; i++) {
|
43
|
+
#{@current_touches.delete(`touches[i].identifier`)}
|
44
|
+
}`
|
45
|
+
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/author_engine/opal.rb
CHANGED
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.
|
4
|
+
version: 0.5.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-
|
11
|
+
date: 2018-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gosu
|
@@ -146,6 +146,8 @@ files:
|
|
146
146
|
- lib/author_engine/game/opal/game_runner.rb
|
147
147
|
- lib/author_engine/game/opal/parts/graphics.rb
|
148
148
|
- lib/author_engine/game/opal/parts/input.rb
|
149
|
+
- lib/author_engine/game/opal/touch_button.rb
|
150
|
+
- lib/author_engine/game/opal/touch_handler.rb
|
149
151
|
- lib/author_engine/image.rb
|
150
152
|
- lib/author_engine/level_picker.rb
|
151
153
|
- lib/author_engine/opal.rb
|