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.

Ruby BitBlt?

Hey guys,
I am looking for a way to use the Win32::BitBlt function inside of RPG Maker. I would be happy to make a DLL in C, but I dont know C at all :(. The reason I want BitBlt functionality is that using it I should be able to combine multiple images quickly using the various rastor methods. I am attempting to do what this script does already: viewtopic.php?f=11&t=74494, but faster so that we can do live updates (almost per frame) and such.

Via C DLL?
I did happen to find the following: viewtopic.php?f=11&t=42375&start=39 where this Bitmap.dll was created (and actual C code is below for the DLL).

Via Ruby?
Here is another outside thread, but being that we dont have access to 'require' methods and such, I dont know how helpful this will be in RPG maker. But perhaps it can help in the other as well?
https://github.com/jarmo/win32screenshot

The question is can I implement the BitBlt function into it, and how? Sorry, I just dont know where to start.
~GubiD
 
Well, I suppose I will just have to learn some C after all. Unless someone else has anything to offer for suggestions?
 
Well I don't want to sound like know-it-all but Win32::BitBlt IS actually Bitmap.blt in RGSS and wether you use DLL or RGSS Bitmap actually doesn't make much difference since GDI is really slow when it comes to performance critical rendering.

Your best bet is to try and find some use of OpenGL or DirectX to get performance critical rendering, so yes you are gonna have to learn some C++/C# after all. XD

And also you're gonna need to code your own Bitmap and Sprite classes to completely exploit those functions, so you pretty much can see why people don't wanna do it. :)

Your best bet is to try and use Bitmap.blt best way you can :)
 
The only problem is that bitmap.blt doesnt give the other blending options. blt is fast enough for what I need, it just always does the SRCCOPY method rather than say.. OR and invert.

While I can do this manually via a similar method used above for the color replacement thing in 'bitmap.dll', it just wouldnt be as fast of bitblt.

2 days ago, I noticed that Zues81 wrote the following for a wavy screen script(below), which exercises bitblt via ruby. I am trying to adapt it to my needs, but I just need to know how to read my bitmap object into memory so that it can be used rather than taking a screenshot. I am guessing that the MoveMemory command is what I am looking for, but again, not really sure since I am not familiar with C.

Code:
 

    module Graphics

      FindWindow = Win32API.new('user32', 'FindWindow', 'pp', 'i')

      GetDC = Win32API.new('user32', 'GetDC', 'i', 'i')

      ReleaseDC = Win32API.new('user32', 'ReleaseDC', 'ii', 'i')

      RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')

      BitBlt = Win32API.new('gdi32', 'BitBlt', 'iiiiiiiii', 'i')

      CreateCompatibleBitmap = Win32API.new('gdi32', 'CreateCompatibleBitmap', 'iii', 'i')

      CreateCompatibleDC = Win32API.new('gdi32', 'CreateCompatibleDC', 'i', 'i')

      DeleteObject = Win32API.new('gdi32', 'DeleteObject', 'i', 'i')

      GetDIBits = Win32API.new('gdi32', 'GetDIBits', 'iiiiipi', 'i')

      SelectObject = Win32API.new('gdi32', 'SelectObject', 'ii', 'i')

      def self.snap_to_bitmap

        bmp = Bitmap.new(w=640, h=480)

        bmp_info = [40,w,h,1,32,0,0,0,0,0,0].pack('LllSSLLllLL')

        RtlMoveMemory_pi.call(bmp_address="\0"*4, bmp.__id__*2+16, 4)

        RtlMoveMemory_pi.call(bmp_address, bmp_address.unpack('L')[0]+8, 4)

        RtlMoveMemory_pi.call(bmp_address, bmp_address.unpack('L')[0]+16, 4)

        bmp_address = bmp_address.unpack('L')[0]

        hWndDC = GetDC.call(hWnd=FindWindow.call('RGSS Player', 0))

        hMemDC = CreateCompatibleDC.call(hWndDC)

        hMemBM = CreateCompatibleBitmap.call(hWndDC, w, h)

        SelectObject.call(hMemDC, hMemBM)

        BitBlt.call(hMemDC, 0, 0, w, h, hWndDC, 0, 0, 0xCC0020)

        GetDIBits.call(hMemDC, hMemBM, 0, h, bmp_address, bmp_info, 0)

        DeleteObject.call(hMemBM)

        DeleteObject.call(hMemDC)

        ReleaseDC.call(hWnd, hWndDC)

        bmp

      end

    end
 
Well Bitmap class itself doesn't have it, but Sprite class has something similar.

blend_type (0: normal, 1: addition, 2: subtraction).

And blt has a opacity so you can quite emulate what you need with it, depending on what you want. :)
 
I played with that option, but it doesnt work the way you are thinking. It actually only applies to the color.set mask. Nothing else. I was hoping that all these being in a particular viewport etc might do the trick, but it didnt.
But good news, I was able to get it to work with some of Zues81's help. Using this I have been able to extend that I wanted. Being that it requires the actual rastor code its still a little annoying, but I got it to work for my needs. I actually setup a looping raster code array that would go through every option in the raster tree of commands.

[rgss] 
# Script by Zues81
class Bitmap
  RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  FindWindow = Win32API.new('user32', 'FindWindow', 'pp', 'i')
  GetDC = Win32API.new('user32', 'GetDC', 'i', 'i')
  ReleaseDC = Win32API.new('user32', 'ReleaseDC', 'ii', 'i')
  BitBlt = Win32API.new('gdi32', 'BitBlt', 'iiiiiiiii', 'i')
  CreateCompatibleBitmap = Win32API.new('gdi32', 'CreateCompatibleBitmap', 'iii', 'i')
  CreateCompatibleDC = Win32API.new('gdi32', 'CreateCompatibleDC', 'i', 'i')
  DeleteObject = Win32API.new('gdi32', 'DeleteObject', 'i', 'i')
  GetDIBits = Win32API.new('gdi32', 'GetDIBits', 'iiiiipi', 'i')
  SelectObject = Win32API.new('gdi32', 'SelectObject', 'ii', 'i')
  SetDIBits = Win32API.new('gdi32', 'SetDIBits', 'iiiiipi', 'i')
 
  def address
    unless @address
      RtlMoveMemory_pi.call(a="\0"*4, __id__*2+16, 4)
      RtlMoveMemory_pi.call(a, a.unpack('L')[0]+8, 4)
      RtlMoveMemory_pi.call(a, a.unpack('L')[0]+16, 4)
      @address = a.unpack('L')[0]
    end
    return @address
  end
  def bitblt(x, y, src_bmp, src_rect, rastor_operation)
    hDC1, hBM1, info = *self.BltApiInit
    hDC2, hBM2 = *src_bmp.BltApiInit
       
    BitBlt.call(hDC1, x, y, src_rect.width, src_rect.height,
                hDC2, src_rect.x, src_rect.y, rastor_operation)
    GetDIBits.call(hDC1, hBM1, 0, height, address, info, 0)
    DeleteObject.call(hBM1); DeleteObject.call(hDC1)
    DeleteObject.call(hBM2); DeleteObject.call(hDC2)
  end
  def BltApiInit
    info = [40,width,height,1,32,0,0,0,0,0,0].pack('LllSSLLllLL')
    hWndDC = GetDC.call(hWnd=FindWindow.call('RGSS Player', 0))
    hMemDC = CreateCompatibleDC.call(hWndDC)
    hMemBM = CreateCompatibleBitmap.call(hWndDC, width, height)
    ReleaseDC.call(hWnd, hWndDC)
    SelectObject.call(hMemDC, hMemBM)
    SetDIBits.call(hMemDC, hMemBM, 0, height, address, info, 0)
    return hMemDC, hMemBM, info
  end
end
[/rgss]
 

Star

Sponsor

Just tell me what we need to update to the script if we're making changes, bro and I'll change it right up. If you get this done, we can refresh lights easier and have lights flicker etc if wanted.

Glad you're making progress, as far as what I'm doing, I'm trying to make shadows for objects that move during the position of the sun. Getting there slowly
 
I already made the base changes to the script that implement it. But now we need to set up another group of events that handle movement (as in they are updated on the overlay bitmap more often) Because its all done with a bitblt now, it should be incredibly much faster.

I am sure you noticed this already, but when doing the bitblt it causes some artifacts to be created in the overlap area's. This is do to the fact that its adding the area together and ends up breaking the 255 value for the opacity. My understanding from a buddy of mine, is that there is a method of running multiple bitblts over the image in order to 'reduce' not remove this effect and still be loads faster than the current method we are using to subtract the alpha channel. I am still exploring that in hopes of finding something that might do it. I have been exploring other options that may not be quite as fast as the bitblt but still similar in speed but cleaner. But I will keep you apprised of that.

Have you tried to run that updated demo I posted? When I run it on my XP computer, it just has big opaque sqaures where all the blended stuff should be. But when I do the same thing in Windows 7, I get the following:
lightingtest1.png

And yeah, you see that overlap, that is what I was talking about when I said you would see what I was talking about.

Obviously I am expecting the same result as I am getting in Windows 7, but that doesnt seem to be the case.
 

Star

Sponsor

Gubid":1mz2fn7f said:
Have you tried to run that updated demo I posted? When I run it on my XP computer, it just has big opaque squares where all the blended stuff should be. But when I do the same thing in Windows 7, I get the following:
And yeah, you see that overlap, that is what I was talking about when I said you would see what I was talking about.

Obviously I am expecting the same result as I am getting in Windows 7, but that doesn't seem to be the case.
I didn't even notice that you had posted there o.o!

I just checked it out and yeah, I'm getting the same thing as your image with windows vista. Your coding strangely reminds me of doing the gameshark codes in pokemon games. or any games. As far as helping you with a method, I can try to look at it but, I think you're making good enough progress that you'll find it eventually. :thumb:
 

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