ExcelVBAゲームプログラミング?

初心者でもきっとできる!
Excelさえ持っていれば特別なソフトは不要!
すぐにでも始められる簡単ゲームプログラミング!
今すぐ始めよう!

サンプルやゲームのダウンロードができる別館も好評運営中です。
ご意見やご質問、ゲームの感想等は掲示板までお気軽に。是非、皆さんの声を聞かせてください。運営、開発の励みになります。



各種ダウンロードはコチラ ↓ 意見・感想・質問はコチラ ↓
影倉庫 Shadow warehouse サポート掲示板
ブログの全体像はコチラ ↓ リンクのページはコチラ ↓
サイトマップ 自分本位なリンク


スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。






Chapter.137 [ APIによる描画処理9:ラスタオペレーション ]

■ラスタオペレーション

前回は、ビットマップのビットブロック転送について、多少本格的に解説しました。
簡単な画像一枚描画するだけなのに、随分と大変な準備が必要でしたね。まぁこればっかりは、何度も言っているように、API による処理の宿命でもありますので、慣れるより他ありません。

前回の講座の内容がかなり盛りだくさんだったので、全てをくまなく理解するのは大変かもしれませんが、厳しいことを言ってしまえば、前回の内容をクリアできないようでは、この先の講座内容にはついてこれないかもしれません。
もし、少しでも不安が残るというかたは、面倒に感じるかもしれませんが、サンプルファイルなどを手直ししたりしつつ前回の内容をしっかり理解してから先に進むことをオススメします。

さて、今回は前回、前々回と利用した BitBlt 関数についてさらに詳細に解説していきます。というより、もっとはっきり言ってしまえば、BitBlt 関数の最終引数に指定するラスタオペレーションについて、詳しく見ていきます。

BitBlt 関数は非常に多機能な API で、本当に様々な描画処理をこの関数ひとつで実現することができます。そしてその多彩な描画方法を指定する方法が、他ならぬラスタオペレーションなのですね。

前回は単純にメモリデバイスコンテキストに割り当てたビットマップをそのまま転送しました。要は、単にコピーしただけの処理ですね。今回は、代表的なラスタオペレーションを紹介すると共に、それぞれどんな描画になるのか、解説したいと思います。

今回は、かなり画像が多くなりました。いやー、大変でした。
まぁ、苦労した分、有意義な講座になっているといいんですが。


■まずはざっくり見てみよう

それでは、まず最初にラスタオペレーションの一覧を見てみましょう。
結構、これを見るだけでもゾッとするかもしれませんね……。

SRCCOPY = &HCC0020
SRCPAINT = &HEE0086
SRCAND = &H8800C6
SRCINVERT = &H660046
SRCERASE = &H440328
NOTSRCCOPY = &H330008
NOTSRCERASE = &H1100A6
MERGECOPY = &HC000CA
MERGEPAINT = &HBB0226
PATCOPY = &HF00021
PATPAINT = &HFB0A09
PATINVERT = &H5A0049
DSTINVERT = &H550009
BLACKNESS = &H42
WHITENESS = &HFF0062

随分たくさんありますね。しかし、驚くなかれ、これで全てではありません。まぁでも、ここに紹介したものであっても、全てを覚える必要は正直言ってないです。代表的なところだけ覚えているだけで十分なのですが、せっかくなので一通り紹介します。

さて、それでは各ラスタオペレーションの意味を見てみましょう。

定数名詳細
SRCCOPYコピー元からコピー先へそのままコピーする
SRCPAINTOR演算子でコピー元の色とコピー先の色を組み合わせる
SRCANDAND演算子でコピー先の色とコピー元の色を組み合わせる
SRCINVERTXOR演算子でコピー先の色とコピー元の色を組み合わせる
SRCERASEAND演算子で、コピー先の色を反転した色とコピー元の色を組み合わせる
NOTSRCCOPY色を反転してコピーする
NOTSRCERASEOR演算子でコピー先の色とコピー元の色を組み合わせ反転する
MERGECOPYAND演算子でコピー元の色とコピー先の色を組み合わせる
MERGEPAINTOR演算子でコピー元の色を反転した色とコピー先の色を組み合わせる
PATCOPY指定したパターンをコピーする
PATINVERTXOR演算子で指定したパターンの色とコピー元の色を組み合わせる
PATPAINTOR演算子で指定したパターンの色とコピー元の色を反転した色を組み合わせ、さらにOR演算子でそれとコピー先の色を組み合わせる
DSTINVERTコピー先の矩形を反転する
BLACKNESS物理的パレットのインデックス0に関連してる色(規定値では黒)でコピー先矩形を塗りつぶす
WHITENESS物理的パレットのインデックス1に関連してる色(規定値では白)でコピー先矩形を塗りつぶす


