#!ruby -Ks # -*- mode: ruby; encoding: sjis -*- # Last updated: <2015/09/15 01:40:45 +0900> # # 矩形を変形描画して多関節処理っぽいことができるか実験 # Ruby 2.0.0 p647 mingw版 + DXRuby 1.4.2 で動作確認 # # Pキーで頂点表示をON/OFF # Bキーで元画像表示をON/OFF # 左側の赤いバーはCPU処理の重さ # # by mieki256 # LICENSE : CC0 / Public Domain require 'dxruby' require 'pp' class ArticulatedSprite01 < Sprite # コンストラクタ # @param [Integer] x x座標 # @param [Integer] y y座標 # @param [Hash] poly_data ポリゴンデータ # @param [Object] org_image 元になるテクスチャ画像 # @param [Integer] z 描画優先順位 def initialize(x, y, poly_data, org_image, z = 0, dvx = 4, dvy = 4) super(x, y, org_image) self.z = z @dividex = dvx @dividey = dvy @point_list = [] @new_point_list = [] @key_point_list = [] poly_data[:point_list].each do |x, y| @point_list.push([x, y]) @new_point_list.push([x, y]) @key_point_list.push([x, y]) end @poly_list = poly_data[:poly_list] @count = 0 @disp_point = true @disp_basetex = true # 画像からポリゴン一枚分を切り出して記録 @imgs = [] @poly_list.each do |p0, p1, p2, p3| x1, y1 = @point_list[p0] x2, y2 = @point_list[p1] x3, y3 = @point_list[p2] x4, y4 = @point_list[p3] w = x2 - x1 h = y4 - y1 # puts "(x,y,w,h)=(#{x1},#{y1},#{w},#{h})" # copy_rect を使う例 # img = Image.new(w, h) # img.copy_rect(0, 0, self.image, x1, y1, w, h) # slice を使う例 img = self.image.slice(x1, y1, w, h) @imgs.push(img) end @new_point_img = Image.new(5, 5) @new_point_img.box(0, 0, 4, 4, C_RED) @point_img = Image.new(9, 9) @point_img.box(0, 0, 8, 8, C_GREEN) @fnt = Font.new(14, "Arial") end # 更新処理 def update # Pキーで頂点の描画を切り替え @disp_point = !(@disp_point) if Input.keyPush?(K_P) # Bキーで元テクスチャ描画を切り替え @disp_basetex = !(@disp_basetex) if Input.keyPush?(K_B) base_ang = @count * 3 # 真ん中の頂点だけ動かす @key_point_list.each_with_index do |pnt, i| x, y = pnt if i % 3 == 1 and i > 2 and i < 18 x += 24 * Math.cos(base_ang * Math::PI / 180.0) y -= 16 * Math.cos(base_ang * Math::PI / 180.0) end @new_point_list[i][0] = x @new_point_list[i][1] = y end # 前腕だけ回転させる cx = 100 cy = 290 @new_point_list.each_with_index do |pnt, i| next if i <= 11 # 上腕部分の頂点は無視 x, y = pnt ang = 45 * Math.cos(base_ang * Math::PI / 180.0) + 40 # cx, cy を中心にして回転 rad = ang * Math::PI / 180.0 nx = (x - cx) * Math.cos(rad) - (y - cy) * Math.sin(rad) + cx ny = (x - cx) * Math.sin(rad) + (y - cy) * Math.cos(rad) + cy @new_point_list[i][0] = nx @new_point_list[i][1] = ny end @count += 1 end # 描画処理 def draw if @disp_basetex # 元画像を描画 Window.draw_alpha(self.x, self.y, self.image, 128, self.z - 1) end # 矩形ポリゴンを描画 i = 0 @poly_list.each do |p0, p1, p2, p3| x1, y1 = @new_point_list[p0] x2, y2 = @new_point_list[p1] x3, y3 = @new_point_list[p2] x4, y4 = @new_point_list[p3] x1 += self.x x2 += self.x x3 += self.x x4 += self.x y1 += self.y y2 += self.y y3 += self.y y4 += self.y Window.draw_morph(x1, y1, x2, y2, x3, y3, x4, y4, @imgs[i], :dividex => @dividex, :dividey => @dividey, :z => self.z) i += 1 end # 頂点を描画 draw_point if @disp_point end # 頂点を描画 def draw_point # 描画に使う・変形後の頂点座標群を描画 img = @new_point_img dx, dy = img.width / 2, img.height / 2 @new_point_list.each do |x, y| x += self.x y += self.y Window.draw(x - dx, y - dy, img, self.z + 1) end # 元々の頂点座標群を描画 img = @point_img dx, dy = img.width / 2, img.height / 2 i = 0 @key_point_list.each do |x, y| x += self.x y += self.y Window.draw(x - dx, y - dy, img, self.z + 1) Window.drawFont(x + 16, y, i.to_s, @fnt, :z => self.z + 1) i += 1 end end # 与えられたx座標リストとy座標リストからポリゴンデータを作成して返す # @param [Array] x_list x座標配列 # @param [Array] y_list y座標配列 # @return [Hash] :point_list に頂点座標リスト、 # :poly_list にポリゴン頂点インデックスが入ったハッシュを返す def self.get_poly_list(x_list, y_list) x_list.sort! y_list.sort! pnt_list = [] y_list.each do |y| x_list.each do |x| pnt_list.push([x, y]) end end poly_list = [] xlen = x_list.length ylen = y_list.length xidx = 0 yidx = 0 while (xidx < xlen - 1 and yidx < ylen - 1) p1 = xidx + (xlen * yidx) p2 = p1 + 1 p3 = p2 + xlen p4 = p1 + xlen poly_list.push([p1, p2, p3, p4]) xidx += 1 if xidx >= (xlen - 1) xidx = 0 yidx += 1 break if yidx >= (ylen -1) end end return { :point_list => pnt_list, :poly_list => poly_list } end end if $0 == __FILE__ # ---------------------------------------- # 動作確認 # 画像(テクスチャ)を分割する座標リスト guides = [ [0,92,163], # x [0,149,222,273,307,399,481,501,594], # y ] # ポリゴンデータに変換 poly_data = ArticulatedSprite01.get_poly_list(guides[0], guides[1]) # pp poly_data # 元画像読み込み img = Image.load("base_tex02.png") as = ArticulatedSprite01.new(256, 20, poly_data, img, 10) Window.resize(640, 640) Window.bgcolor = [96, 96, 96] Window.loop do break if Input.keyPush?(K_ESCAPE) as.update as.draw # CPU処理の重さをバーで描画 h = (Window.height * Window.get_load / 100.0).to_i Window.draw_box_fill(0, 0, 4, h, C_RED) end end