Ruby/SDLを使ってブロック崩しを制作する方法

このQ&Aのポイント
  • Ruby/SDLを使ってブロック崩しを制作している際に画面いっぱいにブロックを並べたら処理が落ちる問題が発生しています。処理を軽くする方法を教えてください。
  • Ruby/SDLの処理を早くするための方法について教えてください。
  • Ruby/SDLを使ってブロック崩しを制作していると、画面いっぱいのブロックを並べると処理が重くなってしまいます。処理を軽くする方法を教えてください。
回答を見る
  • ベストアンサー

Ruby/SDLの処理を早くしたい

Ruby/SDLを使ってブロック崩しを制作しているのですが画面いっぱいにブロックを並べたら処理が落ちて困っています。なにか軽くする方法を教えていただけないでしょうか?お願いします。 ソース抜粋 重要そうなところだけ抜粋してみました require "sdl" require "lib/fpstimer" SCREEN_W = 640 SCREEN_H = 480 def load_image(fname) image = SDL::Surface.load(fname) image.set_color_key(SDL::SRCCOLORKEY, [255, 255, 0]) image end SDL.init(SDL::INIT_EVERYTHING) screen=SDL.set_video_mode(SCREEN_W, SCREEN_H, 16,SDL::SWSURFACE) ball = load_image("image/ball.png") bar = load_image("image/bar.png") block = [load_image("image/block1.png"), load_image("image/block2.png"), (略します) load_image("image/block9.png")] board =[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], (略します 25*32) [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]] loop do screen.fillRect 0, 0, 640, 480, [ 0, 0, 0 ] speedX = 5 if speedX > 5 speedY = 5 if speedY > 5 speedX = -5 if speedX < -5 speedY = -5 if speedY < -5 SDL::Key.scan if SDL::Key.press?(SDL::Key::SPACE) barX -= 12 if SDL::Key.press?(SDL::Key::LEFT) barX += 12 if SDL::Key.press?(SDL::Key::RIGHT) else barX -= 8 if SDL::Key.press?(SDL::Key::LEFT) barX += 8 if SDL::Key.press?(SDL::Key::RIGHT) end if ballenterflag == 0 if SDL::Key.press?(SDL::Key::RETURN) ballenterflag = 1 end if SDL::Key.press?(SDL::Key::LEFT) if SDL::Key.press?(SDL::Key::RETURN) ballenterflag = 2 end end end #バーとボールの判定 if fallball == 0 if ballX + 6< barX + 96 && ballX + 6 > barX && ballY+ 6 > barY - 2 && ballY + 6 < barY + 12 + 2 # 周りにヒット if SDL::Key.press?(SDL::Key::LEFT) if speedX >= 0 && speedY >= 0 speedX = speedX / 1.2 speedY = speedY *1.2 elsif speedX < 0 && speedY > 0 speedX = speedX * 1.2 speedY = speedY / 1.2 end elsif SDL::Key.press?(SDL::Key::RIGHT) if speedX >= 0 && speedY >= 0 speedX = speedX * 1.2 speedY = speedY / 1.2 elsif speedX < 0 && speedY > 0 speedX = speedX / 1.2 speedY = speedY * 1.2 end end speedY = -speedY if ballX + 6< barX + 52 && ballX + 6 > barX + 44 && ballY+ 6 > barY - 2 && ballY + 6 < barY + 12 + 2 #真ん中ヒット kantuu = 1 elsif kantuu = 0 scoreplus = 200 end fallball = 1 #1ならボールを跳ね返さない end end for i in 0..25 for j in 0..32 #高さ if board[j][i] == 1 screen.put(block[0], blockX+i*24, blockY+j*12) elsif board[j][i] == 2 screen.put(block[1], blockX+i*24, blockY+j*12) 略します 1~10です elsif board[j][i] == 10 screen.put(block[9], blockX+i*24, blockY+j*12) end if board[j][i] != 0 if (ballX + 6 > blockX + i*24 && ballX + 6 < blockX + i*24 +24) && ((ballY + 6 > blockY + j*12 -3 && ballY + 6 < blockY + j*12 + 3) || (ballY + 6 > blockY + j*12 + 12 -3 && ballY + 6 < blockY + j*12 +12 + 3)) if kantuu == 0 speedY = -speedY end board[j][i] = 0 score += scoreplus scoreplus += 50 elsif (ballY + 6 > blockY + j*12 && ballY + 6 < blockY + j*12 + 12) && ((ballX + 6 > blockX + i*24 -2 && ballX + 6 < blockY + i*24 +3) || (ballX + 6 > blockX + i*24 + 24 -3 && ballX + 6 < blockY + i*24 +24 +2)) if kantuu == 0 speedX = -speedX end board[j][i] = 0 score += scoreplus scoreplus += 50 end end end end screen.put(ball, ballX, ballY) timer.wait_frame do screen.update_rect(0, 0, 0, 0) end end

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

