Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Rotating Bitmaps

I tried to write a method to rotate Bitmaps:
Code:
class Bitmap

  

  #--------------------------------------------------------------------------

  # * Returns a rotated Bitmap

  #     degree: The angle of rotation.

  #--------------------------------------------------------------------------

  def rotate(degree)

    angle = (degree*Math::PI) / 180

    cos = Math.cos(angle)

    sin = Math.sin(angle)

    point_x = [0, height*sin, width*cos - height*sin, width*cos]

    point_y = [0, height*cos, height*cos - width*sin, width*sin]

    min_x = point_x.min

    max_x = point_x.max

    min_y = point_y.min

    max_y = point_y.max

    w = max_x.abs - min_x

    h = max_y.abs - min_y

    bitmap = Bitmap.new(w.ceil, h.ceil)

    

    for x in 0...bitmap.width

      for y in 0...bitmap.height

        source_x = (x+min_x)*cos + (y+min_y)*sin

        source_y = (y+min_y)*cos - (x+min_y)*sin

        bitmap.set_pixel(x, y, get_pixel(source_x, source_y))

      end

    end

    bitmap

  end

end

But it has some errors.
First, the rotated Bitmap is larger than it should be (for example a 100x100 Bitmap which is rotated by 90° is 200x200 big after that)
And some parts of the Bitmap are cut off (http://img200.imageshack.us/img200/9483/screenpsw.png)
I hope someone can help me :3
 

Zeriab

Sponsor

Can't you get away with using a Sprite and then setting sprite.angle to what you need?
The method you have there is undoubtedly slow.

It is of course possible that you cannot get away with it, but if you can then it's an easier solution ^_^
 
Can't you get away with using a Sprite and then setting sprite.angle to what you need?
The method you have there is undoubtedly slow.

I know that it is slow ^^
But I have a lot of Sprites which have to be rotated and most of them use the same Bitmap.
I don't know if you know but a Sprite which is zoomed or rotated needs more performance ;)
 
well you should always go for the largest possible bitmap, which would be a square with the dimension of the diagonale of the original bitmap. (hypothenuse of the width and height. )
You need to be aware of where is your rotation center is, relative to the bitmap when converting the pixels' coordinates from one bitmap to the other.

Also to get a faster process, you should parse the original bitmap and paste on the rotated one instead, as the original bitmap is more likely to be smaller than the rotated one.
that also makes sure you go through all the pixels of the original bitmap.
 

Zeriab

Sponsor

Yeah I know. It says so in the help file ^_^
That's why I asked if you could get away with it.

If you have the bitmap's width, w, and height, h, then you have the length of the diagonal, d, to be:
d**2 = w**2 + h**2

*hugs*
 
ok :p here is a small snippet i've written ages ago, when i had to move a sprite to new coordinates after "rotating the camera" (where the center of rotation could be variable), you should be able to figure out how to apply it to your bitmaps

old angle is the current "angle of the camera" and "new angle" the new wanted one for the camera

[rgss] 
rx = (self.x - x_center)
ry = (self.y - y_center)
diff = Math::PI * (@old_angle-@new_angle) / 180.0
r = Math.hypot(rx, ry)
@ang = Math.atan2(ry.to_f,rx.to_f)+diff
x = r * Math.cos(@ang)
y = r * Math.sin(@ang)
self.x = x.round + x_center   # new sprite coordinates
self.y = y.round + y_center
 
[/rgss]

Hope it helps
 
you should be able to figure out how to apply it to your bitmaps
No, sorry, I am not ^^"
I tried it like this:
Code:
class Bitmap

  def rotate!(degree)

    for x in 0...bitmap.width

      for y in 0...bitmap.height

        nx, ny = rotate_pixel(x, y, Math::PI * 0-degree / 180.0)

        set_pixel(nx, ny, get_pixel(x, y))

      end

    end

  end

  

  def rotate_pixel(x, y, diff)

    rx = x-width/2

    ry = y-height/2

    r = Math.hypot(rx, ry)

    ang = Math.atan2(ry.to_f,rx.to_f)+diff

    nx = r*Math.cos(ang)

    ny = r*Math.sin(ang)

    [x.round+width/2, y.round+height/2]

  end

end

And I think it won't work because the rotated Bitmap is usually bigger than the source and that is not calculated in your code.

/edit: Didn't see the 2 postings before ^^"
well you should always go for the largest possible bitmap
I could but a bigger Bitmap means more memory. In this case useless memory.
Also to get a faster process, you should parse the original bitmap and paste on the rotated one instead, as the original bitmap is more likely to be smaller than the rotated one.
That is what I am trying to do Oo

Maybe this will help you to help me :)
The link were I got the idea from: http://www.leunen.com/cbuilder/rotbmp.html (number 3)
 
hum ok
about parsing the bitmap thing, i saw the reason why you did that in the link; and that's actually a fair point.

about your original code in your 1st post, in the point_x array, you missed a - from the C++ code.
float Point1x=(-SrcBitmap->Height*sine); => -height*sine

That may explained the problems :p
 
well that's because there is another error in your code, due to bad copy paste :p

here is the complete fixed version:
[rgss] 
class Bitmap
 
  #--------------------------------------------------------------------------
  # * Returns a rotated Bitmap
  #     degree: The angle of rotation.
  #--------------------------------------------------------------------------
  def rotate(degree)
    angle = (degree*Math::PI) / 180
    cos = Math.cos(angle)
    sin = Math.sin(angle)
    point_x = [0, -height*sin, width*cos - height*sin, width*cos]
    point_y = [0, height*cos, height*cos + width*sin, width*sin]
    min_x = point_x.min
    max_x = point_x.max
    min_y = point_y.min
    max_y = point_y.max
    w = max_x.abs - min_x
    h = max_y.abs - min_y
    bitmap = Bitmap.new(w.ceil, h.ceil)
   
    for x in 0...bitmap.width
      for y in 0...bitmap.height
        source_x = (x+min_x)*cos + (y+min_y)*sin
        source_y = (y+min_y)*cos - (x+min_x)*sin
        bitmap.set_pixel(x, y, get_pixel(source_x, source_y))
      end
    end
    bitmap
  end
end
 
 
[/rgss]

Tested and approved!
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top