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,16 @@
|
|
1
|
+
# Helper functions for determining platform
|
2
|
+
|
3
|
+
# TODO how do I do this in ruby 1.9, since PLATFORM doesn't exist?
|
4
|
+
class Platform
|
5
|
+
def self.mac?
|
6
|
+
return PLATFORM =~ /darwin/
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.windows?
|
10
|
+
return PLATFORM =~ /mswin/
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.linux?
|
14
|
+
return PLATFORM =~ /linux/
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'level'
|
2
|
+
require 'ftor'
|
3
|
+
class DemoLevel < Level
|
4
|
+
def setup
|
5
|
+
@my_actor = create_actor :my_actor
|
6
|
+
@my_actor.x = 10
|
7
|
+
@my_actor.y = 10
|
8
|
+
|
9
|
+
@stars = []
|
10
|
+
20.times { @stars << Ftor.new(rand(@width),rand(@height)) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def draw(target, x_off, y_off)
|
14
|
+
target.fill [25,25,25,255]
|
15
|
+
for star in @stars
|
16
|
+
target.draw_circle_s([star.x,star.y],1,[255,255,255,255])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Game
|
2
|
+
|
3
|
+
constructor :wrapped_screen, :input_manager, :sound_manager,
|
4
|
+
:mode_manager
|
5
|
+
|
6
|
+
def setup
|
7
|
+
# @sound_manager.play :current_rider
|
8
|
+
|
9
|
+
@mode_manager.change_mode_to :default
|
10
|
+
end
|
11
|
+
|
12
|
+
def update(time)
|
13
|
+
@mode_manager.update time
|
14
|
+
draw
|
15
|
+
end
|
16
|
+
|
17
|
+
def draw
|
18
|
+
@mode_manager.draw @wrapped_screen
|
19
|
+
@wrapped_screen.flip
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'actor'
|
2
|
+
require 'actor_view'
|
3
|
+
|
4
|
+
class MyActorView < ActorView
|
5
|
+
def draw(target, x_off, y_off)
|
6
|
+
target.draw_box [@actor.x,@actor.y], [20,20], [240,45,45,255]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class MyActor < Actor
|
11
|
+
|
12
|
+
def setup
|
13
|
+
# TODO setup stuff here
|
14
|
+
# subscribe for an event or something?
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'numbers_ext'
|
2
|
+
require 'publisher'
|
3
|
+
|
4
|
+
# Viewport represents the current "camera" location. Essensially it translates from
|
5
|
+
# world to screen coords and from screen coords to world coords.
|
6
|
+
class Viewport
|
7
|
+
extend Publisher
|
8
|
+
can_fire :scrolled
|
9
|
+
|
10
|
+
attr_accessor :x_offset, :y_offset, :follow_target, :width,
|
11
|
+
:height
|
12
|
+
|
13
|
+
def debug
|
14
|
+
"xoff:#{@x_offset} yoff:#{@y_offset}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(width, height)
|
18
|
+
@x_offset = 0
|
19
|
+
@y_offset = 0
|
20
|
+
|
21
|
+
@width = width
|
22
|
+
@height = height
|
23
|
+
end
|
24
|
+
|
25
|
+
def x_offset(layer=1)
|
26
|
+
return 0 if layer == Float::Infinity
|
27
|
+
return @x_offset if layer == 1
|
28
|
+
@x_offset / layer
|
29
|
+
end
|
30
|
+
|
31
|
+
def y_offset(layer=1)
|
32
|
+
return 0 if layer == Float::Infinity
|
33
|
+
return @y_offset if layer == 1
|
34
|
+
@y_offset / layer
|
35
|
+
end
|
36
|
+
|
37
|
+
def update(time)
|
38
|
+
scrolled = false
|
39
|
+
if @follow_target
|
40
|
+
x_diff = @width/2 + @follow_offset_x - @follow_target.x - @x_offset
|
41
|
+
if x_diff.abs > @buffer_x
|
42
|
+
# move screen
|
43
|
+
if x_diff > 0
|
44
|
+
@x_offset += x_diff - @buffer_x
|
45
|
+
scrolled = true
|
46
|
+
else
|
47
|
+
@x_offset += x_diff + @buffer_x
|
48
|
+
scrolled = true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
y_diff = @height/2 + @follow_offset_y - @follow_target.y - @y_offset
|
53
|
+
if y_diff.abs > @buffer_y
|
54
|
+
# move screen
|
55
|
+
if y_diff > 0
|
56
|
+
@y_offset += y_diff - @buffer_y
|
57
|
+
scrolled = true
|
58
|
+
else
|
59
|
+
@y_offset += y_diff + @buffer_y
|
60
|
+
scrolled = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
fire :scrolled if scrolled
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def follow(target, off=[0,0], buff=[0,0])
|
69
|
+
@follow_target = target
|
70
|
+
@follow_offset_x = off[0]
|
71
|
+
@follow_offset_y = off[1]
|
72
|
+
@buffer_x = buff[0]
|
73
|
+
@buffer_y = buff[1]
|
74
|
+
|
75
|
+
@x_offset = @width/2 - @follow_target.x + @follow_offset_x
|
76
|
+
@y_offset = @height/2 - @follow_target.y + @follow_offset_y
|
77
|
+
|
78
|
+
fire :scrolled
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class WrappedScreen
|
2
|
+
constructor :config_manager
|
3
|
+
attr_accessor :screen
|
4
|
+
def setup
|
5
|
+
w,h = @config_manager[:screen_resolution]
|
6
|
+
flags = []
|
7
|
+
flags << HWSURFACE
|
8
|
+
flags << DOUBLEBUF
|
9
|
+
flags << FULLSCREEN if @config_manager[:fullscreen]
|
10
|
+
@screen = Screen.set_mode [w,h], 0, flags
|
11
|
+
end
|
12
|
+
def method_missing(name,*args)
|
13
|
+
@screen.send name, *args
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
$: << File.dirname(__FILE__)+"/../lib/gamebox"
|
2
|
+
|
3
|
+
require 'ai/polaris'
|
4
|
+
require 'ai/two_d_grid_map'
|
5
|
+
|
6
|
+
@map = TwoDGridMap.new 100, 90
|
7
|
+
|
8
|
+
from = TwoDGridLocation.new 0, 0
|
9
|
+
to = TwoDGridLocation.new 9, 0
|
10
|
+
@pather = Polaris.new @map
|
11
|
+
|
12
|
+
require 'benchmark'
|
13
|
+
Benchmark.bm do|b|
|
14
|
+
|
15
|
+
b.report("warm up") do
|
16
|
+
10.times { path = @pather.guide(from,to) }
|
17
|
+
end
|
18
|
+
|
19
|
+
b.report("shorter path") do
|
20
|
+
10.times { path = @pather.guide(from,to) }
|
21
|
+
end
|
22
|
+
|
23
|
+
to = TwoDGridLocation.new 92, 0
|
24
|
+
b.report("longer path") do
|
25
|
+
10.times { path = @pather.guide(from,to) }
|
26
|
+
end
|
27
|
+
|
28
|
+
# put up a wall
|
29
|
+
@map.h.times do |i|
|
30
|
+
@map.place TwoDGridLocation.new(89, i), "ME"
|
31
|
+
end
|
32
|
+
|
33
|
+
b.report("blocked path") do
|
34
|
+
10.times { path = @pather.guide(from,to) }
|
35
|
+
end
|
36
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gamebox'))
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
require 'bacon'
|
6
|
+
require 'mocha'
|
7
|
+
require 'aliasing'
|
8
|
+
|
9
|
+
class Bacon::Context
|
10
|
+
include Mocha::Standalone
|
11
|
+
def it_with_mocha description
|
12
|
+
it_without_mocha description do
|
13
|
+
mocha_setup
|
14
|
+
yield
|
15
|
+
mocha_verify
|
16
|
+
mocha_teardown
|
17
|
+
end
|
18
|
+
end
|
19
|
+
alias_method_chain :it, :mocha
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
require 'metaclass'
|
24
|
+
require 'actor'
|
25
|
+
|
data/test/test_actor.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'actor'
|
3
|
+
|
4
|
+
describe 'A new actor' do
|
5
|
+
before do
|
6
|
+
opts = {:level=>"level", :input=>"input", :resources=>"resource"}
|
7
|
+
@actor = Actor.new opts
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should be alive' do
|
11
|
+
@actor.alive?.should.equal true
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should be at (0,0)' do
|
15
|
+
@actor.x.should.equal 0
|
16
|
+
@actor.y.should.equal 0
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have atts set' do
|
20
|
+
@actor.level.should.equal "level"
|
21
|
+
@actor.input_manager.should.equal "input"
|
22
|
+
@actor.resource_manager.should.equal "resource"
|
23
|
+
@actor.behaviors.size.should.equal 0
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should fire anything' do
|
27
|
+
should.not.raise do
|
28
|
+
@actor.when :foofoo_bar do
|
29
|
+
"blah"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should setup behaviors' do
|
35
|
+
should.flunk 'cannot test easily!'
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'animated'
|
3
|
+
require 'mocha'
|
4
|
+
|
5
|
+
describe 'A new animated behavior' do
|
6
|
+
before do
|
7
|
+
@rm = stub(:load_animation_set => ['1.png_img_obj','2.png_img_obj'])
|
8
|
+
|
9
|
+
opts = {:level=>"level", :input=>"input", :resources=>@rm}
|
10
|
+
@actor = Actor.new opts
|
11
|
+
@animated = Animated.new @actor
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should define methods on actor' do
|
15
|
+
@actor.should.respond_to? :image
|
16
|
+
@actor.should.respond_to? :start_animating
|
17
|
+
@actor.should.respond_to? :stop_animating
|
18
|
+
@actor.should.respond_to? :action=
|
19
|
+
@actor.should.respond_to? :animated
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'shouldn\'t update frame for non-animating' do
|
23
|
+
@animated.stop_animating
|
24
|
+
|
25
|
+
@animated.update Animated::FRAME_UPDATE_TIME+1
|
26
|
+
|
27
|
+
@animated.frame_time.should.equal 0
|
28
|
+
@animated.frame_num.should.equal 0
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should update frame for animating' do
|
32
|
+
time_passed = Animated::FRAME_UPDATE_TIME-1
|
33
|
+
@animated.update time_passed
|
34
|
+
@animated.frame_time.should.equal time_passed
|
35
|
+
@animated.frame_num.should.equal 0
|
36
|
+
|
37
|
+
time_passed_again = 2
|
38
|
+
@animated.update time_passed_again
|
39
|
+
# we rolled over the time
|
40
|
+
@animated.frame_time.should.equal 1
|
41
|
+
@animated.frame_num.should.equal 1
|
42
|
+
|
43
|
+
time_passed_again = Animated::FRAME_UPDATE_TIME
|
44
|
+
@animated.update time_passed_again
|
45
|
+
# we rolled over the time
|
46
|
+
@animated.frame_time.should.equal 1
|
47
|
+
@animated.frame_num.should.equal 0
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should stop animating' do
|
51
|
+
@animated.stop_animating
|
52
|
+
@animated.animating.should.equal false
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should start animating' do
|
56
|
+
@animated.start_animating
|
57
|
+
@animated.animating.should.equal true
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should set the action and animate accordingly' do
|
61
|
+
should.flunk 'finish me'
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'ai/line_of_site'
|
3
|
+
require 'ai/two_d_grid_map'
|
4
|
+
|
5
|
+
describe 'A new LineOfSite' do
|
6
|
+
before do
|
7
|
+
@map = TwoDGridMap.new 10, 20
|
8
|
+
@los = LineOfSite.new @map
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should be sane' do
|
12
|
+
true.should == true
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'physical'
|
3
|
+
require 'actor'
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
class CircleActor < Actor
|
7
|
+
has_behaviors :physical => {:shape => :circle,
|
8
|
+
:mass => 500,
|
9
|
+
:radius => 10}
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'A new physical behavior' do
|
13
|
+
before do
|
14
|
+
@level = stub(:load_animation_set => ['1.png_img_obj','2.png_img_obj'],:register_physical_object => true)
|
15
|
+
|
16
|
+
opts = {:level=>@level, :input=>"input", :resources=>"rm"}
|
17
|
+
@actor = CircleActor.new opts
|
18
|
+
@physical = @actor.physical
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should add methods to its actor' do
|
22
|
+
@actor.should.respond_to? :x
|
23
|
+
should.flunk 'testing this feels dirty...'
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'ai/polaris'
|
3
|
+
require 'ai/two_d_grid_map'
|
4
|
+
|
5
|
+
describe 'A new polaris' do
|
6
|
+
before do
|
7
|
+
@map = TwoDGridMap.new 10, 20
|
8
|
+
@pather = Polaris.new @map
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should return an empty path if destination is not valid' do
|
12
|
+
from = TwoDGridLocation.new @map.w-1, @map.h-1
|
13
|
+
to = TwoDGridLocation.new @map.w, @map.h
|
14
|
+
@pather.guide(from,to).should == nil
|
15
|
+
|
16
|
+
to = TwoDGridLocation.new(-1, -1)
|
17
|
+
@pather.guide(from,to).should == nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should return an empty path if start is not valid' do
|
21
|
+
from = TwoDGridLocation.new @map.w, @map.h
|
22
|
+
to = TwoDGridLocation.new @map.w-1, @map.h-1
|
23
|
+
@pather.guide(from,to).should == nil
|
24
|
+
|
25
|
+
from = TwoDGridLocation.new -1, -1
|
26
|
+
@pather.guide(from,to).should == nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return the path of "to" for accessible neighbor' do
|
30
|
+
from = TwoDGridLocation.new 0, 0
|
31
|
+
to = TwoDGridLocation.new 1, 0
|
32
|
+
|
33
|
+
path = @pather.guide(from,to)
|
34
|
+
path.should != nil
|
35
|
+
path.size.should == 1
|
36
|
+
|
37
|
+
path.first.cost_to.should == TwoDGridMap::TRAVEL_COST_STRAIGHT
|
38
|
+
path.first.dist_from.should == 0
|
39
|
+
path.first.location.x.should == to.x
|
40
|
+
path.first.location.y.should == to.y
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should return the right horizontal path of length 2' do
|
44
|
+
from = TwoDGridLocation.new 0, 0
|
45
|
+
to = TwoDGridLocation.new 2, 0
|
46
|
+
|
47
|
+
path = @pather.guide(from,to)
|
48
|
+
|
49
|
+
path.should != nil
|
50
|
+
path.size.should == 2
|
51
|
+
|
52
|
+
path.first.location.x.should == 1
|
53
|
+
path.first.location.y.should == 0
|
54
|
+
path.last.location.should == to
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should return the left horizontal path of length 2' do
|
58
|
+
from = TwoDGridLocation.new 2, 0
|
59
|
+
to = TwoDGridLocation.new 0, 0
|
60
|
+
|
61
|
+
path = @pather.guide(from,to)
|
62
|
+
|
63
|
+
path.should != nil
|
64
|
+
path.size.should == 2
|
65
|
+
|
66
|
+
path.first.location.x.should == 1
|
67
|
+
path.first.location.y.should == 0
|
68
|
+
path.last.location.should == to
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
it 'should return the left up diag path of length 2' do
|
73
|
+
from = TwoDGridLocation.new 2, 2
|
74
|
+
to = TwoDGridLocation.new 0, 0
|
75
|
+
|
76
|
+
path = @pather.guide(from,to)
|
77
|
+
|
78
|
+
path.should != nil
|
79
|
+
path.size.should == 2
|
80
|
+
|
81
|
+
path.first.location.x.should == 1
|
82
|
+
path.first.location.y.should == 1
|
83
|
+
path.last.location.should == to
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should return the right up diag path of length 2' do
|
87
|
+
from = TwoDGridLocation.new 2, 2
|
88
|
+
to = TwoDGridLocation.new 4, 0
|
89
|
+
|
90
|
+
path = @pather.guide(from,to)
|
91
|
+
|
92
|
+
path.should != nil
|
93
|
+
path.size.should == 2
|
94
|
+
|
95
|
+
path.first.location.x.should == 3
|
96
|
+
path.first.location.y.should == 1
|
97
|
+
path.last.location.should == to
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should return the right down diag path of length 2' do
|
101
|
+
from = TwoDGridLocation.new 2, 2
|
102
|
+
to = TwoDGridLocation.new 4, 4
|
103
|
+
|
104
|
+
path = @pather.guide(from,to)
|
105
|
+
|
106
|
+
path.should != nil
|
107
|
+
path.size.should == 2
|
108
|
+
|
109
|
+
path.first.location.x.should == 3
|
110
|
+
path.first.location.y.should == 3
|
111
|
+
path.last.location.should == to
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should return the left down diag path of length 2' do
|
115
|
+
from = TwoDGridLocation.new 2, 2
|
116
|
+
to = TwoDGridLocation.new 0, 4
|
117
|
+
|
118
|
+
path = @pather.guide(from,to)
|
119
|
+
|
120
|
+
path.should != nil
|
121
|
+
path.size.should == 2
|
122
|
+
|
123
|
+
path.first.location.x.should == 1
|
124
|
+
path.first.location.y.should == 3
|
125
|
+
path.last.location.should == to
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should return go around an obstacle' do
|
129
|
+
from = TwoDGridLocation.new 0, 0
|
130
|
+
to = TwoDGridLocation.new 2, 0
|
131
|
+
|
132
|
+
in_the_way = TwoDGridLocation.new 1, 0
|
133
|
+
@map.place in_the_way, "ME"
|
134
|
+
|
135
|
+
path = @pather.guide(from,to)
|
136
|
+
|
137
|
+
path.should != nil
|
138
|
+
path.size.should == 2
|
139
|
+
|
140
|
+
path.first.location.x.should == 1
|
141
|
+
path.first.location.y.should == 1
|
142
|
+
path.last.location.should == to
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should return shortest path of horizontal and diag length 5' do
|
146
|
+
from = TwoDGridLocation.new 0, 0
|
147
|
+
to = TwoDGridLocation.new 5, 4
|
148
|
+
|
149
|
+
path = @pather.guide(from,to)
|
150
|
+
|
151
|
+
path.should != nil
|
152
|
+
path.size.should == 5
|
153
|
+
|
154
|
+
# make sure that all elements of the path are neighbors
|
155
|
+
prev_el = PathElement.new from, nil
|
156
|
+
path.each do |path_el|
|
157
|
+
@map.neighbors(prev_el.location).should.include? path_el.location
|
158
|
+
prev_el = path_el
|
159
|
+
end
|
160
|
+
|
161
|
+
path.last.location.should == to
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should return nil when the shortest path is longer than the max step passed in' do
|
165
|
+
from = TwoDGridLocation.new 0, 0
|
166
|
+
to = TwoDGridLocation.new 5, 4
|
167
|
+
|
168
|
+
path = @pather.guide(from,to,nil,4)
|
169
|
+
path.should == nil
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should return nil when the path does not exist for unit type' do
|
173
|
+
from = TwoDGridLocation.new 0, 0
|
174
|
+
to = TwoDGridLocation.new 2, 0
|
175
|
+
|
176
|
+
path = @pather.guide(from,to,:blocked)
|
177
|
+
path.should == nil
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should return nil when the path does not exist' do
|
181
|
+
from = TwoDGridLocation.new 0, 0
|
182
|
+
to = TwoDGridLocation.new 2, 0
|
183
|
+
|
184
|
+
# put up a wall
|
185
|
+
@map.h.times do |i|
|
186
|
+
@map.place TwoDGridLocation.new(1, i), "ME"
|
187
|
+
end
|
188
|
+
|
189
|
+
path = @pather.guide(from,to)
|
190
|
+
path.should == nil
|
191
|
+
@pather.nodes_considered.should == @map.h
|
192
|
+
end
|
193
|
+
end
|