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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +6 -0
  4. data/Rakefile +2 -0
  5. data/RubyMan.gemspec +24 -0
  6. data/bin/rubyman +4 -0
  7. data/lib/ruby_man.rb +5 -0
  8. data/lib/ruby_man/GameObjects/door.rb +11 -0
  9. data/lib/ruby_man/GameObjects/food.rb +24 -0
  10. data/lib/ruby_man/GameObjects/game_object.rb +29 -0
  11. data/lib/ruby_man/GameObjects/game_over.rb +44 -0
  12. data/lib/ruby_man/GameObjects/ghost.rb +123 -0
  13. data/lib/ruby_man/GameObjects/ghost_corpse.rb +30 -0
  14. data/lib/ruby_man/GameObjects/grid_object.rb +69 -0
  15. data/lib/ruby_man/GameObjects/hud.rb +26 -0
  16. data/lib/ruby_man/GameObjects/menu.rb +82 -0
  17. data/lib/ruby_man/GameObjects/moving_object.rb +50 -0
  18. data/lib/ruby_man/GameObjects/player.rb +90 -0
  19. data/lib/ruby_man/GameObjects/super_food.rb +16 -0
  20. data/lib/ruby_man/GameObjects/wall.rb +24 -0
  21. data/lib/ruby_man/aabb.rb +17 -0
  22. data/lib/ruby_man/direction.rb +102 -0
  23. data/lib/ruby_man/game_main.rb +213 -0
  24. data/lib/ruby_man/level_loader.rb +49 -0
  25. data/lib/ruby_man/resource_manager.rb +103 -0
  26. data/lib/ruby_man/sprite.rb +26 -0
  27. data/lib/ruby_man/version.rb +4 -0
  28. data/media/door_strip2.png +0 -0
  29. data/media/gem_strip9.png +0 -0
  30. data/media/ghost_death_strip15.png +0 -0
  31. data/media/ghost_down_strip2.png +0 -0
  32. data/media/ghost_left_strip2.png +0 -0
  33. data/media/ghost_right_strip2.png +0 -0
  34. data/media/ghost_scared_strip2.png +0 -0
  35. data/media/ghost_stopscared_strip3.png +0 -0
  36. data/media/ghost_up_strip2.png +0 -0
  37. data/media/levellist.txt +4 -0
  38. data/media/levels/level_1.txt +19 -0
  39. data/media/levels/level_2.txt +19 -0
  40. data/media/levels/level_3.txt +19 -0
  41. data/media/levels/level_4.txt +19 -0
  42. data/media/levels/level_empty.txt +19 -0
  43. data/media/logo.png +0 -0
  44. data/media/resource.cfg +18 -0
  45. data/media/rubyman_strip11.png +0 -0
  46. data/media/sfx/pacman_beginning.wav +0 -0
  47. data/media/sfx/pacman_chomp.wav +0 -0
  48. data/media/sfx/pacman_death.wav +0 -0
  49. data/media/sfx/pacman_eatghost.wav +0 -0
  50. data/media/walls_strip16.png +0 -0
  51. data/test/aabb_spec.rb +41 -0
  52. data/test/direction_spec.rb +48 -0
  53. data/test/game_main_spec.rb +126 -0
  54. metadata +142 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a03426f79e26e9df419b99b564062de38e2a17d1
