space_invaders 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +38 -0
  6. data/Rakefile +1 -0
  7. data/assets/fonts/unifont.ttf +0 -0
  8. data/assets/images/Bullet.png +0 -0
  9. data/assets/images/FullBlock.png +0 -0
  10. data/assets/images/InvaderA1.png +0 -0
  11. data/assets/images/InvaderA2.png +0 -0
  12. data/assets/images/InvaderB1.png +0 -0
  13. data/assets/images/InvaderB2.png +0 -0
  14. data/assets/images/InvaderC1.png +0 -0
  15. data/assets/images/InvaderC2.png +0 -0
  16. data/assets/images/OkBlock.png +0 -0
  17. data/assets/images/RedInvader.png +0 -0
  18. data/assets/images/Ship.png +0 -0
  19. data/assets/images/ShipCrushedLeft.png +0 -0
  20. data/assets/images/ShipCrushedRight.png +0 -0
  21. data/assets/images/WeakBlock.png +0 -0
  22. data/assets/sounds/InvaderBullet.wav +0 -0
  23. data/assets/sounds/InvaderHit.wav +0 -0
  24. data/assets/sounds/ShipBullet.wav +0 -0
  25. data/assets/sounds/ShipHit.wav +0 -0
  26. data/bin/space-invaders +9 -0
  27. data/go.rb +5 -0
  28. data/lib/space_invaders.rb +4 -0
  29. data/lib/space_invaders/app.rb +99 -0
  30. data/lib/space_invaders/base.rb +14 -0
  31. data/lib/space_invaders/behaviors/centerable.rb +13 -0
  32. data/lib/space_invaders/behaviors/collideable.rb +18 -0
  33. data/lib/space_invaders/behaviors/fireable.rb +35 -0
  34. data/lib/space_invaders/behaviors/mesurable.rb +17 -0
  35. data/lib/space_invaders/blocks/block.rb +62 -0
  36. data/lib/space_invaders/blocks/u_block.rb +37 -0
  37. data/lib/space_invaders/blocks/u_block_container.rb +46 -0
  38. data/lib/space_invaders/bullets/bullet.rb +46 -0
  39. data/lib/space_invaders/bullets/bullet_collection.rb +23 -0
  40. data/lib/space_invaders/invaders/invader.rb +38 -0
  41. data/lib/space_invaders/invaders/invader_abc.rb +27 -0
  42. data/lib/space_invaders/invaders/invader_row.rb +52 -0
  43. data/lib/space_invaders/invaders/invaders_container.rb +146 -0
  44. data/lib/space_invaders/invaders/red_invader.rb +66 -0
  45. data/lib/space_invaders/screens/game_over_screen.rb +42 -0
  46. data/lib/space_invaders/screens/next_level_screen.rb +39 -0
  47. data/lib/space_invaders/screens/welcome_screen.rb +46 -0
  48. data/lib/space_invaders/ship/drowned_ship_animator.rb +46 -0
  49. data/lib/space_invaders/ship/ship.rb +99 -0
  50. data/lib/space_invaders/statics/button_controller.rb +33 -0
  51. data/lib/space_invaders/statics/game_status.rb +52 -0
  52. data/lib/space_invaders/statics/images.rb +39 -0
  53. data/lib/space_invaders/statics/sounds.rb +37 -0
  54. data/lib/space_invaders/trackers/lives_tracker.rb +27 -0
  55. data/lib/space_invaders/trackers/score_tracker.rb +27 -0
  56. data/lib/space_invaders/utils.rb +19 -0
  57. data/space_invaders.gemspec +23 -0
  58. metadata +143 -0
