Skip to content

Instantly share code, notes, and snippets.

@myokoym
Last active April 6, 2017 23:45
Show Gist options
  • Save myokoym/10022384 to your computer and use it in GitHub Desktop.
Save myokoym/10022384 to your computer and use it in GitHub Desktop.
A game as Space Invaders using Gosu and Ruby. (under construction...)
#
# space_invaders.rb:
# A game as Space Invaders using Gosu and Ruby.
#
# Authors:
# (c) 2014 Masafumi Yokoyama
#
# License:
# This program is licensed under the MIT License.
#
require "gosu"
module SpaceInvaders
module ZOrder
Background, Object, Message = *0..2
end
module Base
attr_reader :x, :y, :width
def warp(x, y)
@x = x
@y = y
end
def draw_square(window,
x1, y1,
x2, y2,
color, z_order=0)
window.draw_quad(x1, y1, color,
x2, y1, color,
x1, y2, color,
x2, y2, color,
z_order)
end
end
class Ball
include Base
def initialize(window, angle=0.0)
@window = window
@angle = angle
@x = 0
@y = 0
@width = @window.width * 0.03
@color = Gosu::Color::WHITE
end
def move
@y += Gosu.offset_y(@angle, @width * 0.2)
end
def draw
x1 = @x - @width * 0.5
y1 = @y - @width * 0.5
x2 = @x + @width * 0.5
y2 = @y + @width * 0.5
draw_square(@window,
x1, y1,
x2, y2,
@color, ZOrder::Object)
end
end
class Invader
include Base
def initialize(window)
@window = window
@x = 0
@y = 0
@width = @window.width * 0.05
@color = Gosu::Color::WHITE
end
def shot(balls)
ball = Ball.new(@window, 180.0)
ball.warp(@x, @y)
balls << ball
end
def move_left
@x -= @width * 0.1
end
def move_right
@x += @width * 0.1
end
def draw
x1 = @x - @width * 0.3
y1 = @y - @width * 0.5
x2 = @x + @width * 0.3
y2 = @y - @width * 0.5
x3 = @x - @width * 0.7
y3 = @y + @width * 0.5
x4 = @x + @width * 0.7
y4 = @y + @width * 0.5
@window.draw_quad(x1, y1, @color,
x2, y2, @color,
x3, y3, @color,
x4, y4, @color,
ZOrder::Object)
end
end
class Player
include Base
def initialize(window)
@window = window
@x = 0
@y = 0
@width = @window.width * 0.08
@color = Gosu::Color::WHITE
end
def move_left
@x -= @width * 0.1 if @x > 0
end
def move_right
@x += @width * 0.1 if @x < @window.width
end
def draw
x1 = @x
y1 = @y - @width * 0.5
x2 = @x - @width * 0.5
y2 = @y + @width * 0.5
x3 = @x + @width * 0.5
y3 = @y + @width * 0.5
@window.draw_triangle(x1, y1, @color,
x2, y2, @color,
x3, y3, @color,
ZOrder::Object)
end
end
class Message
def initialize(window, text)
@window = window
@text = Gosu::Image.from_text(@window,
text,
Gosu.default_font_name,
@window.height / max_length_each_lines(text),
@window.height / 100,
@window.width,
:center)
end
def draw
@text.draw(0, @window.height / 3,
ZOrder::Message,
1, 1,
Gosu::Color::WHITE)
end
def max_length_each_lines(text)
max_length = 0
text.each_line do |line|
if max_length < line.length
max_length = line.length
end
end
max_length
end
end
class GameWindow < Gosu::Window
def initialize(width=200, height=200)
super(width, height, false)
init
end
def update
@player.move_left if button_down?(Gosu::KbLeft)
@player.move_right if button_down?(Gosu::KbRight)
@player_balls.each {|ball| ball.move }
@invader_balls.each {|ball| ball.move }
@invaders.each do |invader|
@player_balls.each do |ball|
if Gosu.distance(ball.x, ball.y, invader.x, invader.y) < (invader.width * 0.5)
@invaders.delete(invader)
@player_balls.delete(ball)
end
end
invader.shot(@invader_balls) if Random.rand(1000) == 0
end
@invader_balls.each do |ball|
if Gosu.distance(ball.x, ball.y, @player.x, @player.y) < (@player.width * 0.5)
game_over
end
end
@player_balls.reject! {|ball| ball.y < 0 }
@invader_balls.reject! {|ball| ball.y > self.height }
game_clear if @invaders.empty? && @message.nil?
end
def draw
@player.draw
@player_balls.each {|ball| ball.draw }
@invader_balls.each {|ball| ball.draw }
@invaders.each {|invader| invader.draw }
@message.draw if @message
end
def button_down(id)
case id
when Gosu::KbUp
return if @player_balls.size > 2
ball = Ball.new(self)
ball.warp(@player.x, @player.y)
@player_balls << ball
when Gosu::KbEscape
close
end
end
private
def init
@player = Player.new(self)
@player.warp(width * 0.5, height * 0.9)
@player_balls = []
@invader_balls = []
@invaders = []
create_invaders
@message = nil
end
def create_invaders
1.upto(10) do |i|
invader = Invader.new(self)
invader.warp(self.width * (0.09 * i), self.height * 0.2)
@invaders << invader
end
end
def game_over
sleep(3)
init
end
def game_clear
@message = Message.new(self, "Clear!")
end
end
end
SpaceInvaders::GameWindow.new.show
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment