Bitmap Effects

muramasa

Abomination of life, or life itself.
Veteran
Joined
Apr 29, 2012
Messages
581
Reaction score
294
First Language
Spanish
Primarily Uses
Bitmap Effects
By Orochii Zouveleki
RGSS1, tested with RGSS102J.dll

INTRODUCTION
I started doing modifications to a friend's DLL code, and I ended up doing this. Basically, it's a transparency effect. It includes a basic masking for any bitmap by using another bitmap's alpha channel, as well as a more complicated and somewhat powerful scrollable alpha masking using RGB components as alpha layers. It's kind of complicated to explain, but it lets you make something like this.


To the left, a sprite with some kind of animated outline. To the right, a single background with both scrolling alpha and static alpha layers.

CODE
http://share.cherrytree.at/showfile-31871/ozwbitmapextensions.zip
Right now all comments are in Spanish, I need to reupload it in English later. This download includes the necessary DLL, the source code for the DLL, and the wrapping code for using it in RGSS. It also includes an implementation for its easy use with Sprite. Something pretty similar can be done with Plane, but I haven't made it. You're free to do so.

COMPILING THE DLL
Any IDE should work, but just as reference I used Code::Blocks along with the GCC compiler that comes with it (version 4.7.1 if I recall correctly). Just install and open Code::Blocks, create a DLL project from it, throw the code there and you're good to go.

INSTRUCTIONS
New properties for Sprite class:
- @sprite.alpha_mask : a bitmap to be used as alpha mask.
- @sprite.alpha_mask_kind : 0 for simple mode, 1 for composite mode.
- @sprite.alpha_mask_sx : horizontal scrolling speed for the scrolling layer.
- @sprite.alpha_mask_sy : vertical scrolling speed for the scrolling layer.

AVAILABLE METHODS
Use these arbitrarily with any bitmap in order to apply alpha masking effects.
OZWBitmapExtension.simpleMask(srcBitmap, maskBitmap, targetBitmap)

srcBitmap : Source bitmap.
maskBitmap : Bitmap used for masking (multiplying alpha per pixel).
targetBitmap : The resulting bitmap will be stored here. Keep in mind, source and target must be the exact same size.
OZWBitmapExtension.compositeMask(srcBitmap, maskBitmap, targetBitmap, sx, sy)

srcBitmap : Source bitmap.
maskBitmap : Bitmap used for masking (resulting alpha = srcAlpha * (red * green + blue)).
targetBitmap : The resulting bitmap will be stored here. Keep in mind, source and target must be the exact same size.
sx : Horizontal displacement for the G layer.
sy : Vertical displacement for the G layer.
BUILDING A COMPOSITE MASK
A composite mask uses the R G and B channels sepparately for different effects. Each one of them have simple but very distinct properties.
R is the base alpha mask.
G is multiplied by R, which means if an spot in G is zero, it will result in zero.
B is added to R*G, which means it works as a threshold.

Another thing to keep in mind is that G can be scrolled by manipulating sx and sy at the compositeMask method. This is done automatically while updating the sprite by using the property implementation.

Here is an example of the alpha mask used for the example above
->


The image to the right consists of three grayscale images (shown to the left), joined together as a single image, each in a different color channel. Use Photoshop or GIMP or any program with the option to manipulate sepparate channels in order to do this.

LICENSE
MIT License.

Have a nice day. :^)
 
Last edited:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
4,712
Reaction score
5,394
First Language
Indonesian
Primarily Uses
RMVXA
Since this use external dll, can I assume it will works in other version of RGSS?
 

muramasa

Abomination of life, or life itself.
Veteran
Joined
Apr 29, 2012
Messages
581
Reaction score
294
First Language
Spanish
Primarily Uses
Yes it does. I actually use it on my game, which uses RGSS3 binaries to XP adaptation thing, and works smoothly there. Which pretty much means it works in RGSS3, and should work in RGSS2 (but I don't have old VX).

Salut!
 

ZirconStorms

VX & VX Ace Scripts
Veteran
Joined
Dec 22, 2014
Messages
355
Reaction score
112
First Language
English
Primarily Uses
RMVXA
Struggling to understand how to bring a simple mask up for picture sprites displayed on the map/in-game.
Fairly sure this would be done using script calls, but...
 

muramasa

Abomination of life, or life itself.
Veteran
Joined
Apr 29, 2012
Messages
581
Reaction score
294
First Language
Spanish
Primarily Uses
Just realized there was a reply to this. Yeah, this is a scripting library, which means you can implement that by yourself in case you want, and use this code as you wish, AND distribute it freely or whatever (all under MIT which means do as you want).

But I'm not going to implement any specific thing because I'm lazy. So yeah, sorry. :)
 

Tayruu

slate furry thing
Member
Joined
Apr 27, 2014
Messages
28
Reaction score
38
First Language
English
Primarily Uses
RM2k
This seems a really useful feature (because, I mean, masking is something RMXP/Ace is lacking) but I did find this topic and the documentation really difficult to follow. I was confused about whether to use the Sprite properties or new methods.

