gamebox 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/History.txt +18 -0
  2. data/Manifest.txt +85 -0
  3. data/README.txt +33 -0
  4. data/Rakefile +42 -0
  5. data/TODO.txt +29 -0
  6. data/bin/gamebox +49 -0
  7. data/docs/gamebox04_big.png +0 -0
  8. data/docs/getting_started.rdoc +99 -0
  9. data/docs/logo.png +0 -0
  10. data/lib/gamebox.rb +6 -0
  11. data/lib/gamebox/actor.rb +143 -0
  12. data/lib/gamebox/actor_factory.rb +64 -0
  13. data/lib/gamebox/actor_view.rb +35 -0
  14. data/lib/gamebox/ai/line_of_site.rb +61 -0
  15. data/lib/gamebox/ai/polaris.rb +107 -0
  16. data/lib/gamebox/ai/two_d_grid_location.rb +21 -0
  17. data/lib/gamebox/ai/two_d_grid_map.rb +77 -0
  18. data/lib/gamebox/aliasing.rb +16 -0
  19. data/lib/gamebox/animated.rb +84 -0
  20. data/lib/gamebox/behavior.rb +16 -0
  21. data/lib/gamebox/config_manager.rb +22 -0
  22. data/lib/gamebox/console_app.rb +39 -0
  23. data/lib/gamebox/data/fonts/Asimov.ttf +0 -0
  24. data/lib/gamebox/data/fonts/GAMEBOX_FONTS_GO_HERE +0 -0
  25. data/lib/gamebox/data/graphics/GAMEBOX_GRAPHICS_GO_HERE +0 -0
  26. data/lib/gamebox/data/graphics/logo.png +0 -0
  27. data/lib/gamebox/data/music/GAMEBOX_MUSIC_GOES_HERE +0 -0
  28. data/lib/gamebox/data/sounds/GAMEBOX_SOUND_FX_GO_HERE +0 -0
  29. data/lib/gamebox/director.rb +47 -0
  30. data/lib/gamebox/gamebox_application.rb +77 -0
  31. data/lib/gamebox/graphical.rb +24 -0
  32. data/lib/gamebox/graphical_actor_view.rb +31 -0
  33. data/lib/gamebox/inflections.rb +52 -0
  34. data/lib/gamebox/inflector.rb +278 -0
  35. data/lib/gamebox/input_manager.rb +104 -0
  36. data/lib/gamebox/layered.rb +34 -0
  37. data/lib/gamebox/level.rb +64 -0
  38. data/lib/gamebox/linked_list.rb +137 -0
  39. data/lib/gamebox/logo.rb +11 -0
  40. data/lib/gamebox/metaclass.rb +6 -0
  41. data/lib/gamebox/mode.rb +123 -0
  42. data/lib/gamebox/mode_manager.rb +80 -0
  43. data/lib/gamebox/numbers_ext.rb +3 -0
  44. data/lib/gamebox/physical.rb +139 -0
  45. data/lib/gamebox/physical_director.rb +17 -0
  46. data/lib/gamebox/physical_level.rb +89 -0
  47. data/lib/gamebox/physics.rb +27 -0
  48. data/lib/gamebox/publisher_ext.rb +13 -0
  49. data/lib/gamebox/resource_manager.rb +122 -0
  50. data/lib/gamebox/score.rb +35 -0
  51. data/lib/gamebox/sorted_list.rb +59 -0
  52. data/lib/gamebox/sound_manager.rb +84 -0
  53. data/lib/gamebox/surface_ext.rb +37 -0
  54. data/lib/gamebox/svg_actor.rb +55 -0
  55. data/lib/gamebox/svg_document.rb +160 -0
  56. data/lib/gamebox/template_app/README +30 -0
  57. data/lib/gamebox/template_app/Rakefile +20 -0
  58. data/lib/gamebox/template_app/config/boot.rb +5 -0
  59. data/lib/gamebox/template_app/config/environment.rb +29 -0
  60. data/lib/gamebox/template_app/config/game.yml +6 -0
  61. data/lib/gamebox/template_app/config/mode_level_config.yml +3 -0
  62. data/lib/gamebox/template_app/config/objects.yml +29 -0
  63. data/lib/gamebox/template_app/data/fonts/FONTS_GO_HERE +0 -0
  64. data/lib/gamebox/template_app/data/graphics/GRAPHICS_GO_HERE +0 -0
  65. data/lib/gamebox/template_app/data/music/MUSIC_GOES_HERE +0 -0
  66. data/lib/gamebox/template_app/data/sounds/SOUND_FX_GO_HERE +0 -0
  67. data/lib/gamebox/template_app/doc/README_FOR_APP +1 -0
  68. data/lib/gamebox/template_app/lib/code_statistics.rb +107 -0
  69. data/lib/gamebox/template_app/lib/diy.rb +371 -0
  70. data/lib/gamebox/template_app/lib/platform.rb +16 -0
  71. data/lib/gamebox/template_app/src/app.rb +8 -0
  72. data/lib/gamebox/template_app/src/demo_level.rb +20 -0
  73. data/lib/gamebox/template_app/src/game.rb +22 -0
  74. data/lib/gamebox/template_app/src/my_actor.rb +17 -0
  75. data/lib/gamebox/version.rb +10 -0
  76. data/lib/gamebox/viewport.rb +81 -0
  77. data/lib/gamebox/wrapped_screen.rb +15 -0
  78. data/script/perf_polaris.rb +36 -0
  79. data/test/helper.rb +25 -0
  80. data/test/test_actor.rb +38 -0
  81. data/test/test_animated.rb +64 -0
  82. data/test/test_line_of_site.rb +14 -0
  83. data/test/test_physical.rb +26 -0
  84. data/test/test_polaris.rb +193 -0
  85. data/test/test_viewport.rb +116 -0
  86. metadata +188 -0
