smash_and_grab 0.0.3alpha → 0.0.5alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +31 -16
- data/config/gui/schema.yml +3 -2
- data/config/map/entities.yml +36 -12
- data/lib/smash_and_grab/abilities/ability.rb +5 -0
- data/lib/smash_and_grab/abilities/melee.rb +11 -5
- data/lib/smash_and_grab/abilities/ranged.rb +20 -0
- data/lib/smash_and_grab/abilities/sprint.rb +4 -0
- data/lib/smash_and_grab/abilities.rb +3 -1
- data/lib/smash_and_grab/fidgit_ext/event.rb +77 -0
- data/lib/smash_and_grab/gui/editor_selector.rb +54 -73
- data/lib/smash_and_grab/gui/entity_panel.rb +110 -0
- data/lib/smash_and_grab/gui/entity_summary.rb +9 -8
- data/lib/smash_and_grab/gui/game_log.rb +44 -0
- data/lib/smash_and_grab/gui/info_panel.rb +39 -95
- data/lib/smash_and_grab/gui/object_panel.rb +37 -0
- data/lib/smash_and_grab/gui/scenario_panel.rb +21 -0
- data/lib/smash_and_grab/history/editor_actions/place_object.rb +1 -1
- data/lib/smash_and_grab/main.rb +11 -16
- data/lib/smash_and_grab/map/map.rb +1 -0
- data/lib/smash_and_grab/map/tile.rb +6 -3
- data/lib/smash_and_grab/map/wall.rb +4 -2
- data/lib/smash_and_grab/mouse_selection.rb +103 -46
- data/lib/smash_and_grab/objects/entity.rb +219 -30
- data/lib/smash_and_grab/objects/static.rb +7 -5
- data/lib/smash_and_grab/objects/vehicle.rb +7 -5
- data/lib/smash_and_grab/objects/world_object.rb +13 -3
- data/lib/smash_and_grab/path.rb +13 -7
- data/lib/smash_and_grab/players/player.rb +15 -10
- data/lib/smash_and_grab/states/edit_level.rb +17 -0
- data/lib/smash_and_grab/states/play_level.rb +20 -10
- data/lib/smash_and_grab/version.rb +1 -1
- data/lib/smash_and_grab.rb +18 -14
- data/test/smash_and_grab/abilities/melee_test.rb +37 -39
- data/test/teststrap.rb +3 -3
- metadata +21 -16
@@ -0,0 +1,110 @@
|
|
1
|
+
module SmashAndGrab
|
2
|
+
module Gui
|
3
|
+
class EntityPanel < Fidgit::Horizontal
|
4
|
+
event :info_toggled
|
5
|
+
|
6
|
+
def initialize(entity, info_shown, options = {})
|
7
|
+
options = {
|
8
|
+
padding: 0,
|
9
|
+
spacing: 8,
|
10
|
+
}.merge! options
|
11
|
+
|
12
|
+
super options
|
13
|
+
|
14
|
+
@entity = entity
|
15
|
+
@info_shown = info_shown
|
16
|
+
|
17
|
+
vertical padding: 0 do
|
18
|
+
# TODO: Clicking on portrait should center.
|
19
|
+
@portrait = image_frame @entity.image, padding: 0, background_color: Color::GRAY
|
20
|
+
@info_toggle = toggle_button "Bio", value: @info_shown, tip: "Show/hide biography",
|
21
|
+
font_height: 14, align_h: :center do |_, value|
|
22
|
+
@info_shown = value
|
23
|
+
publish :info_toggled, value
|
24
|
+
switch_sub_panel
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
vertical padding: 0, spacing: 4 do
|
29
|
+
@name = label @entity.name
|
30
|
+
@sub_panel_container = vertical spacing: 0, padding: 0
|
31
|
+
end
|
32
|
+
|
33
|
+
create_details_sub_panel
|
34
|
+
create_info_sub_panel
|
35
|
+
switch_sub_panel
|
36
|
+
|
37
|
+
update_details @entity
|
38
|
+
|
39
|
+
@entity.subscribe :changed, method(:update_details)
|
40
|
+
end
|
41
|
+
|
42
|
+
def switch_sub_panel
|
43
|
+
@sub_panel_container.clear
|
44
|
+
@sub_panel_container.add @info_shown ? @info_sub_panel : @details_sub_panel
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_info_sub_panel
|
48
|
+
@info_sub_panel = Fidgit::Vertical.new padding: 0, spacing: 0 do
|
49
|
+
text = nil
|
50
|
+
scroll = scroll_window width: 350, height: 72 do
|
51
|
+
text = text_area text: "#{@entity.name} once ate a pomegranate, but it took all day and all night... " * 5,
|
52
|
+
width: 330, font_height: 14, enabled: false
|
53
|
+
end
|
54
|
+
scroll.background_color = text.background_color
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_details_sub_panel
|
59
|
+
@details_sub_panel = Fidgit::Horizontal.new padding: 0, spacing: 0 do
|
60
|
+
vertical padding: 0, spacing: 1, width: 160 do
|
61
|
+
@health = label "", font_height: 20
|
62
|
+
@movement_points = label "", font_height: 20
|
63
|
+
@action_points = label "", font_height: 20
|
64
|
+
end
|
65
|
+
|
66
|
+
grid num_columns: 4, spacing: 4, padding: 0 do
|
67
|
+
button_options = { font_height: 20, width: 28, height: 28, padding: 0, padding_left: 8 }
|
68
|
+
|
69
|
+
@ability_buttons = {}
|
70
|
+
|
71
|
+
label_options = button_options.merge border_thickness: 2, border_color: Color.rgba(255, 255, 255, 100)
|
72
|
+
|
73
|
+
[:melee, :ranged, :sprint].each do |ability_name|
|
74
|
+
if @entity.has_ability? ability_name
|
75
|
+
ability = @entity.ability ability_name
|
76
|
+
@ability_buttons[ability_name] = button("#{ability_name.to_s[0].upcase}#{ability.skill}",
|
77
|
+
button_options.merge(tip: ability.tip)) do
|
78
|
+
|
79
|
+
@entity.use_ability :sprint if ability_name == :sprint
|
80
|
+
end
|
81
|
+
else
|
82
|
+
label "", label_options
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
5.times do |i|
|
87
|
+
label "", label_options
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def update_details(entity)
|
94
|
+
@health.text = "HP: #{entity.health} / #{entity.max_health}"
|
95
|
+
@movement_points.text = "MP: #{entity.mp} / #{entity.max_mp}"
|
96
|
+
@action_points.text = "AP: #{entity.ap} / #{entity.max_ap}"
|
97
|
+
|
98
|
+
if entity.has_ability? :sprint
|
99
|
+
@movement_points.text += " + #{entity.ability(:sprint).movement_bonus}"
|
100
|
+
end
|
101
|
+
|
102
|
+
@ability_buttons.each do |ability, button|
|
103
|
+
button.enabled = (entity.active? and (entity.has_ability?(ability) and entity.action_points >= entity.ability(ability).action_cost))
|
104
|
+
end
|
105
|
+
|
106
|
+
@portrait.image = entity.image
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -22,8 +22,8 @@ class EntitySummary < Fidgit::Vertical
|
|
22
22
|
|
23
23
|
vertical padding: 0, spacing: 0 do
|
24
24
|
@health = label "", font_height: 15
|
25
|
-
@movement_points = label "", font_height: 15
|
26
25
|
@action_points = label "", font_height: 15
|
26
|
+
@movement_points = label "", font_height: 15
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -31,10 +31,11 @@ class EntitySummary < Fidgit::Vertical
|
|
31
31
|
end
|
32
32
|
|
33
33
|
public
|
34
|
-
def
|
35
|
-
@health.text = "HP: #{
|
36
|
-
@movement_points.text = "MP: #{
|
37
|
-
@action_points.text = "AP: #{
|
34
|
+
def update_details(entity)
|
35
|
+
@health.text = "HP: #{entity.health}"
|
36
|
+
@movement_points.text = "MP: #{entity.mp}"
|
37
|
+
@action_points.text = "AP: #{entity.ap}"
|
38
|
+
@portrait.image = entity.portrait
|
38
39
|
end
|
39
40
|
|
40
41
|
public
|
@@ -46,10 +47,10 @@ class EntitySummary < Fidgit::Vertical
|
|
46
47
|
def entity=(entity)
|
47
48
|
@entity = entity
|
48
49
|
|
49
|
-
@name.text = " " + entity.name[0...13]
|
50
|
-
@
|
50
|
+
@name.text = " " + @entity.name[0...13]
|
51
|
+
@entity.subscribe :changed, &method(:update_details)
|
51
52
|
|
52
|
-
|
53
|
+
update_details @entity
|
53
54
|
|
54
55
|
entity
|
55
56
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SmashAndGrab
|
2
|
+
module Gui
|
3
|
+
class GameLog < Fidgit::Composite
|
4
|
+
include Log
|
5
|
+
|
6
|
+
MAX_ITEMS = 100
|
7
|
+
|
8
|
+
def initialize(state, options = {})
|
9
|
+
options = {
|
10
|
+
padding: 0,
|
11
|
+
}.merge! options
|
12
|
+
|
13
|
+
super options
|
14
|
+
|
15
|
+
@items = []
|
16
|
+
|
17
|
+
@scroll_window = scroll_window width: 420, height: 72, padding: 0 do
|
18
|
+
# TODO: Text-area "editable(?)" seem broken. They don't prevent editing while also allowing copy/pasting.
|
19
|
+
@text = text_area width: 400, font_height: 14, enabled: false
|
20
|
+
end
|
21
|
+
|
22
|
+
@scroll_window.background_color = @text.background_color
|
23
|
+
|
24
|
+
state.subscribe :game_info do |_, text|
|
25
|
+
append text
|
26
|
+
log.info { "game_info: #{text}" }
|
27
|
+
end
|
28
|
+
|
29
|
+
state.subscribe :game_heading do |_, text|
|
30
|
+
append "<c=AAAADD> { #{text} }</c>"
|
31
|
+
log.info { "game_heading: #{text}" }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def append(text)
|
36
|
+
@items.shift until @items.size < MAX_ITEMS
|
37
|
+
@items << text
|
38
|
+
@text.text = @items.join "\n"
|
39
|
+
|
40
|
+
@scroll_window.offset_y = Float::INFINITY # Scroll to bottom.
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,105 +1,49 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
def initialize(options = {})
|
5
|
-
options = {
|
6
|
-
padding: 4,
|
7
|
-
background_color: Color::BLACK,
|
8
|
-
}.merge! options
|
9
|
-
super options
|
10
|
-
|
11
|
-
@frame = horizontal padding: 4, spacing: 8, background_color: Color.rgb(0, 0, 150), width: 440, height: 112 do
|
12
|
-
@portrait = image_frame Objects::Entity.sprites[0, 0], padding: 0, background_color: Color::GRAY
|
1
|
+
require_relative "entity_panel"
|
2
|
+
require_relative "object_panel"
|
3
|
+
require_relative "scenario_panel"
|
13
4
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
5
|
+
module SmashAndGrab
|
6
|
+
module Gui
|
7
|
+
# The info panel contains scenario/entity/object panels based what is selected.
|
8
|
+
class InfoPanel < Fidgit::Vertical
|
9
|
+
attr_reader :object
|
10
|
+
|
11
|
+
def initialize(state, options = {})
|
12
|
+
options = {
|
13
|
+
padding: 4,
|
14
|
+
background_color: Color::BLACK,
|
15
|
+
}.merge! options
|
16
|
+
super options
|
17
|
+
|
18
|
+
@object = nil
|
19
|
+
@show_info = false
|
20
|
+
@scenario_panel = ScenarioPanel.new state
|
21
|
+
@frame = vertical padding: 4, background_color: Color.rgb(0, 0, 150), width: 440, height: 112
|
22
|
+
|
23
|
+
self.x, self.y = ($window.width - width) / 2, $window.height - height
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
+
def object=(object)
|
27
|
+
return if @object == object
|
28
|
+
@scenario_panel.parent = nil
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
@frame.clear
|
31
|
+
case object
|
32
|
+
when Objects::Entity
|
33
|
+
panel = EntityPanel.new(object, @show_info, parent: @frame)
|
34
|
+
panel.subscribe :info_toggled do |_, shown|
|
35
|
+
@show_info = shown
|
32
36
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@
|
37
|
-
|
38
|
-
|
39
|
-
@ability_buttons[:e] = button "P4", button_options.merge(tip: "power4")
|
40
|
-
end
|
37
|
+
when Objects::Static, Objects::Vehicle
|
38
|
+
ObjectPanel.new(object, parent: @frame)
|
39
|
+
when nil
|
40
|
+
@frame.add @scenario_panel
|
41
|
+
else
|
42
|
+
raise object.inspect
|
41
43
|
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
recalc
|
46
|
-
|
47
|
-
self.x, self.y = ($window.width - width) / 2, $window.height - height
|
48
|
-
end
|
49
|
-
|
50
|
-
public
|
51
|
-
def update
|
52
|
-
return unless @entity
|
53
|
-
|
54
|
-
@health.text = "HP: #{@entity.health} / #{@entity.max_health}"
|
55
|
-
@movement_points.text = "MP: #{@entity.mp} / #{@entity.max_mp}"
|
56
|
-
@action_points.text = "AP: #{@entity.ap} / #{@entity.max_ap}"
|
57
|
-
|
58
|
-
if @entity.has_ability? :sprint
|
59
|
-
@movement_points.text += " +#{@entity.ability(:sprint).movement_bonus}"
|
60
|
-
end
|
61
|
-
|
62
|
-
@ability_buttons.each do |ability, button|
|
63
|
-
button.enabled = (@entity.has_ability?(ability) and @entity.action_points >= @entity.ability(ability).action_cost)
|
64
|
-
end
|
65
|
-
end
|
66
44
|
|
67
|
-
|
68
|
-
def entity=(entity)
|
69
|
-
@entity = entity
|
70
|
-
|
71
|
-
@frame.shown = (not entity.nil?)
|
72
|
-
|
73
|
-
if entity
|
74
|
-
@portrait.image = @entity.image
|
75
|
-
@name.text = @entity.name
|
76
|
-
|
77
|
-
if @entity.has_ability? :melee
|
78
|
-
melee = @entity.ability(:melee)
|
79
|
-
@ability_buttons[:melee].tip = "Melee[#{melee.skill}] - attack in hand-to-hand combat"
|
80
|
-
else
|
81
|
-
@ability_buttons[:melee].tip = "Melee[n/a]"
|
45
|
+
@object = object
|
82
46
|
end
|
83
|
-
|
84
|
-
if @entity.has_ability? :ranged
|
85
|
-
ranged = @entity.ability(:ranged)
|
86
|
-
@ability_buttons[:ranged].tip = "Ranged[#{ranged.skill}] - attack in ranged combat"
|
87
|
-
else
|
88
|
-
@ability_buttons[:ranged].tip = "Ranged[n/a]"
|
89
|
-
end
|
90
|
-
|
91
|
-
if @entity.has_ability? :sprint
|
92
|
-
sprint = @entity.ability(:sprint)
|
93
|
-
@ability_buttons[:sprint].tip = "Sprint[#{sprint.skill}] - gain #{sprint.movement_bonus} movement points"
|
94
|
-
else
|
95
|
-
@ability_buttons[:sprint].tip = "Sprint[n/a]"
|
96
|
-
end
|
97
|
-
|
98
|
-
update
|
99
47
|
end
|
100
|
-
|
101
|
-
entity
|
102
48
|
end
|
103
49
|
end
|
104
|
-
end
|
105
|
-
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SmashAndGrab
|
2
|
+
module Gui
|
3
|
+
class ObjectPanel < Fidgit::Horizontal
|
4
|
+
def initialize(object, options = {})
|
5
|
+
options = {
|
6
|
+
padding: 0,
|
7
|
+
spacing: 8,
|
8
|
+
}.merge! options
|
9
|
+
|
10
|
+
super options
|
11
|
+
|
12
|
+
@object = object
|
13
|
+
|
14
|
+
vertical padding: 0 do
|
15
|
+
# TODO: Clicking on portrait should center.
|
16
|
+
@portrait = image_frame @object.image, padding: 0, background_color: Color::GRAY,
|
17
|
+
factor: (@object.is_a?(Objects::Vehicle) ? 0.25 : 1)
|
18
|
+
|
19
|
+
@object.subscribe :changed do
|
20
|
+
@portrait.image = @object.image
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
vertical padding: 0, spacing: 4 do
|
25
|
+
@name = label @object.name
|
26
|
+
|
27
|
+
Fidgit::Vertical.new padding: 0, spacing: 0 do
|
28
|
+
scroll_window width: 350, height: 72 do
|
29
|
+
text_area text: "#{@object.name} once was a pomegranate, but it got better... " * 10,
|
30
|
+
background_color: Color::NONE, width: 330, font_height: 14
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "game_log"
|
2
|
+
|
3
|
+
module SmashAndGrab
|
4
|
+
module Gui
|
5
|
+
class ScenarioPanel < Fidgit::Vertical
|
6
|
+
def initialize(state, options = {})
|
7
|
+
options = {
|
8
|
+
padding: 0,
|
9
|
+
spacing: 8,
|
10
|
+
}.merge! options
|
11
|
+
super options
|
12
|
+
|
13
|
+
label "Scenario: Bank raid"
|
14
|
+
|
15
|
+
horizontal padding_h: 4, padding_v: 0 do
|
16
|
+
@game_log = GameLog.new(state, parent: self)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/smash_and_grab/main.rb
CHANGED
@@ -11,13 +11,7 @@ def require_folder(path, files)
|
|
11
11
|
end
|
12
12
|
|
13
13
|
module SmashAndGrab
|
14
|
-
|
15
|
-
File.join(ENV['APPDATA'].gsub("\\", "/"), "Smash And Grab")
|
16
|
-
else
|
17
|
-
File.expand_path("~/.smash_and_grab")
|
18
|
-
end
|
19
|
-
|
20
|
-
SAVE_PATH = File.join(USER_PATH, "saves")
|
14
|
+
SAVE_PATH = File.join(USER_DATA_PATH, "saves")
|
21
15
|
end
|
22
16
|
|
23
17
|
require_relative "log"
|
@@ -26,13 +20,11 @@ SmashAndGrab::Log.log.info { "Smash and Grab loading; please wait.." }
|
|
26
20
|
t = Time.now
|
27
21
|
|
28
22
|
begin
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
begin
|
35
|
-
require 'bundler/setup' unless defined?(OSX_EXECUTABLE) or ENV['OCRA_EXECUTABLE']
|
23
|
+
# Running as an executable makes bundler irrelevant; from a gem means someone else decides about whether to use Bundler.
|
24
|
+
unless RUNNING_FROM_EXECUTABLE or Gem.loaded_specs.has_key? APP_NAME
|
25
|
+
require 'bundler'
|
26
|
+
Bundler.setup :default
|
27
|
+
end
|
36
28
|
|
37
29
|
rescue LoadError
|
38
30
|
$stderr.puts "Bundler gem not installed. To install:\n gem install bundler"
|
@@ -51,7 +43,7 @@ require 'chingu'
|
|
51
43
|
|
52
44
|
require 'fidgit'
|
53
45
|
Fidgit::Element.schema.merge_schema! YAML.load(File.read(File.expand_path('config/gui/schema.yml', EXTRACT_PATH)))
|
54
|
-
require_folder("fidgit_ext", %w[element container cursor])
|
46
|
+
require_folder("fidgit_ext", %w[event element container cursor])
|
55
47
|
|
56
48
|
require 'texplay'
|
57
49
|
require_folder('texplay_ext', %w[color image window])
|
@@ -76,9 +68,9 @@ require_folder "std_ext", %w[array hash]
|
|
76
68
|
|
77
69
|
# Include other files.
|
78
70
|
require_folder("", %w[version sprite_sheet z_order z_order_recorder game_window mouse_selection])
|
79
|
-
require_folder("gui", %w[minimap editor_selector entity_summary info_panel])
|
80
71
|
require_folder("map", %w[tile wall map])
|
81
72
|
require_folder("objects", %w[static entity vehicle])
|
73
|
+
require_folder("gui", %w[minimap editor_selector entity_summary info_panel])
|
82
74
|
require_folder("states", %w[edit_level play_level main_menu])
|
83
75
|
require_folder("players", %w[player])
|
84
76
|
require_folder("history", %w[editor_action_history game_action_history])
|
@@ -90,5 +82,8 @@ SmashAndGrab::GameWindow.new
|
|
90
82
|
SmashAndGrab::Log.log.debug { "Window created in #{"%.3f" % (Time.now - t)} s" }
|
91
83
|
|
92
84
|
unless defined? Ocra or defined? Bacon
|
85
|
+
SmashAndGrab::Log.log.info { "Game window opened" }
|
93
86
|
$window.show
|
87
|
+
|
88
|
+
SmashAndGrab::Log.log.info { "Game window closed" }
|
94
89
|
end
|
@@ -42,6 +42,7 @@ class Map
|
|
42
42
|
|
43
43
|
def add_effect(effect); @effects << effect; end
|
44
44
|
def remove_effect(effect); @effects.delete effect; end
|
45
|
+
def busy?; factions.any? {|f| f.entities.any?(&:busy?) }; end
|
45
46
|
|
46
47
|
# tile_classes: Nested arrays of Tile class names (Tile::Grass is represented as "Grass")
|
47
48
|
def initialize(data)
|
@@ -25,11 +25,14 @@ class Tile < GameObject
|
|
25
25
|
def position; [@x, @y]; end
|
26
26
|
def needs_to_be_seen?; (@temp_occlusions > 0) or @object; end # Causes walls to become transparent.
|
27
27
|
def blocks_sight?; @type == 'none' or (@object and @object.blocks_sight?); end
|
28
|
+
def zoc?(faction); entities_exerting_zoc(faction).any?; end
|
28
29
|
|
29
30
|
# Blank white tile, useful for colourising tiles.
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
class << self
|
32
|
+
def blank; @sprites[0]; end
|
33
|
+
def config; @config ||= YAML.load_file(File.expand_path("config/map/tiles.yml", EXTRACT_PATH)); end
|
34
|
+
def sprites; @sprites ||= SpriteSheet.new("floor_tiles.png", WIDTH, HEIGHT, 4); end
|
35
|
+
end
|
33
36
|
|
34
37
|
attr_reader :entities_exerting_zoc
|
35
38
|
|
@@ -32,8 +32,10 @@ class Wall < GameObject
|
|
32
32
|
|
33
33
|
def blocks_sight?; @blocks_sight; end
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
class << self
|
36
|
+
def config; @config ||= YAML.load_file(File.expand_path("config/map/walls.yml", EXTRACT_PATH)); end
|
37
|
+
def sprites; @sprites ||= SpriteSheet.new("walls.png", SPRITE_WIDTH, SPRITE_HEIGHT, 8); end
|
38
|
+
end
|
37
39
|
|
38
40
|
def initialize(map, data)
|
39
41
|
options = {
|