I did however eventually manage to recreate the minimap effect in the corner. For the sake of others, here is the code I used to demonstrate the composite mask.
Code:
#==============================================================================
# ** Window_Minimap
#==============================================================================

class Window_Minimap < Window_Base
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize()
    width = 128; height = 128
    x = 640 - width - 16
    y = 16
    super(x, y, width, height)
    self.opacity = 0
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    # Base fill
    w = 128; h = 128
    bitmap = Bitmap.new(w, h)
    bitmap.fill_rect(0, 0, w, h, Color.new(0,0,0,160))
    # Mask
    mask = Bitmap.new(w, h)
    mask.blt(0, 0, RPG::Cache.picture("masktest"), Rect.new(0, 0, w, h))
    # Sprite object
    @graphic = Sprite.new
    @graphic.bitmap = bitmap
    @graphic.x = self.x; @graphic.y = self.y; @graphic.z = self.z + 5
    # Apply mask
    @graphic.alpha_mask = mask
    @graphic.alpha_mask_kind = 1
    @graphic.alpha_mask_sx = 1
    @graphic.alpha_mask_sy = 1
    @graphic.update
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    @graphic.update
  end
  #--------------------------------------------------------------------------
  #  * Dispose Objects
  #--------------------------------------------------------------------------
  def dispose
    super
    @graphic.dispose
  end
end
Code:
# To show window in Scene_Map after @message_window lines add
    @minimap_window = Window_Minimap.new
    @minimap_window.dispose
    @minimap_window.update
# ... under equivalent lines.
tldr: Create a bitmap object for the base image and mask image, then create a Sprite image that uses the base, and use the alpha_mask properties to assign the mask image Bitmap. Make sure to set sx/sy stuff and update the Sprite if it'll animate.

It should also be noted though, the image in the first post is incorrect compared to the preview gif: the green channel should be inverted.
 

ZirconStorms

VX & VX Ace Scripts
Veteran
Joined
Dec 22, 2014
Messages
355
Reaction score
112
First Language
English
Primarily Uses
RMVXA
This seems a really useful feature (because, I mean, masking is something RMXP/Ace is lacking) but I did find this topic and the documentation really difficult to follow. I was confused about whether to use the Sprite properties or new methods.

I did however eventually manage to recreate the minimap effect in the corner. For the sake of others, here is the code I used to demonstrate the composite mask.
Code:
#==============================================================================
# ** Window_Minimap
#==============================================================================

class Window_Minimap < Window_Base
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize()
    width = 128; height = 128
    x = 640 - width - 16
    y = 16
    super(x, y, width, height)
    self.opacity = 0
    refresh
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    # Base fill
    w = 128; h = 128
    bitmap = Bitmap.new(w, h)
    bitmap.fill_rect(0, 0, w, h, Color.new(0,0,0,160))
    # Mask
    mask = Bitmap.new(w, h)
    mask.blt(0, 0, RPG::Cache.picture("masktest"), Rect.new(0, 0, w, h))
    # Sprite object
    @graphic = Sprite.new
    @graphic.bitmap = bitmap
    @graphic.x = self.x; @graphic.y = self.y; @graphic.z = self.z + 5
    # Apply mask
    @graphic.alpha_mask = mask
    @graphic.alpha_mask_kind = 1
    @graphic.alpha_mask_sx = 1
    @graphic.alpha_mask_sy = 1
    @graphic.update
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    @graphic.update
  end
  #--------------------------------------------------------------------------
  #  * Dispose Objects
  #--------------------------------------------------------------------------
  def dispose
    super
    @graphic.dispose
  end
end
Code:
# To show window in Scene_Map after @message_window lines add
    @minimap_window = Window_Minimap.new
    @minimap_window.dispose
    @minimap_window.update
# ... under equivalent lines.
tldr: Create a bitmap object for the base image and mask image, then create a Sprite image that uses the base, and use the alpha_mask properties to assign the mask image Bitmap. Make sure to set sx/sy stuff and update the Sprite if it'll animate.

It should also be noted though, the image in the first post is incorrect compared to the preview gif: the green channel should be inverted.
Testing this with VX Ace, for some reason the @graphic.alpha_mask_sx = 1 and @graphic.alpha_mask_sy = 1 values don't work.

What's the biggest difference with going and manually using these properties vs using OZWBitmapExtension.compositeMask(srcBitmap, maskBitmap, targetBitmap, sx, sy)?
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

What can I sing for my sisters birthday...?

>.<'
Well, I'll have you know that I'm still around, looking for opportunity to resurface with some stuffs.
I like to think of Profile Posts as tiny homes, full of all kinds of unsuspecting suckers "future" friends.... Many of which are of course only going to be excited when a strange man in black suddenly shows up to say hi. :LZSexcite:
Stream will be live shortly with some more Haunting Ground! Today, we encounter a new stalker! Feel free to drop by!
Tried the new Samsung Galaxy S20 Plus today. Very nice device overall, but flagship smartphone prices are getting completely out of control.

Forum statistics

Threads
94,504
Messages
921,491
Members
124,362
Latest member
hogogopfu01
Top