查看: 1868|回复: 4

[已经解决] Bitmap类旋转问题[已解决]

[复制链接]
梦石
0
星屑
60
在线时间
8 小时
注册时间
2015-8-13
回帖
2
发表于 2016-10-23 00:56:54 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 Mirora_Mikasa 于 2016-10-24 23:36 编辑

不小心开到隔壁去了,我来重开一帖

原本的问题是:如何实现位图的旋转
现在我实现之后,发现,效率极其低下,32*32的图片生成360个角度用了少说10s
我的方法:https://rpg.blue/home.php?mod=sp ... o=blog&id=15610
所以有没有什么方法能提高其运输效率
梦石
0
星屑
6891
在线时间
7027 小时
注册时间
2013-11-2
回帖
1263

开拓者剧作品鉴家

发表于 2016-10-23 07:54:31 | 显示全部楼层
本帖最后由 RaidenInfinity 于 2016-10-23 07:58 编辑

使用Bitmap的get_pixel和set_pixel难免缓慢,而RGSS3并没有提供可以直接更改位图数据的方法(如C# Bitmap的LockBits)。
因此,无论如何还是建议使用Sprite来显示图形的旋转。

Sprite的旋转是以原点(ox和oy)作为支点,并逆时针旋转。

假设我们有这样的一段代码:
0.PNG

生成的方形:
1.png

angle = 20的时候
2.png

如果想要以中心为支点来旋转,必须将原点设置到中心。
a.ox = a.width / 2
a.oy = a.height / 2

就会得到想要的效果了:
3.png

虽然有点答非所问,不过关于位图本身的旋转,我本身还在测试中。有结果后再回答。
回复

使用道具 举报

梦石
0
星屑
6891
在线时间
7027 小时
注册时间
2013-11-2
回帖
1263

开拓者剧作品鉴家

发表于 2016-10-23 09:57:49 | 显示全部楼层
本帖最后由 RaidenInfinity 于 2016-10-23 10:30 编辑

[pre lang="ruby"]
#Simple Bitmap Rotation by RaidenInfinity

module Math
   
    def self.deg_to_rad(x)
      return x * (Math::PI / 180.0)
    end
   
    def self.get_rotation_matrix(angle)
      case angle
        when 0; return [1,0,0,1]
        when 90; return [0,1,-1,0]
        when 180; return [0,-1,1,0]
        when 270; return [-1,0,0,-1]
      end
      return [cos(deg_to_rad(angle)),-sin(deg_to_rad(angle)),
                      sin(deg_to_rad(angle)),cos(deg_to_rad(angle))]
    end
   
    def self.matrix_multiply_2x2_1x2(std,vec)
      return [std[0] * vec[0] + std[1] * vec[1],
              std[2] * vec[0] + std[3] * vec[1]]
    end   

    def self.transpose_matrix_2x2(mat)   
      return [mat[0],mat[2],mat[1],mat[3]]
    end      
   
end
  
class Bitmap

  def get_rotated_bitmap(angle)
    mat = Math.get_rotation_matrix(angle)
    arr = get_rotated_size(mat)
    bmp = Bitmap.new(arr[0],arr[1])
    old_ox = (self.width / 2).round.to_i
    old_oy = (self.width / 2).round.to_i
    new_ox = (arr[0] / 2).round.to_i
    new_oy = (arr[1] / 2).round.to_i
    #Reverse Mapping
    mat = Math.transpose_matrix_2x2(mat)
    arr[0].times{|i|
      arr[1].times{|j|
        vec = m_mult(mat,[i - new_ox,j - new_oy])
        c = self.get_pixel((vec[0] + old_ox).round,(vec[1] + old_oy).round)
        bmp.set_pixel(i,j, c)
      }
    }     
    return bmp
  end
  
  def get_rotated_size(mat)
    arr = [m_mult(mat,[0,0]),m_mult(mat,[self.width,0]),
         m_mult(mat,[0,self.height]),m_mult(mat,[self.width,self.height])]
    ax = [arr[0][0], arr[1][0], arr[2][0], arr[3][0]]
    ay = [arr[0][1], arr[1][1], arr[2][1], arr[3][1]]
    return [(ax.max - ax.min).round.to_i.abs, (ay.max - ay.min).round.to_i.abs]
  end
  
  def m_mult(std,vec); Math.matrix_multiply_2x2_1x2(std,vec) end
  
end
[/pre]

尝试写了一个也许比较快的版本。32x32的位图从0到359度,耗时大概2.5秒上下(我的主机核是Pentium E5200 2.50GHz)

测试运行代码:
[pre lang="ruby"]
a = Bitmap.new(32,32)
a.fill_rect(0,0,32,32,Color.new(255,0,0,255))

list = []
z = Time.now
360.times{|i|
  #p i
  list.push(a.get_rotated_bitmap(i))
}  
z -= Time.now
p z
[/pre]

也许你能参考来优化,或者在比较强的电脑上也许运行速度会更快。
这段脚本的主要优化原理是使用矩阵,避免每个像素都调用三角函数。

评分

参与人数 1星屑 +250 梦石 +1 收起 理由
怪蜀黍 + 250 + 1 楼主认可的解答

查看全部评分

回复

使用道具 举报

梦石
0
星屑
60
在线时间
8 小时
注册时间
2015-8-13
回帖
2
 楼主| 发表于 2016-10-23 23:04:33 | 显示全部楼层
本帖最后由 Mirora_Mikasa 于 2016-10-24 00:07 编辑

非常感谢,虽说在下还没有学到矩阵是个啥..........

另外有一个问题:
[pre lang="ruby"]list = {}
360.times do |i|
  list = RSTG_Bitmap.new(bit,i)
end
360.times do |i|
  b = Sprite.new
  b.x,b.y = 200,200
  b.bitmap = list.bitmap
  b.ox,b.oy = list.ox,list.oy
  Graphics.update
  b.dispose
end
[/pre]

这样一个代码在运行时他会提示我 undefined method 'bitmap' for nil:NilClass
但是把第二个 360.times do |i| 改为 360.downto 1 do |i| 便可以正常的运行,所以想请教下是为什么........
回复

使用道具 举报

梦石
0
星屑
6891
在线时间
7027 小时
注册时间
2013-11-2
回帖
1263

开拓者剧作品鉴家

发表于 2016-10-26 13:19:51 | 显示全部楼层
你可以试下把list宣告为数组(Array)而不是键值表(Hash)

[pre lang="ruby"]
list = []
360.times do |i|
  list.push(RSTG_Bitmap.new(bit,i))
end
[/pre]

如果你仍然想要用Hash,也请用
[pre lang="ruby"]
p list
[/pre]
检查你的列表里面是否有list[0] = nil的情况

总结:p是个好东西。在控制台打印出变量的内容可以协助解决很多问题。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部