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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/API.md +20 -0
  4. data/Gemfile.lock +13 -2
  5. data/README.md +8 -4
  6. data/author_engine.gemspec +2 -1
  7. data/bin/author_engine +3 -1
  8. data/lib/author_engine/button.rb +1 -1
  9. data/lib/author_engine/cli.rb +21 -0
  10. data/lib/author_engine/collision_detection/collision_detection.rb +188 -0
  11. data/lib/author_engine/containers/loader.rb +8 -1
  12. data/lib/author_engine/game/common/parts/collision_detection.rb +33 -0
  13. data/lib/author_engine/game/game.rb +28 -2
  14. data/lib/author_engine/game/{parts → gosu/parts}/colors.rb +0 -0
  15. data/lib/author_engine/game/{parts → gosu/parts}/common.rb +0 -0
  16. data/lib/author_engine/game/{parts → gosu/parts}/graphics.rb +19 -1
  17. data/lib/author_engine/game/{parts → gosu/parts}/input.rb +0 -0
  18. data/lib/author_engine/game/opal/exporter.rb +157 -0
  19. data/lib/author_engine/game/opal/game_runner.rb +158 -0
  20. data/lib/author_engine/game/opal/parts/colors.rb +64 -0
  21. data/lib/author_engine/game/opal/parts/common.rb +13 -0
  22. data/lib/author_engine/game/opal/parts/graphics.rb +69 -0
  23. data/lib/author_engine/game/opal/parts/input.rb +30 -0
  24. data/lib/author_engine/image.rb +1 -0
  25. data/lib/author_engine/level_picker.rb +92 -0
  26. data/lib/author_engine/opal.rb +15 -0
  27. data/lib/author_engine/save_file.rb +49 -15
  28. data/lib/author_engine/sprite.rb +1 -2
  29. data/lib/author_engine/sprite_picker.rb +10 -3
  30. data/lib/author_engine/text.rb +2 -2
  31. data/lib/author_engine/version.rb +1 -1
  32. data/lib/author_engine/views/level_editor.rb +161 -0
  33. data/lib/author_engine/views/play_viewer.rb +1 -0
  34. data/lib/author_engine.rb +9 -4
  35. data/screenshots/code_editor.png +0 -0
  36. data/screenshots/play.png +0 -0
  37. data/screenshots/sprite_editor.png +0 -0
  38. metadata +36 -9
  39. data/test_3.authorengine +0 -519
  40. 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
@@ -12,6 +12,7 @@ class AuthorEngine
12
12
  def height; @image.height; end
13
13
 
14
14
  def image_from_cache(path)
15
+ path = "#{File.expand_path("../../../", __FILE__)}/#{path}"
15
16
  image = nil
16
17
  if image = CACHE.dig(path)
17
18
  return image
@@ -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
- # @buffer+= LevelEditor.instance.levels
68
- @buffer+="\n"
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
- file = ""
73
- File.open(@file, "r") {|f| file = f.read}
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(file)
76
- load_spritesheet(file)
77
- load_levels(file)
81
+ load_code(string)
82
+ load_spritesheet(string)
83
+ load_levels(string)
78
84
  end
79
85
 
80
- def load_code(file)
86
+ def load_code(string)
81
87
  buffer = ""
82
88
  in_code= false
83
- file.each_line do |line|
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(file)
104
+ def load_spritesheet(string)
99
105
  buffer = ""
100
106
  width = 0
101
107
  height = 0
102
108
  in_sprites = false
103
109
 
104
- file.each_line do |line|
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 = buffer.scan(/../).map { |x| x.hex }.pack('c*')
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(file)
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
@@ -1,4 +1,3 @@
1
1
  class AuthorEngine
2
- class Sprite
3
- end
2
+ Sprite = Struct.new(:sprite, :x, :y, :z)
4
3
  end
@@ -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, y: @y - 24, z: 100)
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
- Gosu.draw_rect(@x-@offset, @y-@offset, @width+(@offset*2), @height+(@offset*2), Gosu::Color::WHITE, 15)
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
 
@@ -1,8 +1,8 @@
1
1
  class AuthorEngine
2
2
  class Text
3
3
  include Support
4
- FONT_DEFAULT = "assets/fonts/Connection.otf"
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
@@ -1,3 +1,3 @@
1
1
  class AuthorEngine
2
- VERSION = "0.1.0"
2
+ VERSION = "0.3.0"
3
3
  end