キャラと背景の合成(重ね合わせ)

少し前にゲームを作る機会が有りその時に覚えたテクニックを紹介します。


 

  背景とキャラを重ね合わせる場合、背景のCGとキャラのCGの他にマスクCGと呼ばれる
ものが必要になります。マスクCGはキャラCGを黒く塗ったものです。多くの解説書ではこの
マスクCGを自分で用意するように書かれているのですが、いちいち作るのは面倒です。
そこで、プログラムの内部でこれを作らせて重ね合わせをおこないたいと思います。

'=============Win32APIの宣言========================
Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long
Declare Function SetBkColor Lib "gdi32" (ByVal hdc As Long, ByVal crColor As Long) As Long
Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

'======構造体=======
Public Type RECT
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
End Type

'=====ラスターオペレーション===========================
'D:コピー先 S:コピー先 P:ブラシ

Public Const SRCCOPY = &HCC0020 'S
Public Const SRCAND = &H8800C6 'S And D
Public Const SRCINVERT = &H660046 'S Xor D
Public Const SRCERASE = &H440328 'Not(D) And S
Public Const SRCPAINT = &HEE0086 'S Or D
Public Const BLACKNESS = &H42 '黒で塗りつぶす
Public Const DSTINVERT = &H550009 'Not D
Public Const MERGECOPY = &HC000CA 'S And P
Public Const MERGEPAINT = &HBB0226 'Not(S) Or D
Public Const NOTSRCCOPY = &H330008 'Not(S Or D)
Public Const PATCOPY = &HF00021 'ブラシで塗りつぶす
Public Const PATINVERT = &H5A0049 'P Xor D
Public Const PATPAINT = &HFB0A09 '(P Or Not(S)) Or D
Public Const WHITENESS = &HFF0062 '白で塗りつぶす


'==================合成(重ね合わせ)関数================
Public Sub Transmit(OutPicDC As Long, BackDC As Long, ChrDC As Long, picrect As RECT, x As Integer, y As Integer, TC As Long)
' OutPicDC 出力先のデバイスコンテキスト(hDC)
' BackDC , ChrDC 背景、キャラのデバイスコンテキスト(hDC)
' picrect 合成領域
' x , y 表示場所
' TC 透過色

' ====変数の宣言======================================
  Dim R As Long 'API戻り値
  Dim ChrWidth As Long, ChrHeight As Long '画像サイズ
  Dim MaskDC 'マスクCGのDC
  Dim hMask 'マスクCGのハンドル
  Dim MaskInvDC As Long, hMaskinv As Long 'ワーク(反転)
  Dim rBackDC As Long, hBack As Long
  Dim rChrDc As Long, hChr As Long
  Dim hObjMask As Long, hObjMaskinv As Long
  Dim hObjBack As Long, hObjChr As Long
  Dim Old As Long

' ====サイズの設定====================================
  ChrWidth = (picrect.Right - picrect.Left)
  ChrHeight = (picrect.Bottom - picrect.Top)

' ====マスクCGの作成=================================
  MaskDC = CreateCompatibleDC(BackDC)
  MaskInvDC = CreateCompatibleDC(BackDC)

  hMask = CreateBitmap(ChrWidth, ChrHeight, 1, 1, ByVal 0&)
  hMaskinv = CreateBitmap(ChrWidth, ChrHeight, 1, 1, ByVal 0&)

  hObjMask = SelectObject(MaskDC, hMask)
  hObjMaskinv = SelectObject(MaskInvDC, hMaskinv)
' ====================================================

  rBackDC = CreateCompatibleDC(BackDC)
  rChrDc = CreateCompatibleDC(ChrDC)

  hBack = CreateCompatibleBitmap(BackDC, ChrWidth, ChrHeight)
  hChr = CreateCompatibleBitmap(ChrDC, ChrWidth, ChrHeight)

  hObjBack = SelectObject(rBackDC, hBack)
  hObjChr = SelectObject(rChrDc, hChr)

  Old = SetBkColor(ChrDC, TC)
  R = BitBlt(MaskDC, 0, 0, ChrWidth, ChrHeight, ChrDC, 0, 0, SRCCOPY)
  TC = SetBkColor(ChrDC, Old)
  R = BitBlt(MaskInvDC, 0, 0, ChrWidth, ChrHeight, MaskDC, 0, 0, NOTSRCCOPY)

  R = BitBlt(rBackDC, 0, 0, ChrWidth, ChrHeight, BackDC, x, y, SRCCOPY)
  R = BitBlt(rBackDC, 0, 0, ChrWidth, ChrHeight, MaskDC, 0, 0, SRCAND)
  R = BitBlt(rChrDc, 0, 0, ChrWidth, ChrHeight, ChrDC, 0, 0, SRCCOPY)
  R = BitBlt(rChrDc, 0, 0, ChrWidth, ChrHeight, MaskInvDC, 0, 0, SRCAND)
  R = BitBlt(rBackDC, 0, 0, ChrWidth, ChrHeight, rChrDc, 0, 0, SRCINVERT)
  R = BitBlt(OutPicDC, x, y, ChrWidth, ChrHeight, rBackDC, 0, 0, SRCCOPY)

' ====後始末=====================================================
  hMask = SelectObject(MaskDC, hObjMask)
  DeleteObject hMask
  hMaskinv = SelectObject(MaskInvDC, hObjMaskinv)
  DeleteObject hMaskinv
  hBack = SelectObject(rBackDC, hObjBack)
  DeleteObject hBack
  hChr = SelectObject(rChrDc, hObjChr)
  DeleteObject hChr

  DeleteDC MaskDC
  DeleteDC MaskInvDC
  DeleteDC rBackDC
  DeleteDC rChrDc
' ================================================================

End Sub

結構複雑ですが、ゲームを作るときには役に立つと思います。
使うには、スケールモードをピクセルにして

TColor=ChrPic.Point(0,0)
With PR
  .Left=0
  .Right=120
  .Top=0
  .Bottom=120
End With
Transmit ShowPic.hDC , BackPic.hDC , ChrPic.hDC , PR , 0 , 0 , TColor

というようにします。
この場合は、120×120のサイズでShowPicの(0,0)の位置にBasePicを背景にChrPicをキャラ、キャラCGの左上の色を透過色として重ね合わせて表示します。
実は、Windows98から同様のAPI関数が追加されたようです。そこで、次回はWin98ならばそのAPI関数を、その関数が使えない場合はこのTransmit関数を使うプログラムを書こうと思います。
  

戻る