はい、こちらもかなり盛りだくさんですね。
しかも、パッと見ただけでは、意味がよくわからないと思います。ただ、AND や OR などの論理演算の意味をゼロから解説するよりも、まずは実際に描画した場合にどうなるのかを、見た目でイメージしてもらったほうが理解しやすいと思います。

というわけで、ここからは描画イメージを一気に載せていきます。
また、理由は後述しますが、背景が黒の場合と白の場合を掲載します。

ラスタオペレーションに関しては、なるべくカラフルな画像を描画したほうが違いを把握しやすいと思われますので、描画する画像ファイルは次のものを使います。

856.png

ちなみに、この画像は png 形式ですが、実際に描画に使っているのは bmp 形式の画像ファイルです。

それでは、一気にいきます。

黒背景白背景
811.png826.png
812.png827.png
813.png828.png
814.png829.png
815.png830.png
816.png831.png
817.png832.png
818.png833.png
819.png834.png
820.png835.png
821.png836.png
822.png837.png
823.png838.png
824.png839.png
825.png840.png


さて、どうですか。
背景が黒の場合と、白の場合で随分結果が違っていると感じたのではないでしょうか。もし、随分違っているなぁと感じなかったとしたら、むしろそこは、違うなぁと感じて欲しいところです。

実は、この背景色の違いによって描画結果が大きく変化するというのがポイントで、このような仕組みがあるからこそ、BitBlt 関数ひとつで背景透過処理などを実装することができます。

どういうことかと言えば、先ほどのラスタオペレーションの詳細を思い出してみてください。SRCPAINT と、SRCAND のふたつのラスタオペレーションは、どのように説明されていたでしょうか。

 SRCPAINT = OR 演算子でコピー元の色とコピー先の色を組み合わせる
 SRCAND = AND 演算子でコピー元の色とコピー先の色を組み合わせる

AND と OR と言えば、プログラマーにはお馴染みの論理演算ですよね。
双方共に真のときに解が真となる AND、いずれかが真であれば解も真となる OR。先ほどの描画結果をよーく見ると、この演算の仕組みが少しだけ理解できるかもしれません。

812.png827.png
813.png828.png


これを見てもまだピンとこない方もいらっしゃるでしょうから、ここはズバリ、核心を言ってしまいましょう。

これらの SRCPAINT SRCAND といったラスタオペレーションを用いることによって、背景色を透過しての描画処理を行うことが可能です。

そしてさらにわかりやすく言ってしまえば、SRCPAINT で描画した場合には黒が透過されます。逆に、SRCAND で描画した場合には白が透過されます。
このラスタオペレーションの特徴をうまく活用することで、描画能力は飛躍的にアップし、キャラチップなどを描いた一枚のビットマップから、特定の色だけを透過してキャラクターのみを画面上に描画したりすることも可能です。

まぁその話は今後、別の講座でしっかり取り上げますのでいったん置いておくとして、もう少し、各ラスタオペレーションの描画結果について詳細に見ていきましょう。


■背景によってこんなにも結果が変わる

先ほどは、背景が黒一色の場合と、白一色の場合の描画結果を載せました。
微妙に描画結果が違っていたりしてましたが、それでは、白黒以外の色が背景だった場合はどうなるのでしょう。

何も描画されなくなる?

それとも半透明になってしまうとか?

なんとなく、気になりますね。

まぁ、これは先ほどのラスタオペレーションの説明(一覧表にしたやつです)をよく見ればわかりますが、ラスタオペレーションの種類によっては、色が混ざり合った状態で描画されたり、あるいは、全くなにも描画されなかったりします。

