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