author_engine 0.1.0 → 0.3.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/.gitignore +3 -2
- data/API.md +20 -0
- data/Gemfile.lock +13 -2
- data/README.md +8 -4
- data/author_engine.gemspec +2 -1
- data/bin/author_engine +3 -1
- data/lib/author_engine/button.rb +1 -1
- data/lib/author_engine/cli.rb +21 -0
- data/lib/author_engine/collision_detection/collision_detection.rb +188 -0
- data/lib/author_engine/containers/loader.rb +8 -1
- data/lib/author_engine/game/common/parts/collision_detection.rb +33 -0
- data/lib/author_engine/game/game.rb +28 -2
- data/lib/author_engine/game/{parts → gosu/parts}/colors.rb +0 -0
- data/lib/author_engine/game/{parts → gosu/parts}/common.rb +0 -0
- data/lib/author_engine/game/{parts → gosu/parts}/graphics.rb +19 -1
- data/lib/author_engine/game/{parts → gosu/parts}/input.rb +0 -0
- data/lib/author_engine/game/opal/exporter.rb +157 -0
- data/lib/author_engine/game/opal/game_runner.rb +158 -0
- data/lib/author_engine/game/opal/parts/colors.rb +64 -0
- data/lib/author_engine/game/opal/parts/common.rb +13 -0
- data/lib/author_engine/game/opal/parts/graphics.rb +69 -0
- data/lib/author_engine/game/opal/parts/input.rb +30 -0
- data/lib/author_engine/image.rb +1 -0
- data/lib/author_engine/level_picker.rb +92 -0
- data/lib/author_engine/opal.rb +15 -0
- data/lib/author_engine/save_file.rb +49 -15
- data/lib/author_engine/sprite.rb +1 -2
- data/lib/author_engine/sprite_picker.rb +10 -3
- data/lib/author_engine/text.rb +2 -2
- data/lib/author_engine/version.rb +1 -1
- data/lib/author_engine/views/level_editor.rb +161 -0
- data/lib/author_engine/views/play_viewer.rb +1 -0
- data/lib/author_engine.rb +9 -4
- data/screenshots/code_editor.png +0 -0
- data/screenshots/play.png +0 -0
- data/screenshots/sprite_editor.png +0 -0
- metadata +36 -9
- data/test_3.authorengine +0 -519
- data/testing.authorengine +0 -578
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ac3f16a1dc192379088c8f74dde1e6dab90e5edeefa35e1bcb810c7017b6833
|
4
|
+
data.tar.gz: '0860cdd4a930f02a6654fbde557148d8e460bb3666e8e87c10a64ba81dffcf6e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91dc4eace8dcb2c8f3edae461cef1a515e5616a915dd19f7598df02e0fd6f0bab0e45f75713b40869aefa803b9db6cda0f48b0279d9f91cb6cf4a5fa16c4caad
|
7
|
+
data.tar.gz: 6ff618da871039a3786b1bdab78977914d41c7c10e45101ac19865aaee3c7ab3f771af7caec2577bcfb35c03372b1dbf9dfdf0a0af669b45a9ec5a8b77af33b9
|
data/.gitignore
CHANGED
data/API.md
CHANGED
@@ -38,10 +38,30 @@ end
|
|
38
38
|
### milliseconds
|
39
39
|
Milliseconds since game started
|
40
40
|
|
41
|
+
# CollisionDetection
|
42
|
+
### bounding_box(sprite_index)
|
43
|
+
returns the bounding_box for sprite
|
44
|
+
### sprite_vs_sprite(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
45
|
+
determine whether 2 sprites are colliding
|
46
|
+
### sprite_vs_level(sprite_index, sprite_x, sprite_y, level)
|
47
|
+
returns an array of level tiles that sprite is colliding with. returns an empty array if non are colliding.
|
48
|
+
### colliding_edge(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
49
|
+
determine the edge of which sprite is colliding with with target
|
50
|
+
### draw_sprite_box(sprite_index, sprite_x, sprite_y)
|
51
|
+
draws sprites bounding box
|
52
|
+
### draw_level_boxes(level_index)
|
53
|
+
draws bounding boxes around each tile of level
|
54
|
+
### render_bounding_box(sprite_index, box, sprite_x, sprite_y, edges = {}, z = Float::INFINITY)
|
55
|
+
draw bounding box around sprite with optional edges from colliding_edges to show colliding edges
|
56
|
+
|
41
57
|
# Graphics
|
42
58
|
### rect(x = 0, y = 0, width = 1, height = 1, color = white, z = 0)
|
43
59
|
### sprite(sprite_sheet_index, x = 0, y = 0, z = 0, color = white)
|
44
60
|
### text(string, x = 0, y = 0, size = 4, z = 0, color = white)
|
61
|
+
### level(level_index, z = 0)
|
62
|
+
|
63
|
+
### swap(level_index, current_sprite, replacement_sprite)
|
64
|
+
Swap level's current_sprite with replacement_sprite
|
45
65
|
|
46
66
|
### translate(x, y, &block)
|
47
67
|
Translate the contents of block by x and y
|
data/Gemfile.lock
CHANGED
@@ -1,17 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
author_engine (0.
|
4
|
+
author_engine (0.3.0)
|
5
5
|
coderay (~> 1.1.2)
|
6
6
|
gosu (~> 0.14.4)
|
7
|
+
opal (~> 0.11.4)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
10
11
|
specs:
|
12
|
+
ast (2.4.0)
|
11
13
|
coderay (1.1.2)
|
12
14
|
gosu (0.14.4)
|
15
|
+
hike (1.2.3)
|
13
16
|
minitest (5.11.3)
|
17
|
+
opal (0.11.4)
|
18
|
+
ast (>= 2.3.0)
|
19
|
+
hike (~> 1.2)
|
20
|
+
parser (= 2.3.3.1)
|
21
|
+
sourcemap (~> 0.1.0)
|
22
|
+
parser (2.3.3.1)
|
23
|
+
ast (~> 2.2)
|
14
24
|
rake (10.5.0)
|
25
|
+
sourcemap (0.1.1)
|
15
26
|
|
16
27
|
PLATFORMS
|
17
28
|
ruby
|
@@ -23,4 +34,4 @@ DEPENDENCIES
|
|
23
34
|
rake (~> 10.0)
|
24
35
|
|
25
36
|
BUNDLED WITH
|
26
|
-
1.
|
37
|
+
1.17.2
|
data/README.md
CHANGED
@@ -8,19 +8,23 @@ A virtual console¹ that you code in Ruby.
|
|
8
8
|
`gem install author_engine`
|
9
9
|
|
10
10
|
## Run
|
11
|
-
`author_engine`
|
11
|
+
`author_engine [filename] [options]`
|
12
|
+
- Run AuthorEngine editor with optional filename argument to open project.
|
13
|
+
|
14
|
+
`author_engine export filename`
|
15
|
+
- Export project to web using [Opal](https://opalrb.com).
|
12
16
|
### Options
|
13
17
|
`--native` Open AuthorEngine in fullscreen and maximized.
|
14
18
|
|
15
19
|
# Interface
|
16
20
|
## Play
|
17
|
-

|
18
22
|
## Sprite Editor
|
19
|
-

|
20
24
|
## Level Editor
|
21
25
|

|
22
26
|
## Code Editor
|
23
|
-

|
24
28
|
|
25
29
|
|
26
30
|
¹: Does not directly run any kind of assembly
|
data/author_engine.gemspec
CHANGED
@@ -30,10 +30,11 @@ Gem::Specification.new do |spec|
|
|
30
30
|
end
|
31
31
|
spec.bindir = "bin"
|
32
32
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
33
|
-
spec.require_paths = ["lib"]
|
33
|
+
spec.require_paths = ["lib", "assets"]
|
34
34
|
|
35
35
|
spec.add_dependency "gosu", "~> 0.14.4"
|
36
36
|
spec.add_dependency "coderay", "~> 1.1.2"
|
37
|
+
spec.add_dependency "opal", "~> 0.11.4"
|
37
38
|
|
38
39
|
spec.add_development_dependency "bundler", "~> 1.16"
|
39
40
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/bin/author_engine
CHANGED
data/lib/author_engine/button.rb
CHANGED
@@ -111,7 +111,7 @@ class AuthorEngine
|
|
111
111
|
@image.draw(@x+@x_padding, @y+@y_padding, @z, (1 * window.square_scale), (1 * window.square_scale))
|
112
112
|
|
113
113
|
else
|
114
|
-
raise "Nothing to draw! (
|
114
|
+
raise "Nothing to draw! (label and image were nil or invalid types)"
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class CLI
|
3
|
+
def initialize
|
4
|
+
if ARGV[0] && ARGV[0] == "export"
|
5
|
+
if ARGV[1] && ARGV[1].end_with?(".authorengine")
|
6
|
+
require "author_engine/game/opal/exporter"
|
7
|
+
|
8
|
+
AuthorEngine::OpalExporter.new(project_file: ARGV[1])
|
9
|
+
else
|
10
|
+
puts "author_engine export project [exported_name]"
|
11
|
+
end
|
12
|
+
|
13
|
+
elsif ARGV[0] && ARGV[0].end_with?(".authorengine")
|
14
|
+
# The Loader Container handles loading projects
|
15
|
+
AuthorEngine::Window.new.show
|
16
|
+
else
|
17
|
+
AuthorEngine::Window.new.show
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class CollisionDetection
|
3
|
+
Color = Struct.new(:red, :green, :blue, :alpha)
|
4
|
+
BoundingBox = Struct.new(:x, :y, :width, :height)
|
5
|
+
|
6
|
+
def initialize(game_sprites, game_levels)
|
7
|
+
@game_sprites = game_sprites
|
8
|
+
@game_levels = game_levels
|
9
|
+
|
10
|
+
@sprites= []
|
11
|
+
@levels = []
|
12
|
+
|
13
|
+
@known_collisions = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear
|
17
|
+
@known_collisions.clear
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_sprite(image_or_blob)
|
21
|
+
blob = nil
|
22
|
+
if RUBY_ENGINE != "opal"
|
23
|
+
blob = image_or_blob.to_blob
|
24
|
+
else
|
25
|
+
blob = []
|
26
|
+
`#{image_or_blob}.forEach(function(value) {#{blob << `value`}})`#.each {|n| blob << n}
|
27
|
+
end
|
28
|
+
|
29
|
+
@sprites << {blob: blob, box: bounding_box(blob)}
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_level(level_array)
|
33
|
+
@levels << level_array # TODO: Put level's into an optimized structure for fast quadrant look-ups
|
34
|
+
end
|
35
|
+
|
36
|
+
def box(sprite_index)
|
37
|
+
@sprites[sprite_index][:box]
|
38
|
+
end
|
39
|
+
|
40
|
+
def sprite_vs_sprite(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
41
|
+
bounding_boxes_intersect?(box(sprite_index), sprite_x, sprite_y, box(target_sprite_index), target_x, target_y)
|
42
|
+
end
|
43
|
+
|
44
|
+
def sprite_vs_level(sprite_index, sprite_x, sprite_y, level)
|
45
|
+
detected = []
|
46
|
+
|
47
|
+
collider = box(sprite_index)
|
48
|
+
@levels[level].each do |sprite|
|
49
|
+
if bounding_boxes_intersect?(collider, sprite_x, sprite_y, box(sprite.sprite), sprite.x, sprite.y)
|
50
|
+
detected << sprite
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
return detected
|
55
|
+
end
|
56
|
+
|
57
|
+
def colliding_edge(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
58
|
+
sprite_box = box(sprite_index)
|
59
|
+
target_box = box(target_sprite_index)
|
60
|
+
|
61
|
+
edges = {top: false, left: false, right: false, bottom: false}
|
62
|
+
|
63
|
+
# https://gamedev.stackexchange.com/a/24091
|
64
|
+
wy = (sprite_box.width + target_box.width) * ((sprite_y - sprite_box.height) - (target_y - target_box.height/2));
|
65
|
+
hx = (sprite_box.height + target_box.height) * ((sprite_x - sprite_box.width) - (target_x - target_box.height/2));
|
66
|
+
|
67
|
+
if (wy > hx)
|
68
|
+
if (wy > -hx)
|
69
|
+
edges[:bottom] = true
|
70
|
+
else
|
71
|
+
edges[:left] = true
|
72
|
+
end
|
73
|
+
else
|
74
|
+
if (wy > -hx)
|
75
|
+
edges[:right] = true
|
76
|
+
else
|
77
|
+
edges[:top] = true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
return edges
|
82
|
+
end
|
83
|
+
|
84
|
+
def debug_draw_sprite(sprite_index, sprite_x, sprite_y)
|
85
|
+
render_bounding_box(sprite_index, box(sprite_index), sprite_x, sprite_y)
|
86
|
+
end
|
87
|
+
|
88
|
+
def debug_draw_level(level_index)
|
89
|
+
@levels[level_index].each do |sprite|
|
90
|
+
render_bounding_box(sprite.sprite, box(sprite.sprite), sprite.x, sprite.y)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def render_bounding_box(sprite_index, box, sprite_x, sprite_y, edges = {}, z = Float::INFINITY, color = 0xc800ff00, collision_color = 0xc8ff00ff)
|
95
|
+
if RUBY_ENGINE == "opal"
|
96
|
+
color = "green"
|
97
|
+
collision_color = "red"
|
98
|
+
end
|
99
|
+
paint_color = color
|
100
|
+
# EDGE: TOP
|
101
|
+
# TOP LEFT TO TOP RIGHT
|
102
|
+
if edges[:top] then paint_color = collision_color; else paint_color = color; end
|
103
|
+
draw_line(
|
104
|
+
box.x + sprite_x, box.y + sprite_y,
|
105
|
+
box.x + sprite_x + box.width, box.y + sprite_y,
|
106
|
+
paint_color, z
|
107
|
+
)
|
108
|
+
|
109
|
+
# EDGE: RIGHT
|
110
|
+
# TOP RIGHT TO BOTTOM RIGHT
|
111
|
+
if edges[:right] then paint_color = collision_color; else paint_color = color; end
|
112
|
+
draw_line(
|
113
|
+
box.x + sprite_x + box.width, box.y + sprite_y,
|
114
|
+
box.x + sprite_x + box.width, box.y + sprite_y + box.height,
|
115
|
+
paint_color, z
|
116
|
+
)
|
117
|
+
|
118
|
+
# EDGE: BOTTOM
|
119
|
+
# BOTTOM RIGHT to BOTTOM LEFT
|
120
|
+
if edges[:bottom] then paint_color = collision_color; else paint_color = color; end
|
121
|
+
draw_line(
|
122
|
+
box.x + sprite_x + box.width, box.y + sprite_y + box.height,
|
123
|
+
box.x + sprite_x, box.y + sprite_y + box.height,
|
124
|
+
paint_color, z
|
125
|
+
)
|
126
|
+
|
127
|
+
# EDGE: LEFT
|
128
|
+
# BOTTOM LEFT TO TOP LEFT
|
129
|
+
if edges[:left] then paint_color = collision_color; else paint_color = color; end
|
130
|
+
draw_line(
|
131
|
+
box.x + sprite_x, box.y + sprite_y + box.height,
|
132
|
+
box.x + sprite_x, box.y + sprite_y,
|
133
|
+
paint_color, z
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
def bounding_boxes_intersect?(a, a_x, a_y, b, b_x, b_y)
|
139
|
+
(a.x + a_x) <= (b.x + b_x + b.width) && (a.x + a_x + a.width) >= (b.x + b_x) &&
|
140
|
+
(a.y + a_y) <= (b.y + b_y + b.height) && (a.y + a_y + a.height) >= (b.y + b_y)
|
141
|
+
end
|
142
|
+
|
143
|
+
def draw_line(x, y, x2, y2, color, z = 0)
|
144
|
+
if RUBY_ENGINE == "opal"
|
145
|
+
`#{AuthorEngine::GameRunner.instance.game.canvas_context}.strokeStyle = #{color}`
|
146
|
+
`#{AuthorEngine::GameRunner.instance.game.canvas_context}.lineWidth = 1`
|
147
|
+
|
148
|
+
`#{AuthorEngine::GameRunner.instance.game.canvas_context}.beginPath()`
|
149
|
+
`#{AuthorEngine::GameRunner.instance.game.canvas_context}.moveTo(#{x}, #{y})`
|
150
|
+
`#{AuthorEngine::GameRunner.instance.game.canvas_context}.lineTo(#{x2}, #{y2})`
|
151
|
+
`#{AuthorEngine::GameRunner.instance.game.canvas_context}.stroke()`
|
152
|
+
else
|
153
|
+
Gosu.draw_line(x, y, color, x2, y2, color, z)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# returns alpha value of pixel at x and y
|
158
|
+
def solid_at?(blob, x, y)
|
159
|
+
width = 16
|
160
|
+
|
161
|
+
blob[(y * width + x) * 4 + 3].ord
|
162
|
+
end
|
163
|
+
|
164
|
+
def bounding_box(blob, size = 16)
|
165
|
+
box = BoundingBox.new(size, size, 0, 0)
|
166
|
+
size.times do |y|
|
167
|
+
size.times do |x|
|
168
|
+
if solid_at?(blob, x, y) > 0
|
169
|
+
box.x = x if x < box.x
|
170
|
+
box.y = y if y < box.y
|
171
|
+
box.width = x if x > box.width
|
172
|
+
box.height = y if y > box.height
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Correct width/height
|
178
|
+
box.width -= box.x
|
179
|
+
box.height -= box.y
|
180
|
+
|
181
|
+
# Correct off-by-1
|
182
|
+
box.width += 1
|
183
|
+
box.height += 1
|
184
|
+
|
185
|
+
return box
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -26,6 +26,14 @@ class AuthorEngine
|
|
26
26
|
@entering_name = true
|
27
27
|
end
|
28
28
|
@new_button.x = window.width - @new_button.width
|
29
|
+
|
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
|
29
37
|
end
|
30
38
|
|
31
39
|
def load(filename)
|
@@ -54,7 +62,6 @@ class AuthorEngine
|
|
54
62
|
Gosu.draw_rect(0, @new_button.y, window.width, @new_button.height, @header_color)
|
55
63
|
@font.draw_text("AuthorEngine", 1*window.square_scale,@font.height/2,0)
|
56
64
|
@new_button.draw
|
57
|
-
@font.draw_text(@list[@index].name, 0, 0, 0) if @list[@index]
|
58
65
|
|
59
66
|
Gosu.clip_to(0, @font.height*2, window.width, window.height-(@font.height*4)) do
|
60
67
|
y = (window.height/2-@font.height) - (@height/2)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class Part
|
3
|
+
module CollisionDetection
|
4
|
+
def bounding_box(sprite_index)
|
5
|
+
@collision_detection.box(sprite_index)
|
6
|
+
end
|
7
|
+
|
8
|
+
def colliding_edge(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
9
|
+
@collision_detection.colliding_edge(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
10
|
+
end
|
11
|
+
|
12
|
+
def sprite_vs_sprite(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
13
|
+
@collision_detection.sprite_vs_sprite(sprite_index, sprite_x, sprite_y, target_sprite_index, target_x, target_y)
|
14
|
+
end
|
15
|
+
|
16
|
+
def sprite_vs_level(sprite_index, sprite_x, sprite_y, level)
|
17
|
+
@collision_detection.sprite_vs_level(sprite_index, sprite_x, sprite_y, level)
|
18
|
+
end
|
19
|
+
|
20
|
+
def draw_sprite_box(sprite_index, sprite_x, sprite_y)
|
21
|
+
@collision_detection.debug_draw_sprite(sprite_index, sprite_x, sprite_y)
|
22
|
+
end
|
23
|
+
|
24
|
+
def draw_level_boxes(level_index)
|
25
|
+
@collision_detection.debug_draw_level(level_index)
|
26
|
+
end
|
27
|
+
|
28
|
+
def render_bounding_box(sprite_index, box, sprite_x, sprite_y, edges = {}, z = Float::INFINITY)
|
29
|
+
@collision_detection.render_bounding_box(sprite_index, box, sprite_x, sprite_y, edges, z, nil, nil)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,17 +1,43 @@
|
|
1
1
|
class AuthorEngine
|
2
2
|
class Game
|
3
3
|
include AuthorEngine::Part::Common
|
4
|
+
include AuthorEngine::Part::CollisionDetection
|
4
5
|
include AuthorEngine::Part::Colors
|
5
6
|
include AuthorEngine::Part::Graphics
|
6
7
|
include AuthorEngine::Part::Input
|
7
8
|
|
9
|
+
attr_accessor :scale, :canvas, :canvas_context
|
10
|
+
attr_accessor :collision_detection
|
8
11
|
def initialize(code:)
|
9
|
-
|
12
|
+
if RUBY_ENGINE == "opal"
|
13
|
+
@scale = 1.0
|
14
|
+
@canvas = `document.getElementById('canvas')`
|
15
|
+
@canvas_context = `#{@canvas}.getContext('2d')`
|
16
|
+
end
|
17
|
+
|
18
|
+
if RUBY_ENGINE != "opal"
|
19
|
+
@sprites = SpriteEditor.instance.sprites
|
20
|
+
|
21
|
+
@levels = []
|
22
|
+
# Create a "Deep Copy" to allow for swapping of a level's sprites without corrupting LevelEditor's version
|
23
|
+
LevelEditor.instance.levels.each do |level|
|
24
|
+
@levels << level.sort_by {|sprite| sprite.z}.map {|sprite| sprite.dup}
|
25
|
+
end
|
26
|
+
size = 16
|
27
|
+
@levels.each {|level| level.each {|sprite| sprite.x = sprite.x * size; sprite.y = sprite.y * size}}
|
28
|
+
|
29
|
+
@collision_detection = CollisionDetection.new(@sprites, @levels)
|
30
|
+
|
31
|
+
@sprites.each {|sprite| @collision_detection.add_sprite(sprite) }
|
32
|
+
@levels.each {|level| @collision_detection.add_level(level) }
|
33
|
+
end
|
34
|
+
|
35
|
+
@background_color = black
|
10
36
|
self.instance_eval(code)
|
11
37
|
end
|
12
38
|
|
13
39
|
def draw_background
|
14
|
-
|
40
|
+
rect(0, 0, width, height, @background_color)
|
15
41
|
end
|
16
42
|
|
17
43
|
def init
|
File without changes
|
File without changes
|
@@ -20,11 +20,29 @@ class AuthorEngine
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def sprite(index, x = 0, y = 0, z = 0, alpha = 255)
|
23
|
-
image =
|
23
|
+
image = @sprites[index]
|
24
24
|
raise "No sprite at '#{index}'!" unless image
|
25
25
|
image.draw(x, y, z, 1,1, Gosu::Color.rgba(255,255,255, alpha))
|
26
26
|
end
|
27
27
|
|
28
|
+
def level(index, z = 0)
|
29
|
+
_level = @levels[index]
|
30
|
+
raise "No level at '#{index}'!" unless _level
|
31
|
+
|
32
|
+
_level.each do |sprite|
|
33
|
+
sprite(sprite.sprite, sprite.x, sprite.y, z)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def swap(level, current_sprite, replacement_sprite)
|
38
|
+
_level = @levels[level]
|
39
|
+
raise "No level at '#{index}'!" unless _level
|
40
|
+
raise "No sprite at '#{current_sprite}'!" unless @sprites[current_sprite]
|
41
|
+
raise "No sprite at '#{current_sprite}'!" unless @sprites[replacement_sprite]
|
42
|
+
|
43
|
+
_level.each {|sprite| sprite.sprite = replacement_sprite if sprite.sprite == current_sprite}
|
44
|
+
end
|
45
|
+
|
28
46
|
def translate(x, y, &block)
|
29
47
|
Gosu.translate(x, y) do
|
30
48
|
block.call if block
|
File without changes
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "opal"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
class AuthorEngine
|
5
|
+
class OpalExporter
|
6
|
+
def initialize(project_file:)
|
7
|
+
@project_file = project_file
|
8
|
+
|
9
|
+
save(export)
|
10
|
+
end
|
11
|
+
|
12
|
+
def project_name
|
13
|
+
name = File.basename(@project_file, ".authorengine")
|
14
|
+
return name.split("_").map {|n| n.capitalize}.join(" ")
|
15
|
+
end
|
16
|
+
|
17
|
+
def stylesheet
|
18
|
+
%{
|
19
|
+
@font-face { font-family: Connection; src: url('fonts/Connection.otf'); }
|
20
|
+
@font-face { font-family: ConnectionBold; src: url('fonts/ConnectionBold.otf'); }
|
21
|
+
|
22
|
+
body {
|
23
|
+
margin: 0;
|
24
|
+
padding: 0;
|
25
|
+
background: #222;
|
26
|
+
}
|
27
|
+
#canvas {
|
28
|
+
display: block;
|
29
|
+
margin: 0 auto;
|
30
|
+
cursor: none;
|
31
|
+
}
|
32
|
+
#loading {
|
33
|
+
font-family: Connection, sans serif;
|
34
|
+
color: white;
|
35
|
+
text-align: center;
|
36
|
+
|
37
|
+
position: absolute;
|
38
|
+
top: 0;
|
39
|
+
bottom: 0;
|
40
|
+
left: 0;
|
41
|
+
right: 0;
|
42
|
+
width: 50%;
|
43
|
+
height: 30%;
|
44
|
+
margin: auto;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def project
|
50
|
+
%{
|
51
|
+
var projectString = `#{File.open(@project_file).read}`;
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def game_runtime
|
56
|
+
program = %{
|
57
|
+
require "opal"
|
58
|
+
require "opal-parser"
|
59
|
+
require "author_engine/opal"
|
60
|
+
|
61
|
+
`var callback = function(){
|
62
|
+
\#{AuthorEngine::GameRunner.new(`projectString`).show}
|
63
|
+
};
|
64
|
+
|
65
|
+
if (
|
66
|
+
document.readyState === "complete" ||
|
67
|
+
(document.readyState !== "loading" && !document.documentElement.doScroll)
|
68
|
+
) {
|
69
|
+
callback();
|
70
|
+
} else {
|
71
|
+
document.addEventListener("DOMContentLoaded", callback);
|
72
|
+
}`
|
73
|
+
}
|
74
|
+
|
75
|
+
builder = Opal::Builder.new
|
76
|
+
base_path = File.expand_path("../../../..", __FILE__)
|
77
|
+
builder.append_paths("#{base_path}")
|
78
|
+
|
79
|
+
puts "Transpiling to JavaScript using Opal..."
|
80
|
+
|
81
|
+
|
82
|
+
builder.build("opal")
|
83
|
+
builder.build("opal-parser")
|
84
|
+
builder.build_require("author_engine/opal")
|
85
|
+
|
86
|
+
builder.build_str(program, "(inline)").to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def template
|
90
|
+
%{
|
91
|
+
<!doctype html5>
|
92
|
+
<html>
|
93
|
+
<head>
|
94
|
+
<meta charset="utf-8" />
|
95
|
+
<title>#{project_name} | AuthorEngine</title>
|
96
|
+
</head>
|
97
|
+
<style>
|
98
|
+
#{stylesheet}
|
99
|
+
</style>
|
100
|
+
<body>
|
101
|
+
<h1 id="loading">Loading...</h1>
|
102
|
+
<canvas id="canvas">
|
103
|
+
<h1>Your Browser Does Not Support HTML5 Canvas!</h1>
|
104
|
+
</canvas>
|
105
|
+
|
106
|
+
<script>
|
107
|
+
// Add a small delay before loading application in order to finish loading page and show "Loading..."
|
108
|
+
window.setTimeout(function() {
|
109
|
+
var script = document.createElement('script');
|
110
|
+
script.src = "application.js";
|
111
|
+
|
112
|
+
document.head.appendChild(script);
|
113
|
+
}, 500);
|
114
|
+
</script>
|
115
|
+
</body>
|
116
|
+
</html>
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
def export
|
121
|
+
template
|
122
|
+
end
|
123
|
+
|
124
|
+
def save(string)
|
125
|
+
filename = File.basename(@project_file)
|
126
|
+
directory = File.expand_path(@project_file.sub(filename, ''))
|
127
|
+
name = filename.sub(".authorengine", "")
|
128
|
+
|
129
|
+
export_path = "#{directory}/#{name}"
|
130
|
+
unless File.exists?(export_path)
|
131
|
+
Dir.mkdir(export_path)
|
132
|
+
unless File.exists?("#{export_path}/fonts")
|
133
|
+
Dir.mkdir("#{export_path}/fonts")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
puts "Saving to \"#{export_path}\""
|
138
|
+
File.open("#{export_path}/#{name}.html", "w") do |file|
|
139
|
+
file.write(string)
|
140
|
+
end
|
141
|
+
|
142
|
+
File.open("#{export_path}/application.js", "w") do |file|
|
143
|
+
file.write(project)
|
144
|
+
file.write("\n\n\n")
|
145
|
+
file.write(game_runtime)
|
146
|
+
end
|
147
|
+
|
148
|
+
fonts_path = "#{File.expand_path("../../../../../", __FILE__)}/assets/fonts"
|
149
|
+
font_files = Dir.glob("#{fonts_path}/*")
|
150
|
+
font_files.each do |file|
|
151
|
+
FileUtils.cp(file, "#{export_path}/fonts/#{File.basename(file)}")
|
152
|
+
end
|
153
|
+
|
154
|
+
puts "Saved."
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|