正直なところ、白黒背景よりも、背景がカラフルだった場合のほうが、描画結果は興味深い状態になります。せっかくなので、ここはそれも載せちゃいましょう。

今回は、背景にまず、以下の画像を敷き詰めます。

857.png

そのあと、その上から先ほどの画像を同じようにラスタオペレーションを変えながら描画してみます。白黒背景の場合とは打って変わってなかなか面白いことが起こります。


SRCCOPY841.png
SRCPAINT842.png
SRCAND843.png
SRCINVERT844.png
SRCERASE845.png
NOTSRCCOPY846.png
NOTSRCERASE847.png
MERGECOPY848.png
MERGEPAINT849.png
PATCOPY850.png
PATPAINT851.png
PATINVERT852.png
DSTINVERT853.png
BLACKNESS854.png
WHITENESS855.png


はい、どうですか。
かなり興味深いことになっていますね。

半透明になったり、色が反転していたり、あるいは何も描画されていなかったり。

ラスタオペレーションの意味を正しく理解していると、これらの描画結果にも、きちんと納得できます。ただ個人的には、そこはあんまり深く考えなくてもいいと思っています。全てのラスタオペレーションについて完璧に理解する必要はないと思うわけです。

なぜかと言えば、実際にゲームで使用することがあるのは、せいぜい SRCCOPY SRCPAINT SRCAND NOTSRCCOPY くらいだからです。

先ほども書いたように、透過処理を行なうためには、ただ単純にビットマップをコピーして転送する SRCCOPY 以外に、いくつかのラスタオペレーションを組み合わせて使う必要があります。しかし、逆に言ってしまえば、さっき挙げたほんのいくつかのラスタオペレーション以外のものを使う機会は、現実的にはほとんどありません。

予備知識として、このラスタオペレーションで描画すればこんなことが起こるんだなぁと、ざっくりと知っていることは損にはならないでしょう。あまり深く考えすぎず、軽い気持ちで見ていただければそれでいいと思います。

補足コラム:その他のラスタオペレーション

今回、白黒とカラーの背景で、各ラスタオペレーションの描画結果を掲載しましたが、いくつかのラスタオペレーションでは、背景云々ではなく、ずっと描画結果が変わってないものがあることに気が付いた人もいるでしょう。ここでは本編で解説しきれなかったいくつかのラスタオペレーションについて、簡単にですが、補足します。

:PATCOPY・PATPAINT・PATINVERT
これらの PAT から始まるラスタオペレーションでは、画像を転送しても何も描画されません。描画されるのは、デバイスコンテキストに割り当てられているパターン、つまり、パターンブラシです。そう、ブラシが描画されるラスタオペレーションなんですね。
ブラシとは言っても、あくまでもパターンブラシですので、もし使ってみたいという場合にはパターンブラシの生成方法から理解する必要があります。本講座では取り扱いませんが、自分でもやってみたことがなかったので試しにやってみたら、ちゃんとできました。ちなみに、ブラシは転送元のメモリデバイスコンテキストではなく、ユーザーフォームの側のデバイスコンテキストに割り当てたものが使われます。

:DSTINVERT
転送先の指定領域の色を全て反転させます。これも、転送元は関係ないラスタオペレーションですね。

:BLACKNESS・WHITENESS
これは定数名からも、なんとなく想像付きますね。単純に、黒や白で指定領域を塗り潰します。少し話が飛躍しますが、APIを用いた描画処理においては、ループするたびに背景を一度初期化(全ての領域を一度黒などで塗り潰しリセットすること)をしなければならない場合があります。そういった場合に活躍するラスタオペレーションと言えるでしょう。こちらのラスタオペレーションも、やはり転送元が関係しないタイプですね。

上記のいくつかの転送元が影響を与えないラスタオペレーションでは、BitBlt関数の引数に、転送元を指定する必要がありませんね。実際問題を書いてしまうと、仮に転送元のデバイスコンテキストを指定しても無視されるわけですが、基本的にはvbNullというVBの組み込み定数を与えるのが正しい記述と言えます。



