RubyMan 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/Gemfile +6 -0
- data/Rakefile +2 -0
- data/RubyMan.gemspec +24 -0
- data/bin/rubyman +4 -0
- data/lib/ruby_man.rb +5 -0
- data/lib/ruby_man/GameObjects/door.rb +11 -0
- data/lib/ruby_man/GameObjects/food.rb +24 -0
- data/lib/ruby_man/GameObjects/game_object.rb +29 -0
- data/lib/ruby_man/GameObjects/game_over.rb +44 -0
- data/lib/ruby_man/GameObjects/ghost.rb +123 -0
- data/lib/ruby_man/GameObjects/ghost_corpse.rb +30 -0
- data/lib/ruby_man/GameObjects/grid_object.rb +69 -0
- data/lib/ruby_man/GameObjects/hud.rb +26 -0
- data/lib/ruby_man/GameObjects/menu.rb +82 -0
- data/lib/ruby_man/GameObjects/moving_object.rb +50 -0
- data/lib/ruby_man/GameObjects/player.rb +90 -0
- data/lib/ruby_man/GameObjects/super_food.rb +16 -0
- data/lib/ruby_man/GameObjects/wall.rb +24 -0
- data/lib/ruby_man/aabb.rb +17 -0
- data/lib/ruby_man/direction.rb +102 -0
- data/lib/ruby_man/game_main.rb +213 -0
- data/lib/ruby_man/level_loader.rb +49 -0
- data/lib/ruby_man/resource_manager.rb +103 -0
- data/lib/ruby_man/sprite.rb +26 -0
- data/lib/ruby_man/version.rb +4 -0
- data/media/door_strip2.png +0 -0
- data/media/gem_strip9.png +0 -0
- data/media/ghost_death_strip15.png +0 -0
- data/media/ghost_down_strip2.png +0 -0
- data/media/ghost_left_strip2.png +0 -0
- data/media/ghost_right_strip2.png +0 -0
- data/media/ghost_scared_strip2.png +0 -0
- data/media/ghost_stopscared_strip3.png +0 -0
- data/media/ghost_up_strip2.png +0 -0
- data/media/levellist.txt +4 -0
- data/media/levels/level_1.txt +19 -0
- data/media/levels/level_2.txt +19 -0
- data/media/levels/level_3.txt +19 -0
- data/media/levels/level_4.txt +19 -0
- data/media/levels/level_empty.txt +19 -0
- data/media/logo.png +0 -0
- data/media/resource.cfg +18 -0
- data/media/rubyman_strip11.png +0 -0
- data/media/sfx/pacman_beginning.wav +0 -0
- data/media/sfx/pacman_chomp.wav +0 -0
- data/media/sfx/pacman_death.wav +0 -0
- data/media/sfx/pacman_eatghost.wav +0 -0
- data/media/walls_strip16.png +0 -0
- data/test/aabb_spec.rb +41 -0
- data/test/direction_spec.rb +48 -0
- data/test/game_main_spec.rb +126 -0
- metadata +142 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'ruby_man/GameObjects/wall'
|
2
|
+
require 'ruby_man/GameObjects/player'
|
3
|
+
require 'ruby_man/GameObjects/food'
|
4
|
+
require 'ruby_man/GameObjects/ghost'
|
5
|
+
require 'ruby_man/GameObjects/hud'
|
6
|
+
require 'ruby_man/GameObjects/door'
|
7
|
+
require 'ruby_man/GameObjects/super_food'
|
8
|
+
|
9
|
+
module RubyMan
|
10
|
+
# mixin for loading levels from files
|
11
|
+
# required method - add_object, level_loaded
|
12
|
+
module LevelLoader
|
13
|
+
def load_level_string(level_string, restart)
|
14
|
+
y = 0
|
15
|
+
level_string.lines do |line|
|
16
|
+
x = -1
|
17
|
+
line.each_char do |char|
|
18
|
+
x += 1
|
19
|
+
obj = LevelLoader.object_from_char(char)
|
20
|
+
next unless obj
|
21
|
+
next if restart && obj.class.persistent == true
|
22
|
+
obj.set_pos(x, y)
|
23
|
+
add_object(obj)
|
24
|
+
end
|
25
|
+
y += 1
|
26
|
+
end
|
27
|
+
|
28
|
+
add_object(Hud.new)
|
29
|
+
|
30
|
+
level_loaded
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_level_file(level_name, restart)
|
34
|
+
f = File.open(ResourceManager.media(level_name))
|
35
|
+
load_level_string(f.read, restart)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.object_from_char(char)
|
39
|
+
case char.downcase
|
40
|
+
when 'p' then return Player.new
|
41
|
+
when '.' then return Food.new
|
42
|
+
when ':' then return SuperFood.new
|
43
|
+
when 'g' then return Ghost.new
|
44
|
+
when '_' then return Door.new
|
45
|
+
end
|
46
|
+
Wall.from_char(char) unless Wall.chars.index(char).nil?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'gosu'
|
2
|
+
require 'ruby_man/sprite'
|
3
|
+
|
4
|
+
module Gosu
|
5
|
+
# extension of Font for easier centered drawing
|
6
|
+
class Font
|
7
|
+
def draw_centered(text, x, y, z = 0,
|
8
|
+
factor_x = 1, factor_y = 1,
|
9
|
+
color = 0xffffffff, mode = :default)
|
10
|
+
w = text_width(text, factor_x)
|
11
|
+
draw(text, x - w / 2, y, z, factor_x, factor_y, color, mode)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module RubyMan
|
17
|
+
# Handles loading of resources for faster and centralized access.
|
18
|
+
class ResourceManager
|
19
|
+
class << self
|
20
|
+
attr_accessor :inst
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(window)
|
24
|
+
ResourceManager.inst = self
|
25
|
+
@window = window
|
26
|
+
@resources = {}
|
27
|
+
@media_dir = "#{__dir__}/../../media"
|
28
|
+
load_config
|
29
|
+
end
|
30
|
+
|
31
|
+
def media_file_path(media_path)
|
32
|
+
"#{@media_dir}/#{media_path}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def load_config
|
36
|
+
File.open(media_file_path('resource.cfg')).each do |line|
|
37
|
+
cfg = line.split(';').map!(&:strip)
|
38
|
+
next unless cfg.size >= 3
|
39
|
+
case cfg[1]
|
40
|
+
when 'image' then load_image(cfg)
|
41
|
+
when 'animation' then load_animation(cfg)
|
42
|
+
when 'font' then load_font(cfg)
|
43
|
+
when 'sound' then load_sound(cfg)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_animation(cfg)
|
49
|
+
return unless cfg.size >= 7
|
50
|
+
|
51
|
+
sprite = Sprite.new
|
52
|
+
x_offset = cfg[3].to_i
|
53
|
+
y_offset = cfg[4].to_i
|
54
|
+
sprite.width = cfg[5].to_i
|
55
|
+
sprite.height = cfg[6].to_i
|
56
|
+
frames = cfg[7].to_i
|
57
|
+
|
58
|
+
(0...frames).each do |i|
|
59
|
+
image = Gosu::Image.new(@window, media_file_path(cfg[2]), true,
|
60
|
+
x_offset + i * sprite.width, y_offset,
|
61
|
+
sprite.width, sprite.height)
|
62
|
+
sprite.frames.push(image)
|
63
|
+
end
|
64
|
+
|
65
|
+
@resources[cfg[0]] = sprite
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_image(cfg)
|
69
|
+
sprite = Sprite.new
|
70
|
+
sprite.frames.push(Gosu::Image.new(@window, media_file_path(cfg[2]), false))
|
71
|
+
sprite.width = sprite.frames[0].width
|
72
|
+
sprite.height = sprite.frames[0].height
|
73
|
+
@resources[cfg[0]] = sprite
|
74
|
+
end
|
75
|
+
|
76
|
+
def load_sound(cfg)
|
77
|
+
sound = Gosu::Sample.new(@window, media_file_path(cfg[2]))
|
78
|
+
@resources[cfg[0]] = sound
|
79
|
+
end
|
80
|
+
|
81
|
+
def load_font(cfg)
|
82
|
+
begin
|
83
|
+
font = Gosu::Font.new(@window, media_file_path(cfg[2]), cfg[3].to_i)
|
84
|
+
font.text_width('font found test')
|
85
|
+
rescue
|
86
|
+
font = Gosu::Font.new(@window, Gosu::default_font_name, cfg[3].to_i)
|
87
|
+
end
|
88
|
+
@resources[cfg[0]] = font
|
89
|
+
end
|
90
|
+
|
91
|
+
def resource(name)
|
92
|
+
@resources[name]
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.[](resource_name)
|
96
|
+
@inst.resource(resource_name)
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.media(media_path)
|
100
|
+
@inst.media_file_path(media_path)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'ruby_man/resource_manager'
|
2
|
+
|
3
|
+
module RubyMan
|
4
|
+
# drawable animated image
|
5
|
+
class Sprite
|
6
|
+
attr_accessor :frames
|
7
|
+
attr_accessor :width, :height
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@frames = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.[](resource_name)
|
14
|
+
ResourceManager[resource_name]
|
15
|
+
end
|
16
|
+
|
17
|
+
def draw(x, y, depth = 0, rotation = 0, frame = 0, scale = 1.0)
|
18
|
+
frames[frame].draw_rot(x + @width / 2, y + @height / 2, -depth,
|
19
|
+
rotation, 0.5, 0.5, scale, scale)
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw_centered(x, y, depth = 0, rotation = 0, frame = 0, scale = 1.0)
|
23
|
+
frames[frame].draw_rot(x, y, -depth, rotation, 0.5, 0.5, scale, scale)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/media/levellist.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
/-----------------------\
|
2
|
+
|...........:...........|
|
3
|
+
|./----\./-----\./----\.|
|
4
|
+
|.| |.| |.| |.|
|
5
|
+
|.| |.| |.| |.|
|
6
|
+
|.L----J.L-----J.L----J.|
|
7
|
+
|.......................|
|
8
|
+
|.o.o.o.o./-_-\.o.o.o.o.|
|
9
|
+
|....:....|GGG|....:....|
|
10
|
+
|.o.o.o.o.L---J.o.o.o.o.|
|
11
|
+
|.......................|
|
12
|
+
|./----\./-----\./----\.|
|
13
|
+
|.| |.| |.| |.|
|
14
|
+
|.| |.| |.| |.|
|
15
|
+
|.L----J.L-----J.L----J.|
|
16
|
+
|.......................|
|
17
|
+
|.<-------->P<-------->.|
|
18
|
+
|:.....................:|
|
19
|
+
L-----------------------J
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/-----------------------\
|
2
|
+
|:.....................:|
|
3
|
+
|./-----\./---\./-----\.|
|
4
|
+
|.| /---J.L\ /J.L---\ |.|
|
5
|
+
|.| |:.....L-J.....:| |.|
|
6
|
+
|.L-J.<-->.....<-->.L-J.|
|
7
|
+
|........../_\..........|
|
8
|
+
F-------\./JGL\./-------3
|
9
|
+
| G |.|GGG|.| G |
|
10
|
+
| |.L---J.| |
|
11
|
+
F-------J.......L-------3
|
12
|
+
|........./\P/\.........|
|
13
|
+
|./-\.<---3L-JF--->./-\.|
|
14
|
+
|.| |:....| |....:| |.|
|
15
|
+
|.| L---\.| G |./---J |.|
|
16
|
+
|.L-----J.| |.L-----J.|
|
17
|
+
|.........L---J.........|
|
18
|
+
L-------\...:.../-------J
|
19
|
+
L-------J
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/-----------T-----------\
|
2
|
+
|...........|...........|
|
3
|
+
|./--\./--\.|./--\./--\.|
|
4
|
+
|:| |.| |.|.| |.| |:|
|
5
|
+
|.L--J.L--J.|.L--J.L--J.|
|
6
|
+
|...........:...........|
|
7
|
+
|.<--\./\./-_-\./\./-->.|
|
8
|
+
|....|.||.| GG|.||.|....|
|
9
|
+
F--\.|.||.|GGG|.||.|./--3
|
10
|
+
| |.|.||.L-T-J.||.|.| |
|
11
|
+
F--J.V.LJ...|...LJ.V.L--3
|
12
|
+
|.........A.P.A.........|
|
13
|
+
|./\./--\.V.|.V./--\./\.|
|
14
|
+
|.||.L--3...|...F--J.||.|
|
15
|
+
|:||....L->.V.<-J....||:|
|
16
|
+
|.|L--\.........../--J|.|
|
17
|
+
|.L---J.<>./-\.<>.L---J.|
|
18
|
+
|..........| |..........|
|
19
|
+
L----------4-4----------J
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/----T-T---------T-T----\
|
2
|
+
|...:|G|....:....|G|:...|
|
3
|
+
|.<--4_4--->.<---4_4-->.|
|
4
|
+
|.......................|
|
5
|
+
F----\./-\./-\./-\./----3
|
6
|
+
| |.| |.L-J.| |.| |
|
7
|
+
| |.| |.....| |.| |
|
8
|
+
F----J.L-J./-\.L-J.L----3
|
9
|
+
|..........|G|..........|
|
10
|
+
|./--\.<---3 F--->./--\.|
|
11
|
+
|.| |.....L-J.....| |.|
|
12
|
+
|.| L\./\..P../\./J |.|
|
13
|
+
|.L---J.|L-----J|.L---J.|
|
14
|
+
|.......| |.......|
|
15
|
+
|./-\./-J/-----\L-\./-\.|
|
16
|
+
|.|G|.| |.....| |.|G|.|
|
17
|
+
|.L_J.L--J./_\.L--J.L_J.|
|
18
|
+
|:.........|G|.........:|
|
19
|
+
L----------4-4----------J
|
data/media/logo.png
ADDED
Binary file
|
data/media/resource.cfg
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
rubyman;animation;rubyman_strip11.png;0;0;32;32;11
|
2
|
+
walls;animation;walls_strip16.png;0;0;32;32;16
|
3
|
+
door;animation;door_strip2.png;0;0;32;32;2
|
4
|
+
ghost_left;animation;ghost_left_strip2.png;0;0;32;32;2
|
5
|
+
ghost_right;animation;ghost_right_strip2.png;0;0;32;32;2
|
6
|
+
ghost_up;animation;ghost_up_strip2.png;0;0;32;32;2
|
7
|
+
ghost_down;animation;ghost_down_strip2.png;0;0;32;32;2
|
8
|
+
ghost_scared;animation;ghost_scared_strip2.png;0;0;32;32;2
|
9
|
+
ghost_stop_scared;animation;ghost_stopscared_strip3.png;0;0;32;32;3
|
10
|
+
ghost_death;animation;ghost_death_strip15.png;0;0;32;32;15
|
11
|
+
gem;animation;gem_strip9.png;0;0;32;32;9
|
12
|
+
logo;image;logo.png
|
13
|
+
sfx_begin;sound;sfx/pacman_beginning.wav
|
14
|
+
sfx_death;sound;sfx/pacman_death.wav
|
15
|
+
sfx_eatghost;sound;sfx/pacman_eatghost.wav
|
16
|
+
sfx_eat;sound;sfx/pacman_chomp.wav
|
17
|
+
text_normal;font;Arial;22
|
18
|
+
text_large;font;Arial;48
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/aabb_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'ruby_man/aabb'
|
3
|
+
|
4
|
+
# Common RubyMan namespace
|
5
|
+
module RubyMan
|
6
|
+
describe 'AABB' do
|
7
|
+
context 'intersection' do
|
8
|
+
subject(:box) { AABB.new(2, 2, 8, 8) }
|
9
|
+
it 'intersects basic cases' do
|
10
|
+
expect(box.intersects?(AABB.new(0, 0, 4, 4))).to be true
|
11
|
+
expect(box.intersects?(AABB.new(4, 4, 10, 10))).to be true
|
12
|
+
expect(box.intersects?(AABB.new(0, 4, 5, 10))).to be true
|
13
|
+
expect(box.intersects?(AABB.new(4, 0, 10, 5))).to be true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'intersects edges' do
|
17
|
+
expect(box.intersects?(AABB.new(3, 0, 4, 10))).to be true
|
18
|
+
expect(box.intersects?(AABB.new(0, 3, 10, 4))).to be true
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'accepts floats' do
|
22
|
+
expect(box.intersects?(AABB.new(2.1, 0, 7.9, 10))).to be true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does not intersect' do
|
26
|
+
expect(box.intersects?(AABB.new(-1000, -1000, 1, 1))).to be false
|
27
|
+
expect(box.intersects?(AABB.new(9, 9, 1000, 1000))).to be false
|
28
|
+
expect(box.intersects?(AABB.new(-1000, -1000, 1000, 1))).to be false
|
29
|
+
expect(box.intersects?(AABB.new(-1000, 9, 1000, 1000))).to be false
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'intersects when contained inside other' do
|
33
|
+
expect(box.intersects?(AABB.new(0, 0, 10, 10))).to be true
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'intersects when containing other' do
|
37
|
+
expect(box.intersects?(AABB.new(4, 4, 5, 5))).to be true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'ruby_man/direction'
|
3
|
+
|
4
|
+
# Common RubyMan namespace
|
5
|
+
module RubyMan
|
6
|
+
describe 'Direction' do
|
7
|
+
context 'should work with Array booleans' do
|
8
|
+
subject(:arr) { [Direction.left, Direction.right, Direction.up] }
|
9
|
+
|
10
|
+
it 'works with intersection' do
|
11
|
+
expect(arr & [Direction.right,
|
12
|
+
Direction.down,
|
13
|
+
Direction.up]).to eq [Direction.right, Direction.up]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'works with subtraction' do
|
17
|
+
expect(arr - [Direction.right,
|
18
|
+
Direction.down,
|
19
|
+
Direction.up]).to eq [Direction.left]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'works with equal' do
|
23
|
+
expect(arr).to eq [Direction.left, Direction.right, Direction.up]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'functionality' do
|
28
|
+
subject(:dir) { Direction.up }
|
29
|
+
it { expect(dir).to eq Direction.up }
|
30
|
+
it { expect(dir.opposite).to eq Direction.down }
|
31
|
+
it do
|
32
|
+
expect(dir.inverted).to eq [Direction.right,
|
33
|
+
Direction.down,
|
34
|
+
Direction.left]
|
35
|
+
end
|
36
|
+
it do
|
37
|
+
expect(Direction.each.to_a).to eq [Direction.right,
|
38
|
+
Direction.down,
|
39
|
+
Direction.left,
|
40
|
+
Direction.up]
|
41
|
+
end
|
42
|
+
it { expect(Direction.each.to_a.map(&:to_i)).to eq [0, 1, 2, 3] }
|
43
|
+
it { expect(Direction.each.to_a.map(&:to_angle)).to eq [0, 90, 180, 270] }
|
44
|
+
it { expect(Direction.each.to_a.map(&:rel_x)).to eq [1, 0, -1, 0] }
|
45
|
+
it { expect(Direction.each.to_a.map(&:rel_y)).to eq [0, 1, 0, -1] }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'ruby_man/game_main'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
# Common RubyMan namespace
|
6
|
+
module RubyMan
|
7
|
+
describe 'GameMain' do
|
8
|
+
context 'game' do
|
9
|
+
subject(:game) { GameMain.new }
|
10
|
+
|
11
|
+
def select_type(arr, type)
|
12
|
+
arr.select { |obj| obj.is_a?(type) }
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'starts in menu' do
|
16
|
+
expect(select_type(game.objects, Menu).size).to eq 1
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'has at least one level' do
|
20
|
+
expect(game.instance_variable_get(:@levels).size).to be > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'first level' do
|
24
|
+
before { game.start }
|
25
|
+
|
26
|
+
it 'has 3 lives' do
|
27
|
+
expect(game.lives).to eq 3
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'spawns correct number of required game objects' do
|
31
|
+
expect(select_type(game.objects, Player).size).to eq 1
|
32
|
+
expect(select_type(game.moving_objects, Player).size).to eq 1
|
33
|
+
expect(select_type(game.objects, Food).size).to be > 0
|
34
|
+
expect(select_type(game.objects, Hud).size).to eq 1
|
35
|
+
# ghosts aren't mandatory for the game to work
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'spawns player on a free spot' do
|
39
|
+
expect(game.place_free(game.player.grid_x,
|
40
|
+
game.player.grid_y)).to be true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'does not crash after start' do
|
44
|
+
expect { game.update_delta(0.01) }.to_not raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'sets player variable' do
|
48
|
+
expect(game.player).to be_a Player
|
49
|
+
end
|
50
|
+
|
51
|
+
after { game.main_menu }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'test level' do
|
55
|
+
def setup
|
56
|
+
level = '|G..:' + "\n" \
|
57
|
+
'L_P| '
|
58
|
+
game.end_level
|
59
|
+
game.load_level_string(level, false)
|
60
|
+
# verify test sanity - the player should be at (2,1)
|
61
|
+
raise_error unless game.player.grid_x == 2 && game.player.grid_y == 1
|
62
|
+
end
|
63
|
+
|
64
|
+
before { setup }
|
65
|
+
|
66
|
+
it 'player detects walls' do
|
67
|
+
expect(game.player.direction_free(Direction.up)).to be true
|
68
|
+
expect(game.player.direction_free(Direction.left)).to be false
|
69
|
+
expect(game.player.direction_free(Direction.right)).to be false
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'player is killed by ghost' do
|
73
|
+
before do
|
74
|
+
game.lives = 3
|
75
|
+
ghost = game.objects_at(1, 0).first
|
76
|
+
ghost.set_pos(2, 1)
|
77
|
+
# process collision
|
78
|
+
game.update_delta(0)
|
79
|
+
# skip time after pause
|
80
|
+
game.update_delta(2.5)
|
81
|
+
# process level restart
|
82
|
+
game.update_delta(0)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'reduces player lives' do
|
86
|
+
expect(game.lives).to eq 2
|
87
|
+
end
|
88
|
+
|
89
|
+
after do
|
90
|
+
game.lives = 3
|
91
|
+
setup
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'ghost' do
|
96
|
+
subject(:ghost) { game.objects_at(1, 0).first }
|
97
|
+
|
98
|
+
before { ghost.change_direction(Direction.up) }
|
99
|
+
|
100
|
+
it 'starts in chase mode' do
|
101
|
+
expect(instance_variable_get(:@scared)).to be_nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'knows where it can go' do
|
105
|
+
# down would be turning back, left would be into the wall
|
106
|
+
expect(ghost.possible_directions).to match_array [Direction.right,
|
107
|
+
Direction.up]
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'knows directions to player' do
|
111
|
+
expect(ghost.directions_to_player).to match_array [Direction.right,
|
112
|
+
Direction.down]
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'knows directions in which to run away from player' do
|
116
|
+
expect(ghost.scared_directions).to eq [Direction.up]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
after do
|
121
|
+
game.main_menu
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|