author_engine 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,158 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class GameRunner
|
3
|
+
def self.instance
|
4
|
+
@instance
|
5
|
+
end
|
6
|
+
def self.instance=(klass)
|
7
|
+
@instance = klass
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :save_file, :spritesheet, :sprites, :levels, :fps
|
11
|
+
attr_reader :game
|
12
|
+
def initialize(project_string)
|
13
|
+
AuthorEngine::GameRunner.instance=(self)
|
14
|
+
|
15
|
+
@save_file = AuthorEngine::SaveFile.new(nil)
|
16
|
+
@save_file.load(false, project_string)
|
17
|
+
|
18
|
+
size = 16
|
19
|
+
|
20
|
+
@levels = @save_file.levels
|
21
|
+
@levels.each {|level| level.each {|sprite| sprite.x = sprite.x * size; sprite.y = sprite.y * size}}
|
22
|
+
|
23
|
+
@sprites = []
|
24
|
+
@spritesheet = nil
|
25
|
+
@spritesheet_width = @save_file.sprites.columns
|
26
|
+
@spritesheet_height = @save_file.sprites.rows
|
27
|
+
@sprite_size = 16
|
28
|
+
|
29
|
+
@fps = 0
|
30
|
+
@counted_frames = 0
|
31
|
+
@frame_count_stated_at = 0
|
32
|
+
|
33
|
+
@game = Game.new(code: @save_file.code)
|
34
|
+
build_spritesheet_and_sprites_list
|
35
|
+
resize_canvas
|
36
|
+
|
37
|
+
@collision_detection = AuthorEngine::CollisionDetection.new(@sprites, @levels)
|
38
|
+
@game.collision_detection = @collision_detection
|
39
|
+
|
40
|
+
@levels.each {|level| @collision_detection.add_level(level) }
|
41
|
+
|
42
|
+
@game.init
|
43
|
+
|
44
|
+
return self
|
45
|
+
end
|
46
|
+
|
47
|
+
def draw
|
48
|
+
@game.draw_background
|
49
|
+
@game.draw
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def update
|
54
|
+
@game.update
|
55
|
+
return nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_game
|
59
|
+
`window.requestAnimationFrame(function() {#{run_game}})` # placed here to ensure next frame is called even if draw or update throw an error
|
60
|
+
|
61
|
+
@counted_frames+=1
|
62
|
+
|
63
|
+
if @game.milliseconds - @frame_count_stated_at >= 1000.0
|
64
|
+
@fps = @counted_frames
|
65
|
+
@frame_count_stated_at = @game.milliseconds
|
66
|
+
@counted_frames = 0
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
if @sprites.size == (@spritesheet_width/@sprite_size)*(@spritesheet_height/@sprite_size)
|
71
|
+
draw
|
72
|
+
update
|
73
|
+
else
|
74
|
+
@game.draw_background
|
75
|
+
@game.text("Loading sprite #{@sprites.size}/#{(@spritesheet_width/@sprite_size)*(@spritesheet_height/@sprite_size)}.", 0, @game.height/2, 8)
|
76
|
+
end
|
77
|
+
|
78
|
+
return nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def resize_canvas
|
82
|
+
width = `window.innerWidth`
|
83
|
+
height = `window.innerHeight`
|
84
|
+
|
85
|
+
if width < height
|
86
|
+
@game.scale = `window.innerWidth / 128.0`
|
87
|
+
else
|
88
|
+
@game.scale = `window.innerHeight / 128.0`
|
89
|
+
end
|
90
|
+
|
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}`
|
95
|
+
|
96
|
+
`#{@game.canvas_context}.scale(#{@game.scale}, #{@game.scale})`
|
97
|
+
`#{@game.canvas_context}.imageSmoothingEnabled = false`
|
98
|
+
return nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def build_spritesheet_and_sprites_list
|
102
|
+
spritesheet_data = @save_file.sprites
|
103
|
+
width = spritesheet_data.columns
|
104
|
+
height= spritesheet_data.rows
|
105
|
+
size = 16
|
106
|
+
|
107
|
+
temp_canvas = `document.createElement('canvas')`
|
108
|
+
temp_canvas_context = `#{temp_canvas}.getContext('2d')`
|
109
|
+
`#{temp_canvas}.width = #{spritesheet_data.columns}`
|
110
|
+
`#{temp_canvas}.height = #{spritesheet_data.rows}`
|
111
|
+
|
112
|
+
buffer = `new Uint8ClampedArray(#{spritesheet_data.to_blob})`
|
113
|
+
image_data = `new ImageData(#{buffer}, #{width})`
|
114
|
+
`#{temp_canvas_context}.putImageData(#{image_data}, 0, 0)`
|
115
|
+
|
116
|
+
@spritesheet = `new Image()`
|
117
|
+
`#{@spritesheet}.onload = function() { #{load_sprites} }`
|
118
|
+
`#{@spritesheet}.src = #{temp_canvas}.toDataURL()`
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
def load_sprites
|
123
|
+
spritesheet_data = @save_file.sprites
|
124
|
+
width = spritesheet_data.columns
|
125
|
+
height= spritesheet_data.rows
|
126
|
+
size = 16
|
127
|
+
|
128
|
+
temp_canvas = `document.createElement('canvas')`
|
129
|
+
temp_canvas_context = `#{temp_canvas}.getContext('2d')`
|
130
|
+
`#{temp_canvas}.width = #{size}`
|
131
|
+
`#{temp_canvas}.height = #{size}`
|
132
|
+
|
133
|
+
(height/size).times do |y|
|
134
|
+
(width/size).times do |x|
|
135
|
+
`#{temp_canvas_context}.clearRect(0,0, #{size}, #{size})`
|
136
|
+
`#{temp_canvas_context}.drawImage(#{@spritesheet}, #{x * size}, #{y * size}, #{size}, #{size}, 0, 0, #{size}, #{size})`
|
137
|
+
@collision_detection.add_sprite(`#{temp_canvas_context}.getImageData(0,0, #{size}, #{size}).data`)
|
138
|
+
|
139
|
+
`createImageBitmap(#{@spritesheet}, #{x * size}, #{y * size}, #{size}, #{size}).then(sprite => { #{@sprites.push(`sprite`)} })`
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
return nil
|
144
|
+
end
|
145
|
+
|
146
|
+
def show(update_interval = (1000.0 / 60))
|
147
|
+
return unless RUBY_ENGINE == "opal"
|
148
|
+
|
149
|
+
`window.addEventListener('resize', () => { #{resize_canvas} })`
|
150
|
+
`document.addEventListener('keydown', (event) => { #{AuthorEngine::Part::Input::KEY_STATES[`event.key`] = true} })`
|
151
|
+
`document.addEventListener('keyup', (event) => { #{AuthorEngine::Part::Input::KEY_STATES[`event.key`] = false} })`
|
152
|
+
|
153
|
+
`document.getElementById('loading').style.display = "none"`
|
154
|
+
`window.requestAnimationFrame(function() {#{run_game}})`
|
155
|
+
return nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class Part
|
3
|
+
module Colors
|
4
|
+
Color = Struct.new(:red, :green, :blue)
|
5
|
+
COLORS = {
|
6
|
+
0 => Color.new(0,0,0),
|
7
|
+
1 => Color.new(29, 43, 83),
|
8
|
+
2 => Color.new(126, 37, 83),
|
9
|
+
3 => Color.new(0, 135, 81),
|
10
|
+
|
11
|
+
4 => Color.new(171, 82, 54),
|
12
|
+
5 => Color.new(95, 87, 79),
|
13
|
+
6 => Color.new(194, 195, 199),
|
14
|
+
7 => Color.new(255, 241, 232),
|
15
|
+
|
16
|
+
8 => Color.new(255, 0, 77),
|
17
|
+
9 => Color.new(255, 163, 0),
|
18
|
+
10 => Color.new(225, 236, 39),
|
19
|
+
11 => Color.new(0, 228, 54),
|
20
|
+
|
21
|
+
12 => Color.new(41, 173, 255),
|
22
|
+
13 => Color.new(131, 118, 156),
|
23
|
+
14 => Color.new(225, 119, 168),
|
24
|
+
15 => Color.new(255, 204, 170)
|
25
|
+
}
|
26
|
+
|
27
|
+
def black; rgb(COLORS.dig(0)); end
|
28
|
+
def dark_blue; rgb(COLORS.dig(1)); end
|
29
|
+
def dark_purple; rgb(COLORS.dig(2)); end
|
30
|
+
def dark_green; rgb(COLORS.dig(3)); end
|
31
|
+
|
32
|
+
def brown; rgb(COLORS.dig(4)); end
|
33
|
+
def dark_gray; rgb(COLORS.dig(5)); end
|
34
|
+
def light_gray; rgb(COLORS.dig(6)); end
|
35
|
+
def white; rgb(COLORS.dig(7)); end
|
36
|
+
|
37
|
+
def red; rgb(COLORS.dig(8)); end
|
38
|
+
def orange; rgb(COLORS.dig(9)); end
|
39
|
+
def yellow; rgb(COLORS.dig(10)); end
|
40
|
+
def green; rgb(COLORS.dig(11)); end
|
41
|
+
|
42
|
+
def blue; rgb(COLORS.dig(12)); end
|
43
|
+
def indigo; rgb(COLORS.dig(13)); end
|
44
|
+
def pink; rgb(COLORS.dig(14)); end
|
45
|
+
def peach; rgb(COLORS.dig(15)); end
|
46
|
+
|
47
|
+
def rgb(color)
|
48
|
+
return "rgb(#{color.red}, #{color.green}, #{color.blue})"
|
49
|
+
end
|
50
|
+
|
51
|
+
def xml_color(color)
|
52
|
+
red = color.red.to_s(16)
|
53
|
+
green = color.green.to_s(16)
|
54
|
+
blue = color.blue.to_s(16)
|
55
|
+
|
56
|
+
red = "0#{red}" if color.red < 10
|
57
|
+
green = "0#{green}" if color.green < 10
|
58
|
+
blue = "0#{blue}" if color.blue < 10
|
59
|
+
|
60
|
+
return "#{red}#{green}#{blue}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class Part
|
3
|
+
module Common
|
4
|
+
def width; 128; end
|
5
|
+
def height; 128; end
|
6
|
+
def fps; AuthorEngine::GameRunner.instance.fps; end
|
7
|
+
def milliseconds
|
8
|
+
@__initial_milliseconds ||= `performance.now()`
|
9
|
+
(`performance.now()` - @__initial_milliseconds).round(3)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class Part
|
3
|
+
module Graphics
|
4
|
+
def rect(x = 0, y = 0, width = 1, height = 1, color = "white", z = 0)
|
5
|
+
`#{@canvas_context}.fillStyle = #{color}`
|
6
|
+
`#{@canvas_context}.fillRect(#{x}, #{y}, #{width}, #{height})`
|
7
|
+
return nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def sprite(sprite_sheet_index, x = 0, y = 0, z = 0, alpha = 255)
|
11
|
+
size = 16 # sprite size
|
12
|
+
sprites = AuthorEngine::GameRunner.instance.sprites
|
13
|
+
|
14
|
+
`#{@canvas_context}.save()`
|
15
|
+
if alpha <= 0
|
16
|
+
alpha = 0
|
17
|
+
else
|
18
|
+
alpha = (alpha / 255.0)
|
19
|
+
end
|
20
|
+
`#{@canvas_context}.globalAlpha = #{alpha}`
|
21
|
+
|
22
|
+
`#{@canvas_context}.drawImage(#{sprites[sprite_sheet_index]}, #{x}, #{y})`
|
23
|
+
|
24
|
+
`#{@canvas_context}.restore()`
|
25
|
+
end
|
26
|
+
|
27
|
+
def text(string, x = 0, y = 0, size = 4, z = 0, color = "white")
|
28
|
+
font = "#{size}px Connection, Consolas"
|
29
|
+
`#{@canvas_context}.font = #{font}`
|
30
|
+
`#{@canvas_context}.fillStyle = #{color}`
|
31
|
+
`#{@canvas_context}.textBaseline = "top"`
|
32
|
+
`#{@canvas_context}.fillText(#{string}, #{x}, #{y})`
|
33
|
+
end
|
34
|
+
|
35
|
+
def level(index, z = 0)
|
36
|
+
_level = AuthorEngine::GameRunner.instance.levels[index]
|
37
|
+
raise "No level at '#{index}'!" unless _level
|
38
|
+
|
39
|
+
_level.each do |sprite|
|
40
|
+
sprite(sprite.sprite, sprite.x, sprite.y, z)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def swap(level, current_sprite, replacement_sprite)
|
45
|
+
_level = AuthorEngine::GameRunner.instance.levels[level]
|
46
|
+
raise "No level at '#{index}'!" unless _level
|
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]
|
49
|
+
|
50
|
+
_level.each {|sprite| sprite.sprite = replacement_sprite if sprite.sprite == current_sprite}
|
51
|
+
end
|
52
|
+
|
53
|
+
def translate(x, y, &block)
|
54
|
+
`#{@canvas_context}.save()`
|
55
|
+
`#{@canvas_context}.translate(#{x}, #{y})`
|
56
|
+
block.call if block
|
57
|
+
`#{@canvas_context}.restore()`
|
58
|
+
end
|
59
|
+
|
60
|
+
def rotate(angle, x = 0, y = 0, &block)
|
61
|
+
`#{@canvas_context}.save()`
|
62
|
+
`#{@canvas_context}.translate(#{x}, #{y})`
|
63
|
+
`#{@canvas_context}.rotate(#{angle})`
|
64
|
+
block.call if block
|
65
|
+
`#{@canvas_context}.restore()`
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class Part
|
3
|
+
module Input
|
4
|
+
BUTTONS = {
|
5
|
+
"left" => "ArrowLeft",
|
6
|
+
"right" => "ArrowRight",
|
7
|
+
"up" => "ArrowUp",
|
8
|
+
"down" => "ArrowDown",
|
9
|
+
"x" => "x",
|
10
|
+
"y" => "c",
|
11
|
+
}
|
12
|
+
|
13
|
+
# Store keys state
|
14
|
+
KEY_STATES = {
|
15
|
+
}
|
16
|
+
|
17
|
+
def button?(name)
|
18
|
+
down = false
|
19
|
+
|
20
|
+
if BUTTONS.dig(name)
|
21
|
+
down = KEY_STATES.dig(BUTTONS.dig(name)) # dig returns false if key not found
|
22
|
+
else
|
23
|
+
raise "Button '#{name}' not found!"
|
24
|
+
end
|
25
|
+
|
26
|
+
return down
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/author_engine/image.rb
CHANGED
@@ -0,0 +1,92 @@
|
|
1
|
+
class AuthorEngine
|
2
|
+
class LevelPicker
|
3
|
+
include Support
|
4
|
+
|
5
|
+
attr_reader :x, :y, :z, :width, :height, :offset
|
6
|
+
attr_reader :active_level, :active_layer
|
7
|
+
def initialize(x: nil, y: nil, z: 15)
|
8
|
+
@x, @y, @z = x, y, z
|
9
|
+
|
10
|
+
@offset = 1 * window.square_scale
|
11
|
+
@width = window.width - @offset * 4
|
12
|
+
@height = (window.sprite_size * window.square_scale) + @offset * 2
|
13
|
+
|
14
|
+
@x = window.width / 2 - self.width / 2
|
15
|
+
|
16
|
+
@current_level = AuthorEngine::Text.new(y: @y + @offset*2, z: @z + 1)
|
17
|
+
|
18
|
+
@active_level = 0
|
19
|
+
@active_layer = 0
|
20
|
+
|
21
|
+
@max_layers = 16
|
22
|
+
|
23
|
+
@buttons = []
|
24
|
+
|
25
|
+
@buttons << Button.new(label: "-", color: Gosu::Color::GRAY, x: (window.width / 2) - @offset*8, y: @y + @offset*2, z: 18, tooltip: "↓ Decrease Layer") do
|
26
|
+
@active_layer-=1 unless @active_layer < 1
|
27
|
+
end
|
28
|
+
@buttons << Button.new(label: "+", color: Gosu::Color::GRAY, x: (@buttons.last.x + @buttons.last.width) + @offset*2, y: @y + @offset*2, z: 18, tooltip: "↑ Increase Layer") do
|
29
|
+
@active_layer+=1 if @active_layer < @max_layers
|
30
|
+
end
|
31
|
+
|
32
|
+
@buttons << Button.new(label: "<", x: (@x + @width) - @width/3, y: @y + @offset*2, z: 18, tooltip: "← Previous Level", color: Gosu::Color::GRAY) do
|
33
|
+
@active_level-=1
|
34
|
+
@active_level = LevelEditor.instance.levels.size - 1 if @active_level < 0
|
35
|
+
end
|
36
|
+
|
37
|
+
@buttons << Button.new(label: "-", x: @buttons.last.x + @buttons.last.width + @offset, y: @y + @offset*2, z: 18, tooltip: "Destroy Level (Non-recoverable)", color: Gosu::Color::RED) do
|
38
|
+
if LevelEditor.instance.levels[@active_level].is_a?(Array)
|
39
|
+
LevelEditor.instance.levels.delete_at(@active_level)
|
40
|
+
@active_level-=1
|
41
|
+
end
|
42
|
+
|
43
|
+
if LevelEditor.instance.levels.size == 0
|
44
|
+
LevelEditor.instance.levels.push([])
|
45
|
+
@active_level = LevelEditor.instance.levels.size - 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
@buttons << Button.new(label: "+", x: @buttons.last.x + @buttons.last.width + @offset, y: @y + @offset*2, z: 18, tooltip: "Add Level", color: Gosu::Color::GREEN) do
|
50
|
+
LevelEditor.instance.levels.push([])
|
51
|
+
@active_level = LevelEditor.instance.levels.size - 1
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
@buttons << Button.new(label: ">", x: @buttons.last.x + @buttons.last.width + @offset, y: @y + @offset*2, z: 18, tooltip: "→ Next Level", color: Gosu::Color::GRAY) do
|
56
|
+
@active_level+=1
|
57
|
+
@active_level = 0 if @active_level >= LevelEditor.instance.levels.size - 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def draw
|
62
|
+
Gosu.draw_rect(@x, @y, @width, @height, Gosu::Color.rgba(255,255,255,220), @z)
|
63
|
+
Gosu.draw_rect(@x+4, @y+4, @width-8, @height-8, Gosu::Color.rgba(10, 10, 10,200), @z)
|
64
|
+
|
65
|
+
@buttons.each(&:draw)
|
66
|
+
|
67
|
+
@current_level.message = "Level: #{@active_level}\nLayer: #{@active_layer}/#{@max_layers}"
|
68
|
+
@current_level.x = @x + @offset*2
|
69
|
+
@current_level.draw
|
70
|
+
end
|
71
|
+
|
72
|
+
def button_up(id)
|
73
|
+
@buttons.each {|b| b.button_up(id) }
|
74
|
+
|
75
|
+
case id
|
76
|
+
when Gosu::KbUp
|
77
|
+
@active_layer+=1 if @active_layer < @max_layers
|
78
|
+
|
79
|
+
when Gosu::KbDown
|
80
|
+
@active_layer-=1 unless @active_layer < 1
|
81
|
+
|
82
|
+
when Gosu::KbLeft
|
83
|
+
@active_level -= 1
|
84
|
+
@active_level = LevelEditor.instance.levels.size - 1 if @active_level < 0
|
85
|
+
|
86
|
+
when Gosu::KbRight
|
87
|
+
@active_level += 1
|
88
|
+
@active_level = 0 unless @active_level < LevelEditor.instance.levels.size
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
raise "Only require \"author_engine/opal\" with Opal!" unless RUBY_ENGINE == "opal"
|
2
|
+
|
3
|
+
require_relative "game/common/parts/collision_detection"
|
4
|
+
|
5
|
+
require_relative "game/opal/parts/common"
|
6
|
+
require_relative "game/opal/parts/colors"
|
7
|
+
require_relative "game/opal/parts/graphics"
|
8
|
+
require_relative "game/opal/parts/input"
|
9
|
+
|
10
|
+
require_relative "collision_detection/collision_detection"
|
11
|
+
require_relative "sprite"
|
12
|
+
|
13
|
+
require_relative "game/game"
|
14
|
+
require_relative "save_file"
|
15
|
+
require_relative "game/opal/game_runner"
|
@@ -23,7 +23,7 @@ class AuthorEngine
|
|
23
23
|
|
24
24
|
@code, @sprites, @levels = nil, nil, nil
|
25
25
|
|
26
|
-
load
|
26
|
+
load unless RUBY_ENGINE == "opal"
|
27
27
|
end
|
28
28
|
|
29
29
|
def save
|
@@ -64,23 +64,29 @@ class AuthorEngine
|
|
64
64
|
|
65
65
|
def save_levels
|
66
66
|
@buffer+= "___LEVELS___\n"
|
67
|
-
|
68
|
-
|
67
|
+
LevelEditor.instance.levels.each do |level|
|
68
|
+
@buffer+= "#{level.map {|s| "#{s.sprite},#{s.x},#{s.y},#{s.z}"}.join(",")}\n"
|
69
|
+
end
|
70
|
+
@buffer.strip # Level is the last element saved
|
69
71
|
end
|
70
72
|
|
71
|
-
def load
|
72
|
-
|
73
|
-
|
73
|
+
def load(from_file = true, data = nil)
|
74
|
+
string = ""
|
75
|
+
if from_file
|
76
|
+
File.open(@file, "r") {|f| string = f.read}
|
77
|
+
else
|
78
|
+
string = data
|
79
|
+
end
|
74
80
|
|
75
|
-
load_code(
|
76
|
-
load_spritesheet(
|
77
|
-
load_levels(
|
81
|
+
load_code(string)
|
82
|
+
load_spritesheet(string)
|
83
|
+
load_levels(string)
|
78
84
|
end
|
79
85
|
|
80
|
-
def load_code(
|
86
|
+
def load_code(string)
|
81
87
|
buffer = ""
|
82
88
|
in_code= false
|
83
|
-
|
89
|
+
string.each_line do |line|
|
84
90
|
if line.start_with?("___CODE___")
|
85
91
|
in_code = true
|
86
92
|
next
|
@@ -95,13 +101,13 @@ class AuthorEngine
|
|
95
101
|
@code = buffer
|
96
102
|
end
|
97
103
|
|
98
|
-
def load_spritesheet(
|
104
|
+
def load_spritesheet(string)
|
99
105
|
buffer = ""
|
100
106
|
width = 0
|
101
107
|
height = 0
|
102
108
|
in_sprites = false
|
103
109
|
|
104
|
-
|
110
|
+
string.each_line do |line|
|
105
111
|
if line.strip.start_with?("___SPRITES___")
|
106
112
|
in_sprites = true
|
107
113
|
next
|
@@ -123,12 +129,40 @@ class AuthorEngine
|
|
123
129
|
buffer += line.strip
|
124
130
|
end
|
125
131
|
|
126
|
-
stream =
|
132
|
+
stream = nil
|
133
|
+
if RUBY_ENGINE != "opal"
|
134
|
+
stream = buffer.scan(/../).map { |x| x.hex }.pack('c*')
|
135
|
+
else
|
136
|
+
stream = buffer.scan(/../).map { |x| Integer(x.hex) }
|
137
|
+
end
|
127
138
|
|
128
139
|
@sprites = SpriteSheetData.new(width, height, stream)
|
129
140
|
end
|
130
141
|
|
131
|
-
def load_levels(
|
142
|
+
def load_levels(string)
|
143
|
+
levels = []
|
144
|
+
in_level = false
|
145
|
+
|
146
|
+
string.each_line do |line|
|
147
|
+
if line.start_with?("___LEVELS___")
|
148
|
+
in_level = true
|
149
|
+
next
|
150
|
+
end
|
151
|
+
if line.start_with?("___") && in_level
|
152
|
+
break
|
153
|
+
end
|
154
|
+
|
155
|
+
if in_level
|
156
|
+
level = []
|
157
|
+
# 0 - Sprite, 1 - X, 2 - Y, 3 - Z
|
158
|
+
line.strip.split(",").each_slice(4) do |sprite|
|
159
|
+
level << Sprite.new(Integer(sprite[0]), Integer(sprite[1]), Integer(sprite[2]), Integer(sprite[3]))
|
160
|
+
end
|
161
|
+
levels << level
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
@levels = levels
|
132
166
|
end
|
133
167
|
end
|
134
168
|
end
|
data/lib/author_engine/sprite.rb
CHANGED
@@ -4,7 +4,7 @@ class AuthorEngine
|
|
4
4
|
|
5
5
|
attr_reader :active_sprite
|
6
6
|
attr_reader :x, :y, :width, :height
|
7
|
-
attr_reader :rows, :columns
|
7
|
+
attr_reader :rows, :columns, :offset
|
8
8
|
def initialize(x: nil, y:, width: nil, height: nil)
|
9
9
|
@x, @y, @width, @height = x, y, width, height
|
10
10
|
@sprite_size = window.sprite_size
|
@@ -21,19 +21,26 @@ class AuthorEngine
|
|
21
21
|
|
22
22
|
@offset = 1 * window.square_scale
|
23
23
|
@tooltip = AuthorEngine::Text.new(message: "", z: 100)
|
24
|
-
@current_page = AuthorEngine::Text.new(message: "Page 0", size: 20, x: window.width/2,
|
24
|
+
@current_page = AuthorEngine::Text.new(message: "Page 0", size: 20, x: window.width/2, z: 100)
|
25
25
|
|
26
26
|
@page = 0
|
27
27
|
end
|
28
28
|
|
29
|
+
def y=(n)
|
30
|
+
@y = n
|
31
|
+
end
|
32
|
+
|
29
33
|
def draw
|
30
|
-
|
34
|
+
@current_page.y = @y - 24
|
35
|
+
|
36
|
+
Gosu.draw_rect(@x-@offset, @y-@offset, @width+(@offset*2), @height+(@offset*2), Gosu::Color.rgba(255,255,255,220), 15)
|
31
37
|
Gosu.draw_rect(@x, @y, @width, @height, Gosu::Color.rgba(10, 10, 10, 200), 15)
|
32
38
|
draw_grid
|
33
39
|
draw_sprites
|
34
40
|
|
35
41
|
draw_and_update_tooltip
|
36
42
|
@current_page.message = "Page #{@page}"
|
43
|
+
@current_page.x = @width/2 - @current_page.width/2
|
37
44
|
@current_page.draw
|
38
45
|
end
|
39
46
|
|
data/lib/author_engine/text.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
class AuthorEngine
|
2
2
|
class Text
|
3
3
|
include Support
|
4
|
-
FONT_DEFAULT
|
5
|
-
FONT_DEFAULT_BOLD = "assets/fonts/ConnectionBold.otf"
|
4
|
+
FONT_DEFAULT = "#{File.expand_path("../../../", __FILE__)}/assets/fonts/Connection.otf"
|
5
|
+
FONT_DEFAULT_BOLD = "#{File.expand_path("../../../", __FILE__)}/assets/fonts/ConnectionBold.otf"
|
6
6
|
|
7
7
|
attr_accessor :message, :x, :y, :z, :color
|
8
8
|
attr_reader :size, :font
|