■まとめ

さて、いかがでしたでしょうか。
BitBlt 関数とラスタオペレーションの不思議を、じっくり堪能できたのではないかと思います。

正直、ちょっと難しい話なので、いまいちよくわからないよという人もいるのではないかと思っています。ただ、ラスタオペレーションに関しては、特殊な処理でもしない限りは、それほど理解が深くなくてもいいと思っています。
ラスタオペレーションにおいて重要なのは、意味よりもむしろ使い方です。どのラスタオペレーションを用いると、いったいなにが実現できるのか。その答えさえ知っていれば、それでいいのではないかと個人的には思います。

途中で少し話題にしましたが、BitBlt 関数を駆使すれば、背景を透過してキャラクターなどを描画する、いわゆるマスク処理を行なうことが可能です。これには、いくつかのラスタオペレーションを組み合わせて用いる必要がありますが、 BitBlt 関数一本で実現できる処理です。

AND だの OR だの、よくわかんねーよ! という人でも、やり方さえわかってしまえば、BitBlt 関数ひとつでマスク処理はできます。もちろん、理解しているほうが良いに決まっていますが、そこは割り切って覚えてしまうというのもひとつの手です。
私個人は、意味まで理解したくなってしまうタイプなのですが、別に、理解はあとからでもいいと思いますし、まずは使い方を理解し、何度か使ううちに理解するのだって、間違いではないでしょう。

焦らず、じっくりと、取り組んでいただけたらと思います。



■格言

ラスタオペレーションを変えることで様々な描画結果が得られる
背景の状態によって描画結果は様々な影響を受ける


次回はいよいよマスク描画をやります。難しい話になるかもしれませんが、今回までの内容をしっかり理解していることが重要になりますので、がんばりましょう。

関連記事






Comment

Name
E-mail
URL
Comment
Pass  *
Secret? (管理者にだけ表示)
このコメントは管理者の承認待ちです
  • #
  • 2017.04.08(Sat)
  • Edit

メールフォーム

影斬に物申すという方はこちら

名前 :
メール:
件名 :
本文 :

可能な限り要望には応えますが、必ず返信や回答ができることを、保障するものではありません。
ご了承ください。

Chapters

コンテンツ一覧