4
+ data.tar.gz: 6d5a6118f6fb3a5db10eaa7aac549b0217835f17
5
+ SHA512:
6
+ metadata.gz: 807f1d45014a8a63c1894424d93ffc4f41ba7832d3a404b4f58e4f6b55b0a311e76d24d81eb04e64b3aced57c0cfe6ea5644a11bfd654a03eb5e96ae93fe3416
7
+ data.tar.gz: 04711b7c9ebfa87dc67e1976e59e06dbb57a445b640d24a5367fd3cb89637c842b1f7abeef97bfc1566537589151f70c75194fcad1297bd36f04c849e7a3f905
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ /.idea
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in RubyMan.gemspec
4
+ gemspec
5
+ gem 'gosu'
6
+ gem 'rspec'
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby_man/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "RubyMan"
8
+ spec.version = RubyMan::VERSION
9
+ spec.authors = ["Bc. Marek Manukjan"]
10
+ spec.email = ["manukmar@fit.cvut.cz"]
11
+ spec.summary = %q{Ruby-themed PacMan}
12
+ spec.description = %q{Simple Ruby-themed implementation of PacMan}
13
+ spec.homepage = "https://gitlab.fit.cvut.cz/manukmar/rubyman"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_runtime_dependency "gosu", "~> 0.8"
24
+ end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'ruby_man/game_main'
3
+
4
+ RubyMan::GameMain.new.show
@@ -0,0 +1,5 @@
1
+ require 'ruby_man/version'
2
+
3
+ # Common RubyMan namespace
4
+ module RubyMan
5
+ end
@@ -0,0 +1,11 @@
1
+ require 'ruby_man/GameObjects/grid_object'
2
+
3
+ module RubyMan
4
+ # Door object impassable by player, passable by ghosts
5
+ class Door < GridObject
6
+ def created
7
+ self.sprite = Sprite['door']
8
+ @image_speed = 5
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ require 'ruby_man/GameObjects/grid_object'
2
+
3
+ module RubyMan
4
+ # Food eatable by player
5
+ class Food < GridObject
6
+ def self.persistent
7
+ true
8
+ end
9
+
10
+ def created
11
+ super
12
+ self.sprite = Sprite['gem']
13
+ @scale = 0.5
14
+ @depth = 1
15
+ @game.food_created
16
+ end
17
+
18
+ def destroyed
19
+ super
20
+ ResourceManager['sfx_eat'].play
21
+ @game.food_destroyed
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module RubyMan
2
+ # Generic object attachable to game loop
3
+ class GameObject
4
+ attr_accessor :game
5
+
6
+ def self.persistent
7
+ false
8
+ end
9
+
10
+ def button_down(_key)
11
+ end
12
+
13
+ def draw
14
+ end
15
+
16
+ def update(_delta)
17
+ end
18
+
19
+ def destroy
20
+ @game.destroy_object(self)
21
+ end
22
+
23
+ def destroyed
24
+ end
25
+
26
+ def created
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ require 'ruby_man/GameObjects/menu'
2
+
3
+ module RubyMan
4
+ # Helper object for inputting player name
5
+ class PlayerName < Gosu::TextInput
6
+ def filter(text_in)
7
+ return '' if text.size >= 10
8
+ text_in.gsub(/[^A-Za-z0-9]/, '')
9
+ end
10
+ end
11
+
12
+ # Game Over screen with enterable player name
13
+ class GameOver < GameObject
14
+ def created
15
+ super
16
+ @text = ResourceManager['text_normal']
17
+ @large_text = ResourceManager['text_large']
18
+ @name = ''
19
+ @input = PlayerName.new
20
+ @game.text_input = @input
21
+ end
22
+
23
+ def main_menu
24
+ @game.add_score(@input.text)
25
+ @game.text_input = nil
26
+ @game.main_menu
27
+ end
28
+
29
+ def draw
30
+ super
31
+ @large_text.draw_centered('Game over!', x_center, @game.y_res / 6, 0)
32
+ @text.draw_centered('Enter name:', x_center, @game.y_res / 2, 0)
33
+ @text.draw_centered(@input.text, x_center, @game.y_res / 2 + 32, 0)
34
+ end
35
+
36
+ def x_center
37
+ @game.x_res / 2
38
+ end
39
+
40
+ def button_down(id)
41
+ main_menu if id == Gosu::KbEnter || id == Gosu::KbReturn
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,123 @@
1
+ require 'ruby_man/GameObjects/moving_object'
2
+ require 'ruby_man/GameObjects/ghost_corpse'
3
+
4
+ module RubyMan
5
+ # Ghost that chases player
6
+ class Ghost < MovingObject
7
+ def created
8
+ self.sprite = Sprite['ghost_left']
9
+ @spawn_x, @spawn_y = @grid_x, @grid_y
10
+ stop_scared
11
+ end
12
+
13
+ def update(delta)
14
+ super
15
+ update_scared(delta) unless @dead
16
+ end
17
+
18
+ def grid_step
19
+ select_direction!
20
+ end
21
+
22
+ def possible_directions
23
+ directions = []
24
+ Direction.each do |dir|
25
+ next unless dir != @direction.opposite && direction_free(dir)
26
+ directions.push(dir)
27
+ end
28
+ directions
29
+ end
30
+
31
+ def scared_directions
32
+ to_pl = directions_to_player
33
+ possible = possible_directions
34
+ away = possible - to_pl
35
+ return possible if away.empty?
36
+ away
37
+ end
38
+
39
+ def chase_directions
40
+ directions = possible_directions
41
+ directions_to_player.each do |dir|
42
+ 2.times { directions.push(dir) } if directions.include?(dir)
43
+ end
44
+ directions
45
+ end
46
+
47
+ def weighted_directions
48
+ directions = @scared ? scared_directions : chase_directions
49
+ directions.push(Direction.none) if directions.empty?
50
+ directions
51
+ end
52
+
53
+ def directions_to_player
54
+ return [] unless @game.player
55
+ rel_x = @game.player.grid_x - @grid_x
56
+ rel_y = @game.player.grid_y - @grid_y
57
+ directions = []
58
+ directions.push(Direction.right) if rel_x > 0
59
+ directions.push(Direction.left) if rel_x < 0
60
+ directions.push(Direction.down) if rel_y > 0
61
+ directions.push(Direction.up) if rel_y < 0
62
+ directions
63
+ end
64
+
65
+ def select_direction!
66
+ directions = weighted_directions
67
+ change_direction(directions[rand(directions.size)])
68
+ end
69
+
70
+ def change_direction(direction)
71
+ @direction = direction
72
+ return if @scared
73
+ case direction
74
+ when Direction.left then self.sprite = Sprite['ghost_left']
75
+ when Direction.right then self.sprite = Sprite['ghost_right']
76
+ when Direction.up then self.sprite = Sprite['ghost_up']
77
+ when Direction.down then self.sprite = Sprite['ghost_down']
78
+ end
79
+ end
80
+
81
+ def set_pos(x, y)
82
+ super
83
+ select_direction! if @game
84
+ end
85
+
86
+ def scare
87
+ @scared = 7.0
88
+ @speed = 1.5
89
+ update_scared(0.0)
90
+ end
91
+
92
+ def scared?
93
+ @scared != nil
94
+ end
95
+
96
+ def update_scared(delta)
97
+ return unless @scared
98
+ @scared -= delta
99
+ return stop_scared if @scared <= 0.0
100
+ if @scared > 2.0
101
+ self.sprite = Sprite['ghost_scared']
102
+ else
103
+ self.sprite = Sprite['ghost_stop_scared']
104
+ end
105
+ end
106
+
107
+ def stop_scared
108
+ @speed = 2.5
109
+ @scared = nil
110
+ # reset sprite according to current direction
111
+ change_direction(@direction)
112
+ end
113
+
114
+ def die
115
+ ResourceManager['sfx_eatghost'].play
116
+ @game.score += 500
117
+ @game.add_object(GhostCorpse.new(@grid_x, @grid_y,
118
+ @phase, @direction,
119
+ @spawn_x, @spawn_y))
120
+ destroy
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,30 @@
1
+ require 'ruby_man/GameObjects/moving_object'
2
+
3
+ module RubyMan
4
+ # simple object representing dying ghost with respawn functionality
5
+ class GhostCorpse < MovingObject
6
+ def initialize(x, y, phase, direction, res_x, res_y)
7
+ super()
8
+ @grid_x, @grid_y, = x, y
9
+ @phase, @direction = phase, direction
10
+ @res_x, @res_y = res_x, res_y
11
+ self.sprite = Sprite['ghost_death']
12
+ end
13
+
14
+ def update(delta)
15
+ next_index = @image_index + @image_speed * delta * @sprite.frames.size
16
+ if next_index < @sprite.frames.size
17
+ @image_index = next_index
18
+ else
19
+ respawn
20
+ end
21
+ end
22
+
23
+ def respawn
24
+ ghost = Ghost.new
25
+ ghost.set_pos(@res_x, @res_y)
26
+ @game.add_object(ghost)
27
+ destroy
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,69 @@
1
+ require 'ruby_man/GameObjects/game_object'
2
+ require 'ruby_man/aabb'
3
+
4
+ module RubyMan
5
+ # GameObject aligned to game's grid
6
+ class GridObject < GameObject
7
+ attr_accessor :grid_x, :grid_y, :depth
8
+ attr_reader :sprite
9
+ attr_accessor :image_index, :image_speed, :image_angle
10
+ attr_accessor :solid
11
+
12
+ def initialize
13
+ super
14
+ @grid_x = -1
15
+ @grid_y = -1
16
+ @depth = 0
17
+ @image_index = 0
18
+ @image_speed = 1
19
+ @image_angle = 0
20
+ @solid = false
21
+ @scale = 1.0
22
+ end
23
+
24
+ def update(delta)
25
+ super
26
+ return unless sprite
27
+ @image_index += @image_speed * delta * @sprite.frames.size
28
+ @image_index %= @sprite.frames.size
29
+ end
30
+
31
+ def draw
32
+ super
33
+ return unless sprite
34
+ sprite.draw(pixel_x, pixel_y, depth,
35
+ image_angle, image_index.to_i, @scale)
36
+ end
37
+
38
+ def sprite=(new_sprite)
39
+ return if @sprite == new_sprite
40
+ @image_index = 0
41
+ @sprite = new_sprite
42
+ end
43
+
44
+ def pixel_x
45
+ @grid_x * 32
46
+ end
47
+
48
+ def pixel_y
49
+ @grid_y * 32
50
+ end
51
+
52
+ def bbox
53
+ AABB.new(pixel_x, pixel_y,
54
+ pixel_x + @sprite.width, pixel_y + @sprite.height)
55
+ end
56
+
57
+ def distance_to(other)
58
+ rel_x = other.pixel_x - pixel_x
59
+ rel_y = other.pixel_y - pixel_y
60
+ Math.sqrt(rel_x.abs2 + rel_y.abs2)
61
+ end
62
+
63
+ def set_pos(x, y)
64
+ @grid_x = x
65
+ @grid_y = y
66
+ @phase = 0
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,26 @@
1
+ require 'ruby_man/GameObjects/game_object'
2
+ require 'ruby_man/resource_manager'
3
+
4
+ module RubyMan
5
+ # Game overlay showing number of lives and score
6
+ class Hud < GameObject
7
+ def initialize
8
+ super
9
+ @text = ResourceManager['text_normal']
10
+ @life_sprite = ResourceManager['rubyman']
11
+ end
12
+
13
+ def draw
14
+ y_offset = 608
15
+ @text.draw("Score: #{@game.score}", 8, y_offset + 2, 0)
16
+ x_offset = 160
17
+ lives_text = 'Lives: '
18
+ @text.draw(lives_text, x_offset, y_offset + 2, 0)
19
+ x_offset += @text.text_width(lives_text)
20
+ @game.lives.times do
21
+ @life_sprite.draw(x_offset + 2, y_offset)
22
+ x_offset += @life_sprite.width
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,82 @@
1
+ require 'ruby_man/resource_manager'
2
+ require 'ruby_man/GameObjects/moving_object'
3
+
4
+ module RubyMan
5
+ # RubyMan object for decorating main menu
6
+ class MenuRubyMan < MovingObject
7
+ def created
8
+ self.sprite = Sprite['rubyman']
9
+ set_pos(-4, 8)
10
+ change_direction(Direction.right)
11
+ @speed = 3
12
+ @image_speed = 3
13
+ end
14
+
15
+ def grid_step
16
+ if @direction == Direction.right
17
+ change_direction(Direction.left) if @grid_x >= 31
18
+ else
19
+ change_direction(Direction.right) if @grid_x <= -4
20
+ end
21
+ end
22
+ end
23
+
24
+ # Ghost object for decorating main menu
25
+ class MenuGhost < MovingObject
26
+ def created
27
+ set_pos(-6, 8)
28
+ @speed = 3
29
+ @image_speed = 3
30
+ set_chase
31
+ end
32
+
33
+ def set_chase
34
+ @direction = Direction.right
35
+ self.sprite = Sprite['ghost_right']
36
+ end
37
+
38
+ def set_run
39
+ @direction = Direction.left
40
+ self.sprite = Sprite['ghost_scared']
41
+ end
42
+
43
+ def grid_step
44
+ if @direction == Direction.right
45
+ set_run if @grid_x >= 29
46
+ else
47
+ set_chase if @grid_x <= -6
48
+ end
49
+ end
50
+ end
51
+
52
+ # title screen showing high scores
53
+ class Menu < GameObject
54
+ def created
55
+ @logo = Sprite['logo']
56
+ @text = ResourceManager['text_normal']
57
+ @large_text = ResourceManager['text_large']
58
+ @game.add_object(MenuRubyMan.new)
59
+ @game.add_object(MenuGhost.new)
60
+ end
61
+
62
+ def button_down(id)
63
+ @game.start if id == Gosu::KbEnter || id == Gosu::KbReturn
64
+ end
65
+
66
+ def draw
67
+ @logo.draw_centered(@game.x_res / 2, 92)
68
+ @large_text.draw_centered('Press Enter to start!', @game.x_res / 2, 200)
69
+ draw_scores(@game.x_res / 2 - 192, @game.y_res / 2)
70
+ end
71
+
72
+ def draw_scores(x, y)
73
+ y_offset = 0
74
+ @game.scores.each do |entry|
75
+ @text.draw(entry[0], x, y + y_offset, 0)
76
+ @text.draw(entry[1], x + 128, y + y_offset, 0)
77
+ @text.draw(entry[2], x + 320, y + y_offset, 0)
78
+ y_offset += 32
79
+ end
80
+ end
81
+ end
82
+ end