Star RubyでHello World!

前回からの続き

ぱらぱらアニメ

  • サンプルコードのhelloworld.rbは、コメント行を削除してみると、以下のようなシンプルな構成となっている。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)
  game.screen.clear
  game.screen.render_text("Hello, World!", 8, 8, font, white)
end
  • Game.runブロックによって、ゲームウィンドウが表示される。
  • game.screenをクリアして、
  • game.screenに"Hello, World!"を表示する。
  • Game.runブロックを抜ける(break)と、ゲームウィンドウは閉じ、終了する。
  • 止まっている"Hello, World!"を見ていると実感できないが、
  • 実はゲームウィンドウの中身は、激しく描画を繰り返している。
  • その証拠に、表示位置の座標を変化させると、"Hello, World!"が動く!
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

y = 0
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)

  y += 1
  y = 0 if y > 240

  game.screen.clear
  game.screen.render_text("Hello, World!", 8, y, font, white)
end
  • デフォルトでは1秒間に30回の描画を試みるらしい。
  • つまり、Game.runブロックを1秒間に30回、繰り返そうとするのだ。
  • ちなみに、この描画回数は自由に変更できる。
Game.run(320, 240, :title => "Hello, World!", :fps => 10) do |game|
...中略...
  • これで、1秒間に10回描画するゲーム環境となる。
  • あるいは、Game.runブロックの中で、描画回数を変化させることも出来る。
game.fps = 10
  • :fpsの描画回数は保証される訳ではなく、目標回数である。
  • ブロック内の処理の負荷が高いと、実際の描画回数は指定した:fpsより少なくなる。
  • 実際の描画回数は、game.real_fpsで取得できる。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

y = 0
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)

  y += 1
  y = 0 if y > 240

  game.screen.clear
  game.screen.render_text(game.real_fps.to_s, 8, y, font, white) #<---real_fpsを表示する
end
  • 動いて見えるのは、一旦クリアしてから描き直しているからである。
  • 「game.screen.clear」をコメントアウトしてしまうと、前回の描画内容が残り続けてしまう...。

キー入力を捕まえる

  • helloworld.rbは、escキーを押すと終了する。
  • それは「break if Input.keys(:keyboard).include?(:escape)」によって、escキーの入力を感知するからである。
  • Input.keys(:keyboard)は、その時押されているキーの配列を返すようだ。
  • 押されたキーに対応する値は、API リファレンスのStarRuby::Inputに書かれている。
  • よって、以下のように修正すると、矢印キーで"Hello, World!"が左右に動くのだ。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

y = 0
x = 8
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)
  x += 8 if Input.keys(:keyboard).include?(:right)
  x -= 8 if Input.keys(:keyboard).include?(:left)

  y += 1
  y = 0 if y > 240

  game.screen.clear
  game.screen.render_text("Hello, World!", x, y, font, white)
end

スカッシュのようなもの

描画したものを自由に動かせるようになると、あと一工夫でゲームになる。

動くボール
  • まずは、ランダムな方向にボールが落ちてくる。
  • そして、左右の壁に当たった時は、はね返る。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

x = rand(80..240)
y = 0
ax, ay = rand(-4..4), rand(2..4)
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)

  x += ax
  y += ay
  ax *= -1 if x < 0 || x > 312 #左右の壁ではね返り

  if y > 240 then
    x = rand(80..240)
    y = 0
    ax, ay = rand(-4..4), rand(2..4)
  end

  game.screen.clear
  game.screen.render_text("O", x, y, font, white)
end
バーを追加
  • 左右に動かせるバーを追加してみる。
  • そして、バーと天井にボールが当たった時も、はね返るようにしておく。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

x = rand(80..240)
y = 0
ax, ay = rand(-4..4), rand(2..4)

bar_x = 140
bar_y = 220
bar_w = 35
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)
  bar_x += 8 if Input.keys(:keyboard).include?(:right)  #バーの移動
  bar_x -= 8 if Input.keys(:keyboard).include?(:left)   #バーの移動
  
  bar_x = 0 if bar_x < 0                      #バー移動の左制限
  bar_x = 320 - bar_w if bar_x + bar_w > 320  #バー移動の右制限

  x += ax
  y += ay
  ax *= -1 if x < 0 || x > 312 #左右の壁ではね返り
  ay *= -1 if y < 0            #天井のはね返り
  ay *= -1 if 215 <= y && y <= 220 && bar_x <= x && x <= bar_x + bar_w && ay > 0 #バーのはね返り

  #打ち損ない
  if y > 240 then
    x = rand(80..240)
    y = 0
    ax, ay = rand(-4..4), rand(2..4)
  end

  game.screen.clear
  game.screen.render_text("O", x, y, font, white)
  game.screen.render_text("_______", bar_x, bar_y, font, white)