■Chapter 一覧■
    全てのChapterの一覧です。
    直接アクセスしたい方はこちらをご利用下さい。

    Chapter.1 [ 知っておくべき心得 ]
    Chapter.2 [ Excelってなんだろう ]
    Chapter.3 [ Excelの基本画面 ]
    Chapter.4 [ VBAとは? ]
    Chapter.5 [ モジュールについて ]
    Chapter.6 [ 変数 ]
    Chapter.7 [ 変数の型と宣言 ]
    Chapter.8 [ プロシージャとスコープ ]
    Chapter.9 [ ゲームつくる様々な手法 ]
    Chapter.10 [ ユーザーフォーム ]
    Chapter.11 [ プロパティウィンドウ ]
    Chapter.12 [ 乱数 ]
    Chapter.13 [ 条件分岐 ]
    Chapter.14 [ ゲーム画面のデザイン ]
    Chapter.15 [ コード記述の基本作法 ]
    Chapter.16 [ じゃんけんゲーム:1 名前をつける ]
    Chapter.17 [ じゃんけんゲーム:2 フォームの起動 ]
    Chapter.18 [ じゃんけんゲーム:3 乱数の種 ]
    Chapter.19 [ じゃんけんゲーム:4 イベント ]
    Chapter.20 [ じゃんけんゲーム:5 引数 ]
    Chapter.21 [ じゃんけんゲーム:6 役判定 ]
    Chapter.22 [ じゃんけんゲーム:7 予測と制限 ]
    Chapter.23 [ Withステートメント ]
    Chapter.24 [ 画像を表示させる ]
    Chapter.25 [ 画像表示の発展形 ]
    Chapter.26 [ 繰り返し処理 For文 ]
    Chapter.27 [ 繰り返し処理 Do~Loop文 ]
    Chapter.28 [ Exitステートメント ]
    Chapter.29 [ フォーム上の位置情報 ]
    Chapter.30 [ API基礎知識 ]
    Chapter.31 [ API補足知識 ]
    Chapter.32 [ メインループを考える ]
    Chapter.33 [ 同期処理の概念 ]
    Chapter.34 [ 移動処理その1:画面設定と考え方 ]
    Chapter.35 [ 移動処理その2:DoEvents ]
    Chapter.36 [ 移動処理その3:キー入力判定API ]
    Chapter.37 [ 条件分岐のさらなる探求 Select Case ]
    Chapter.38 [ アニメーション ]
    Chapter.39 [ 配列変数 ]
    Chapter.40 [ ゲームの初期化 ]
    Chapter.41 [ シューティングゲーム1:ゲーム設計 ]
    Chapter.42 [ シューティングゲーム2:メインプロセス ]
    Chapter.43 [ シューティングゲーム3:構造体 ]
    Chapter.44 [ シューティングゲーム4:定数 ]
    Chapter.45 [ シューティングゲーム5:プレイヤーキャラクター ]
    Chapter.46 [ シューティングゲーム6:ショットを撃つ① ]
    Chapter.47 [ シューティングゲーム7:ショットを撃つ② ]
    Chapter.48 [ シューティングゲーム8:Mod演算子の活用 ]
    Chapter.49 [ シューティングゲーム9:敵キャラクター登場 ]
    Chapter.50 [ シューティングゲーム10:衝突判定 ]
    Chapter.51 [ シューティングゲーム11:衝突の実体 ]
    Chapter.52 [ シューティングゲーム12:敵の攻撃 ]
    Chapter.53 [ シューティングゲーム13:爆発エフェクト ]
    Chapter.54 [ シューティングゲーム14:残機数表示① ]
    Chapter.55 [ シューティングゲーム15:残機数表示② ]
    Chapter.56 [ シューティングゲーム16:スコアの表示 ]
    Chapter.57 [ シューティングゲーム17:タイトル画面 ]
    Chapter.58 [ シューティングゲーム18:ボスキャラクター ]
    Chapter.59 [ シューティングゲーム19:最後の仕上げへ ]
    Chapter.60 [ シューティングゲーム20:いよいよ完成STG ]
    Chapter.61 [ カードゲームで使えるめくり効果 ]
    Chapter.62 [ ラジアンと角度 ]
    Chapter.63 [ ラジアンの活用:円運動 ]
    Chapter.64 [ ラジアンの活用:任意の角度へ移動する ]
    Chapter.65 [ APIによるサウンド再生:基礎 ]
    Chapter.66 [ APIによるサウンド再生:MIDIと多重再生 ]
    Chapter.67 [ APIによるサウンド再生:MCIコマンドとループ再生 ]
    Chapter.68 [ Function プロシージャ ]
    Chapter.69 [ 値渡しと参照渡し ]
    Chapter.70 [ デバッグ1:イミディエイトウィンドウ ]
    Chapter.71 [ デバッグ2:ローカルウィンドウ ]
    Chapter.72 [ デバッグ3:コード実行の中断 ]
    Chapter.73 [ オブジェクトってなんだ ]
    Chapter.74 [ プロパティ・メソッド・イベント ]
    Chapter.75 [ オブジェクト変数 ]
    Chapter.76 [ オブジェクトとコレクション ]
    Chapter.77 [ 特殊な繰り返し:For Each ]
    Chapter.78 [ エラー処理 ]
    Chapter.79 [ On Error と GoTo文 ]
    Chapter.80 [ Resumeステートメント ]
    Chapter.81 [ バイトとビット ]
    Chapter.82 [ ウィンドウメッセージとイベント ]
    Chapter.83 [ 文字列の基礎 ]
    Chapter.84 [ 文字列操作① ]
    Chapter.85 [ 文字列操作② ]
    Chapter.86 [ タイピングゲーム1:仕様を決める ]
    Chapter.87 [ タイピングゲーム2:キー入力検知 ]
    Chapter.88 [ タイピングゲーム3:文字列照合 ]
    Chapter.89 [ タイピングゲーム4:判定関数 ]
    Chapter.90 [ タイピングゲーム5:ゲーム画面設計 ]
    Chapter.91 [ タイピングゲーム6:問題文のソート ]
    Chapter.92 [ タイピングゲーム7:動的配列 ]
    Chapter.93 [ タイピングゲーム8:キーダウンイベント ]
    Chapter.94 [ タイピングゲーム9:正打数の表示 ]
    Chapter.95 [ タイピングゲーム10:タイムの表示 ]
    Chapter.96 [ クリックゲーム1:イベントの種類 ]
    Chapter.97 [ クリックゲーム2:画面設計 ]
    Chapter.98 [ クリックゲーム3:クリック座標検知 ]
    Chapter.99 [ クリックゲーム4:キャラクター準備 ]
    Chapter.100 [ クリックゲーム5:キャラクターの配置 ]
    Chapter.101 [ クリックゲーム6:キャラクター移動とNot演算子 ]
    Chapter.102 [ クリックゲーム7:クリックのヒット判定 ]
    Chapter.103 [ クリックゲーム8:ヒットマークエフェクト ]
    Chapter.104 [ クリックゲーム9:サウンド処理の実装 ]
    Chapter.105 [ クリックゲーム10:マウスカーソルの変更 ]
    Chapter.106 [ ブロック崩しゲーム1:仕様と概要を決める ]
    Chapter.107 [ ブロック崩しゲーム2:基本概念の確認 ]
    Chapter.108 [ ブロック崩しゲーム3:ベクトルとは ]
    Chapter.109 [ ブロック崩しゲーム4:変数や定数の宣言 ]
    Chapter.110 [ ブロック崩しゲーム5:初期化処理の実装 ]
    Chapter.111 [ ブロック崩しゲーム6:ブロックの配置 ]
    Chapter.112 [ ブロック崩しゲーム7:根幹処理とバーの処理 ]
    Chapter.113 [ ブロック崩しゲーム8:線分と線分の交差を判定 ]
    Chapter.114 [ ブロック崩しゲーム9:線分同士の交点 ]
    Chapter.115 [ ブロック崩しゲーム10:ボールの処理 ]
    Chapter.116 [ ブロック崩しゲーム11:最終調整して完成へ ]
    Chapter.117 [ テキストファイル操作基礎 ]
    Chapter.118 [ テキストファイル操作:読み込み編 ]
    Chapter.119 [ テキストファイル操作:CSV読み込み編 ]
    Chapter.120 [ テキストファイル操作:様々な読込編 ]
    Chapter.121 [ テキストファイル操作:バイナリ編 ]
    Chapter.122 [ テキストファイル操作:暗号化編 ]
    Chapter.123 [ テキストファイル操作:復号化編 ]
    Chapter.124 [ クラスモジュールとは ]
    Chapter.125 [ クラスモジュール:メソッド編 ]
    Chapter.126 [ クラスモジュール:プロパティ編 ]
    Chapter.127 [ クラスモジュール:イベント拡張編 ]
    Chapter.128 [ クラスモジュール:イベント自作編 ]
    Chapter.129 [ APIによる描画処理1:ハンドル ]
    Chapter.130 [ APIによる描画処理2:デバイスコンテキスト ]
    Chapter.131 [ APIによる描画処理3:ペン オブジェクト ]
    Chapter.132 [ APIによる描画処理4:ブラシ オブジェクト ]
    Chapter.133 [ APIによる描画処理5:図形描画準備編 ]
    Chapter.134 [ APIによる描画処理6:図形描画実践編 ]
    Chapter.135 [ APIによる描画処理7:画像描画の仕組み編 ]
    Chapter.136 [ APIによる描画処理8:ビットブロック転送編 ]
    Chapter.137 [ APIによる描画処理9:ラスタオペレーション ]
    Chapter.138 [ APIによる描画処理10:マスク描画 概念編 ]
    Chapter.139 [ APIによる描画処理11:マスク描画 実践編 ]


    コードやVBAに関する質問などはサポート掲示板(別館)までお気軽にどうぞ。




fc2 seotool Excel VBA ゲーム プログラミング 講座

Counter

twitter


Shadow BBS - 影掲示板

VBA 関連書籍



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。