StarRubyで波紋生成シミュレーション
実行ファイル:RippleSimulator.exe
####################################################################### # # DESCRIPTION: タスクシステム管理 # AUTHOR: shom # DATE: 2012/10/13 # ####################################################################### require "starruby" include StarRuby class Task def exec( tex, keys, mouse, mouseLocat ) #virtual end end load "Ripple.rb" # 中間レンダリングバッファ生成 midTex = Texture.new( 480, 480 ) # タスク生成 # -タスクリスト HashTask = Hash.new # -移動体 HashTask.store( :ripple, Ripple.new(midTex) ) # フォント生成 font = Font.new( "MS UI Gothic", 20 ) font_color = Color.new( 255, 255, 255 ) # ゲームループ w = midTex.width() h = midTex.height() title = "Ripple Simulator ( powered by StarRuby )" Game.run( w, h, :cursor => true, :fps => 15, :title => title ) do |game| # 中間バッファリセット midTex.clear # 入力受付 keys = Input.keys( :keyboard ) mouse = Input.keys( :mouse ) mouseLocat = Input.mouse_location() # ESCキーで中断 break if keys.include?( :escape ) # タスク毎時処理 HashTask.each_value do |task| task.exec( midTex, mouse, mouseLocat ) end # 中間バッファ反映 game.screen.clear game.screen.render_texture( midTex, 0, 0 ) # デバッグテキスト出力 debug_text = "" debug_text << "[ fps ( ideal : "; debug_text << game.fps().to_i().to_s(); debug_text << " ) ] : "; debug_text << game.real_fps().to_i().to_s(); game.screen.render_text( debug_text, 8, 8, font, font_color ) debug_text = "[ produce ripple ] : "; if mouse.include?( :left ) debug_text << "on" else debug_text << "off" end game.screen.render_text( debug_text, 8, 8 + 24, font, font_color ) debug_text = "[ update ] : "; if mouse.include?( :right ) debug_text << "stopping" else debug_text << "working" end game.screen.render_text( debug_text, 8, 8 + 24 * 2, font, font_color ) if mouse.include?( :middle ) game.screen.render_text( "CLEAR!", 240 - 24 / 2 * 3, 240 - 24 / 2, font, font_color ) end end
####################################################################### # # DESCRIPTION: 波紋生成 # AUTHOR: shom # DATE: 2012/10/13 # ####################################################################### require "starruby" include StarRuby class Ripple < Task #定数 GRID_HEIGHT = 6 GRID_WIDTH = 6 ATTENUATION = 0.999 #減衰率(1に限りなく近いほど、波の伝搬力が高くなる) def initialize(tex) @xmax = ( (tex.width())/GRID_WIDTH ).floor() @ymax = ( (tex.height())/GRID_HEIGHT ).floor() @heightTbl = Array.new @heightPrevTbl = Array.new for y in 0..(@ymax-1) for x in 0..(@xmax-1) @heightTbl.push( 0 ) @heightPrevTbl.push( 0 ) end end end # 関数:色情報獲得:クリア def getHeightClear(tex, elColors = @heightTbl) for y in 0..(@ymax-1) for x in 0..(@xmax-1) @heightTbl[y*@xmax+x] = 0 @heightPrevTbl[y*@xmax+x] = 0 end end end # 関数:色情報獲得:マウスの位置を黒に def getHeightMouse(tex, mouse, mouseLocat) #マウスの位置を高さを最大にする if mouse.include?( :left ) then x,y = mouseLocat idxX = (x/GRID_WIDTH).floor idxY = (y/GRID_HEIGHT).floor idx = idxY * @xmax + idxX @heightTbl[ idx ] = 100 end end # 関数:色情報に波の効果を出す def effectRipple(tex) # バッファ確保 nextHeightTbl = Array.new(@heightTbl) # for y in 0..(@ymax-1) for x in 0..(@xmax-1) surroundSum = 0 if x!=0 surroundSum += @heightTbl[y*@xmax+(x-1)] else surroundSum += @heightTbl[y*@xmax+x] end if x!=(@xmax-1) surroundSum += @heightTbl[y*@xmax+(x+1)] else surroundSum += @heightTbl[y*@xmax+x] end if y!=0 surroundSum += @heightTbl[(y-1)*@xmax+x] else surroundSum += @heightTbl[y*@xmax+x] end if y!=(@ymax-1) surroundSum += @heightTbl[(y+1)*@xmax+x] else surroundSum += @heightTbl[y*@xmax+x] end if x!=0 and y!=0 surroundSum += @heightTbl[(y-1)*@xmax+(x-1)] else surroundSum += @heightTbl[y*@xmax+x] end if x!=(@xmax-1) and y!=0 surroundSum += @heightTbl[(y-1)*@xmax+(x+1)] else surroundSum += @heightTbl[y*@xmax+x] end if x!=0 and y!=(@ymax-1) surroundSum += @heightTbl[(y+1)*@xmax+(x-1)] else surroundSum += @heightTbl[y*@xmax+x] end if x!=(@xmax-1) and y!=(@ymax-1) surroundSum += @heightTbl[(y+1)*@xmax+(x+1)] else surroundSum += @heightTbl[y*@xmax+x] end difSurround = ( surroundSum / 8 * ATTENUATION - @heightTbl[y*@xmax+x] ) difCenter = @heightTbl[y*@xmax+x] - @heightPrevTbl[y*@xmax+x] nextHeight = @heightTbl[y*@xmax+x] + difSurround + difCenter if nextHeight > 100 then nextHeight = 100 elsif nextHeight < 0 then nextHeight = 0 end nextHeightTbl[y*@xmax+x] = nextHeight end end # 色情報更新 @heightPrevTbl = @heightTbl.clone @heightTbl = nextHeightTbl.clone end # 関数:描画 def renderRect(tex) heightTbl = @heightTbl.clone # 矩形を並べる 0.step(tex.height()-1, GRID_HEIGHT) do |y| 0.step(tex.width()-1, GRID_WIDTH) do |x| height = ( heightTbl.shift() ).floor color = Color.new( 0, 0, 255 * height / 100 ) tex.render_rect(x, y, GRID_WIDTH, GRID_HEIGHT, color) end end end # 関数:毎時処理 def exec(tex, mouse, mouseLocat) # 色情報を獲得 if mouse.include?( :middle ) then getHeightClear(tex, @heightTbl) getHeightClear(tex, @heightPrevTbl) else getHeightMouse(tex, mouse, mouseLocat) end # 色情報に波の効果を出す if !mouse.include?( :right ) then effectRipple(tex) end # 矩形を色情報を使って描画 renderRect(tex) end end