author_engine 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 694fa108a1f195431f1a2e19a9c27f23b26b1749d671f564f8cbbf4a5763b6a7
4
- data.tar.gz: 0b366a28a323cd1dbc2fff3854ee6785fd35561ec0c0f6cf2d175dcddf5eba7d
3
+ metadata.gz: 240a86f7ca8210f55b1000684999a28d178bb8aee05816924c09987279930acb
4
+ data.tar.gz: b020c530b4e217ff3b2c6fa8f956eae3a7faef8c3e07de8226fdbd239a0adec9
5
5
  SHA512:
6
- metadata.gz: 5516f268ab834bc8ea4b78e81a12ece30471e9dfd8a88a79bd21265067a161345bc923825572917afb17a2222cec2214b7d02768b9ec1fe4836346f007914769
7
- data.tar.gz: f047c5ca5837b0ccac07690fb9ce939e22705bb90357837e66ca8d35bb3570ac1de98b22bbbeeb774b4cd07462334833cfb3d691054e56e1c197c20a44bb1b19
6
+ metadata.gz: 979bd0fc59a1767dede59ca38f1ac63965beb8c538c95c25fd824d7d5c0b4449508d83f4dec6bc2e4b0d8c046f37f35c1995da4f2460e4d9562534d59b4e41fd
7
+ data.tar.gz: d105fe0793a73d82bb36c69623a031ad0a45ffd0dfbae4027a55e4a77e05bcd75be360fc9fa8427080a2ab1dc4f993f87065a63b0fdbb7e1ec89c99dbc2649d6
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- author_engine (0.4.0)
4
+ author_engine (0.5.0)
5
5
  coderay (~> 1.1.2)
6
6
  gosu (~> 0.14.4)
7
7
  opal (~> 0.11.4)
@@ -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
- builder = Opal::Builder.new
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
- builder.append_paths("#{base_path}")
106
+ game_builder.append_paths("#{base_path}")
78
107
 
79
- puts "Transpiling to JavaScript using Opal..."
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
- builder.build("opal")
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
- builder.build_str(program, "(inline)").to_s
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
- var script = document.createElement('script');
110
- script.src = "application.js";
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
- document.head.appendChild(script);
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 save(string)
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
- unless File.exists?("#{export_path}/fonts")
133
- Dir.mkdir("#{export_path}/fonts")
134
- end
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
- File.open("#{export_path}/application.js", "w") do |file|
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
- file.write("\n\n\n")
145
- file.write(game_runtime)
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 = 128 * #{@game.scale}`
92
- `#{@game.canvas}.height = 128 * #{@game.scale}`
93
- `#{@game.canvas}.style.width = 128 * #{@game.scale}`
94
- `#{@game.canvas}.style.height = 128 * #{@game.scale}`
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
@@ -10,7 +10,7 @@ class AuthorEngine
10
10
  "y" => "c",
11
11
  }
12
12
 
13
- # Store keys state
13
+ # Store key states
14
14
  KEY_STATES = {
15
15
  }
16
16
 
@@ -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
@@ -12,4 +12,6 @@ require_relative "sprite"
12
12
 
13
13
  require_relative "game/game"
14
14
  require_relative "save_file"
15
+ require_relative "game/opal/touch_handler"
16
+ require_relative "game/opal/touch_button"
15
17
  require_relative "game/opal/game_runner"
@@ -1,3 +1,3 @@
1
1
  class AuthorEngine
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
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.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-22 00:00:00.000000000 Z
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