end
ゲームバランスの調整
  • 単純にはね返るだけでは単調になり過ぎるので、バーの位置によってはね返る方向を変化させてみた。
  • また、バーで打ち返す度に、上下方向のスピードを少しずつ早めてみた。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

x = rand(80..240)
y = 0
ax, ay = rand(-4..4), 2

bar_x = 140
bar_y = 220
bar_w = 35
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)
  bar_x += 5 if Input.keys(:keyboard).include?(:right)  #バーの移動
  bar_x -= 5 if Input.keys(:keyboard).include?(:left)   #バーの移動
  
  bar_x = 0 if bar_x < 0                      #バー移動の左制限
  bar_x = 320 - bar_w if bar_x + bar_w > 320  #バー移動の右制限

  x += ax
  y += ay
  ax *= -1 if x < 0 || x > 312 #左右の壁ではね返り
  ay *= -1 if y < 0            #天井のはね返り

  #バーのはね返り
  if 215 <= y && y <= 220 && bar_x - 5  <= x && x <= bar_x + bar_w && ay > 0 then
    d = x - bar_x - (bar_w / 2.0) #ボールが当たった位置が、バー中心からどれだけズレているか
    ax += (d / bar_w) * 4         #バーの位置ではね返る方向を変化させる
    ay += 0.1                     #スピードを加速
    ay *= -1
  end

  #打ち損ない
  if y > 240 then
    x = rand(80..240)
    y = 0
    ax, ay = rand(-4..4), 2
  end

  game.screen.clear
  game.screen.render_text("O", x, y, font, white)
  game.screen.render_text("_______", bar_x, bar_y, font, white)
end
スコア表示
  • スコア表示してみた。
require "starruby"
include StarRuby

font = Font.new("fonts/ORANGEKI", 12)
white = Color.new(255, 255, 255)

x = rand(80..240)
y = 0
ax, ay = rand(-4..4), 2

bar_x = 140
bar_y = 220
bar_w = 35

score = 0
Game.run(320, 240, :title => "Hello, World!") do |game|
  break if Input.keys(:keyboard).include?(:escape)
  bar_x += 5 if Input.keys(:keyboard).include?(:right)  #バーの移動
  bar_x -= 5 if Input.keys(:keyboard).include?(:left)   #バーの移動
  
  bar_x = 0 if bar_x < 0                      #バー移動の左制限
  bar_x = 320 - bar_w if bar_x + bar_w > 320  #バー移動の右制限

  x += ax
  y += ay
  
  #左右の壁のはね返り
  if x < 0 || x > 312 then
    ax *= -1
    score += ax.abs + ay.abs #スコア計算
  end
  
  #天井のはね返り
  if y < 0 then
    ay *= -1
    score += ax.abs + ay.abs #スコア計算
  end
  
  #バーのはね返り
  if 215 <= y && y <= 220 && bar_x - 5  <= x && x <= bar_x + bar_w && ay > 0 then
    d = x - bar_x - (bar_w / 2.0) #ボールが当たった位置が、バー中心からどれだけズレているか
    ax += (d / bar_w) * 4         #バーの位置ではね返る方向を変化させる
    ay += 0.1                     #スピードを加速
    ay *= -1
    score += ax.abs + ay.abs #スコア計算
  end
  
  #打ち損ない
  if y > 240 then
    x = rand(80..240)
    y = 0
    ax, ay = rand(-4..4), 2
    score = 0
  end

  game.screen.clear
  game.screen.render_text("O", x, y, font, white)
  game.screen.render_text("_______", bar_x, bar_y, font, white)
  game.screen.render_text("SCORE = "+score.to_i.to_s, 240, 230, font, white) #スコア表示
end

少し楽しめるようになったかも。

  • 古き良き時代のBASIC風な作りなのだけど、ちょっと楽しめるゲームが出来ると嬉しくなる。
  • プログラミングの勉強にシンプルなゲーム作りは最適かもしれない。