◇ゲームの概要
このゲームは、プレイヤーがパドルを操作してボールを打ち返し、ブロックを壊していくゲームです。
プレイヤーが全てのブロックを壊すと、ゲームクリアとなります。
ボールが画面下部に落ちると、ゲームオーバーとなります。
◇必要な準備
このゲームを作成するためには、DXRubyのインストールが必要です。
※Ruby自体のインストールは済んでいるものと仮定します。
以下のコマンドを使用して、DXRubyをインストールできます。
gem install dxruby
◇ソースコード
require 'dxruby' # ブロックを表すクラス class Block attr_reader :x, :y, :width, :height def initialize(x, y, width, height, color) @x = x @y = y @width = width @height = height @color = color @visible = true end def draw if @visible Window.draw(@x, @y, Image.new(@width, @height, @color)) end end # ブロックが衝突したかどうかを判定する def collides_with?(ball) return false unless @visible ball_x = ball.x + ball.radius ball_y = ball.y + ball.radius if ball_x < @x dx = @x - ball_x elsif ball_x > @x + @width dx = ball_x - (@x + @width) else dx = 0 end if ball_y < @y dy = @y - ball_y elsif ball_y > @y + @height dy = ball_y - (@y + @height) else dy = 0 end return (dx * dx + dy * dy) < (ball.radius * ball.radius) end # ブロックを消す def hide @visible = false end end # ボールを表すクラス class Ball attr_reader :x, :y, :radius def initialize(x, y, radius, speed) @x = x @y = y @radius = radius @speed = speed @angle = rand(60..120) end def draw Window.draw_circle(@x, @y, @radius, C_WHITE) end # ボールを動かす def move @x += @speed * Math.cos(Math::PI / 180 * @angle) @y -= @speed * Math.sin(Math::PI / 180 * @angle) end # 壁やパドルに衝突した場合の処理 def reflect_horizontal @angle = 180 - @angle end def reflect_vertical @angle = -@angle end # パドルに衝突した場合の処理 def reflect_from_paddle(paddle) @angle = 180 - (@x - paddle.x - paddle.width / 2) * 160 / paddle.width @angle = @angle.clamp(60, 120) reflect_vertical end end # パドルを表すクラス class Paddle attr_reader :x, :y, :width, :height def initialize(x, y, width, height, color) @x = x @y = y @width = width @height = height @color = color end def draw Window.draw(@x, @y, Image.new(@width, @height, @color)) end # パドルを動かす def move(dx) @x += dx @x = @x.clamp(0, Window.width - @width) end end # ゲームのメインクラス class Game def initialize @blocks = [] 5.times do |y| 10.times do |x| block_width = 50 block_height = 20 block_color = [rand(256), rand(256), rand(256)] block = Block.new(x * block_width, y * block_height + 50, block_width, block_height, block_color) @blocks << block end end @paddle = Paddle.new(200, 500, 80, 20, C_WHITE) @ball = Ball.new(240, 480, 8, 6) @score = 0 end def update if Input.key_down?(K_LEFT) @paddle.move(-8) elsif Input.key_down?(K_RIGHT) @paddle.move(8) end @ball.move # ボールが壁に衝突した場合の処理 if @ball.x < @ball.radius || @ball.x > Window.width - @ball.radius @ball.reflect_horizontal end if @ball.y < @ball.radius @ball.reflect_vertical end # ボールがパドルに衝突した場合の処理 if @ball.collides_with?(@paddle) @ball.reflect_from_paddle(@paddle) end # ボールがブロックに衝突した場合の処理 @blocks.each do |block| if @ball.collides_with?(block) block.hide @score += 10 if @score == @blocks.size * 10 Window.alert("You win!") exit end if @ball.x < block.x || @ball.x > block.x + block.width @ball.reflect_horizontal else @ball.reflect_vertical end break end end # ボールが画面下部に落ちた場合の処理 if @ball.y > Window.height Window.alert("Game Over! ") exit end end def draw Window.draw_font(10, 10, "Score: #{@score}", Font.default) @paddle.draw @ball.draw @blocks.each(&:draw) end end Game.new.run
◇コード解説
このゲームでは、Window.loopを使ってゲームのメインループを処理しています。
Window.loop内では、以下のような処理を行っています。
①パドルの移動をキーボードの入力に応じて処理する
②ボールの移動を処理する
③ボールが壁に衝突した場合、反射させる
④ボールがパドルに衝突した場合、反射させる
⑤ボールがブロックに衝突した場合、ブロックを消去し、スコアを加算する
⑥ボールが画面下部に落ちた場合、ゲームオーバーとする
また、Window.drawを使ってパドル/ボール/ブロックを画面に描画しています。