ゲームでパフォーマンスが問題になったとき、とにかく描画が重くなっていることが多いです。 お示しになったソースコードを見る限り、毎フレーム画面全体を描き直しているようですので(たしかにそのほうがコーディングは楽なのですが)、 これをボールや消滅したブロックの位置だけを再描画するようにしたらいかがでしょうか? 示されたソースコードは断片ですし未整理のようですのですべてを把握できませんが、 いくら遅いと呼ばれているRubyでもブロック崩し程度の当たり判定なんかが問題になるとは考えにくいです。 自分はRubyからSDLを使ったことはありませんし、Ruby/SDL特有の問題である可能性もありますが、 試してみる価値はあるんじゃないかと思います。 もしどんな場合でもパフォーマンス改善に有効な方法があるとしたら、 それはより高性能な環境で動かすことぐらいでしょうか。

redspore
質問者

お礼

回答ありがとうございます。 screen.fillRect 0, 0, 640, 480, [ 0, 0, 0 ] この処理を無くし、画面の更新だけにしたところとても軽くなりました。ありがとうございました

関連するQ&A

  • DXライブラリの透過処理について

    #include "DxLib.h" int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { ChangeWindowMode(TRUE); SetDrawScreen(DX_SCREEN_BACK); if(DxLib_Init()==1) { return -1; } char key[256]; // int haikei; int mapchip[2][152]; int i,j; //int x = 0, y = 0; //haikei = LoadGraph("haikei/草原.jpg"); LoadDivGraph("03.png",5,1,5,32,32,mapchip[0]); LoadDivGraph("mura.png",1,1,1,32,32,mapchip[1]); while(ScreenFlip()==0 && ProcessMessage() == 0 && GetHitKeyStateAll(key)==0) { // ClearDrawScreen(); // DrawGraph(x,y,haikei,FALSE); for(i = 0; i<15;i++) { for(j=0;j<20;j++) { DrawGraph(j*32,i*32,mapchip[0][4],FALSE); } } DrawGraph(32,32,mapchip[1][0],TRUE); /* if(CheckHitKey(KEY_INPUT_RIGHT) == 1) x+=10; if(CheckHitKey(KEY_INPUT_LEFT) == 1) x-=10; if(CheckHitKey(KEY_INPUT_UP) == 1) y-=10; if(CheckHitKey(KEY_INPUT_DOWN) == 1) y+=10; */ if(key[KEY_INPUT_ESCAPE] == 1) { DxLib_End(); return 0; } } } 「DrawGraph(32,32,mapchip[1][0],TRUE);」という処理でmura.pngの左上のカラーキーで透過するはずですがしません。 Win10のペイントで作ったpngファイル形式に対応してないかと思うのですが、よくわかりまえん。 なぜ?

  • Rubyプログラミングの課題について☆

    大学のレポートで下のような課題が出て、実際プログラムを自分で作って実行してみたのですが、全く無反応でいくら考えても原因がわかりません(T_T)批判されそうな質問かもしれないですが、留年かかっているので親切な方、助言お願いします。。 ●下の動作をするプログラム(a.rb)を作れ  %a.rb "+[1,20] =>21 %a.rb "*[-1,25,4] =>-100 ●作ってみたプログラム↓ class Array def list_ope d=0 #最終的に返す値 s=0 #状態番号 x="" #一時的に数値を入れる op="" #[+,-,*,/] sgn=1 #マイナスの符号のあるなし err=999999 self.each{|i| case s #とりあえず、[+,-,*,/]をopに代入 when 0 op=i s=1 when 1 if /\[/ =~ i  s=2 else s=err; bleak end when 2 sgn=1; x=0; if /[1-9]/ =~ i #1~9の時 x+=i; s=3 elsif /-/ =~ i #マイナスの時 sgn=-1; s=3 else s=err; bleak end when 3 if /[0-9]/ =~ i #0~9の時 x+=i; elsif /,/ =~ i #コンマの時 x=sgn*x.to_i; s=4 elsif /\]/ =~ i #]の時 x=sgn*x.to_i; s=5 else s=err; bleak end when 4 #コンマの時の処理 if /\+/ =~op d=d+x elsif /-/ =~ op d=d-x elsif /\*/ =~ op d=d*x elsif / =~ op d=d/x end s=2 when 5 #]のときの処理 if /\+/ =~op d=d+x elsif /-/ =~ op d=d-x elsif /\*/ =~ op d=d*x elsif / =~ op d=d/x end s=6 #終了状態 end } if s==6 return d #dを返す else print "error!" end end end

  • どこが間違いか分かりません。(Ruby)

    Rubyを使ったプログラムが巧く行かないのですが、どこでエラーが出ているのか分かりません。どなたか何が原因でエラーが起こったのか教えて頂けないでしょうか。 以下ソースコードです。 class SolitaireCipher $deck = (1..52).to_a+['A','B'] def solitaire(count) key_stream = [] until key_stream.size == count a = $deck.index("A") $deck.delete("A") if a == 53 a = 0 else a += 1 end $deck.insert(a,"A") b = $deck.index("B") $deck.delete("B") if b == 52 b = 1 elsif b == 53 b = 2 else b = b+2 end $deck.insert(b,"B") a1 = $deck[0..b-1] a2 = $deck[b..a] a3 = $deck[a+1..53] $deck = a3+a2+a1 if $deck[53] == 'A' t1 = 27 elsif $deck[53] == 'B' t1 = 27 else t1 = $deck[53] end a4 = $deck[0..t1-1] $deck = ($deck-a4).insert(52,a4).flatten! i = $deck[0].to_i key = $deck[i] key_stream << key end key_stream_s = key_stream.join n = 5 while n < key_stream_s.size key_stream_s[n,0] = " " n += 6 end key_stream = key_stream_s.split(" ") end end s = SolitaireCipher.new p s.solitaire(20) このプログラムを実行したときに、どういう訳かuntil文の中で毎回$deckの値が初期化されるようです。 そのため結果が以下のようになります。 ["44444", "44444", "44444", "44444"] 初心者プログラマーなので何か初歩的な間違いをしているのかもしれません。 どなたかエラーの原因を教えて頂けないでしょうか。 読みにくいプログラムではありますがよろしくおねがいします。

  • rubyにおけるPOSTされたデータの処理について

    言語はRubyです。 場面としては、railsにPOSTされたパラメータを受け取ってオブジェクトであるdetaを保存しているところです。 #case1 #params = {'a' => 1, 'b'=> 2 ,'c' => 3} #case2 #params = [{'a' => 1, 'b'=> 2 ,'c' => 3}, {'a' => 4, 'c' => 5}] if params.kind_of?(Array) params.length.times do |i| @deta.new if a = params[i]['a'] end if b = params[i]['b'] end if c = params[i]['c'] end @deta.save! end else @deta.new if a = params['a'] end if b = params['b'] end if c = params['c'] end @deta.save! end paramsが配列の可能性がある上、 paramsのハッシュである a, b, c のキーが毎回存在するかわからないので、 if文で例外がでないようにチェックしています。 自分で書いてて冗長な感じがして気持ち悪いです。 なにかよい方法があれば、教えてください。 よろしくお願いします。

    • ベストアンサー
    • Ruby
  • rubyの繰り返し処理の仕方を教えてください

    rubyの繰り返し処理の仕方がわかりません rubyを使ってのプログラムを勉強してます。最終的には表の書き換えをする プログラムがつくりたいのですが最初でコケましたruby イテレーター ネストで検索してもわからなかったので質問します。どなたか お時間あれ ば教えてください。 お店の番号SA003とSA005を次の "SA001",0,10,20,10 "SA003",0,10,20,20 "SA004",0,10,20,100 "SA005",0,10,20,50 の表なかから探すプログラムを作成しようとしましたが。 繰り返し処理の仕方がわかりません変数のスコープが外れていると思いますし dataの行数は4とはかぎらないので 4.times は使えないのはわかるのですが とりあえずイメージ的に描いたプログラムです。よろしくお願いいたします。 ====testimage.rb======== class Shop_number def initialize @mise=["SA003","SA005"] end def tenposuu() return @mise.size end def tenpo_no(n) return @mise[n] end end data =[["SA001",0,10,20,10],["SA003",0,10,20,20],["SA004",0,10,20,100],["SA005",0,10,20,50]] obj = Shop_number.new obj.tenposuu.times do |i| 4.times do |j| if data[j][0]=~/{obj.tenpo_no(i)}/ then puts data end end ======================= =>["SA003",0,10,20,20] =>["SA005",0,10,20,50] と出したいのですが・・・

    • ベストアンサー
    • Ruby
  • ruby for文

    for文を用いる s=1+2+5+10+17...+50 s=0;i=1;j=1 for i in 1..100 s+=1 i+=j if i>50 break end j+=2 end puts s この問題の意味がよくわかりません。。 よかったら説明してくれると助かります。。 j+=2 ここはなんで2なんしょうか? 特にここのところはなんでこうなっているんですか? iとかjとかを使っている意味がわかりません。。

    • ベストアンサー
    • Ruby
  • Javaのプログラムをルビー言語に。

    10~50までの素数が格納されている配列を rubyで作りたいのですが、どのようにすればいいいのかよくわかりません。 下のプログラムにも間違いがあるかもしれませんので もしありましたご指摘お願い致します。 for i=start i<=end i++; //iは割られる数 for(j=1;j<=i;j++){ //jは割る数 if(i%j==0){ count++; } } if(count==2){ System.out.println(i); } iをjで割っていき、余りが0になったらカウントを増やしていくプログラムです。 素数は1とその数字でしか割れないので、カウントは2になり、 それを配列に格納したいのですが、ここではただ表示するだけに留まってしまっています。 どなたかよろしくお願い致します。

  • Javaのプログラムをルビー言語に。

    10~50までの素数が格納されている配列を rubyで作りたいのですが、どのようにすればいいいのかよくわかりません。 下のプログラムにも間違いがあるかもしれませんので もしありましたご指摘お願い致します。 for i=start i<=end i++;//iは割られる数 for(j=1;j<=i;j++){//jは割る数 if(i%j==0){ count++; } } if(count==2){ System.out.println(i); } iをjで割っていき、余りが0になったらカウントを増やしていくプログラムです。 素数は1とその数字でしか割れないので、カウントは2になり、 それを配列に格納したいのですが、ここではただ表示するだけに留まってしまっています。 まだruby初心者で分からないことだらけですので、 簡単な方法ではなく、出来ればfor文を使用したやり方で教えていただけると 幸いです。 よろしくお願い致します。

    • ベストアンサー
    • Ruby
  • ループ処理について。

    下記のようなプログラムを作りました。 機能としては同じDB内にある異なるテーブルの日付を比較し、 違うものがあれば挿入するというものです。 ただしこの場合ではうまくいきません。 (1)テーブルの値を順に読み取り、 (2)にあるテーブル全ての行に対応させ、 ある行に値があれば、ループをぬけて そのsql文には空にするという形にしたいのですが、 このままですと条件文だけしかぬけていません。。。 何かよい方法があればご教授お願いいたします。 //比較するテーブル・・・(1) for($i=0;$i<$num;$i++){ $num_i=(レコードを取得する関数); //挿入するテーブル・・・(2) for($j=0;$j<$num;$j++)} $num_j=(レコードを取得する関数);    //日付が同じでなければ挿入する if($num_i["start_date"] != $num_j["start_date"] && $num_i["end_date"] != $num_j["end_date"]){ $sql[$i]="INSERT INTO date (start_date,end_date) VALUES(".$num_i["start_date"].",".$num_i["end_date"].");"; } else{ $sql[$i]=""; break; } } if($sql[$i] != ""){ print($sql[$i]); } }

    • ベストアンサー
    • PHP
  • (.NET)IF文の計算結果が思ったのと違う!?

    IF文でiとjの足す処理が括弧にくくられているので、きちんと足される思ったのですがラベルでの実行結果が0になります。 コード上は計算されているように見えるのですがなぜ計算されていないのでしょうか?計算できないとしたらIF文の中では計算処理ができないということでしょうか? 回答のほどよろしくお願い致します。 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim i, j i = 0 j = 0 If (i = i + 1) = 0 Or (j = j + 1) = 0 Then MessageBox.Show("+1") End If Label1.Text = i Label2.Text = j End Sub

専門家に質問してみよう