Skip to content

Instantly share code, notes, and snippets.

@myokoym
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save myokoym/9722262 to your computer and use it in GitHub Desktop.
Save myokoym/9722262 to your computer and use it in GitHub Desktop.
GosuとRubyで動くブロック崩しゲーム (リリース版はこちら: https://github.com/myokoym/bricks_meet_balls
require "gosu"
module ZOrder
Background, Block, Bar, Ball, Message = *0..5
end
module Util
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
def hit?(x, y)
x >= @x1 && x <= @x2 &&
y >= @y1 && y <= @y2
end
def hit_on_top_or_bottom?(x, y)
[(@x1 - x).abs, (@x2 - x).abs].min >=
[(@y1 - y).abs, (@y2 - y).abs].min
end
def hit_on_left_or_right?(x, y)
[(@x1 - x).abs, (@x2 - x).abs].min <
[(@y1 - y).abs, (@y2 - y).abs].min
end
def out_from_left_or_right?(x)
x <= @x1 ||
x >= @x2
end
def out_from_top?(y)
y <= @y1
end
def drop?(y)
y > @y2
end
end
class Block
include Util
def initialize(window, x, y, width, height)
@window = window
@width = width
@height = height
@margin = @width * 0.01
@border_width = @width * 0.025 + @margin
@x1 = 1.0 * @width * (x - 1)
@y1 = 1.0 * @height * (y - 1)
@x2 = 1.0 * @width * x
@y2 = 1.0 * @height * y
end
def draw
draw_square(@window,
@x1 + @margin, @y1 + @margin,
@x2 - @margin, @y2 - @margin,
Gosu::Color::BLACK, ZOrder::Block)
draw_square(@window,
@x1 + @border_width, @y1 + @border_width,
@x2 - @border_width, @y2 - @border_width,
Gosu::Color::WHITE, ZOrder::Block)
end
end
class Ball
include Util
attr_reader :x, :y
def initialize(window)
@window = window
@x = @y = 0.0
@ball_radius = @window.height * 0.008
@angle = 30 + (5.0 * [*1..10, *14..24].sample) - 90
@speed = @window.height * 0.01
@moving = true
end
def draw
draw_square(@window,
@x - @ball_radius, @y - @ball_radius,
@x + @ball_radius, @y + @ball_radius,
Gosu::Color::BLACK, ZOrder::Ball)
end
def warp(x, y)
@x, @y = x, y
end
def move
return unless @moving
@x += Gosu.offset_x(@angle, @speed)
@y += Gosu.offset_y(@angle, @speed)
end
def moving?
@moving
end
def stop
@moving = false
end
def start
@moving = true
end
def reflect(target)
if target.hit_on_top_or_bottom?(@x, @y)
reflect_x_axis
elsif target.hit_on_left_or_right?(@x, @y)
reflect_y_axis
end
end
def reflect_x_axis
if @angle <= 180
@angle = 180 - @angle
else
@angle = 360 - (@angle - 180)
end
end
def reflect_y_axis
if @angle <= 180
@angle = 180 + (180 - @angle)
else
@angle = 360 - @angle
end
end
end
class Bar
include Util
def initialize(window)
@window = window
@width = @window.width * 0.3
@height = @window.height * 0.01
@x1 = @window.width * 0.5
@y1 = @window.height * 0.9
@x2 = @x1 + @width
@y2 = @y1 + @height
@movement = @width * 0.04
end
def draw
draw_square(@window,
@x1, @y1,
@x2, @y2,
Gosu::Color::BLACK, ZOrder::Bar)
end
def move_left
@x1 -= @movement
@x2 = @x1 + @width
end
def move_right
@x1 += @movement
@x2 = @x1 + @width
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::BLACK)
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
include Util
def initialize(width=240, height=480,
num_of_rows=2, num_of_columns=3, num_of_balls=1)
super(width, height, false)
self.caption = "Blocks"
@x1 = 0
@y1 = 0
@x2 = width
@y2 = height
@blocks = []
@bar = Bar.new(self)
@balls = []
@message = nil
create_blocks(num_of_columns, num_of_rows)
create_balls(num_of_balls)
end
def update
if button_down?(Gosu::KbLeft) ||
button_down?(Gosu::MsLeft)
@bar.move_left
end
if button_down?(Gosu::KbRight) ||
button_down?(Gosu::MsRight)
@bar.move_right
end
@balls.each do |ball|
ball.move
@blocks.each do |block|
if block.hit?(ball.x, ball.y)
@blocks.delete(block)
ball.reflect(block)
end
end
if @bar.hit?(ball.x, ball.y)
ball.reflect(@bar)
end
if self.out_from_left_or_right?(ball.x)
ball.reflect_y_axis
elsif self.out_from_top?(ball.y)
ball.reflect_x_axis
end
if self.drop?(ball.y)
@balls.delete(ball)
end
end
if @message.nil? && @balls.empty?
@message = Message.new(self, "Game Over...")
end
if @message.nil? && @blocks.empty?
@message = Message.new(self, "Congratulations!")
end
end
def draw
draw_area
@blocks.each {|block| block.draw }
@balls.each {|ball| ball.draw }
@bar.draw
@message.draw if @message
end
def button_down(id)
case id
when Gosu::KbSpace
@balls.each do |ball|
if ball.moving?
ball.stop
else
ball.start
end
end
when Gosu::KbEscape
close
end
end
private
def draw_area
draw_square(self,
0, 0,
self.width, self.height,
Gosu::Color::WHITE, ZOrder::Background)
end
def create_blocks(num_of_columns, num_of_rows)
1.upto(num_of_columns) do |column|
1.upto(num_of_rows) do |row|
@blocks << Block.new(self,
column,
row,
self.width / num_of_columns,
self.height / 30)
end
end
end
def create_balls(n)
n.times do
ball = Ball.new(self)
ball.warp(self.width * 0.5,
self.height * 0.8)
@balls << ball
end
end
end
window = GameWindow.new(240, 480, 20, 4, 40)
window.show
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment