space_invaders 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +1 -0
- data/assets/fonts/unifont.ttf +0 -0
- data/assets/images/Bullet.png +0 -0
- data/assets/images/FullBlock.png +0 -0
- data/assets/images/InvaderA1.png +0 -0
- data/assets/images/InvaderA2.png +0 -0
- data/assets/images/InvaderB1.png +0 -0
- data/assets/images/InvaderB2.png +0 -0
- data/assets/images/InvaderC1.png +0 -0
- data/assets/images/InvaderC2.png +0 -0
- data/assets/images/OkBlock.png +0 -0
- data/assets/images/RedInvader.png +0 -0
- data/assets/images/Ship.png +0 -0
- data/assets/images/ShipCrushedLeft.png +0 -0
- data/assets/images/ShipCrushedRight.png +0 -0
- data/assets/images/WeakBlock.png +0 -0
- data/assets/sounds/InvaderBullet.wav +0 -0
- data/assets/sounds/InvaderHit.wav +0 -0
- data/assets/sounds/ShipBullet.wav +0 -0
- data/assets/sounds/ShipHit.wav +0 -0
- data/bin/space-invaders +9 -0
- data/go.rb +5 -0
- data/lib/space_invaders.rb +4 -0
- data/lib/space_invaders/app.rb +99 -0
- data/lib/space_invaders/base.rb +14 -0
- data/lib/space_invaders/behaviors/centerable.rb +13 -0
- data/lib/space_invaders/behaviors/collideable.rb +18 -0
- data/lib/space_invaders/behaviors/fireable.rb +35 -0
- data/lib/space_invaders/behaviors/mesurable.rb +17 -0
- data/lib/space_invaders/blocks/block.rb +62 -0
- data/lib/space_invaders/blocks/u_block.rb +37 -0
- data/lib/space_invaders/blocks/u_block_container.rb +46 -0
- data/lib/space_invaders/bullets/bullet.rb +46 -0
- data/lib/space_invaders/bullets/bullet_collection.rb +23 -0
- data/lib/space_invaders/invaders/invader.rb +38 -0
- data/lib/space_invaders/invaders/invader_abc.rb +27 -0
- data/lib/space_invaders/invaders/invader_row.rb +52 -0
- data/lib/space_invaders/invaders/invaders_container.rb +146 -0
- data/lib/space_invaders/invaders/red_invader.rb +66 -0
- data/lib/space_invaders/screens/game_over_screen.rb +42 -0
- data/lib/space_invaders/screens/next_level_screen.rb +39 -0
- data/lib/space_invaders/screens/welcome_screen.rb +46 -0
- data/lib/space_invaders/ship/drowned_ship_animator.rb +46 -0
- data/lib/space_invaders/ship/ship.rb +99 -0
- data/lib/space_invaders/statics/button_controller.rb +33 -0
- data/lib/space_invaders/statics/game_status.rb +52 -0
- data/lib/space_invaders/statics/images.rb +39 -0
- data/lib/space_invaders/statics/sounds.rb +37 -0
- data/lib/space_invaders/trackers/lives_tracker.rb +27 -0
- data/lib/space_invaders/trackers/score_tracker.rb +27 -0
- data/lib/space_invaders/utils.rb +19 -0
- data/space_invaders.gemspec +23 -0
- metadata +143 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'space_invaders/base'
|
2
|
+
require 'space_invaders/behaviors/centerable'
|
3
|
+
|
4
|
+
module SpaceInvaders
|
5
|
+
class GameOverScreen < Base
|
6
|
+
include Centerable
|
7
|
+
|
8
|
+
attr_reader :game_over_message, :result, :control_index, :press_play
|
9
|
+
|
10
|
+
def initialize app
|
11
|
+
super
|
12
|
+
@game_over_message = Gosu::Image.from_text app, "G A M E O V E R", App::DEFAULT_FONT, 50
|
13
|
+
@press_play = Gosu::Image.from_text app, "PRESS SPACE TO PLAY AGAIN", App::DEFAULT_FONT, 30
|
14
|
+
@press_play_counter = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def draw
|
18
|
+
set_result
|
19
|
+
horizontal_center_draw game_over_message, 100
|
20
|
+
horizontal_center_draw result, 200
|
21
|
+
|
22
|
+
horizontal_center_draw press_play, 300 if press_play_counter.between?(30,60)
|
23
|
+
update_press_play_counter
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :press_play_counter
|
29
|
+
|
30
|
+
def update_press_play_counter
|
31
|
+
if press_play_counter == 60
|
32
|
+
@press_play_counter = 0
|
33
|
+
else
|
34
|
+
@press_play_counter += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_result
|
39
|
+
@result ||= Gosu::Image.from_text app, "SCORE: #{app.score_tracker.score}", App::DEFAULT_FONT, 40
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'space_invaders/base'
|
2
|
+
require 'space_invaders/behaviors/centerable'
|
3
|
+
|
4
|
+
module SpaceInvaders
|
5
|
+
class NextLevelScreen < Base
|
6
|
+
include Centerable
|
7
|
+
|
8
|
+
attr_reader :next_level_message
|
9
|
+
|
10
|
+
def initialize app
|
11
|
+
super
|
12
|
+
@next_level_message = Gosu::Image.from_text app, "NEXT LEVEL", App::DEFAULT_FONT, 50
|
13
|
+
end
|
14
|
+
|
15
|
+
def draw
|
16
|
+
if time_passed?
|
17
|
+
timer_stop!
|
18
|
+
game_status.continue!
|
19
|
+
else
|
20
|
+
horizontal_center_draw next_level_message, 300
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def timer_start!
|
25
|
+
@timeout = Time.now
|
26
|
+
end
|
27
|
+
|
28
|
+
def timer_stop!
|
29
|
+
app.invaders_container.reinitialize!
|
30
|
+
@timeout = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def time_passed?
|
36
|
+
Time.now - @timeout > 3
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'space_invaders/base'
|
2
|
+
require 'space_invaders/behaviors/centerable'
|
3
|
+
|
4
|
+
module SpaceInvaders
|
5
|
+
class WelcomeScreen < Base
|
6
|
+
include Centerable
|
7
|
+
|
8
|
+
attr_reader :welcome_message, :control_index, :press_play
|
9
|
+
|
10
|
+
def initialize app
|
11
|
+
super
|
12
|
+
@welcome_message = Gosu::Image.from_text app, "SpaceInvaders.rb", App::DEFAULT_FONT, 50
|
13
|
+
@control_index = Gosu::Image.from_text app, control_index_string, App::DEFAULT_FONT, 20
|
14
|
+
@press_play = Gosu::Image.from_text app, "PRESS SPACE TO PLAY", App::DEFAULT_FONT, 30
|
15
|
+
@press_play_counter = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def draw
|
19
|
+
horizontal_center_draw welcome_message, 100
|
20
|
+
horizontal_center_draw control_index, 200
|
21
|
+
|
22
|
+
|
23
|
+
horizontal_center_draw press_play, 350 if press_play_counter.between?(30,60)
|
24
|
+
update_press_play_counter
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :press_play_counter
|
30
|
+
|
31
|
+
def control_index_string
|
32
|
+
" :space => :fire \n" +
|
33
|
+
" :left_arrow => :move_left \n" +
|
34
|
+
":right_arrow => :move_right\n"
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_press_play_counter
|
38
|
+
if press_play_counter == 60
|
39
|
+
@press_play_counter = 0
|
40
|
+
else
|
41
|
+
@press_play_counter += 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module SpaceInvaders
|
2
|
+
class DrownedShipAnimator < Base
|
3
|
+
|
4
|
+
ANIMATION_LENGTH_IN_SECONDS = 2
|
5
|
+
|
6
|
+
attr_accessor :ship
|
7
|
+
|
8
|
+
def initialize(app, ship)
|
9
|
+
super(app)
|
10
|
+
@ship = ship
|
11
|
+
end
|
12
|
+
|
13
|
+
def start!
|
14
|
+
@start_time = Time.now
|
15
|
+
end
|
16
|
+
|
17
|
+
def animation_time_is_over?
|
18
|
+
passed_time > ANIMATION_LENGTH_IN_SECONDS
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset!
|
22
|
+
@start_time = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def update
|
26
|
+
ship.image = if animation_time_is_over?
|
27
|
+
app.game_status.continue!
|
28
|
+
app.images.ship
|
29
|
+
elsif left_image_time?
|
30
|
+
app.images.ship_crushed_left
|
31
|
+
else
|
32
|
+
app.images.ship_crushed_right
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def passed_time
|
39
|
+
Time.now - @start_time
|
40
|
+
end
|
41
|
+
|
42
|
+
def left_image_time?
|
43
|
+
(passed_time * 10 % 10).round.even?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'space_invaders/ship/drowned_ship_animator'
|
2
|
+
require 'space_invaders/behaviors/mesurable'
|
3
|
+
require 'space_invaders/behaviors/collideable'
|
4
|
+
require 'space_invaders/behaviors/fireable'
|
5
|
+
module SpaceInvaders
|
6
|
+
class Ship < Base
|
7
|
+
include Mesurable
|
8
|
+
include Fireable
|
9
|
+
include Collideable
|
10
|
+
|
11
|
+
attr_accessor :lives, :image, :drowned_ship_animator
|
12
|
+
|
13
|
+
def initialize app
|
14
|
+
super
|
15
|
+
@image = app.images.ship
|
16
|
+
@x_position = app.width/2 - 40
|
17
|
+
@y_position = app.height - 50
|
18
|
+
@lives = 3
|
19
|
+
@drowned_ship_animator = DrownedShipAnimator.new app, self
|
20
|
+
end
|
21
|
+
|
22
|
+
def update
|
23
|
+
if game_status.drowned_ship?
|
24
|
+
drowned_ship_animator.update
|
25
|
+
else
|
26
|
+
if collides_with? rival_bullets
|
27
|
+
handle_collision
|
28
|
+
else
|
29
|
+
move_ship
|
30
|
+
bullet_collection.update
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def no_more_lives?
|
36
|
+
lives == 0
|
37
|
+
end
|
38
|
+
|
39
|
+
def shooter
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def sound
|
44
|
+
app.sounds.ship_bullet_sound
|
45
|
+
end
|
46
|
+
|
47
|
+
def bullets_going_down?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def bullet_offset_speed
|
52
|
+
10
|
53
|
+
end
|
54
|
+
|
55
|
+
def draw
|
56
|
+
@image.draw @x_position, @y_position, 1
|
57
|
+
bullet_collection.draw
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def rival_bullets
|
63
|
+
app.invaders_container.bullets
|
64
|
+
end
|
65
|
+
|
66
|
+
def decrease_lives!
|
67
|
+
@lives -= 1
|
68
|
+
app.lives_tracker.decrease_lives!
|
69
|
+
end
|
70
|
+
|
71
|
+
def animate_drowned_ship!
|
72
|
+
if @image == app.images.ship_crushed_left
|
73
|
+
@image = app.images.ship_crushed_right
|
74
|
+
else
|
75
|
+
@image = app.images.ship_crushed_left
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def handle_collision
|
80
|
+
app.sounds.play_ship_hit!
|
81
|
+
decrease_lives!
|
82
|
+
if no_more_lives?
|
83
|
+
game_status.finished!
|
84
|
+
else
|
85
|
+
drowned_ship_animator.start!
|
86
|
+
game_status.drowned_ship!
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def move_ship
|
91
|
+
if app.button_down? Gosu::KbLeft and x_position > 20
|
92
|
+
@x_position += -5
|
93
|
+
elsif app.button_down? Gosu::KbRight and x_position < app.width - 90
|
94
|
+
@x_position += 5
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'space_invaders/base'
|
2
|
+
|
3
|
+
module SpaceInvaders
|
4
|
+
class ButtonController < Base
|
5
|
+
|
6
|
+
def button_down id
|
7
|
+
case id
|
8
|
+
when Gosu::KbEscape
|
9
|
+
escape
|
10
|
+
when Gosu::KbSpace
|
11
|
+
space
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def escape
|
18
|
+
app.close
|
19
|
+
end
|
20
|
+
|
21
|
+
def space
|
22
|
+
if game_status.hasnt_started?
|
23
|
+
game_status.start!
|
24
|
+
elsif game_status.being_played?
|
25
|
+
app.ship.fire!
|
26
|
+
elsif game_status.finished?
|
27
|
+
app.initialize_dynamics_and_trackers
|
28
|
+
game_status.start!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SpaceInvaders
|
2
|
+
class GameStatus < Base
|
3
|
+
|
4
|
+
attr_accessor :started, :finished, :drowned_ship, :next_level
|
5
|
+
|
6
|
+
alias_method :started?, :started
|
7
|
+
alias_method :finished?, :finished
|
8
|
+
alias_method :drowned_ship?, :drowned_ship
|
9
|
+
alias_method :next_level?, :next_level
|
10
|
+
|
11
|
+
def initialze app
|
12
|
+
super
|
13
|
+
@started = false
|
14
|
+
@finished = false
|
15
|
+
@drowned_ship = false
|
16
|
+
@next_level = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def being_played?
|
20
|
+
started? && !drowned_ship && !next_level? && !finished?
|
21
|
+
end
|
22
|
+
|
23
|
+
def hasnt_started?
|
24
|
+
not started?
|
25
|
+
end
|
26
|
+
|
27
|
+
def next_level!
|
28
|
+
@next_level = true
|
29
|
+
end
|
30
|
+
|
31
|
+
def start!
|
32
|
+
@started = true
|
33
|
+
@finished = false
|
34
|
+
end
|
35
|
+
|
36
|
+
def finished!
|
37
|
+
@finished = true
|
38
|
+
end
|
39
|
+
|
40
|
+
def drowned_ship!
|
41
|
+
@drowned_ship = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def continue!
|
45
|
+
@drowned_ship = false
|
46
|
+
@next_level = false
|
47
|
+
end
|
48
|
+
|
49
|
+
def status
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'space_invaders/base'
|
2
|
+
require 'space_invaders/utils'
|
3
|
+
|
4
|
+
module SpaceInvaders
|
5
|
+
class Images < Base
|
6
|
+
|
7
|
+
IMAGES = [ :invader_a1,
|
8
|
+
:invader_a2,
|
9
|
+
:invader_b1,
|
10
|
+
:invader_b2,
|
11
|
+
:invader_c1,
|
12
|
+
:invader_c2,
|
13
|
+
:red_invader,
|
14
|
+
:ship,
|
15
|
+
:ship_crushed_left,
|
16
|
+
:ship_crushed_right,
|
17
|
+
:bullet,
|
18
|
+
:full_block,
|
19
|
+
:ok_block,
|
20
|
+
:weak_block
|
21
|
+
]
|
22
|
+
|
23
|
+
IMAGES.each do |image|
|
24
|
+
define_method image do
|
25
|
+
if instance_variable_get("@#{image}").nil?
|
26
|
+
instance_variable_set("@#{image}", Gosu::Image.new(app, asset_path(image)))
|
27
|
+
end
|
28
|
+
instance_variable_get("@#{image}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def asset_path(image_name)
|
35
|
+
camel_case_name = Utils.camelcase(image_name)
|
36
|
+
File.join("assets", "images", "#{camel_case_name}.png")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'space_invaders/base'
|
2
|
+
module SpaceInvaders
|
3
|
+
class Sounds < Base
|
4
|
+
|
5
|
+
def ship_hit_sound
|
6
|
+
@ship_hit_sound ||= Gosu::Sample.new(app, "assets/sounds/ShipHit.wav")
|
7
|
+
end
|
8
|
+
|
9
|
+
def ship_bullet_sound
|
10
|
+
@ship_bullet_sound ||= Gosu::Sample.new(app, "assets/sounds/ShipBullet.wav")
|
11
|
+
end
|
12
|
+
|
13
|
+
def invader_hit_sound
|
14
|
+
@invader_hit_sound ||= Gosu::Sample.new(app, "assets/sounds/InvaderHit.wav")
|
15
|
+
end
|
16
|
+
|
17
|
+
def invader_bullet_sound
|
18
|
+
@invader_bullet_sound ||= Gosu::Sample.new(app, "assets/sounds/InvaderBullet.wav")
|
19
|
+
end
|
20
|
+
|
21
|
+
def play_ship_hit!
|
22
|
+
ship_hit_sound.play volume=0.5
|
23
|
+
end
|
24
|
+
|
25
|
+
def play_ship_fire!
|
26
|
+
ship_bullet_sound.play volume=0.05
|
27
|
+
end
|
28
|
+
|
29
|
+
def play_invader_hit!
|
30
|
+
invader_hit_sound.play volume=0.5
|
31
|
+
end
|
32
|
+
|
33
|
+
def play_invader_fire!
|
34
|
+
invader_bullet_sound.play volume=0.05
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SpaceInvaders
|
2
|
+
class LivesTracker < Base
|
3
|
+
|
4
|
+
attr_reader :lives
|
5
|
+
|
6
|
+
def initialize app
|
7
|
+
@app = app
|
8
|
+
@lives = app.ship.lives
|
9
|
+
@lives_headline = Gosu::Image.from_text @app, "Lives:", App::DEFAULT_FONT, 30
|
10
|
+
set_lives_number
|
11
|
+
end
|
12
|
+
|
13
|
+
def decrease_lives!
|
14
|
+
@lives -= 1
|
15
|
+
set_lives_number
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_lives_number
|
19
|
+
@lives_number = Gosu::Image.from_text @app, @lives, App::DEFAULT_FONT, 30
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw
|
23
|
+
@lives_headline.draw app.width - 150, 10, 1
|
24
|
+
@lives_number.draw app.width - 50, 10, 1, 1, 1, Gosu::Color::GREEN
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|