require 'gosu'
require_relative 'credit'
require_relative 'player'
require_relative 'enemy'
require_relative 'bullet'
require_relative 'explosion'
require_relative 'score'
require_relative 'boss'
require_relative 'bossbullet'
class SectorFive < Gosu::Window
# THE BELOW VARIABLES ARE CALLED CONSTANTS
WIDTH = 800
HEIGHT = 600
#ENEMY_FREQUENCY = 0.005
MAX_ENEMIES = 10000
EXPIRE = 180
# THE INITIALIZE METHOD STARTS THE INITIAL GAME AND SETS THE SCENE :START
def initialize
super(WIDTH, HEIGHT)
self.caption = "Sector Five"
@background_image = Gosu::Image.new('ima/start.png')
@start_music = Gosu::Song.new('sounds/heart.ogg')
@start_music.play(true)
@scene = :start
end
# THIS METHOD CALLS THE DIFFERENT DRAW METHOD DEPENDING ON WHICH PART IN THE
# GAME THE PLAYER IS AT>> START< GAME < END
def draw
case @scene
when:start
draw_start
when:game
draw_game
when:level
draw_level
when:end
draw_end
end
end
# THIS METHOD DRAWS THE BACKGROUND IMAGE DURING THE START WINDOW
def draw_start
@background_image.draw(0,0,0)
end
# THIS METHOD DRAWS THE IMAGES ON THE WINDOW
def draw_game
@player.draw
@background_image.draw(0,0,0)
@score_board.draw_text("Score=#{@enemies_destroyed}",40,40,1,1,1,Gosu::Color::AQUA)
@time.draw_text("Time=#{@countdown}",650,40,1,1,1,Gosu::Color::RED)
@time.draw_text("Health#{@bosshealth}",50,500,1,1,1,Gosu::Color::GREEN)
@score_board.draw_text("Location#{@distance},#{@distance}",400,400,1,1,1,Gosu::Color::AQUA)
@time.draw_text("level#{@wave_count}",460,460,1,1,1,Gosu::Color::GREEN)
@enemies.each do |enemy|
enemy.draw
end
@enemybullets.each do |bullet|
bullet.draw
end
@bullets.each do |bullet|
bullet.draw_two
end
@explosions.each do |explosion|
explosion.draw
end
@playerexplosions.each do |explosion|
explosion.draw_two
end
@boss.each do |b|
b.draw
end
@bossbullets.each do |bullet|
bullet.draw
end
end
# THIS METHOD TELLS THE GAME WHICH UPDATE TO FOLLOW DEPENDING ON WHICH PART
# THE GAME IS ON. GAME OR END
def update
case @scene
when :game
update_game
when :end
update_end
end
end
# THIS METHOD SPECIFIES THE DIFFERENT USABLE BUTTONS DEPENDING ON WHICH PART
# OF THE GAME THE PLAYER IS ON. START < GAME < END
def button_down(id)
case @scene
when :start
button_down_start(id)
when :game
button_down_game(id)
when :level
button_down_level(id)
when :end
button_down_end(id)
end
end
# THIS METHOD STARTS THE GAME
def button_down_start(id)
initialize_game
end
# THIS METHOD CONTAINS ALL THE VARIABLES TO BE MANIPULATED
def initialize_game
@background_image = Gosu::Image.new('ima/space.png')
@player = Player.new(self)
@enemy_frequency = 0.0
@boss = []
@bosshealth = 0
@enemies = []
@bullets = []
@enemybullets = []
@bossbullets = []
@random_enemy_bullets = []
@explosions = []
@playerexplosions = []
@bossexplosions = []
@framecounter = 0
@scene = :game
@enemies_appeared = 0
@enemies_destroyed = 0
@credits = []
@game_music = Gosu::Song.new('sounds/chill.ogg')
@game_music.play(true)
@explosion_sound = Gosu::Sample.new('sounds/explosion.ogg')
@shooting_sound = Gosu::Sample.new('sounds/shoot.ogg')
@falling_sound = Gosu::Sample.new('sounds/fall.ogg')
@score_board = Gosu::Font.new(30)
@counter = 0
@time = Gosu::Font.new(30)
@distance = 0
@distance_two = 0
@bossbulletdistance = 0
@turn_r_counter = 0
@turn_l_counter = 0
@killedenemies = 100
@countdown = 10
@level = update_level
end
def update_game
@countdown -= 1 if @framecounter % 60 == 0
@framecounter += 1
@counter += 1 if @framecounter % 60 == 0
# @enemy_frequency += 0 if @counter % 3600 == 0
@player.turn_left if button_down?(Gosu::KbLeft)
@player.turn_right if button_down?(Gosu::KbRight)
@player.accelerate if button_down?(Gosu::KbUp)
@player.backward if button_down?(Gosu::KbDown)
@player.move
#CREATES THE ENEMEY
if rand < @enemy_frequency
@enemies.push Enemy.new(self)
@enemies_appeared += 1
end
#THE BOSS CREATION
if @framecounter % 900 == 0
@boss.push Boss.new(self)
@bosshealth += 100
end
@boss.each do |b|
if @boss.length > 1
@boss.delete b
end
end
# When A Bullet Hits a Boss AN EXPLOSION IS CREATED
@boss.dup.each do |b|
@bullets.dup.each do |bullet|
distance = Gosu.distance(b.x, b.y, bullet.x, bullet.y)
if distance < b.radius + bullet.radius
@bullets.delete bullet
@explosions. push Explosion.new(self, b.x, b.y)
@enemies_destroyed += 5
@bosshealth -= 20
if @bosshealth <= 0
@boss.delete b
end
@explosion_sound.play(0.3)
end
end
end
# ENEMY Fires a bullet
@enemies.select do |enemy|
if @framecounter % 600 == 0
@enemybullets.push Bullet.new(self, @enemies[-1].x, @enemies[-1].y, @enemies[-1].angle)
if @enemies.length > 3
@enemybullets.push Bullet.new(self, enemy.x, enemy.y, enemy.angle)
end
end
end
#Boss Fires A Bullet
@boss.select do |b|
if @framecounter % 60 == 0
@bossbullets.push BBullet.new(self, @boss[-1].x, @boss[-1].y, @boss[-1].angle)
end
end
#Direction of Boss Bullet
@bossbullets.each do |bullet|
@bossbulletdistance = Gosu::distance(@player.x, @player.y, bullet.x, bullet.y)
@bossbulletdistance < 800
if @player.x > bullet.x
bullet.move
end
if @player.y < bullet.y
bullet.move_four
end
if @player.x < bullet.x
bullet.move_three
end
if @player.y > bullet.y
bullet.move_two
end
if @bossbulletdistance < bullet.radius + @player.radius
@bossbullets.delete bullet
end
end
# THE BOSS FOLLOWS THE ENEMY
@boss.each do |b|
@distance = Gosu::distance(@player.x, @player.y, b.x, b.y)
x1 = @player.x
y1 = @player.y
x2 = b.x
y2 = b.y
@distance < 800
if @player.x > b.x
b.move
end
# if @player.y < b.y
# b.move_four
# end
# if @player.x < b.x
# b.move_three
# end
# if @player.y > b.y
# b.move_two
# end
end
#TURN THE BOSS TO THE PLAYER
@boss.each do |b|
@ang = b.angle
b.angle
end
# Detects whether there is a collision between a player bullet and an enemy.
@enemies.dup.each do |enemy|
@bullets.dup.each do |bullet|
distance = Gosu.distance(enemy.x, enemy.y, bullet.x, bullet.y)
if distance < enemy.radius + bullet.radius
@enemies.delete enemy
@bullets.delete bullet
@explosions.push Explosion.new(self, enemy.x, enemy.y)
@enemies_destroyed += 1
@explosion_sound.play(0.3)
end
end
end
# DELETES THE EXPLOSIONS AFTER THE EXPLOSION ARRAY LENGTH IS GREATER THAN 15
@explosions.dup.each do |explosion|
if @explosions.length > 15
@explosions.delete explosion
@explosions.delete explosion
end
end
# DELETES AN ENEMY IF THE ENEMY COMES IN CONTACT WITH AN EXPLOSION
@explosions.dup.each do |explosion|
@enemies.dup.each do |enemy|
distance = Gosu.distance(explosion.x, explosion.y, enemy.x, enemy.y)
if distance < explosion.radius + enemy.radius
@enemies.delete enemy
@explosions.push Explosion.new(self, enemy.x, enemy.y)
@enemies_destroyed += 1
@explosion_sound.play(0.3)
end
end
end
# CREATES AN EXPLOSION IF A BULLET TOUCHES AN ENEMY
@enemybullets.each do |bullet|
distance = Gosu.distance(bullet.x, bullet.y, @player.x, @player.y)
if distance < bullet.radius + @player.radius
@enemybullets.delete bullet
@playerexplosions.push Explosion.new(self, @player.x, @player.y)
@explosion_sound.play(0.3)
end
end
@playerexplosions.dup.each do |explosion|
@explosions.delete explosion unless explosion.finishedtwo
end
# CREATES A SOUND IF AN ENEMY LEAVES SOUTH OF THE GAMEBOARD
@enemies.dup.each do |enemy|
if enemy.y > HEIGHT + enemy.radius
@enemies.delete enemy
@falling_sound.play(0.2)
end
end
# THE BELOW COMMANDS MOVE THE DIFFERENT CLASSES
@bullets.dup.each do |bullet|
@bullets.delete bullet unless bullet.onscreen?
end
@enemybullets.each do |bullet|
bullet.enemy_move
end
@bullets.each do |bullet|
bullet.move
end
@explosions.each do |explosion|
explosion.move
end
@playerexplosions.each do |explosion|
explosion.move
end
@enemies.each do |enemy|
enemy.move
end
# STARTS THE INITIALIZE_END METHOD DEPENDING IF ONE OF THE CONDITIONS BELOW IS MET
initialize_end(:count_reached) if @enemies_appeared > MAX_ENEMIES
@enemies.each do |enemy|
distance = Gosu::distance(enemy.x, enemy.y, @player.x, @player.y)
initialize_end(:hit_by_enemy) if distance < @player.radius + enemy.radius
end
initialize_end(:off_top) if @player.y < -@player.radius
initialize_level(:time_expire) if @countdown == 0
update_level if @count_down == 0
end
# CONTROLS THE PLAYERS FIRING MECHONISIM
def button_down_game(id)
if id == Gosu::KbSpace
@bullets.push Bullet.new(self, @player.x, @player.y, @player.angle)
@shooting_sound.play(0.9)
end
end
# THE INITILIALIZE END METHOD CREATES THE MESSAGES AFTER THE GAME IS OVER
def end_of_level(what)
case what
when :time_expire
@message3 = "Congratulations!!! :) You Survived the Swarm"
when :enemy
@message4 = " Congratulations!!! :) You Killed all the Enemies"
end
@final_message = "THE NEXT LEVEL WILL BEGIN SOON"
@final_message2 = " OR YOU CAN PRESS P to play again, or Q to quit."
end
def initialize_end(fate)
case fate
when :count_reached
@message = "You Made it! You destroyed #{@enemies_destroyed} ships"
@message2 = "and #{100 - @enemies_destroyed} reached the base."
when :hit_by_enemy
@message = "You were struck by an enemy ship"
@message2 = "Before your ship was destroyed, "
@message2 += "you took out #{@enemies_destroyed} enemy ships!"
when :off_top
@message = "You got too close to the enemy mothership."
@message2 = "Before your ship was destroyed, "
@message2 += "you took out #{@enemies_destroyed} enemy ships!"
end
@bottom_message = "Press P to play again, or Q to quit."
@message_font = Gosu::Font.new(28)
y = 700
# THIS FUNCTION FILE.OPEN LINKS TO THE FILE WITH THE END CREDIT INFORMATION
# AND APPLIES A SCROLLING FUNCTION
File.open('credits.txt').each do |line|
@credits.push(Credit.new(self,line.chomp,100,y))
y+=30
end
#>>> @SCENE CHANGES TO :END
@scene = :end
@end_music = Gosu::Song.new('sounds/mind.ogg')
@end_music.play(true)
end
# THIS PART DRAWS THE SCORE ON THE TOP LEFT CORNER OF THE WINDOW
def score_counter
clip_to(50,140,700,360) do
@score += 1 if @enemies_destroyed +=1
@score.draw
end
end
# THIS METHOD PLACES THE FILE INFORMATION IN THE MIDDLE OF THE SCREEN
def draw_end
clip_to(50,140,700,360) do
@credits.each do |credit|
credit.draw
end
end
# THIS PORTION OF THE METHOD ADDS COLOR TO THE TEXT AND SEPARATES
# PIECES OF THE WINDOW USING LINES>
draw_line(10,140,Gosu::Color::GREEN,WIDTH,140,Gosu::Color::RED)
@message_font.draw(@message,40,40,1,1,1,Gosu::Color::FUCHSIA)
@message_font.draw(@message2,40,75,1,1,1,Gosu::Color::FUCHSIA)
draw_line(0,500,Gosu::Color::GREEN,WIDTH,500,Gosu::Color::RED)
@message_font.draw(@bottom_message,180,540,1,1,1,Gosu::Color::AQUA)
end
# THIS PORTION CALLS THE MOVE METHOD FROM THE CREDITS FILE
def update_end
@credits.each do |credit|
credit.move
end
if @credits.last.y < 150
@credits.each do |credit|
credit.reset
end
end
end
# COMMANDS THE GAME TO RUN AGAIN IF PLAYER PRESSES "P" OR QUIT GAME IF THE
# PLAYER PRESSES "Q"
def button_down_end(id)
if id == Gosu::KbP
initialize_game
elsif id == Gosu::KbQ
close
end
end
end
def initialize_level(medium)
case medium
when :time_expire
@message_three = "You survived wave number #{@level}. Congratualations!
Prepare for the next level by Pressing P!"
@message_font_two = Gosu::Font.new(40)
@scene = :level
end
end
def draw_level
@message_font_two.draw(@message_three,30,300,1,1,1,Gosu::Color::FUCHSIA)
end
def update_level
@wave_count = 0
if @scene = :game
@wave_count += 1
end
return @wave_count
end
def button_down_level(id)
if id == Gosu::KbP
initialize_game
end
end
# THIS FUNCTION OPENS THE WINDOW
window = SectorFive.new
window.show
#THANK YOU!