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.
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