#!ruby # -*- mode: ruby; coding: utf-8 -*- # Last updated: <2016/12/11 15:50:30 +0900> # # Gosuの動作確認 # スプライト+BG表示を試してみる。 # # 動作確認環境: # Windows10 x64 + Ruby 2.2.6 p396 mingw32 + Gosu 0.10.8 x86-mingw32 require 'gosu' # スプライト相当のクラス class MySpr # コンストラクタ def initialize(x, y, vx, vy, img, z, scrw, scrh) @fpx = x @fpy = y @fpvx = vx @fpvy = vy @scrw = scrw @scrh = scrh @z = z @w = img.width @h = img.height @whf = @w / 2 @hhf = @h / 2 @image = img @x = (@fpx - @whf).to_i @y = (@fpy - @hhf).to_i end # 更新処理 def update @fpx += @fpvx @fpy += @fpvy @x = (@fpx - @whf).to_i @y = (@fpy - @hhf).to_i @fpvx *= -1 if @x + @w >= @scrw or @x <= 0 @fpvy *= -1 if @y + @h >= @scrh or @y <= 0 end # 描画処理 def draw @image.draw(@x, @y, @z) end end # 背景描画用クラス class Map # コンストラクタ # @param wdw_w [Integer] ウインドウ横幅 # @param wdw_h [Integer] ウインドウ縦幅 def initialize(wdw_w, wdw_h, z) @wdw_w = wdw_w @wdw_h = wdw_h @z = z # 画像の読み込み @imgs = [] ['tmp_bg1.png', 'tmp_bg2.png'].each do |fn| # Gosu::Image.load_tiles()を使えば画像を分割して読み込める。 # ここでは 512x512の画像を、1チップ32x32として読み込んでるので # 16x16個 = 256個の画像に分割されているはず imgs = Gosu::Image.load_tiles(fn, 32, 32, :tileable => true) @imgs.push(imgs) end # タイルマップ用の配列を作成 @bgarr = [] c = 0 16.times do |by| @bgarr[by] = [] 16.times do |bx| @bgarr[by][bx] = c c = (c + 1) % 256 end end end # 背景描画処理 # @param bx [Integer] BG座標x # @param by [Integer] BG座標y # @param n [Integer] BG番号(0 or 1) def draw(bx, by, n) cw, ch = 32, 32 # セル1つ分のサイズ bx = bx.to_i by = by.to_i imgs = @imgs[n] lenx = @bgarr[0].length leny = @bgarr.length cx = (bx / cw) % lenx cy = (by / ch) % leny sx = (bx % cw) sy = (by % ch) wcnt = @wdw_w / cw + 1 hcnt = @wdw_h / ch + 1 hcnt.times do |y| wcnt.times do |x| k = @bgarr[(cy + y) % leny][(cx + x) % lenx] imgs[k].draw(x * cw - sx, y * ch - sy, @z + n) end end end end # フレームレートを測定するクラス class FrameRate attr_reader :framerate def initialize @cnt = 0 @framerate = 0 @start_time = Time.now end # 毎フレーム呼ぶ def update @cnt += 1 n = Time.now nd = n - @start_time return if nd < 1.0 @framerate = @cnt / nd @start_time = n @cnt = 0 end end # メインウインドウ相当 class MyWindow < Gosu::Window # コンストラクタ def initialize super 640, 480, false self.caption = 'Sprite Test' scrw = self.width # ウインドウ横幅 scrh = self.height # ウインドウ縦幅 # フォントを用意 @font = Gosu::Font.new(20) # BG初期化 @maps = Map.new(scrw, scrh, 0) @bgx = [0, 0] @bgy = [0, 0] # スプライト発生 pmax = 512 img = Gosu::Image.new('tmp_ufo.png', :tileable => true) x = 320 y = 240 @sprgroup = [] pmax.times do |i| rad = (i * 360 / pmax) * Math::PI / 180 d = 3.0 dx = d * Math.cos(rad) dy = d * Math.sin(rad) @sprgroup.push(MySpr.new(x, y, dx, dy, img, 100, scrw, scrh)) end @frate = FrameRate.new @frame = 0 @draw_frame = 0 end # 更新処理 def update # BGスクロール位置を更新 ang = Math.cos(@frame * Math::PI / 180.0) @bgx[0] = -64 + (64.0 * ang) + 640 @bgx[1] = -128 + (128.0 * ang) + 640 @bgy[0] = (@bgy[0] + 2) @bgy[1] = (@bgy[1] + 6) # スプライト更新 @sprgroup.each do |spr| spr.update end @frame += 1 end # 描画処理 def draw # BG描画 2.times do |i| @maps.draw(-@bgx[i], -@bgy[i], i) end # スプライト描画 @sprgroup.each do |spr| spr.draw end @draw_frame += 1 @frate.update f = @frate.framerate.to_s # テキスト表示 col = 0xff_ffff00 fps = sprintf("%.3f", f) @font.draw("#{fps} FPS", 10, 10, 2000, 1.0, 1.0, col) @font.draw("#{@frame} : update frame", 10, 30, 2000, 1.0, 1.0, col) @font.draw("#{@draw_frame} : draw frame", 10, 50, 2000, 1.0, 1.0, col) end # キーボードチェック def button_down(id) # ESCキーが押されたらウインドウを閉じて終了する # Gosu::Window.close() を呼ぶとウインドウが閉じる close if id == Gosu::KbEscape end end window = MyWindow.new window.show