gamebox 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +18 -0
- data/Manifest.txt +85 -0
- data/README.txt +33 -0
- data/Rakefile +42 -0
- data/TODO.txt +29 -0
- data/bin/gamebox +49 -0
- data/docs/gamebox04_big.png +0 -0
- data/docs/getting_started.rdoc +99 -0
- data/docs/logo.png +0 -0
- data/lib/gamebox.rb +6 -0
- data/lib/gamebox/actor.rb +143 -0
- data/lib/gamebox/actor_factory.rb +64 -0
- data/lib/gamebox/actor_view.rb +35 -0
- data/lib/gamebox/ai/line_of_site.rb +61 -0
- data/lib/gamebox/ai/polaris.rb +107 -0
- data/lib/gamebox/ai/two_d_grid_location.rb +21 -0
- data/lib/gamebox/ai/two_d_grid_map.rb +77 -0
- data/lib/gamebox/aliasing.rb +16 -0
- data/lib/gamebox/animated.rb +84 -0
- data/lib/gamebox/behavior.rb +16 -0
- data/lib/gamebox/config_manager.rb +22 -0
- data/lib/gamebox/console_app.rb +39 -0
- data/lib/gamebox/data/fonts/Asimov.ttf +0 -0
- data/lib/gamebox/data/fonts/GAMEBOX_FONTS_GO_HERE +0 -0
- data/lib/gamebox/data/graphics/GAMEBOX_GRAPHICS_GO_HERE +0 -0
- data/lib/gamebox/data/graphics/logo.png +0 -0
- data/lib/gamebox/data/music/GAMEBOX_MUSIC_GOES_HERE +0 -0
- data/lib/gamebox/data/sounds/GAMEBOX_SOUND_FX_GO_HERE +0 -0
- data/lib/gamebox/director.rb +47 -0
- data/lib/gamebox/gamebox_application.rb +77 -0
- data/lib/gamebox/graphical.rb +24 -0
- data/lib/gamebox/graphical_actor_view.rb +31 -0
- data/lib/gamebox/inflections.rb +52 -0
- data/lib/gamebox/inflector.rb +278 -0
- data/lib/gamebox/input_manager.rb +104 -0
- data/lib/gamebox/layered.rb +34 -0
- data/lib/gamebox/level.rb +64 -0
- data/lib/gamebox/linked_list.rb +137 -0
- data/lib/gamebox/logo.rb +11 -0
- data/lib/gamebox/metaclass.rb +6 -0
- data/lib/gamebox/mode.rb +123 -0
- data/lib/gamebox/mode_manager.rb +80 -0
- data/lib/gamebox/numbers_ext.rb +3 -0
- data/lib/gamebox/physical.rb +139 -0
- data/lib/gamebox/physical_director.rb +17 -0
- data/lib/gamebox/physical_level.rb +89 -0
- data/lib/gamebox/physics.rb +27 -0
- data/lib/gamebox/publisher_ext.rb +13 -0
- data/lib/gamebox/resource_manager.rb +122 -0
- data/lib/gamebox/score.rb +35 -0
- data/lib/gamebox/sorted_list.rb +59 -0
- data/lib/gamebox/sound_manager.rb +84 -0
- data/lib/gamebox/surface_ext.rb +37 -0
- data/lib/gamebox/svg_actor.rb +55 -0
- data/lib/gamebox/svg_document.rb +160 -0
- data/lib/gamebox/template_app/README +30 -0
- data/lib/gamebox/template_app/Rakefile +20 -0
- data/lib/gamebox/template_app/config/boot.rb +5 -0
- data/lib/gamebox/template_app/config/environment.rb +29 -0
- data/lib/gamebox/template_app/config/game.yml +6 -0
- data/lib/gamebox/template_app/config/mode_level_config.yml +3 -0
- data/lib/gamebox/template_app/config/objects.yml +29 -0
- data/lib/gamebox/template_app/data/fonts/FONTS_GO_HERE +0 -0
- data/lib/gamebox/template_app/data/graphics/GRAPHICS_GO_HERE +0 -0
- data/lib/gamebox/template_app/data/music/MUSIC_GOES_HERE +0 -0
- data/lib/gamebox/template_app/data/sounds/SOUND_FX_GO_HERE +0 -0
- data/lib/gamebox/template_app/doc/README_FOR_APP +1 -0
- data/lib/gamebox/template_app/lib/code_statistics.rb +107 -0
- data/lib/gamebox/template_app/lib/diy.rb +371 -0
- data/lib/gamebox/template_app/lib/platform.rb +16 -0
- data/lib/gamebox/template_app/src/app.rb +8 -0
- data/lib/gamebox/template_app/src/demo_level.rb +20 -0
- data/lib/gamebox/template_app/src/game.rb +22 -0
- data/lib/gamebox/template_app/src/my_actor.rb +17 -0
- data/lib/gamebox/version.rb +10 -0
- data/lib/gamebox/viewport.rb +81 -0
- data/lib/gamebox/wrapped_screen.rb +15 -0
- data/script/perf_polaris.rb +36 -0
- data/test/helper.rb +25 -0
- data/test/test_actor.rb +38 -0
- data/test/test_animated.rb +64 -0
- data/test/test_line_of_site.rb +14 -0
- data/test/test_physical.rb +26 -0
- data/test/test_polaris.rb +193 -0
- data/test/test_viewport.rb +116 -0
- metadata +188 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'inflector'
|
2
|
+
require 'mode'
|
3
|
+
class ModeManager
|
4
|
+
|
5
|
+
constructor :resource_manager, :actor_factory, :input_manager,
|
6
|
+
:sound_manager, :config_manager
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@modes = {}
|
10
|
+
@actor_factory.mode_manager = self
|
11
|
+
modes = @resource_manager.load_config('mode_level_config')[:modes]
|
12
|
+
|
13
|
+
@mode_names = []
|
14
|
+
for mode_hash in modes
|
15
|
+
for mode, levels in mode_hash
|
16
|
+
@mode_names << mode
|
17
|
+
mode_klass_name = "Mode"
|
18
|
+
unless mode == :default
|
19
|
+
mode_klass_name = Inflector.camelize mode.to_s+"Mode"
|
20
|
+
end
|
21
|
+
begin
|
22
|
+
require mode.to_s+"_mode"
|
23
|
+
rescue LoadError
|
24
|
+
# hope it's defined somewhere else
|
25
|
+
end
|
26
|
+
mode_klass = ObjectSpace.const_get mode_klass_name
|
27
|
+
mode_instance = mode_klass.new(@input_manager, @actor_factory, @resource_manager, @sound_manager, @config_manager, levels)
|
28
|
+
mode_instance.when :next_mode do
|
29
|
+
next_mode
|
30
|
+
end
|
31
|
+
mode_instance.when :prev_mode do
|
32
|
+
prev_mode
|
33
|
+
end
|
34
|
+
add_mode mode, mode_instance
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_mode
|
40
|
+
index = @mode_names.index @mode
|
41
|
+
if index == @mode_names.size-1
|
42
|
+
puts "last mode, exiting"
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
change_mode_to @mode_names[index+1]
|
46
|
+
end
|
47
|
+
|
48
|
+
def prev_mode
|
49
|
+
index = @mode_names.index @mode
|
50
|
+
if index == 0
|
51
|
+
puts "first mode, exiting"
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
change_mode_to @mode_names[index-1]
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_mode(mode_sym, mode_instance)
|
58
|
+
@modes[mode_sym] = mode_instance
|
59
|
+
@mode = mode_sym unless @mode
|
60
|
+
mode_instance
|
61
|
+
end
|
62
|
+
|
63
|
+
def change_mode_to(mode, *args)
|
64
|
+
@modes[@mode].stop unless @modes[@mode].nil?
|
65
|
+
@mode = mode
|
66
|
+
@modes[@mode].start *args
|
67
|
+
end
|
68
|
+
|
69
|
+
def current_mode
|
70
|
+
@modes[@mode]
|
71
|
+
end
|
72
|
+
|
73
|
+
def update(time)
|
74
|
+
@modes[@mode].update time unless @modes[@mode].nil?
|
75
|
+
end
|
76
|
+
|
77
|
+
def draw(target)
|
78
|
+
@modes[@mode].draw target unless @modes[@mode].nil?
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'physics'
|
2
|
+
require 'behavior'
|
3
|
+
require 'inflector'
|
4
|
+
require 'publisher'
|
5
|
+
class Physical < Behavior
|
6
|
+
attr_accessor :shapes, :body, :opts, :parts
|
7
|
+
|
8
|
+
def shape
|
9
|
+
@shapes.first if @shapes
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
# TODO add defaults?
|
14
|
+
@mass = @opts[:mass]
|
15
|
+
@mass ||= Float::Infinity
|
16
|
+
@parts = {}
|
17
|
+
@shapes = []
|
18
|
+
|
19
|
+
moment_of_inertia = @opts[:moment]
|
20
|
+
|
21
|
+
case @opts[:shape]
|
22
|
+
when :circle
|
23
|
+
@radius = @opts[:radius]
|
24
|
+
|
25
|
+
moment_of_inertia ||= @opts[:fixed] ? Float::Infinity : moment_for_circle(@mass, @radius, 0, ZeroVec2)
|
26
|
+
@body = Body.new(@mass, moment_of_inertia)
|
27
|
+
@shape = Shape::Circle.new(@body, @radius, ZeroVec2)
|
28
|
+
|
29
|
+
when :poly
|
30
|
+
shape_array = @opts[:verts].collect{|v| vec2(v[0],v[1])}
|
31
|
+
|
32
|
+
moment_of_inertia ||= @opts[:fixed] ? Float::Infinity : moment_for_poly(@mass, shape_array, ZeroVec2)
|
33
|
+
@body = Body.new(@mass, moment_of_inertia)
|
34
|
+
@shape = Shape::Poly.new(@body, shape_array, ZeroVec2)
|
35
|
+
end
|
36
|
+
|
37
|
+
collision_type = @opts[:collision_group]
|
38
|
+
collision_type ||=
|
39
|
+
Inflector.underscore(@actor.class).to_sym
|
40
|
+
|
41
|
+
@body.a = @opts[:angle] if @opts[:angle]
|
42
|
+
|
43
|
+
@shape.collision_type = collision_type
|
44
|
+
start_x = @opts[:x]
|
45
|
+
start_y = @opts[:y]
|
46
|
+
start_x ||= @actor.x
|
47
|
+
start_y ||= @actor.y
|
48
|
+
@shape.body.p = vec2(start_x,start_y)
|
49
|
+
@shape.e = 0
|
50
|
+
friction = @opts[:friction]
|
51
|
+
friction ||= 0.4
|
52
|
+
@shape.u = friction
|
53
|
+
|
54
|
+
@shapes << @shape
|
55
|
+
|
56
|
+
if @opts[:parts]
|
57
|
+
for obj in @opts[:parts]
|
58
|
+
for part_name, part_def in obj
|
59
|
+
# add another shape here
|
60
|
+
part_shape_array = part_def[:verts].collect{|v| vec2(v[0],v[1])}
|
61
|
+
part_shape = Shape::Poly.new(@body, part_shape_array, part_def[:offset])
|
62
|
+
part_shape.collision_type = part_name.to_sym
|
63
|
+
# TODO pass all physics params to parts (ie u and e)
|
64
|
+
part_shape.u = friction
|
65
|
+
@shapes << part_shape
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
physical_obj = self
|
72
|
+
|
73
|
+
if @actor.level.respond_to? :register_physical_object
|
74
|
+
if @opts[:fixed]
|
75
|
+
@actor.level.register_physical_object physical_obj, true
|
76
|
+
else
|
77
|
+
@actor.level.register_physical_object physical_obj
|
78
|
+
end
|
79
|
+
else
|
80
|
+
raise "physical actor in a non-physical level!"
|
81
|
+
end
|
82
|
+
|
83
|
+
# write code here to keep physics and x,y of actor in sync
|
84
|
+
@actor.instance_eval do
|
85
|
+
(class << self; self; end).class_eval do
|
86
|
+
define_method :x do
|
87
|
+
physical_obj.body.p.x
|
88
|
+
end
|
89
|
+
define_method :y do
|
90
|
+
physical_obj.body.p.y
|
91
|
+
end
|
92
|
+
define_method :x= do |new_x|
|
93
|
+
raise "I am physical, you should apply forces"
|
94
|
+
end
|
95
|
+
define_method :y= do |new_y|
|
96
|
+
raise "I am physical, you should apply forces"
|
97
|
+
end
|
98
|
+
define_method :shape do
|
99
|
+
physical_obj.shape
|
100
|
+
end
|
101
|
+
define_method :body do
|
102
|
+
physical_obj.body
|
103
|
+
end
|
104
|
+
define_method :parts do
|
105
|
+
physical_obj.parts
|
106
|
+
end
|
107
|
+
define_method :deg do
|
108
|
+
# TODO hack!! why do poly's not work the same?
|
109
|
+
if physical_obj.opts[:shape] == :poly
|
110
|
+
-((physical_obj.body.a-1.57) * 180.0 / Math::PI + 90)
|
111
|
+
else
|
112
|
+
-((physical_obj.body.a) * 180.0 / Math::PI + 90)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
define_method :warp do |new_p|
|
116
|
+
physical_obj.body.p = new_p
|
117
|
+
@level.space.rehash_static if physical_obj.opts[:fixed]
|
118
|
+
end
|
119
|
+
define_method :physical do
|
120
|
+
physical_obj
|
121
|
+
end
|
122
|
+
define_method :image do
|
123
|
+
old_image = nil
|
124
|
+
rot_deg = deg.round % 360
|
125
|
+
|
126
|
+
if is? :animated
|
127
|
+
old_image = animated.image
|
128
|
+
elsif is? :graphical
|
129
|
+
old_image = graphical.image
|
130
|
+
end
|
131
|
+
|
132
|
+
if old_image
|
133
|
+
old_image.rotozoom(rot_deg,1,true)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'director'
|
2
|
+
|
3
|
+
class PhysicalDirector < Director
|
4
|
+
def find_physical_obj(shape)
|
5
|
+
@actors.select{|a|a.respond_to?(:shape) && a.shape==shape}.first
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove_physical_obj(shape)
|
9
|
+
act = find_physical_obj shape
|
10
|
+
act.remove_self
|
11
|
+
act
|
12
|
+
end
|
13
|
+
|
14
|
+
def actor_removed(act)
|
15
|
+
act.level.unregister_physical_object act if act.is? :physical
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Levels represent on level of game play. Some games will likely have only one
|
2
|
+
# level. Level is responsible for loading its background, props, and directors.
|
3
|
+
# PhysicalLevel adds a physics space to the Level
|
4
|
+
require 'level'
|
5
|
+
require 'physics'
|
6
|
+
require 'physical_director'
|
7
|
+
class PhysicalLevel < Level
|
8
|
+
|
9
|
+
attr_accessor :space
|
10
|
+
|
11
|
+
def initialize(actor_factory, resource_manager, sound_manager, viewport, opts={})
|
12
|
+
@actor_factory = actor_factory
|
13
|
+
@director = PhysicalDirector.new
|
14
|
+
@actor_factory.director = @director
|
15
|
+
|
16
|
+
@resource_manager = resource_manager
|
17
|
+
@sound_manager = sound_manager
|
18
|
+
@viewport = viewport
|
19
|
+
@opts = opts
|
20
|
+
|
21
|
+
@space = Space.new
|
22
|
+
@space.iterations = 20
|
23
|
+
@space.elastic_iterations = 0
|
24
|
+
|
25
|
+
setup
|
26
|
+
end
|
27
|
+
|
28
|
+
PHYSICS_STEP = 25.0
|
29
|
+
def update_physics(time)
|
30
|
+
unless @physics_paused
|
31
|
+
steps = (time/PHYSICS_STEP).ceil
|
32
|
+
# from chipmunk demo
|
33
|
+
dt = 1.0/60/steps
|
34
|
+
steps.times do
|
35
|
+
@space.step dt
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def pause_physics
|
41
|
+
@physics_paused = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def restart_physics
|
45
|
+
@physics_paused = false
|
46
|
+
end
|
47
|
+
|
48
|
+
def update(time)
|
49
|
+
update_physics time
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def register_physical_object(obj,static=false)
|
54
|
+
if static
|
55
|
+
obj.shapes.each do |shape|
|
56
|
+
@space.add_static_shape shape
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@space.add_body(obj.body)
|
60
|
+
|
61
|
+
obj.shapes.each do |shape|
|
62
|
+
@space.add_shape shape
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def register_physical_constraint(constraint)
|
68
|
+
@space.add_constraint constraint
|
69
|
+
end
|
70
|
+
|
71
|
+
def unregister_physical_constraint(constraint)
|
72
|
+
@space.remove_constraint constraint
|
73
|
+
end
|
74
|
+
|
75
|
+
def unregister_physical_object(obj,static=false)
|
76
|
+
if static
|
77
|
+
obj.physical.shapes.each do |shape|
|
78
|
+
@space.remove_static_shape shape
|
79
|
+
end
|
80
|
+
else
|
81
|
+
@space.remove_body(obj.body)
|
82
|
+
|
83
|
+
obj.physical.shapes.each do |shape|
|
84
|
+
@space.remove_shape shape
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'chipmunk'
|
2
|
+
|
3
|
+
require 'numbers_ext'
|
4
|
+
include CP
|
5
|
+
ZeroVec2 = vec2(0,0)
|
6
|
+
|
7
|
+
class Space
|
8
|
+
alias :add_collision_func_old :add_collision_func
|
9
|
+
|
10
|
+
# allows for passing arrays of collision types not just single ones
|
11
|
+
# add_collision_func([:foo,:bar], [:baz,:yar]) becomes:
|
12
|
+
# add_collision_func(:foo, :baz)
|
13
|
+
# add_collision_func(:foo, :yar)
|
14
|
+
# add_collision_func(:bar, :baz)
|
15
|
+
# add_collision_func(:bar, :yar)
|
16
|
+
def add_collision_func(first_objs, second_objs, &block)
|
17
|
+
firsts = [first_objs].flatten
|
18
|
+
seconds = [second_objs].flatten
|
19
|
+
|
20
|
+
firsts.each do |f|
|
21
|
+
seconds.each do |s|
|
22
|
+
add_collision_func_old(f,s,&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Publisher
|
2
|
+
module InstanceMethods
|
3
|
+
def unsubscribe_all(listener)
|
4
|
+
if @subscriptions
|
5
|
+
for event in @subscriptions.keys
|
6
|
+
@subscriptions[event].delete_if do |block|
|
7
|
+
eval('self',block.binding).equal?(listener)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << "#{File.dirname(__FILE__)}/../config"
|
3
|
+
require "fileutils"
|
4
|
+
require 'inflector'
|
5
|
+
require 'svg_document'
|
6
|
+
|
7
|
+
class ResourceManager
|
8
|
+
def initialize
|
9
|
+
@loaded_images = {}
|
10
|
+
@loaded_fonts = {}
|
11
|
+
@loaded_svgs = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_actor_image(actor)
|
15
|
+
# use pngs only for now
|
16
|
+
actor_name = Inflector.underscore(actor.class)
|
17
|
+
return load_image("#{actor_name}.png")
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_animation_set(actor, action)
|
21
|
+
# use pngs only for now
|
22
|
+
actor_dir = Inflector.underscore(actor.class)
|
23
|
+
frames = Dir.glob("#{GFX_PATH}#{actor_dir}/#{action}/*.png")
|
24
|
+
action_imgs = []
|
25
|
+
|
26
|
+
frames = frames.sort_by {|f| File.basename(f).to_i }
|
27
|
+
|
28
|
+
for frame in frames
|
29
|
+
rel_path = frame.slice(GFX_PATH.size,frame.size)
|
30
|
+
action_imgs << load_image(rel_path)
|
31
|
+
end
|
32
|
+
action_imgs
|
33
|
+
end
|
34
|
+
|
35
|
+
def load_image(file_name)
|
36
|
+
cached_img = @loaded_images[file_name]
|
37
|
+
if cached_img.nil?
|
38
|
+
begin
|
39
|
+
cached_img = Rubygame::Surface.load(File.expand_path(GFX_PATH + file_name))
|
40
|
+
rescue Exception => ex
|
41
|
+
#check global gamebox location
|
42
|
+
cached_img = Rubygame::Surface.load(File.expand_path(GAMEBOX_GFX_PATH + file_name))
|
43
|
+
end
|
44
|
+
@loaded_images[file_name] = cached_img
|
45
|
+
end
|
46
|
+
cached_img
|
47
|
+
end
|
48
|
+
|
49
|
+
def load_music(full_name)
|
50
|
+
begin
|
51
|
+
sound = Rubygame::Music.load(full_name)
|
52
|
+
return sound
|
53
|
+
rescue Rubygame::SDLError => ex
|
54
|
+
puts "Cannot load music " + full_name + " : " + ex
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_sound(full_name)
|
59
|
+
begin
|
60
|
+
sound = Rubygame::Sound.load(full_name)
|
61
|
+
return sound
|
62
|
+
rescue Rubygame::SDLError => ex
|
63
|
+
puts "Cannot load sound " + full_name + " : " + ex
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# loads TTF fonts from the fonts dir and caches them for later
|
68
|
+
def load_font(name, size)
|
69
|
+
@loaded_fonts[name] ||= {}
|
70
|
+
return @loaded_fonts[name][size] if @loaded_fonts[name][size]
|
71
|
+
begin
|
72
|
+
unless @ttf_loaded
|
73
|
+
TTF.setup
|
74
|
+
@ttf_loaded = true
|
75
|
+
end
|
76
|
+
full_name = File.expand_path(FONTS_PATH + name)
|
77
|
+
begin
|
78
|
+
font = TTF.new(full_name, size)
|
79
|
+
@loaded_fonts[name][size] = font
|
80
|
+
rescue Exception => ex
|
81
|
+
full_name = File.expand_path(GAMEBOX_FONTS_PATH + name)
|
82
|
+
font = TTF.new(full_name, size)
|
83
|
+
@loaded_fonts[name][size] = font
|
84
|
+
end
|
85
|
+
return font
|
86
|
+
rescue Exception => ex
|
87
|
+
puts "Cannot load font #{full_name}:#{ex}"
|
88
|
+
end
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
# TODO make this path include that app name?
|
93
|
+
def load_config(name)
|
94
|
+
conf = YAML::load_file(CONFIG_PATH + name + ".yml")
|
95
|
+
user_file = "#{ENV['HOME']}/.gamebox/#{name}.yml"
|
96
|
+
if File.exist? user_file
|
97
|
+
user_conf = YAML::load_file user_file
|
98
|
+
conf = conf.merge user_conf
|
99
|
+
end
|
100
|
+
conf
|
101
|
+
end
|
102
|
+
|
103
|
+
def save_settings(name, settings)
|
104
|
+
user_gamebox_dir = "#{ENV['HOME']}/.gamebox"
|
105
|
+
FileUtils.mkdir_p user_gamebox_dir
|
106
|
+
user_file = "#{ENV['HOME']}/.gamebox/#{name}.yml"
|
107
|
+
File.open user_file, "w" do |f|
|
108
|
+
f.write settings.to_yaml
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def load_svg(file_name)
|
113
|
+
# TODO create LEVEL_PATH in environment
|
114
|
+
cached_svg = @loaded_svgs[file_name]
|
115
|
+
if cached_svg.nil?
|
116
|
+
cached_svg = SvgDocument.new(File.open(File.expand_path(DATA_PATH + "levels/" + file_name + ".svg")))
|
117
|
+
@loaded_svgs[file_name] = cached_svg
|
118
|
+
end
|
119
|
+
cached_svg
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|