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風な作りなのだけど、ちょっと楽しめるゲームが出来ると嬉しくなる。
- プログラミングの勉強にシンプルなゲーム作りは最適かもしれない。