Last active
April 6, 2017 23:45
-
-
Save myokoym/10022384 to your computer and use it in GitHub Desktop.
A game as Space Invaders using Gosu and Ruby. (under construction...)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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