@@ -0,0 +1,46 @@
1
+ require 'space_invaders/base'
2
+ require 'space_invaders/blocks/u_block'
3
+
4
+ module SpaceInvaders
5
+ class UBlockContainer < Base
6
+
7
+ attr_reader :u_blocks
8
+
9
+ def initialize app
10
+ super
11
+ initialize_u_blocks
12
+ end
13
+
14
+ def update
15
+ @u_blocks.each { |item| item.update }
16
+ end
17
+
18
+ def draw
19
+ @u_blocks.each {|item| item.draw }
20
+ end
21
+
22
+ def initialize_u_blocks
23
+ @u_blocks = [
24
+ UBlock.new(app, 150, 400),
25
+ UBlock.new(app, 350, 400),
26
+ UBlock.new(app, 550, 400)
27
+ ]
28
+ end
29
+
30
+ def each(&block)
31
+ @u_blocks.each(&block)
32
+ end
33
+
34
+ def delete(item)
35
+ @u_blocks.delete(item)
36
+ end
37
+
38
+ def <<(item)
39
+ @u_blocks << item
40
+ end
41
+
42
+ alias_method :push, :<<
43
+ alias_method :add, :<<
44
+
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ module SpaceInvaders
2
+ class Bullet < Base
3
+
4
+ attr_reader :x_position, :y_position, :going_down, :bullet_offset, :bullet_collection, :image, :fireing_vehicle
5
+
6
+ alias_method :going_down?, :going_down
7
+
8
+ def initialize fireing_vehicle, going_down, bullet_collection, bullet_offset=10
9
+ super(fireing_vehicle.app)
10
+ @fireing_vehicle = fireing_vehicle
11
+ @image = app.images.bullet
12
+ @bullet_offset = bullet_offset
13
+ @going_down = going_down
14
+ @bullet_collection = bullet_collection
15
+ @bullet_collection << self
16
+ set_position
17
+ end
18
+
19
+ def update
20
+ @y_position += going_down? ? bullet_offset : -bullet_offset
21
+ end
22
+
23
+ def draw
24
+ image.draw x_position, y_position, 1
25
+ end
26
+
27
+ def delete
28
+ bullet_collection.delete(self)
29
+ end
30
+
31
+ def out_of_screen
32
+ if going_down
33
+ y_position > app.height
34
+ else
35
+ y_position < 0
36
+ end
37
+ end
38
+
39
+ def set_position
40
+ @x_position = fireing_vehicle.x_middle - image.width/2
41
+ @y_position = fireing_vehicle.y_position
42
+ @y_position += fireing_vehicle.height if going_down
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ require 'forwardable'
2
+
3
+ module SpaceInvaders
4
+ class BulletCollection
5
+ extend Forwardable
6
+ attr_reader :bullets
7
+
8
+ def initialize
9
+ @bullets = []
10
+ end
11
+
12
+ def update
13
+ @bullets.delete_if {|bullet| bullet.out_of_screen}
14
+ @bullets.each { |bullet| bullet.update }
15
+ end
16
+
17
+ def draw
18
+ @bullets.each {|bullet| bullet.draw }
19
+ end
20
+
21
+ def_delegators :@bullets, :each, :delete, :<<, :clear
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ require 'space_invaders/behaviors/mesurable'
2
+ require 'space_invaders/behaviors/collideable'
3
+ module SpaceInvaders
4
+ class Invader < Base
5
+ include Mesurable
6
+ include Collideable
7
+
8
+ attr_reader :original_x_position
9
+
10
+ def initialize app, x_position, y_position
11
+ super app
12
+
13
+ @was_first_image = true
14
+ @x_position = x_position
15
+ @original_x_position = x_position
16
+ @y_position = y_position
17
+ @image = @first_image
18
+ end
19
+
20
+ def update(direction, y_offset=0)
21
+ x_offset = direction == :right ? 10 : -10
22
+ @x_position += x_offset
23
+ @y_position += y_offset
24
+
25
+ @was_first_image = !@was_first_image
26
+ @image = @was_first_image ? @first_image : @second_image
27
+ end
28
+
29
+ def draw
30
+ @image.draw x_position, y_position, 1
31
+ end
32
+
33
+ def points
34
+ raise NotImplementedError.new("You must implement the inherited points method")
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ require 'space_invaders/invaders/invader'
2
+ require 'space_invaders/utils'
3
+
4
+ module SpaceInvaders
5
+ [:invader_a, :invader_b, :invader_c].each do |invader_name|
6
+ clazz_name = Utils.camelcase(invader_name)
7
+ clazz = Class.new(Invader) do
8
+ def initialize app, x_position=0, y_position=0
9
+ @first_image = Gosu::Image.new app, app.images.send("#{Utils.snake_klazz_name(self.class)}1")
10
+ @second_image = Gosu::Image.new app, app.images.send("#{Utils.snake_klazz_name(self.class)}2")
11
+ super
12
+ end
13
+
14
+ def points
15
+ case self
16
+ when InvaderA
17
+ 40
18
+ when InvaderB
19
+ 20
20
+ when InvaderC
21
+ 10
22
+ end
23
+ end
24
+ end
25
+ Object.const_set(clazz_name, clazz)
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ require 'forwardable'
2
+ require 'space_invaders/base'
3
+
4
+ module SpaceInvaders
5
+ class InvaderRow < Base
6
+ extend Forwardable
7
+
8
+ attr_accessor :direction
9
+ attr_reader :invader_clazz
10
+
11
+ X_POSITIONS = [40, 110, 180, 250, 320, 390, 460, 530]
12
+
13
+ def initialize app, y_position, invader_clazz
14
+ super(app)
15
+ @y_position = y_position
16
+ @direction = :right
17
+ @invader_clazz = invader_clazz
18
+ @invaders = []
19
+ X_POSITIONS.each do |x_position|
20
+ @invaders << invader_clazz.new(app, x_position, y_position)
21
+ end
22
+ end
23
+
24
+ def_delegators :@invaders, :each, :count, :select, :find, :empty?
25
+
26
+ def update direction, y_offset
27
+ @invaders.each {|invader| invader.update direction, y_offset }
28
+ end
29
+
30
+ def draw
31
+ @invaders.each {|invader| invader.draw }
32
+ end
33
+
34
+ def farmost_right_position
35
+ @invaders.max_by {|invader| invader.x_position }.x_position
36
+ end
37
+
38
+ def farmost_left_position
39
+ @invaders.min_by {|invader| invader.x_position }.x_position
40
+ end
41
+
42
+ def check_collision(bullets)
43
+ @invaders.delete_if do |invader|
44
+ if invader.collides_with? bullets
45
+ app.score_tracker.increase_by(invader.points)
46
+ app.sounds.play_invader_hit!
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,146 @@
1
+ require 'space_invaders/invaders/invader_row'
2
+ require 'space_invaders/invaders/invader_abc'
3
+ require 'space_invaders/behaviors/fireable'
4
+
5
+ module SpaceInvaders
6
+ class InvadersContainer < Base
7
+ include Fireable
8
+ attr_reader :invader_rows
9
+
10
+ def initialize app
11
+ super
12
+ create_invader_rows
13
+ @change_time = Time.now
14
+ @can_fire = Time.now
15
+ @direction = :right
16
+ @y_offset = 0
17
+ end
18
+
19
+ def update
20
+ check_collision
21
+
22
+ if no_invaders?
23
+ app.next_level_screen.timer_start!
24
+ return game_status.next_level!
25
+ end
26
+
27
+ if can_change?
28
+ change_direction
29
+ @change_time = Time.now
30
+ end
31
+
32
+ if can_fire?
33
+ fire!
34
+ @can_fire = Time.now
35
+ end
36
+
37
+ bullets.update
38
+ end
39
+
40
+ def draw
41
+ invader_rows.each {|invader_row| invader_row.draw }
42
+ bullets.draw
43
+ end
44
+
45
+ def count
46
+ invader_rows.map {|invader_row| invader_row.count}.inject(:+) || 0
47
+ end
48
+
49
+ def any_invaders?
50
+ not count.zero?
51
+ end
52
+
53
+ def no_invaders?
54
+ count.zero?
55
+ end
56
+
57
+ def reinitialize!
58
+ create_invader_rows
59
+ bullets.clear
60
+ rival_bullets.clear
61
+ @change_time = Time.now
62
+ @can_fire = Time.now
63
+ end
64
+
65
+ private
66
+
67
+ def check_collision
68
+ invader_rows.each { |invader_row| invader_row.check_collision(rival_bullets) }
69
+ invader_rows.delete_if {|invader_row| invader_row.empty?}
70
+ hit_rock_bottom? if any_invaders?
71
+ end
72
+
73
+ def hit_rock_bottom?
74
+ if any_invaders? and fireable_invaders.first.y_position == app.height
75
+ app.game_status.finished!
76
+ end
77
+ end
78
+
79
+ def change_direction
80
+ if farmost_right_position >= app.width - 80
81
+ @direction = :left
82
+ @y_offset = 10
83
+ elsif farmost_left_position <= 20
84
+ @direction = :right
85
+ @y_offset = 10
86
+ else
87
+ @y_offset = 0
88
+ end
89
+ update_direction(@direction, @y_offset)
90
+ end
91
+
92
+ def update_direction direction, y_offset
93
+ invader_rows.each {|invader_row| invader_row.update direction, y_offset }
94
+ end
95
+
96
+ def shooter
97
+ fireable_invaders.sample
98
+ end
99
+
100
+ def sound
101
+ app.sounds.invader_bullet_sound
102
+ end
103
+
104
+ def can_fire?
105
+ Time.now > @can_fire + 2
106
+ end
107
+
108
+ def can_change?
109
+ Time.now > @change_time + 0.25
110
+ end
111
+
112
+ def fireable_invaders
113
+ InvaderRow::X_POSITIONS.map do |x_position|
114
+ invader_rows.reverse.map do |invader_row|
115
+ invader_row.find {|invader| invader.original_x_position == x_position }
116
+ end.compact.first
117
+ end.compact
118
+ end
119
+
120
+ def create_invader_rows
121
+ @invader_rows = [
122
+ InvaderRow.new(app, 100, InvaderA),
123
+ InvaderRow.new(app, 150, InvaderB),
124
+ InvaderRow.new(app, 200, InvaderB),
125
+ InvaderRow.new(app, 250, InvaderC),
126
+ InvaderRow.new(app, 300, InvaderC),
127
+ ]
128
+ end
129
+
130
+ def rival_bullets
131
+ app.ship.bullets
132
+ end
133
+
134
+ def farmost_right_position
135
+ invader_rows.max_by do |invader_row|
136
+ invader_row.farmost_right_position
137
+ end.farmost_right_position
138
+ end
139
+
140
+ def farmost_left_position
141
+ invader_rows.min_by do |invader_row|
142
+ invader_row.farmost_left_position
143
+ end.farmost_left_position
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,66 @@
1
+ require 'space_invaders/invaders/invader'
2
+
3
+ module SpaceInvaders
4
+ class RedInvader < Invader
5
+ attr_accessor :dead
6
+
7
+ alias_method :dead?, :dead
8
+
9
+ def initialize app, x_position=0, y_position=50
10
+ @first_image = app.images.red_invader
11
+ @second_image = app.images.red_invader
12
+ @can_move = Time.now
13
+ @direction = :right
14
+ @dead = false
15
+ super
16
+ end
17
+
18
+ def points
19
+ 100
20
+ end
21
+
22
+ def alive?
23
+ not dead?
24
+ end
25
+
26
+ def update
27
+ return if dead?
28
+
29
+ if collides_with? rival_bullets
30
+ handle_death
31
+ elsif can_move?
32
+ set_direction
33
+ @x_position += @direction == :right ? 10 : -10
34
+ @can_move = Time.now
35
+ end
36
+ end
37
+
38
+ def draw
39
+ return if dead?
40
+ @image.draw @x_position, @y_position, 1
41
+ end
42
+
43
+ def handle_death
44
+ @dead = true
45
+ app.score_tracker.increase_by(points)
46
+ app.sounds.play_invader_hit!
47
+ end
48
+
49
+ def set_direction
50
+ if @x_position >= app.width - 80
51
+ @direction = :left
52
+ elsif @x_position <= 20
53
+ @direction = :right
54
+ end
55
+ end
56
+
57
+ def rival_bullets
58
+ app.ship.bullets
59
+ end
60
+
61
+ def can_move?
62
+ Time.now - @can_move > 0.1
63
+ end
64
+
65
+ end
66
+ end