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,35 @@
|
|
1
|
+
class ScoreView < ActorView
|
2
|
+
def draw(target,x_off,y_off)
|
3
|
+
text = @actor.score.to_s
|
4
|
+
text = '0'*(6-text.size)+text
|
5
|
+
|
6
|
+
font = @mode.resource_manager.load_font 'Asimov.ttf', 30
|
7
|
+
text_image = font.render text, true, [250,250,250,255]
|
8
|
+
|
9
|
+
x = @actor.x
|
10
|
+
y = @actor.y
|
11
|
+
|
12
|
+
text_image.blit target.screen, [x,y]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class Score < Actor
|
16
|
+
attr_accessor :score
|
17
|
+
|
18
|
+
def setup
|
19
|
+
clear
|
20
|
+
end
|
21
|
+
|
22
|
+
def clear
|
23
|
+
@score = 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def +(amount)
|
27
|
+
@score += amount
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def -(amount)
|
32
|
+
@score -= amount
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'linked_list'
|
2
|
+
|
3
|
+
# Keeps a list of items sorted. Elements must be comparable
|
4
|
+
class SortedList
|
5
|
+
attr_reader :list
|
6
|
+
def initialize(initial_list=nil)
|
7
|
+
@list = LinkedList.new
|
8
|
+
unless initial_list.nil?
|
9
|
+
initial_list.each do |item|
|
10
|
+
add item
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(item)
|
16
|
+
added = false
|
17
|
+
@list.each_element do |node|
|
18
|
+
if node.obj > item
|
19
|
+
added = true
|
20
|
+
@list.place item, :before, node
|
21
|
+
break
|
22
|
+
end
|
23
|
+
end
|
24
|
+
@list << item unless added
|
25
|
+
item
|
26
|
+
end
|
27
|
+
alias :<< :add
|
28
|
+
|
29
|
+
def shift
|
30
|
+
@list.shift
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty?
|
34
|
+
@list.empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
def contains?(item)
|
38
|
+
@list.each do |obj|
|
39
|
+
if obj == item
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def find(item)
|
47
|
+
@list.each do |obj|
|
48
|
+
if obj == item
|
49
|
+
return obj
|
50
|
+
end
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def size
|
56
|
+
@list.size
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
class SoundManager
|
2
|
+
|
3
|
+
constructor :resource_manager, :config_manager
|
4
|
+
def setup
|
5
|
+
# Not in the pygame version - for Rubygame, we need to
|
6
|
+
# explicitly open the audio device.
|
7
|
+
# Args are:
|
8
|
+
# Frequency - Sampling frequency in samples per second (Hz).
|
9
|
+
# 22050 is recommended for most games; 44100 is
|
10
|
+
# CD audio rate. The larger the value, the more
|
11
|
+
# processing required.
|
12
|
+
# Format - Output sample format. This is one of the
|
13
|
+
# AUDIO_* constants in Rubygame::Mixer
|
14
|
+
# Channels -output sound channels. Use 2 for stereo,
|
15
|
+
# 1 for mono. (this option does not affect number
|
16
|
+
# of mixing channels)
|
17
|
+
# Samplesize - Bytes per output sample. Specifically, this
|
18
|
+
# determines the size of the buffer that the
|
19
|
+
# sounds will be mixed in.
|
20
|
+
# Rubygame::Mixer::open_audio( 22050, Rubygame::Mixer::AUDIO_U8, 2, 1024 )
|
21
|
+
Rubygame::Mixer::open_audio( 22050, nil, 2, 1024 )
|
22
|
+
|
23
|
+
puts 'Warning, sound disabled' unless
|
24
|
+
(@enabled = (Rubygame::VERSIONS[:sdl_mixer] != nil))
|
25
|
+
@enabled = (@enabled and (@config_manager.settings[:sound].nil? or @config_manager.settings[:sound] == true))
|
26
|
+
|
27
|
+
if @enabled
|
28
|
+
@music = {}
|
29
|
+
files = Dir.glob "#{MUSIC_PATH}**"
|
30
|
+
for f in files
|
31
|
+
name = File.basename(f)
|
32
|
+
begin
|
33
|
+
sym = name.gsub(" ","_").split(".")[0..-2].join(".").to_sym
|
34
|
+
@music[sym] = @resource_manager.load_music(f)
|
35
|
+
rescue;end
|
36
|
+
end if files
|
37
|
+
|
38
|
+
@sounds = {}
|
39
|
+
files = Dir.glob "#{SOUND_PATH}**"
|
40
|
+
for f in files
|
41
|
+
name = File.basename(f)
|
42
|
+
begin
|
43
|
+
sym = name.gsub(" ","_").split(".")[0..-2].join(".").to_sym
|
44
|
+
@sounds[sym] = @resource_manager.load_sound(f)
|
45
|
+
rescue;end
|
46
|
+
end if files
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def enabled?
|
51
|
+
@enabled
|
52
|
+
end
|
53
|
+
|
54
|
+
def play_sound(what, volume=nil)
|
55
|
+
if @enabled && @sounds[what]
|
56
|
+
@sound_thread = Thread.new do
|
57
|
+
@sounds[what].volume = volume if volume
|
58
|
+
@sounds[what].play
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def play_music(what, volume=nil)
|
64
|
+
if @enabled && @music[what]
|
65
|
+
@music_thread = Thread.new do
|
66
|
+
@music[what].volume = volume if volume
|
67
|
+
@music[what].play :repeats => -1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def stop_music(what)
|
73
|
+
if @enabled
|
74
|
+
@music[what].stop if @music[what]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def stop_sound(what)
|
79
|
+
if @enabled
|
80
|
+
@sounds[what].stop if @sounds[what]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'ftor'
|
2
|
+
module Rubygame
|
3
|
+
|
4
|
+
class Surface
|
5
|
+
def draw_line_s(point1, point2, color, thickness)
|
6
|
+
half_thickness = thickness/2.0
|
7
|
+
x1 = point1[0]
|
8
|
+
y1 = point1[1]
|
9
|
+
x2 = point2[0]
|
10
|
+
y2 = point2[1]
|
11
|
+
|
12
|
+
point1_vector = Ftor.new x1, y1
|
13
|
+
point2_vector = Ftor.new x2, y2
|
14
|
+
|
15
|
+
line_vector = point2_vector-point1_vector
|
16
|
+
perp_vector = line_vector.normal.unit
|
17
|
+
|
18
|
+
points = []
|
19
|
+
pvt = perp_vector*half_thickness
|
20
|
+
poly_point1 = Ftor.new(x1,y1)+pvt
|
21
|
+
poly_point2 = Ftor.new(x2,y2)+pvt
|
22
|
+
poly_point3 = Ftor.new(x2,y2)-pvt
|
23
|
+
poly_point4 = Ftor.new(x1,y1)-pvt
|
24
|
+
|
25
|
+
points << [poly_point1.x,poly_point1.y]
|
26
|
+
points << [poly_point2.x,poly_point2.y]
|
27
|
+
points << [poly_point3.x,poly_point3.y]
|
28
|
+
points << [poly_point4.x,poly_point4.y]
|
29
|
+
points << [poly_point1.x,poly_point1.y]
|
30
|
+
|
31
|
+
draw_polygon_s points, color
|
32
|
+
draw_circle_s [x1,y1], half_thickness, color
|
33
|
+
draw_circle_s [x2,y2], half_thickness, color
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end # module Rubygame
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'actor'
|
2
|
+
require 'actor_view'
|
3
|
+
|
4
|
+
require "enumerator"
|
5
|
+
|
6
|
+
|
7
|
+
# SvgActor knows how to build himself based on an svg document based on the :name
|
8
|
+
# passed in being the group name in the doc (layer).
|
9
|
+
class SvgActor < Actor
|
10
|
+
|
11
|
+
attr_accessor :segments, :type
|
12
|
+
def setup
|
13
|
+
@name = @opts[:name]
|
14
|
+
@svg_doc = @opts[:svg_doc]
|
15
|
+
|
16
|
+
my_layer = @svg_doc.find_group_by_label(@name.to_s)
|
17
|
+
build_from_vertices my_layer.path.vertices
|
18
|
+
@visible = my_layer.path.visible?
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_from_vertices(vertices)
|
22
|
+
|
23
|
+
moment_of_inertia,mass = Float::Infinity,Float::Infinity
|
24
|
+
terrain_body = CP::Body.new(mass,moment_of_inertia)
|
25
|
+
elasticity = 0
|
26
|
+
friction = 0.7
|
27
|
+
thickness = 6
|
28
|
+
@segments = []
|
29
|
+
vertices.each_cons(2) do |a,b|
|
30
|
+
seg = CP::Shape::Segment.new(terrain_body, a,b, thickness)
|
31
|
+
seg.collision_type = @name
|
32
|
+
seg.e = elasticity
|
33
|
+
seg.u = friction
|
34
|
+
seg.group = :terrain
|
35
|
+
@segments << [a,b]
|
36
|
+
@level.space.add_static_shape(seg)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def visible?
|
41
|
+
@visible
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class SvgActorView < ActorView
|
47
|
+
def draw(target,x_off,y_off)
|
48
|
+
return unless @actor.visible?
|
49
|
+
@actor.segments.each do |seg|
|
50
|
+
p1 = seg[0]
|
51
|
+
p2 = seg[1]
|
52
|
+
target.draw_line_s [p1.x+x_off,p1.y+y_off], [p2.x+x_off,p2.y+y_off], [25,255,25,255], 6
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
class SvgDocument
|
5
|
+
|
6
|
+
def initialize(xml_string)
|
7
|
+
@document = REXML::Document.new(xml_string)
|
8
|
+
@root = @document.root
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_group_by_label(label)
|
12
|
+
g = REXML::XPath.first(@root, "//g[@inkscape:label='#{label}']")
|
13
|
+
return nil unless g
|
14
|
+
Group.new(g)
|
15
|
+
end
|
16
|
+
|
17
|
+
module HasBounds
|
18
|
+
attr_accessor :bounds
|
19
|
+
|
20
|
+
def translate(vec)
|
21
|
+
@bounds.translate(vec) if @bounds
|
22
|
+
end
|
23
|
+
|
24
|
+
def center
|
25
|
+
@bounds.center if @bounds
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def set_bounds_from_attributes
|
31
|
+
x = @node.attributes["x"].to_f
|
32
|
+
y = @node.attributes["y"].to_f
|
33
|
+
width = @node.attributes["width"].to_f
|
34
|
+
height = @node.attributes["height"].to_f
|
35
|
+
@bounds = Rect.new [x,y,width,height]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module HasTranslation
|
40
|
+
def translation
|
41
|
+
transform = @node.attributes["transform"]
|
42
|
+
if transform and transform =~ /translate\(\s*(.+?)\s*,\s*(.+?\)\s*)/
|
43
|
+
vec2($1.to_f, ty = $2.to_f)
|
44
|
+
else
|
45
|
+
ZeroVec2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Base
|
51
|
+
include HasTranslation
|
52
|
+
attr_reader :node
|
53
|
+
|
54
|
+
def initialize(node)
|
55
|
+
raise "Can't make #{self.class.name} from nil" if node.nil?
|
56
|
+
@node = node
|
57
|
+
end
|
58
|
+
|
59
|
+
def game_class
|
60
|
+
@node.attributes['game:class']
|
61
|
+
end
|
62
|
+
|
63
|
+
def game_handle
|
64
|
+
@node.attributes['game:handle']
|
65
|
+
end
|
66
|
+
|
67
|
+
def visible?
|
68
|
+
@node.attributes['visible'] != 'false'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Group < Base
|
73
|
+
def paths(opts={})
|
74
|
+
inst_from_xpath "path", Path, opts
|
75
|
+
end
|
76
|
+
|
77
|
+
def path(opts={})
|
78
|
+
paths(opts).first
|
79
|
+
end
|
80
|
+
|
81
|
+
def rects(opts={})
|
82
|
+
inst_from_xpath "rect", Rectangle, opts
|
83
|
+
end
|
84
|
+
|
85
|
+
def rect(opts={})
|
86
|
+
rects(opts).first
|
87
|
+
end
|
88
|
+
|
89
|
+
def images(opts={})
|
90
|
+
inst_from_xpath "image", Image, opts
|
91
|
+
end
|
92
|
+
|
93
|
+
def image(opts={})
|
94
|
+
images(opts).first
|
95
|
+
end
|
96
|
+
|
97
|
+
def groups(opts={})
|
98
|
+
inst_from_xpath "g", Group, opts
|
99
|
+
end
|
100
|
+
|
101
|
+
def group(opts={})
|
102
|
+
groups(opts).first
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def map_from_xpath(xpr, opts={})
|
108
|
+
opts.each do |key,val|
|
109
|
+
xpr << "[@#{key}='#{val}']"
|
110
|
+
end
|
111
|
+
REXML::XPath.match(@node, xpr).map do |n|
|
112
|
+
yield n
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def inst_from_xpath(xpr, clazz, opts={})
|
117
|
+
map_from_xpath(xpr,opts) do |n|
|
118
|
+
clazz.new(n)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Path < Base
|
124
|
+
# The bezier path object must have all its nodes turned "sharp",
|
125
|
+
# or non-curve-handle-ish, or this parser will not work properly
|
126
|
+
def vertices
|
127
|
+
unless @verts
|
128
|
+
@verts = []
|
129
|
+
data = @node.attributes['d']
|
130
|
+
scanner = StringScanner.new(data)
|
131
|
+
pat = /[ML]\s+([-0-9.,]+)\s*/
|
132
|
+
hit = scanner.scan(pat)
|
133
|
+
while hit
|
134
|
+
x,y = scanner[1].split(/,/).map { |s| s.to_f }
|
135
|
+
@verts << vec2(x,y)
|
136
|
+
hit = scanner.scan(pat)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
@verts
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class Rectangle < Base
|
144
|
+
include HasBounds
|
145
|
+
|
146
|
+
def initialize(node)
|
147
|
+
super node
|
148
|
+
set_bounds_from_attributes
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class Image < Rectangle
|
153
|
+
attr_reader :image_name
|
154
|
+
|
155
|
+
def initialize(node)
|
156
|
+
super(node)
|
157
|
+
@image_name = @node.attributes["xlink:href"]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
== Welcome to Gamebox
|
2
|
+
Blurb here
|
3
|
+
|
4
|
+
== Description of Contents
|
5
|
+
|
6
|
+
src
|
7
|
+
Holds all the code that's specific to this particular application.
|
8
|
+
|
9
|
+
config
|
10
|
+
Configuration files for the Gamebox environment and other dependencies.
|
11
|
+
|
12
|
+
doc
|
13
|
+
This directory is where your application documentation will be stored when generated
|
14
|
+
using <tt>rake doc:app</tt>
|
15
|
+
|
16
|
+
lib
|
17
|
+
Application specific libraries. Basically, any kind of custom code that doesn't
|
18
|
+
belong under controllers, models, or helpers. This directory is in the load path.
|
19
|
+
|
20
|
+
script
|
21
|
+
Helper scripts for automation and generation.
|
22
|
+
|
23
|
+
test
|
24
|
+
Unit and functional tests along with fixtures. When using the script/generate scripts, template
|
25
|
+
test files will be generated for you and placed in this directory.
|
26
|
+
|
27
|
+
vendor
|
28
|
+
External libraries that the application depends on. Also includes the plugins subdirectory.
|
29
|
+
If the app has frozen rails, those gems also go here, under vendor/rails/.
|
30
|
+
This directory is in the load path.
|