@@ -0,0 +1,64 @@
1
+ require 'actor'
2
+ require 'graphical_actor_view'
3
+ class ActorFactory
4
+ constructor :input_manager, :sound_manager
5
+
6
+ attr_accessor :mode_manager, :director
7
+
8
+ # returns a hash of actor params
9
+ def cached_actor_def(actor)
10
+ @actor_cache ||= {}
11
+ cached_actor = @actor_cache[actor]
12
+ return cached_actor if cached_actor
13
+
14
+ begin
15
+ require actor.to_s
16
+ require actor.to_s+"_view"
17
+ rescue LoadError => ex
18
+ # maybe its included somewhere else
19
+ end
20
+ model_klass_name = Inflector.camelize actor
21
+ model_klass = Object.const_get model_klass_name
22
+
23
+ begin
24
+ view_klass = Object.const_get model_klass_name+"View"
25
+ rescue Exception => ex
26
+ # hrm...
27
+ end
28
+
29
+ actor_def = {
30
+ :model_klass => model_klass,
31
+ :view_klass => view_klass
32
+ }
33
+ @actor_cache[actor] = actor_def
34
+ actor_def
35
+ end
36
+
37
+
38
+ def build(actor, level, opts={})
39
+ actor_def = cached_actor_def actor
40
+
41
+ basic_opts = {
42
+ :level => level,
43
+ :input => @input_manager,
44
+ :sound => @sound_manager,
45
+ :resources => level.resource_manager
46
+ }
47
+ merged_opts = basic_opts.merge(opts)
48
+
49
+ model = actor_def[:model_klass].new merged_opts
50
+
51
+ view_klass = opts[:view]
52
+ view_klass ||= actor_def[:view_klass]
53
+
54
+ if model.is? :animated or model.is? :graphical or model.is? :physical
55
+ view_klass ||= GraphicalActorView
56
+ end
57
+ view_klass.new @mode_manager.current_mode, model if view_klass
58
+
59
+ # Register our new actor with the system
60
+ @director.add_actor model
61
+
62
+ return model
63
+ end
64
+ end
@@ -0,0 +1,35 @@
1
+ class ActorView
2
+ attr_accessor :actor, :mode, :layer, :parallax
3
+ def initialize(mode,actor)
4
+ @mode = mode
5
+ @actor = actor
6
+
7
+ @layer = 0
8
+ @parallax = 1
9
+ if @actor.is? :layered
10
+ @layer = @actor.layer
11
+ @parallax = @actor.parallax
12
+ end
13
+
14
+ actor.when :remove_me do
15
+ @mode.unregister_drawable self
16
+ end
17
+
18
+ actor.when :hide_me do
19
+ @mode.unregister_drawable self
20
+ end
21
+
22
+ actor.when :show_me do
23
+ @mode.register_drawable self
24
+ end
25
+
26
+ actor.show
27
+
28
+ setup
29
+ end
30
+
31
+ def setup
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,61 @@
1
+ # LineOfSite is a class for finding neighbors in a map that are visible
2
+ class LineOfSite
3
+ def initialize(map)
4
+ @map = map
5
+ end
6
+
7
+ def losline(x, y, x2, y2)
8
+ brensenham_line(x, y, x2, y2).each do |i|
9
+ iterx, itery = *i
10
+ occ = @map.occupant(loc2(iterx,itery))
11
+ return unless occ
12
+ occ.lit = true
13
+ occ.seen = true
14
+
15
+ return if occ.solid?
16
+ end
17
+ end
18
+
19
+ # Brensenham line algorithm
20
+ def brensenham_line(x,y,x2,y2)
21
+ steep = false
22
+ coords = []
23
+ dx = (x2 - x).abs
24
+ if (x2 - x) > 0
25
+ sx = 1
26
+ else
27
+ sx = -1
28
+ end
29
+ dy = (y2 - y).abs
30
+ if (y2 - y) > 0
31
+ sy = 1
32
+ else
33
+ sy = -1
34
+ end
35
+ if dy > dx
36
+ steep = true
37
+ x,y = y,x
38
+ dx,dy = dy,dx
39
+ sx,sy = sy,sx
40
+ end
41
+ d = (2 * dy) - dx
42
+
43
+ dx.times do
44
+ if steep
45
+ coords << [y,x]
46
+ else
47
+ coords << [x,y]
48
+ end
49
+ while d >= 0
50
+ y = y + sy
51
+ d = d - (2 * dx)
52
+ end
53
+ x = x + sx
54
+ d = d + (2 * dy)
55
+ end
56
+ coords << [x2,y2]
57
+
58
+ coords
59
+ end
60
+
61
+ end
@@ -0,0 +1,107 @@
1
+ require 'algorithms'
2
+ include Containers
3
+
4
+ # Polaris is a star that guides, aka "The North Star". It implements the A* algorithm.
5
+ class Polaris
6
+ attr_reader :nodes_considered
7
+
8
+ def initialize(map)
9
+ @map = map
10
+ @nodes_considered = 0
11
+ end
12
+
13
+ def guide(from, to, unit_type=nil, max_depth=400)
14
+ return nil if @map.blocked?(from, unit_type) || @map.blocked?(to, unit_type)
15
+ from_element = PathElement.new(from)
16
+ from_element.dist_from = @map.distance(from,to)
17
+ open = PriorityQueue.new { |x, y| (x <=> y) == -1 }
18
+ open.push from_element, from_element.rating
19
+ closed = SplayTreeMap.new
20
+ step = 0
21
+
22
+ until open.empty? || step > max_depth
23
+ step += 1
24
+
25
+ current_element = open.pop
26
+ @nodes_considered += 1
27
+
28
+ loc = current_element.location
29
+ if @map.cost(loc,to) == 0
30
+ path = []
31
+ until current_element.parent.nil?
32
+ path.unshift current_element
33
+ current_element = current_element.parent
34
+ end
35
+
36
+ return path
37
+ else
38
+ closed.push current_element.location, current_element
39
+ @map.neighbors(loc).each do |next_door|
40
+ el = PathElement.new(next_door,current_element)
41
+ next if closed.has_key? next_door
42
+
43
+ if @map.blocked? next_door, unit_type
44
+ #closed.push el.location, el
45
+ else
46
+ current_rating = current_element.cost_to + @map.cost(loc, next_door)
47
+
48
+ # add to open
49
+ el.cost_to = current_rating
50
+ el.dist_from = @map.distance(next_door,to)
51
+
52
+ open.push el, el.rating
53
+ end
54
+ end
55
+ end
56
+ end
57
+ nil
58
+ end
59
+ end
60
+
61
+ class PathElement
62
+ include Comparable
63
+
64
+ attr_accessor :location, :parent
65
+ attr_reader :cost_to, :dist_from, :rating
66
+ def initialize(location=nil,parent=nil)
67
+ @location = location
68
+ @parent = parent
69
+ @cost_to = 0
70
+ @dist_from = 0
71
+ @rating = 99_999
72
+ end
73
+
74
+ def cost_to=(new_cost)
75
+ @cost_to = new_cost
76
+ reset_rating
77
+ end
78
+
79
+ def dist_from=(new_dist_from)
80
+ @dist_from = new_dist_from
81
+ reset_rating
82
+ end
83
+
84
+ def reset_rating
85
+ @rating = @cost_to + @dist_from
86
+ end
87
+
88
+ def to_s
89
+ "#{@location} at cost of #{@cost_to} and rating of #{@rating}"
90
+ end
91
+
92
+ def <=>(b)
93
+ a = self
94
+ if a.rating < b.rating
95
+ return -1
96
+ elsif a.rating > b.rating
97
+ return 1
98
+ else
99
+ 0
100
+ end
101
+ end
102
+
103
+ def ==(other)
104
+ return false if other.nil?
105
+ @location == other.location
106
+ end
107
+ end
@@ -0,0 +1,21 @@
1
+ # TwoDGridLocation exibits an x,y,cost location
2
+ class TwoDGridLocation
3
+ attr_accessor :x,:y
4
+ def initialize(x,y);@x=x;@y=y;end
5
+ def ==(other)
6
+ @x == other.x and @y == other.y
7
+ end
8
+
9
+ def <=>(b)
10
+ ret = 1
11
+ if @x == b.x && @y == b.y
12
+ ret = 0
13
+ end
14
+ ret = -1 if @x <= b.x && @y < b.y
15
+ return ret
16
+ end
17
+
18
+ def to_s
19
+ "#{@x},#{@y}"
20
+ end
21
+ end
@@ -0,0 +1,77 @@
1
+ require 'ai/two_d_grid_location'
2
+
3
+ # TwoDGridMap exibits the contract that the map requires.
4
+ # Works on an X,Y grid that uses Ftors for 2D vectors
5
+ class TwoDGridMap
6
+ attr_accessor :w, :h
7
+ TRAVEL_COST_DIAG = 14
8
+ TRAVEL_COST_STRAIGHT = 10
9
+
10
+ def initialize(w,h)
11
+ @w = w
12
+ @h = h
13
+ @grid = {}
14
+ end
15
+
16
+ # place thing at location. If thing is nil, location will be placed in the map
17
+ def place(location, thing=nil)
18
+ thing ||= location
19
+ @grid[location.x] ||= {}
20
+ @grid[location.x][location.y] = thing
21
+ end
22
+
23
+ def occupant(location)
24
+ @grid[location.x][location.y] if @grid[location.x]
25
+ end
26
+
27
+ def clear(location)
28
+ @grid[location.x] ||= {}
29
+ @grid[location.x][location.y] = nil
30
+ end
31
+
32
+ # is the location available for the specified type
33
+ def blocked?(location, type=nil)
34
+ return true if type == :blocked
35
+ return true if location.x >= @w || location.y >= @h || location.x < 0 || location.y < 0
36
+ if @grid[location.x] and @grid[location.x][location.y]
37
+ return true
38
+ else
39
+ return false
40
+ end
41
+ end
42
+
43
+ # returns a list of neighbors and their distance
44
+ def neighbors(location)
45
+ x = location.x
46
+ y = location.y
47
+ [
48
+ TwoDGridLocation.new(x-1, y-1),
49
+ TwoDGridLocation.new(x-1, y+1),
50
+ TwoDGridLocation.new(x+1, y-1),
51
+ TwoDGridLocation.new(x+1, y+1),
52
+ TwoDGridLocation.new(x-1, y),
53
+ TwoDGridLocation.new(x+1, y),
54
+ TwoDGridLocation.new(x, y-1),
55
+ TwoDGridLocation.new(x, y+1)
56
+ ]
57
+ end
58
+
59
+ def distance(from,to)
60
+ h_diagonal = [(from.x-to.x).abs, (from.y-to.y).abs].min
61
+ h_straight = ((from.x-to.x).abs + (from.y-to.y).abs)
62
+ return TRAVEL_COST_DIAG * h_diagonal + TRAVEL_COST_STRAIGHT * (h_straight - 2*h_diagonal)
63
+ end
64
+
65
+ # return the cost to go from => to (assuming from and to are neighbors)
66
+ def cost(from, to)
67
+ if from.x == to.x or from.y == to.y
68
+ if from.x == to.x and from.y == to.y
69
+ 0
70
+ else
71
+ TRAVEL_COST_STRAIGHT
72
+ end
73
+ else
74
+ TRAVEL_COST_DIAG
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,16 @@
1
+ class Module
2
+ # Encapsulates the common pattern of:
3
+ #
4
+ # alias_method :foo_without_feature, :foo
5
+ # alias_method :foo, :foo_with_feature
6
+ #
7
+ # With this, you simply do:
8
+ #
9
+ # alias_method_chain :foo, :feature
10
+ #
11
+ # And both aliases are set up for you.
12
+ def alias_method_chain(target, feature)
13
+ alias_method "#{target}_without_#{feature}", target
14
+ alias_method target, "#{target}_with_#{feature}"
15
+ end
16
+ end
@@ -0,0 +1,84 @@
1
+ require 'behavior'
2
+ # keeps track of an image for you based on the actor's class, and
3
+ # current action, and frame num
4
+ # by default it expects images to be:
5
+ # data/graphics/classname/action/01..n.png
6
+ class Animated < Behavior
7
+ FRAME_UPDATE_TIME = 60
8
+
9
+ attr_accessor :frame_time, :frame_num, :animating
10
+ def setup
11
+ @images = {}
12
+ @frame_time = 0
13
+
14
+ # all animated actors have to have an idle animation
15
+ # data/graphics/ship/idle/1.png
16
+ @frame_num = 0
17
+ self.action = :idle
18
+
19
+ animated_obj = self
20
+
21
+ @actor.instance_eval do
22
+ (class << self; self; end).class_eval do
23
+ define_method :image do
24
+ animated_obj.image
25
+ end
26
+ define_method :start_animating do
27
+ animated_obj.start_animating
28
+ end
29
+ define_method :stop_animating do
30
+ animated_obj.stop_animating
31
+ end
32
+ define_method :action= do |action_sym|
33
+ animated_obj.action = action_sym
34
+ end
35
+ define_method :animated do
36
+ animated_obj
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ def update(time)
44
+ return unless @animating
45
+ @frame_time += time
46
+ if @frame_time > FRAME_UPDATE_TIME
47
+ next_frame
48
+ @frame_time = @frame_time-FRAME_UPDATE_TIME
49
+ end
50
+ end
51
+
52
+ def next_frame()
53
+ @frame_num = (@frame_num + 1) % @images[@action].size
54
+ end
55
+
56
+ # load all the images for this action
57
+ def load_action(action)
58
+ @actor.resource_manager.load_animation_set @actor, action
59
+ end
60
+
61
+ def action=(new_action)
62
+ @images[new_action] ||= load_action(new_action)
63
+ if @images[new_action].size > 1
64
+ start_animating
65
+ else
66
+ stop_animating
67
+ end
68
+ @frame_num = 0
69
+ @action = new_action
70
+ end
71
+
72
+ # returns the current image, or nil if no action is defined
73
+ def image
74
+ @images[@action][@frame_num]
75
+ end
76
+
77
+ def start_animating
78
+ @animating = true
79
+ end
80
+
81
+ def stop_animating
82
+ @animating = false
83
+ end
84
+ end