概要
この記事は中学高校生向けプログラミング教室の教材として作ったものを一部改変したものです。
Rubyでプログラミングの初歩を学んだ次のステップとして、ゲームライブラリDXRubyの使い方を学んでいきます。
続編
・ プログラミング初心者向け:DXRubyで 1ステップずつ作っていく「ブロック崩し」 - Qiita
技術解説
ソースコード
使用ライブラリ
Windows向けRuby用2DゲームライブラリDXRuby
を使用します。
バージョン1.4.2
以上を想定しています。
1.4.2
より前のバージョンとの主な相違点
-
Window.loop
が複数置ける -
マウス位置を取得する
Input.mouse_pos_x
、Input.mouse_pos_y
の新しい書き方として、Input.mouse_x
、Input.mouse_y
が追加
→ DXRuby 1.4.6:更新履歴
http://mirichi.github.io/dxruby-doc/CHANGELOG.html
DXRubyインストールの注意点
→ DXRuby 1.4.6 をWindows10で使う時の注意点とインストール方法 - noanoa07 - Qiita
https://qiita.com/noanoa07/items/0ce14c2404df38de94b7
参考サイト
-
DXRuby のホームページ
http://dxruby.osdn.jp -
DXRuby 1.4.6 リファレンスマニュアル
http://mirichi.github.io/dxruby-doc/index.html
困ったときは、このページの「チュートリアル」と「マニュアル」にだいたい書いてあります。
- DXRuby 1.4.1 リファレンスマニュアル
http://dxruby.osdn.jp/DXRubyReference/20095313382446.htm
古いバージョンのリファレンスも役に立つときがあります。
- DXRubyで 0から作る「ブロック崩し」 - noanoa 日々の日記
http://blog.livedoor.jp/noanoa07/archives/2045851.html
このテキストのブログ記事での解説です。
- ブラウザではじめるRubyゲームプログラミング:Nyle-canvas(DXRubyスタイル)入門 -Qiita
https://qiita.com/noanoa07/items/e7ebf97edef4ae9b448a
Nyle-canvas(DXRubyスタイル)で書き直した記事です。
ライセンス
本解説文および解説内のソースコードはともにパブリックドメイン
(DXRuby本体のソースコードは、zlib/libpngライセンス)
プログラム解説
1. DXRubyの練習
DXRubyの基本の使い方を練習します。
使い方を学んだ後は、「ブロック崩し」を作っていくのを目標にしています。
1-1. DXRubyのウィンドウを出す(dx01.rb)
DXRubyの基本の形です。
大きさを指定しないと、横640、縦480のウィンドウが開きます(左上の座標が(0, 0))。
Window.loop do 〜 end
の間に書いたコードは、1秒間に60回繰り返し実行されます。
→ DXRubyリファレンス:チュートリアル 1. 基本の形
http://mirichi.github.io/dxruby-doc/tutorial/basic.html
require 'dxruby'
Window.loop do
end
1-2. ウィンドウの大きさを変える(dx02.rb)
ウィンドウの大きさを変えるには、Window.width =
、Window.height =
を使います。
プログラムの内、最初の1回だけ実行されて以後変える必要のないものは、Window.loop do 〜 end
より前に書いておきます。
→ DXRubyリファレンス:API INDEX;module Window
http://mirichi.github.io/dxruby-doc/api/Window.html
require 'dxruby'
Window.width = 400
Window.height = 300
Window.loop do
end
1-3. ウィンドウの背景の色を変える(dx03.rb)
ウィンドウの背景の色を変えるには、Window.bgcolor =
を使います。
色の指定は、「DXRubyリファレンス:色配列と色定数について」
http://mirichi.github.io/dxruby-doc/api/constant_color.html
を見てください。
→ DXRubyリファレンス:API INDEX;module Window
http://mirichi.github.io/dxruby-doc/api/Window.html
require 'dxruby'
Window.bgcolor = C_CYAN
Window.loop do
end
1-4. タイトルを表示する;文字(dx04.rb)
ウィンドウの左上にタイトルを表示するには、Window.caption =
を使います。
→ DXRubyリファレンス:API INDEX;module Window
http://mirichi.github.io/dxruby-doc/api/Window.html
require 'dxruby'
Window.caption = "ブロック崩し"
Window.loop do
end
1-5. 画面に文字を出す(dx05.rb)
画面に文字を出すには、
font = Font.new(文字サイズ)
で文字サイズ(とフォント名)を指定しておいて、
Window.draw_font(x位置, y位置, "文字列", フォント, {:color => 色})
で表示します。
→ DXRubyリファレンス:チュートリアル 9. 文字の描画
http://mirichi.github.io/dxruby-doc/tutorial/basic.html
→ DXRubyリファレンス:API INDEX;Font.new
require 'dxruby'
font = Font.new(32)
Window.loop do
Window.draw_font(200, 100, "ブロック崩し", font, {:color => C_GREEN})
end
1-6. キー入力をとらえる(dx06.rb)
キー入力はInput.key_down?(キーコード定数)
を使います。
キーコード定数については、「DXリファレンス:キーコード定数」
http://mirichi.github.io/dxruby-doc/api/constant_keycode.html
を見てください。
→ DXRubyリファレンス:チュートリアル 8. キーボードの入力
http://mirichi.github.io/dxruby-doc/tutorial/basic.html
require 'dxruby'
font = Font.new(32)
Window.loop do
Window.draw_font(200, 100, "ESCキーで終了します", font, {:color => C_GREEN})
if Input.key_down?(K_ESCAPE)
exit # exit でプログラムを終了する
end
end
1-7. ウィンドウを切り替える(dx07.rb)
DXRuby 1.4.2 から、Window.loop do 〜 end
が複数置けるようになったので、break
でループを抜けると次のWindow.loop do 〜 end
が始まり、別のウィンドウを表示できます。
→ Window.loopを複数置く - mirichiの日記 2014-11-24
https://mirichi.hatenadiary.org/entry/20141124/p1
require 'dxruby'
font = Font.new(32)
Window.loop do
Window.draw_font(200, 100, "Nキーで次の画面へ", font, {:color => C_WHITE})
if Input.key_down?(K_N)
break # breakで loopを抜ける
end
end
Window.loop do
Window.draw_font(200, 100, "ブロック崩し", font, {:color => C_GREEN})
Window.draw_font(200, 150, "(ESCキーで終了)", font, {:color => C_RED})
if Input.key_down?(K_ESCAPE)
exit # exit でプログラムを終了する
end
end
1-8. 画像の読み込み(dx08.rb)
画像ファイルの読み込みは、Image.load(画像ファイル)
を使います。対応するファイル形式は、jpg
、png
、bmp
です。
読み込んだ画像はイメージになります。
→ DXRubyリファレンス:チュートリアル 2. 画像の読み込みと描画
http://mirichi.github.io/dxruby-doc/tutorial/basic.html
→ DXRubyリファレンス:API INDEX;Image.load
http://mirichi.github.io/dxruby-doc/api/Image_load.html
require 'dxruby'
image = Image.load('../image/apple.png')
Window.loop do
Window.draw(100, 100, image)
end
1-9. 画像の背景色の透明化(dx09.rb)
イメージでset_color_key(色)
を使うと、指定した色を透明にできます。
→ DXRubyリファレンス:Image;set_color_key
http://mirichi.github.io/dxruby-doc/api/Image_23set_color_key.html
require 'dxruby'
image = Image.load('../image/apple.png')
image.set_color_key(C_WHITE)
Window.loop do
Window.draw(100, 100, image)
end
1-10. 画像の拡大・縮小(dx10.rb)
イメージを拡大・縮小して表示したい時は、Window.draw_scale(x位置, y位置, イメージ, 横の拡大率, 縦の拡大率)
を使います。
→ DXRubyリファレンス:API INDEX;Image;Window.draw_scale
http://mirichi.github.io/dxruby-doc/api/Window_draw_scale.html
require 'dxruby'
image = Image.load('../image/apple.png')
image.set_color_key(C_WHITE)
Window.loop do
Window.draw_scale(100, 100, image, 0.2, 0.2)
end
1-11. トウフを表示(イメージで表示)(dx11.rb)
画像は元の画像ファイルがなくても、作ることもできます。Image.new(横幅, 縦幅, 色)
で、四角形のイメージ
を作ります。
(白い四角形の見た目で豆腐(トウフ)
)
表示するには、Window.draw(x位置, y位置, イメージ)
を使います。位置の基準はイメージの左上になります。
→ DXRubyリファレンス:API INDEX;class Image
http://mirichi.github.io/dxruby-doc/api/Image.html
→ DXRubyリファレンス:API INDEX;Window.draw
http://mirichi.github.io/dxruby-doc/api/Window_draw.html
require 'dxruby'
img_tohu = Image.new(100, 100, C_WHITE)
Window.loop do
Window.draw(200, 200, img_tohu)
end
1-12. トウフを表示(スプライトで表示)(dx12.rb)
DXRubyには画像を扱うのに、もう一つスプライト
というクラスがあります。スプライト
は、x位置
、y位置
のデータを自分で持ち、描画メソッドも独自に持っており、衝突判定もできるのが特徴です。そのため、「ブロック崩し」ではスプライト
を主に使います。
スプライト
は、Sprite.new(x位置, y位置, イメージ)
で作ります。(イメージはあらかじめ作っておきます。)
表示させるのは、draw
です。
→ DXRubyリファレンス:Spriteを使うためのチュートリアル
http://mirichi.github.io/dxruby-doc/tutorial/sprite.html
→ DXRubyリファレンス:API INDEX;class Sprite
http://mirichi.github.io/dxruby-doc/api/Sprite.html
require 'dxruby'
img_tohu = Image.new(100, 100, C_WHITE)
tohu = Sprite.new(200, 200, img_tohu)
Window.loop do
tohu.draw
end
1-13. トウフの中に赤丸を描く(dx13.rb)
丸を描くには、イメージにcircle_fill(中心のx位置, 中心のy位置, 半径, 色)
を使います。中心の位置の座標は、(ウィンドウの位置ではなく)そのイメージの左上が(0, 0)になります。
→ DXRubyリファレンス:API INDEX;Image#circle_fill
http://mirichi.github.io/dxruby-doc/api/Image_23circle_fill.html
require 'dxruby'
img_tohu = Image.new(100, 100, C_WHITE).circle_fill(50, 50, 50, C_RED)
tohu = Sprite.new(200, 200, img_tohu)
Window.loop do
tohu.draw
end
1-14. 赤丸だけにする(dx14.rb)
Image.new(横幅, 縦幅, 色)
で色
の指定を省略すると、透明色が指定されたことになり、見えなくなります。
→ DXRuby1.4.1 リファレンス:Imageクラス;Image.new
http://dxruby.osdn.jp/DXRubyReference/200953184038328.htm
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
ball = Sprite.new(200, 200, img_ball)
Window.loop do
ball.draw
end
1-15. カーソルキーで移動(dx15.rb)
カーソルキーが押されると、左右方向はInput.x
、上下方向はInput.y
が -1
, 0
, 1
に変化します。
これを利用することで、画面上を移動させることができます。
→ DXRuby 1.4.1 リファレンス:Inputモジュール
http://dxruby.osdn.jp/DXRubyReference/200953184011156.htm
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
ball = Sprite.new(0, 0, img_ball)
ball.x = 200
ball.y = 200
Window.loop do
ball.x = ball.x + Input.x
ball.y = ball.y + Input.y
ball.draw
end
1-16. カーソルキーで移動(別の書き方)(dx16.rb)
ball.x = ball.x + Input.x
を別の書き方である、
ball.x += Input.x
に書き換えてみます。同じ意味ですが、こちらの方が文字数が少なくて済むので、間違いが減らせるかも。
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
ball = Sprite.new(0, 0, img_ball)
ball.x = 200
ball.y = 200
Window.loop do
ball.x += Input.x
ball.y += Input.y
ball.draw
end
1-17. マウスに合わせて移動(dx17.rb)
マウスのx座標、y座標はそれぞれmouse_pos_x
、mouse_pos_y
で取得できます。
(DXRuby 1.4.2 からは、mouse_x
、mouse_y
という書き方もできます。)
→ DXRubyリファレンス:API INDEX;module Input
http://mirichi.github.io/dxruby-doc/api/Input.html
→ DXRubyリファレンス:API INDEX;Input.mouse_pos_x
http://mirichi.github.io/dxruby-doc/api/Input_23mouse_pos_x.html
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
ball = Sprite.new(0, 0, img_ball)
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
ball.draw
end
1-18. 画像を切り替える(dx18.rb)
スプライトの画像イメージは、スプライト.image =
で変更できます。
ここでは、x位置が300を超えるかどうかで、画像が変わるようにしています。
→ DXRubyリファレンス:API INDEX;Sprite.image =
http://mirichi.github.io/dxruby-doc/api/Sprite_23image_3D.html
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
img_tohu = Image.new(100, 100, C_WHITE)
ball = Sprite.new(0, 0, img_ball)
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
if ball.x > 300
ball.image = img_ball
else
ball.image = img_tohu
end
ball.draw
end
1-19. 2つの画像を表示する(dx19.rb)
ひとつの画像は位置が固定で、もうひとつはマウスに追従します。
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
img_tohu = Image.new(100, 100, C_WHITE)
ball = Sprite.new(0, 0, img_ball)
tohu = Sprite.new(100, 100, img_tohu)
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
ball.draw
tohu.draw
end
1-20. 画像をまとめて表示する(dx20.rb)
複数のスプライトを配列にまとめると、ひとつの命令Sprite.draw
で表示させることができます。
ここでは、スプライトball
とスプライトtohu
を配列imgs
にまとめて、Sprite.draw(imgs)
で一気に表示させています。
→ DXRubyリファレンス:Spriteを使うためのチュートリアル
http://mirichi.github.io/dxruby-doc/tutorial/sprite.html
→ DXRubyリファレンス:API INDEX;Sprite.draw
http://mirichi.github.io/dxruby-doc/api/Sprite_draw.html
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
img_tohu = Image.new(100, 100, C_WHITE)
ball = Sprite.new(0, 0, img_ball)
tohu = Sprite.new(100, 100, img_tohu)
imgs = [ball, tohu]
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
Sprite.draw(imgs)
end
1-21. 衝突判定1;===(dx21.rb)
スプライトは衝突したかを判定する===
があります。
衝突している
/していない
をtrue
/false
で返します。
→ DXRubyリファレンス:Spriteを使うためのチュートリアル;衝突判定
http://mirichi.github.io/dxruby-doc/tutorial/sprite.html
→ DXRubyリファレンス:API INDEX;Sprite;===
http://mirichi.github.io/dxruby-doc/api/Sprite_23_3D_3D_3D.html
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
img_tohu = Image.new(100, 100, C_WHITE)
ball = Sprite.new(0, 0, img_ball)
tohu = Sprite.new(100, 100, img_tohu)
imgs = [ball, tohu]
font = Font.new(24)
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
if ball === tohu
Window.draw_font(200, 300, "衝突!", font)
end
Sprite.draw(imgs)
end
1-22. 衝突判定2;check(dx22.rb)
スプライトの衝突判定===
では、衝突の有無は分かりますが、衝突した相手は分かりません。そんな時は、check
を使います。check
は衝突している相手を配列で返します。
配列をcoll
とすると(collision
:衝突)、0番目のcoll[0]
に何か入っていれば衝突してるし、空
ならば衝突していないという、衝突判定にも使えます。
→ DXRubyリファレンス:Spriteを使うためのチュートリアル;衝突したオブジェクトを取得する
http://mirichi.github.io/dxruby-doc/tutorial/sprite.html
→ DXRubyリファレンス:API INDEX;Sprite;check
http://mirichi.github.io/dxruby-doc/api/Sprite_23check.html
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
img_tohu = Image.new(100, 100, C_WHITE)
img_tohu_r = Image.new(100, 100, C_RED)
ball = Sprite.new( 0, 0, img_ball)
tohu1 = Sprite.new(150, 150, img_tohu)
tohu2 = Sprite.new(300, 150, img_tohu)
tohu3 = Sprite.new(300, 300, img_tohu)
blocks = [tohu1, tohu2, tohu3]
font = Font.new(24)
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
coll = ball.check(blocks)
if coll[0]
coll[0].image = img_tohu_r
end
Window.draw_font(200, 10, "#{blocks.size}個中、#{coll.size}個 衝突!", font)
Sprite.draw(blocks)
ball.draw
end
1-23. 衝突判定3;check後に、vanish, clean(dx23.rb)
vanish
は、check
で衝突していると判定されたスプライトを無効化します。無効化されたスプライトは描画されません。ただし、無効化されただけで、そのスプライトは削除された訳ではありません。
衝突したスプライトを削除したい時は、Sprite.clean(配列)
を使います。これは、配列内のスプライトで無効化されているものを配列から削除します。まだ衝突していないスプライトの数を知りたい時などに使えます。
→ DXRubyリファレンス:Spriteを使うためのチュートリアル;ライフサイクルを管理する
http://mirichi.github.io/dxruby-doc/tutorial/sprite.htmlSpriteの
→ DXRubyリファレンス:API INDEX;Sprite;vanish
http://mirichi.github.io/dxruby-doc/api/Sprite_23vanish.html
→ DXRubyリファレンス:API INDEX;Sprite.clean
http://mirichi.github.io/dxruby-doc/api/Sprite_clean.html
require 'dxruby'
img_ball = Image.new(100, 100).circle_fill(50, 50, 50, C_RED)
img_tohu = Image.new(100, 100, C_WHITE)
ball = Sprite.new( 0, 0, img_ball)
tohu1 = Sprite.new(150, 150, img_tohu)
tohu2 = Sprite.new(300, 150, img_tohu)
tohu3 = Sprite.new(300, 300, img_tohu)
blocks = [tohu1, tohu2, tohu3]
font = Font.new(24)
Window.loop do
ball.x = Input.mouse_pos_x
ball.y = Input.mouse_pos_y
coll = ball.check(blocks)
if coll[0]
coll[0].vanish
end
Sprite.clean(blocks)
Window.draw_font(200, 10, "#{blocks.size}個中、#{coll.size}個 衝突!", font)
Sprite.draw(blocks)
ball.draw
end
これで、DXRubyの練習は終わりです。
次は、「ブロック崩し」を作っていきます。